2
0

FoxActiveCells.Mod 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818
  1. MODULE FoxActiveCells; (** AUTHOR "fof"; PURPOSE "hardware library for the ActiveCells compiler"; *)
  2. (*! deprecated -- not used any more in Active Cells 3 *)
  3. IMPORT SyntaxTree := FoxSyntaxTree, Basic := FoxBasic, Global := FoxGlobal, Files, Streams, D := Debugging, Diagnostics, Strings, Commands, GenericLinker, Linker, SYSTEM, Modules;
  4. CONST
  5. In*= SyntaxTree.InPort; Out*= SyntaxTree.OutPort;
  6. defaultInstructionMemorySize*=0; (* in code units *)
  7. defaultDataMemorySize *=2048; (* in data units *)
  8. defaultPortWidth *=32; (* bits *)
  9. defaultFifoSize *=32; (* "words" of port width size *)
  10. defaultChannelWidth* = 32;
  11. CodeFileExtension*="code";
  12. DataFileExtension*="data";
  13. SpecificationFileExtension*="spec";
  14. ObjectFileExtension*="Gof";
  15. VectorCapability*=Global.VectorCapability;
  16. FloatingPointCapability*=Global.FloatingPointCapability;
  17. TRMSCapability*=Global.TRMSCapability;
  18. TraceError=FALSE;
  19. BasePortAddress=LONGINT(0FFFFFFE0H);
  20. TraceSame= FALSE;
  21. (* comparison flags *)
  22. CheckModules= 0;
  23. CheckParameters=1;
  24. CheckCapabilityParameters = 2;
  25. TYPE
  26. Name*= ARRAY 256 OF CHAR;
  27. PortInstance*=RECORD
  28. instance-: Instance; port-: Port
  29. END;
  30. (* base type of all ingredients of the specification graph *)
  31. Symbol*=OBJECT
  32. VAR name-: Name;
  33. scope-: Scope;
  34. PROCEDURE GetFullName*(VAR name: ARRAY OF CHAR; in: Scope);
  35. PROCEDURE InScope(this,in : Scope): BOOLEAN;
  36. BEGIN
  37. WHILE (this # NIL) & (this # in) DO
  38. this := this.scope;
  39. END;
  40. RETURN this # NIL
  41. END InScope;
  42. BEGIN
  43. IF (SELF.scope # NIL) & ~InScope(in,SELF.scope) THEN
  44. SELF.scope.GetFullName(name,in);
  45. Strings.Append(name,".");
  46. Strings.Append(name,SELF.name);
  47. ELSE
  48. COPY(SELF.name,name)
  49. END;
  50. END GetFullName;
  51. PROCEDURE InitSymbol(CONST name: ARRAY OF CHAR; scope: Scope);
  52. BEGIN
  53. COPY(name,SELF.name);
  54. SELF.scope := scope;
  55. END InitSymbol;
  56. PROCEDURE AppendToMsg*(VAR msg: ARRAY OF CHAR);
  57. VAR name:Name;
  58. BEGIN
  59. GetFullName(name, NIL);
  60. Strings.Append(msg, name);
  61. END AppendToMsg;
  62. PROCEDURE Same*(as: Symbol; flags: SET): BOOLEAN;
  63. BEGIN
  64. RETURN name = as.name
  65. END Same;
  66. END Symbol;
  67. SymbolList*= OBJECT(Basic.List)
  68. PROCEDURE GetSymbol*(i: LONGINT): Symbol;
  69. VAR a: ANY;
  70. BEGIN
  71. a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Symbol) END
  72. END GetSymbol;
  73. PROCEDURE AddSymbol(a: Symbol);
  74. BEGIN Add(a);
  75. END AddSymbol;
  76. PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Symbol;
  77. VAR a: Symbol; i: LONGINT;
  78. BEGIN
  79. FOR i := 0 TO Length()-1 DO
  80. a := GetSymbol(i);
  81. IF (a # NIL) & (a.name = name) THEN RETURN a END;
  82. END;
  83. RETURN NIL
  84. END ByName;
  85. PROCEDURE Same(as: SymbolList; flags: SET): BOOLEAN;
  86. VAR i: LONGINT; left, right: Symbol;
  87. BEGIN
  88. IF as.Length() # Length() THEN RETURN FALSE END;
  89. FOR i := 0 TO Length()-1 DO
  90. left := GetSymbol(i);
  91. right := as.GetSymbol(i);
  92. IF ~left.Same(right, flags) THEN RETURN FALSE END;
  93. END;
  94. RETURN TRUE
  95. END Same;
  96. END SymbolList;
  97. (* representation of a channel end point
  98. - represented as PORT parameter in the language
  99. - endpoint of FIFOs in hardware
  100. *)
  101. Port*= OBJECT (Symbol)
  102. VAR
  103. direction-: LONGINT;
  104. adr-: LONGINT;
  105. width-: LONGINT;
  106. delegate-: PortInstance;
  107. index-: LONGINT;
  108. PROCEDURE Same*(as: Symbol; flags: SET): BOOLEAN;
  109. BEGIN
  110. IF TraceSame THEN TRACE("Port",name) END;
  111. IF (as = NIL) OR ~(as IS Port) THEN RETURN FALSE END;
  112. WITH as: Port DO
  113. IF (direction # as.direction) OR (adr # as.adr) OR (width # as.width) THEN RETURN FALSE END;
  114. END;
  115. RETURN Same^(as, flags)
  116. END Same;
  117. PROCEDURE &InitPort*(CONST name: ARRAY OF CHAR; scope: Scope; direction: LONGINT; adr: LONGINT);
  118. BEGIN
  119. InitSymbol(name,scope);
  120. SELF.direction := direction;
  121. SELF.adr := adr;
  122. width := defaultPortWidth;
  123. delegate.instance := NIL;
  124. index := -1;
  125. END InitPort;
  126. PROCEDURE SetWidth*(widthInBits: LONGINT);
  127. BEGIN width := widthInBits
  128. END SetWidth;
  129. PROCEDURE Delegate*(instance: Instance; port: Port);
  130. BEGIN
  131. delegate.instance := instance; delegate.port := port
  132. END Delegate;
  133. PROCEDURE Write*(w: Streams.Writer; indent: LONGINT);
  134. BEGIN
  135. Indent(w,indent);
  136. w.Int(index,1);
  137. w.String(" name="); w.String(name);
  138. w.String(" direction=");
  139. IF direction = In THEN w.String("in ");
  140. ELSIF direction=Out THEN w.String("out ");
  141. END;
  142. w.String(" adr="); w.Int(adr,1);
  143. w.String(" width="); w.Int(width,1);
  144. w.String(" delegateInstance=");
  145. IF delegate.instance = NIL THEN
  146. w.String("none")
  147. ELSE
  148. w.String(delegate.instance.name);
  149. w.String(" delegatePort="); w.String(delegate.port.name);
  150. END;
  151. w.Ln;
  152. w.Update;
  153. END Write;
  154. PROCEDURE Read*(r: Streams.Reader): BOOLEAN;
  155. VAR s: Name; index: LONGINT;
  156. BEGIN
  157. IF ~r.GetInteger(index,FALSE) OR (index # SELF.index) OR ~CheckItem(r,"name") OR ~GetString(r,name)
  158. OR ~CheckItem(r,"direction") OR ~GetString(r,s)
  159. THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  160. IF s = "in" THEN direction := In
  161. ELSIF s="out" THEN direction := Out
  162. END;
  163. IF ~CheckItem(r,"adr") OR ~r.GetInteger(adr,FALSE) OR
  164. ~CheckItem(r,"width") OR ~r.GetInteger(width,FALSE) OR
  165. ~CheckItem(r,"delegateInstance") OR ~GetString(r,s)
  166. THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  167. IF s = "none" THEN delegate.instance := NIL
  168. ELSE
  169. delegate.instance := scope.instances.ByName(s);
  170. ASSERT(delegate.instance # NIL);
  171. IF ~CheckItem(r,"delegatePort") OR ~GetString(r,s) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  172. delegate.port := delegate.instance.instanceType.ports.ByName(s);
  173. END;
  174. RETURN TRUE
  175. END Read;
  176. END Port;
  177. PortList*= OBJECT(Basic.List)
  178. PROCEDURE GetPort*(i: LONGINT): Port;
  179. VAR a: ANY;
  180. BEGIN
  181. a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Port) END
  182. END GetPort;
  183. PROCEDURE AddPort(a: Port);
  184. BEGIN a.index := Length(); Add(a);
  185. END AddPort;
  186. PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Port;
  187. VAR a: Port; i: LONGINT;
  188. BEGIN
  189. FOR i := 0 TO Length()-1 DO
  190. a := GetPort(i);
  191. IF (a # NIL) & (a.name = name) THEN RETURN a END;
  192. END;
  193. RETURN NIL
  194. END ByName;
  195. PROCEDURE Same(as: PortList; flags: SET): BOOLEAN;
  196. VAR i: LONGINT; left, right: Port;
  197. BEGIN
  198. IF as.Length() # Length() THEN RETURN FALSE END;
  199. FOR i := 0 TO Length()-1 DO
  200. left := GetPort(i);
  201. right := as.GetPort(i);
  202. IF ~left.Same(right, flags) THEN RETURN FALSE END;
  203. END;
  204. RETURN TRUE
  205. END Same;
  206. END PortList;
  207. (* devices are additional components that can be attached to processors
  208. - implicitly represented as imported module and used interface in the language
  209. - represented as components attached to processor in hardware
  210. *)
  211. Device*= OBJECT (Symbol)
  212. VAR
  213. adr-: LONGINT;
  214. index-: LONGINT;
  215. PROCEDURE Same*(as: Symbol; flags: SET): BOOLEAN;
  216. BEGIN
  217. IF TraceSame THEN TRACE("Device",name) END;
  218. IF (as = NIL) OR ~(as IS Device) THEN RETURN FALSE END;
  219. WITH as: Device DO
  220. IF (adr # as.adr) OR (index # as.index) THEN RETURN FALSE END;
  221. END;
  222. RETURN Same^(as, flags)
  223. END Same;
  224. PROCEDURE &InitDevice*(CONST name: ARRAY OF CHAR; scope: Scope; adr: LONGINT);
  225. BEGIN
  226. InitSymbol(name,scope);
  227. SELF.adr := adr;
  228. index := -1;
  229. END InitDevice;
  230. PROCEDURE Write*(w:Streams.Writer; indent: LONGINT);
  231. BEGIN
  232. Indent(w,indent);
  233. w.Int(index,1);
  234. w.String(" name="); w.String(name); w.String(" adr="); w.Int(adr,1); w.Ln;
  235. w.Update;
  236. END Write;
  237. PROCEDURE Read*(r: Streams.Reader): BOOLEAN;
  238. VAR i: LONGINT;
  239. BEGIN
  240. RETURN r.GetInteger(i,FALSE) & (i=index) &
  241. CheckItem(r,"name") & GetString(r,name) &
  242. CheckItem(r,"adr") & r.GetInteger(adr,FALSE);
  243. END Read;
  244. END Device;
  245. DeviceList*= OBJECT(Basic.List)
  246. PROCEDURE GetDevice*(i: LONGINT): Device;
  247. VAR a: ANY;
  248. BEGIN
  249. a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Device) END
  250. END GetDevice;
  251. PROCEDURE AddDevice(p: Device);
  252. BEGIN
  253. ASSERT(ByName(p.name) = NIL);
  254. p.index := Length(); Add(p);
  255. END AddDevice;
  256. PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Device;
  257. VAR a: Device; i: LONGINT;
  258. BEGIN
  259. FOR i := 0 TO Length()-1 DO
  260. a := GetDevice(i);
  261. IF (a # NIL) & (a.name = name) THEN RETURN a END;
  262. END;
  263. RETURN NIL
  264. END ByName;
  265. PROCEDURE Same(as: DeviceList; flags: SET): BOOLEAN;
  266. VAR i: LONGINT; left, right: Device;
  267. BEGIN
  268. IF as.Length() # Length() THEN RETURN FALSE END;
  269. FOR i := 0 TO Length()-1 DO
  270. left := GetDevice(i);
  271. right := as.GetDevice(i);
  272. IF ~left.Same(right, flags) THEN RETURN FALSE END;
  273. END;
  274. RETURN TRUE
  275. END Same;
  276. END DeviceList;
  277. (*
  278. a module is a collection of actors
  279. - represented as IMPORT in source code
  280. - has no representation in hardware
  281. *)
  282. Module*=OBJECT (Symbol)
  283. VAR
  284. fileName*: Files.FileName; (* preparation for separate compilation (optimization) *)
  285. index-: LONGINT;
  286. PROCEDURE Same*(as: Symbol; flags: SET): BOOLEAN;
  287. BEGIN
  288. IF TraceSame THEN TRACE("Module",name) END;
  289. IF (as = NIL) OR ~(as IS Module) THEN RETURN FALSE END;
  290. WITH as: Module DO
  291. IF (index # as.index) OR (fileName # as.fileName) THEN RETURN FALSE END;
  292. END;
  293. RETURN Same^(as, flags)
  294. END Same;
  295. PROCEDURE & InitModule(CONST name: ARRAY OF CHAR; scope: Scope; CONST fileName: ARRAY OF CHAR);
  296. BEGIN
  297. InitSymbol(name,scope);
  298. COPY(name, SELF.name);
  299. COPY(fileName, SELF.fileName);
  300. index := -1;
  301. END InitModule;
  302. PROCEDURE Write*(w:Streams.Writer; indent: LONGINT);
  303. BEGIN
  304. Indent(w,indent);
  305. w.Int(index,1);
  306. w.String(" name="); w.String(name);
  307. w.String(" filename="); w.String("'"); w.String(fileName); w.String("'");
  308. w.Ln;
  309. w.Update;
  310. END Write;
  311. PROCEDURE Read*(r: Streams.Reader): BOOLEAN;
  312. VAR i: LONGINT;
  313. BEGIN
  314. RETURN r.GetInteger(i,FALSE) & (i=index) & CheckItem(r,"name") & GetString(r,name)
  315. &CheckItem(r,"filename") & GetString(r,fileName);
  316. END Read;
  317. END Module;
  318. ModuleList*= OBJECT(Basic.List)
  319. PROCEDURE GetModule*(i: LONGINT): Module;
  320. VAR a: ANY;
  321. BEGIN
  322. a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Module) END
  323. END GetModule;
  324. PROCEDURE AddModule(a: Module);
  325. BEGIN a.index := Length(); Add(a);
  326. END AddModule;
  327. PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Module;
  328. VAR a: Module; i: LONGINT;
  329. BEGIN
  330. FOR i := 0 TO Length()-1 DO
  331. a := GetModule(i);
  332. IF (a # NIL) & (a.name = name) THEN RETURN a END;
  333. END;
  334. RETURN NIL
  335. END ByName;
  336. PROCEDURE Same(as: ModuleList; flags: SET): BOOLEAN;
  337. VAR i: LONGINT; left, right: Module;
  338. BEGIN
  339. IF as.Length() # Length() THEN RETURN FALSE END;
  340. FOR i := 0 TO Length()-1 DO
  341. left := GetModule(i);
  342. right := as.GetModule(i);
  343. IF ~left.Same(right, flags) THEN RETURN FALSE END;
  344. END;
  345. RETURN TRUE
  346. END Same;
  347. END ModuleList;
  348. (*
  349. parameters are used for setting up initial values on instances
  350. *)
  351. Parameter*=OBJECT (Symbol)
  352. CONST
  353. Boolean=0;Integer=1;String=2;
  354. VAR
  355. index-: LONGINT;
  356. parameterType-: SHORTINT; (* Integer or Boolean, for the time being *)
  357. integer-: LONGINT;
  358. boolean-: BOOLEAN;
  359. string-: Strings.String;
  360. PROCEDURE Same*(as: Symbol; flags: SET): BOOLEAN;
  361. BEGIN
  362. IF TraceSame THEN TRACE("Parameter",name) END;
  363. IF (as = NIL) OR ~(as IS Parameter) THEN RETURN FALSE END;
  364. WITH as: Parameter DO
  365. (*IF (index # as.index) OR (type # as.type) OR (integer # as.integer) OR (as.boolean # boolean) THEN RETURN FALSE END;*)
  366. IF (index # as.index) OR (parameterType # as.parameterType) THEN RETURN FALSE; END;
  367. IF ((parameterType = 0) & (as.boolean # boolean))
  368. OR ((parameterType = 1) & (as.integer # integer))
  369. OR ((parameterType = 2) & (as.string^ # string^)) THEN RETURN FALSE; END;
  370. END;
  371. RETURN Same^(as, flags)
  372. END Same;
  373. PROCEDURE &Init(CONST name: ARRAY OF CHAR; scope: Scope);
  374. BEGIN
  375. InitSymbol(name,scope);
  376. END Init;
  377. PROCEDURE SetBoolean*(b: BOOLEAN);
  378. BEGIN
  379. parameterType := Boolean; boolean := b
  380. END SetBoolean;
  381. PROCEDURE SetInteger*(i: LONGINT);
  382. BEGIN
  383. parameterType := Integer; integer := i
  384. END SetInteger;
  385. PROCEDURE SetString*(CONST s: ARRAY OF CHAR);
  386. BEGIN
  387. parameterType := String; string := Strings.NewString(s);
  388. END SetString;
  389. PROCEDURE Write(w: Streams.Writer; indent: LONGINT);
  390. VAR typeName: SyntaxTree.String;
  391. BEGIN
  392. Indent(w,indent);
  393. w.Int(index,1);
  394. w.String(" name="); w.String(name);
  395. w.String(" type=");
  396. IF parameterType = Integer THEN w.String("INTEGER")
  397. ELSIF parameterType=Boolean THEN w.String("BOOLEAN")
  398. ELSIF parameterType=String THEN w.String("STRING");
  399. END;
  400. w.String(" value=");
  401. IF parameterType = Integer THEN w.Int(integer,1)
  402. ELSIF parameterType=Boolean THEN
  403. IF boolean THEN w.String("TRUE") ELSE w.String("FALSE") END
  404. ELSIF parameterType = String THEN w.String("'"); w.String(string^); w.String("'");
  405. END;
  406. w.Ln;
  407. w.Update;
  408. END Write;
  409. PROCEDURE Read(r: Streams.Reader): BOOLEAN;
  410. VAR index: LONGINT; s: Name;
  411. BEGIN
  412. IF r.GetInteger(index,FALSE) & CheckItem(r,"name") & GetString(r,name)
  413. &CheckItem(r,"type") & GetString(r,s) & CheckItem(r,"value") THEN
  414. IF s= "INTEGER" THEN parameterType := Integer
  415. ELSIF s = "BOOLEAN" THEN parameterType := Boolean
  416. ELSIF s = "STRING" THEN parameterType := String
  417. ELSE RETURN FALSE
  418. END;
  419. IF (parameterType = Integer) & r.GetInteger(integer,FALSE) THEN
  420. ELSIF (parameterType=Boolean) & GetString(r,s) THEN
  421. IF s="TRUE" THEN boolean := TRUE ELSE boolean := FALSE END;
  422. ELSIF (parameterType=String) & GetString(r,s) THEN
  423. string := Strings.NewString(s);
  424. ELSE RETURN FALSE
  425. END;
  426. ELSE RETURN FALSE
  427. END;
  428. RETURN TRUE
  429. END Read;
  430. END Parameter;
  431. ParameterList*= OBJECT(Basic.List)
  432. PROCEDURE GetParameter*(i: LONGINT): Parameter;
  433. VAR a: ANY;
  434. BEGIN
  435. a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Parameter) END
  436. END GetParameter;
  437. PROCEDURE AddParameter(a: Parameter);
  438. BEGIN a.index := Length(); Add(a);
  439. END AddParameter;
  440. PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Parameter;
  441. VAR a: Parameter; i: LONGINT;
  442. BEGIN
  443. FOR i := 0 TO Length()-1 DO
  444. a := GetParameter(i);
  445. IF (a # NIL) & (a.name = name) THEN RETURN a END;
  446. END;
  447. RETURN NIL
  448. END ByName;
  449. PROCEDURE Same(as: ParameterList; flags: SET): BOOLEAN;
  450. VAR i: LONGINT; left, right: Parameter;
  451. BEGIN
  452. IF as.Length() # Length() THEN RETURN FALSE END;
  453. FOR i := 0 TO Length()-1 DO
  454. left := GetParameter(i);
  455. right := as.GetParameter(i);
  456. IF ~left.Same(right, flags) THEN RETURN FALSE END;
  457. END;
  458. RETURN TRUE
  459. END Same;
  460. END ParameterList;
  461. (*
  462. instances are variables in networks pointing to a type
  463. - represented as VAR ... in assemblies (networks)
  464. - when instantiated the instance represents the instance of a processor in hardware
  465. *)
  466. Instance*=OBJECT (Symbol)
  467. VAR
  468. instanceType-: Type; (* instance type *)
  469. parameters-: ParameterList;
  470. capabilityParameters-: ParameterList;
  471. index-: LONGINT;
  472. (* caches: *)
  473. instructionMemorySize-, dataMemorySize-: LONGINT;
  474. capabilities-: SET;
  475. PROCEDURE Same*(as: Symbol; flags: SET): BOOLEAN;
  476. BEGIN
  477. IF TraceSame THEN TRACE("Instance",name) END;
  478. IF (as = NIL) OR ~(as IS Instance) THEN RETURN FALSE END;
  479. WITH as: Instance DO
  480. IF (index # as.index) THEN RETURN FALSE END;
  481. IF ~instanceType.Same(as.instanceType, flags) THEN RETURN FALSE END;
  482. IF (CheckParameters IN flags) & ~parameters.Same(as.parameters, flags) THEN RETURN FALSE END;
  483. IF (CheckCapabilityParameters IN flags) & ~capabilityParameters.Same(as.capabilityParameters, flags) THEN RETURN FALSE END;
  484. IF (instructionMemorySize # as.instructionMemorySize) THEN RETURN FALSE END;
  485. IF (dataMemorySize # as.dataMemorySize) THEN RETURN FALSE END;
  486. END;
  487. RETURN Same^(as, flags)
  488. END Same;
  489. PROCEDURE IsEngine*(): BOOLEAN;
  490. BEGIN
  491. RETURN Global.EngineCapability IN capabilities
  492. END IsEngine;
  493. PROCEDURE &Init(CONST name: ARRAY OF CHAR; scope: Scope; c: Type);
  494. BEGIN
  495. InitSymbol(name,scope);
  496. instanceType := c;
  497. index := -1; SELF.scope := scope; NEW(parameters,4); NEW(capabilityParameters, 4);
  498. ASSERT(scope # NIL);
  499. SetType(c);
  500. END Init;
  501. PROCEDURE SetType(type: Type);
  502. BEGIN
  503. IF type # NIL THEN
  504. SELF.instanceType := type;
  505. dataMemorySize := type.dataMemorySize;
  506. capabilities := type.capabilities;
  507. END;
  508. END SetType;
  509. PROCEDURE SetInstructionMemorySize*(value: LONGINT);
  510. BEGIN instructionMemorySize := value
  511. END SetInstructionMemorySize;
  512. PROCEDURE SetDataMemorySize*(value: LONGINT);
  513. BEGIN dataMemorySize := value
  514. END SetDataMemorySize;
  515. PROCEDURE AddParameter*(CONST name: ARRAY OF CHAR): Parameter;
  516. VAR parameter: Parameter;
  517. BEGIN
  518. NEW(parameter,name,NIL); parameters.Add(parameter);
  519. RETURN parameter
  520. END AddParameter;
  521. PROCEDURE AddCapabilityParameter*(CONST name: ARRAY OF CHAR): Parameter;
  522. VAR parameter: Parameter;
  523. BEGIN
  524. NEW(parameter,name,NIL); capabilityParameters.Add(parameter);
  525. RETURN parameter
  526. END AddCapabilityParameter;
  527. PROCEDURE Write(w: Streams.Writer; indent: LONGINT);
  528. VAR typeName: Name; parameter: Parameter; i: LONGINT;
  529. BEGIN
  530. Indent(w,indent); INC(indent);
  531. w.Int(index,1);
  532. w.String(" name="); w.String(name);
  533. instanceType.GetFullName(typeName,scope);
  534. w.String(" type="); w.String(typeName);
  535. w.String(" instructionMemorySize="); w.Int(instructionMemorySize,1);
  536. w.String(" dataMemorySize="); w.Int(dataMemorySize,1);
  537. w.String(" capabilities="); WriteSet(w,capabilities);
  538. w.Ln;
  539. Indent(w,indent);
  540. w.String("parameters=");w.Int(parameters.Length(),1); w.Ln;
  541. FOR i := 0 TO parameters.Length()-1 DO
  542. parameter := parameters.GetParameter(i);
  543. parameter.Write(w,indent+1);
  544. END;
  545. Indent(w,indent);
  546. w.String("capabilityParameters=");w.Int(capabilityParameters.Length(),1); w.Ln;
  547. FOR i := 0 TO capabilityParameters.Length()-1 DO
  548. parameter := capabilityParameters.GetParameter(i);
  549. parameter.Write(w,indent+1);
  550. END;
  551. w.Update;
  552. END Write;
  553. PROCEDURE Read(r: Streams.Reader): BOOLEAN;
  554. VAR index: LONGINT; s: Name; symbol: Symbol; i,number: LONGINT; parameter: Parameter;
  555. BEGIN
  556. IF r.GetInteger(index,FALSE) & CheckItem(r,"name") & GetString(r,name) &
  557. CheckItem(r,"type") & GetString(r,s) &
  558. CheckItem(r,"instructionMemorySize") & r.GetInteger(instructionMemorySize,FALSE) &
  559. CheckItem(r,"dataMemorySize") & r.GetInteger(dataMemorySize,FALSE) &
  560. CheckItem(r,"capabilities") & GetSet(r,capabilities)
  561. THEN
  562. symbol := GetSymbol(scope,s);
  563. IF symbol = NIL THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  564. SetType(symbol(Type));
  565. IF ~CheckItem(r,"parameters") OR ~r.GetInteger(number,FALSE)
  566. THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  567. FOR i := 0 TO number-1 DO
  568. parameter := AddParameter("");
  569. IF ~parameter.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  570. END;
  571. IF ~CheckItem(r,"capabilityParameters") OR ~r.GetInteger(number,FALSE)
  572. THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  573. FOR i := 0 TO number-1 DO
  574. parameter := AddCapabilityParameter("");
  575. IF ~parameter.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  576. END;
  577. RETURN TRUE
  578. ELSE IF TraceError THEN HALT(100) ELSE RETURN FALSE END
  579. END;
  580. END Read;
  581. PROCEDURE AppendToMsg*(VAR msg: ARRAY OF CHAR);
  582. VAR name:Name;
  583. BEGIN
  584. AppendToMsg^(msg);
  585. instanceType.GetFullName(name,NIL);
  586. Strings.Append(msg," (");
  587. Strings.Append(msg,name);
  588. Strings.Append(msg,")");
  589. END AppendToMsg;
  590. END Instance;
  591. InstanceList*= OBJECT(Basic.List)
  592. PROCEDURE GetInstance*(i: LONGINT): Instance;
  593. VAR a: ANY;
  594. BEGIN
  595. a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Instance) END
  596. END GetInstance;
  597. PROCEDURE AddInstance(a: Instance);
  598. BEGIN a.index := Length(); Add(a);
  599. END AddInstance;
  600. PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Instance;
  601. VAR a: Instance; i: LONGINT;
  602. BEGIN
  603. FOR i := 0 TO Length()-1 DO
  604. a := GetInstance(i);
  605. IF (a # NIL) & (a.name = name) THEN RETURN a END;
  606. END;
  607. RETURN NIL
  608. END ByName;
  609. PROCEDURE Same(as: InstanceList; flags: SET): BOOLEAN;
  610. VAR i: LONGINT; left, right: Symbol;
  611. BEGIN
  612. IF as.Length() # Length() THEN RETURN FALSE END;
  613. FOR i := 0 TO Length()-1 DO
  614. left := GetInstance(i);
  615. right := as.GetInstance(i);
  616. IF ~left.Same(right, flags) THEN RETURN FALSE END;
  617. END;
  618. RETURN TRUE
  619. END Same;
  620. END InstanceList;
  621. InstanceMethod*= PROCEDURE {DELEGATE} (instance: Instance): BOOLEAN;
  622. TypeMethod*= PROCEDURE {DELEGATE} (type: Type): BOOLEAN;
  623. Scope*=OBJECT (Symbol)
  624. VAR
  625. symbols-: SymbolList;
  626. instances-: InstanceList;
  627. channels-: ChannelList;
  628. types-: TypeList;
  629. ports-: PortList;
  630. index-: LONGINT;
  631. specification-: Specification;
  632. PROCEDURE &InitScope(CONST name: ARRAY OF CHAR; scope: Scope; specification: Specification);
  633. BEGIN
  634. COPY(name,SELF.name); SELF.specification := specification;
  635. NEW(instances,4); NEW(channels,4);
  636. NEW(ports,4); NEW(types,4);
  637. NEW(symbols,4);
  638. index := -1;
  639. END InitScope;
  640. PROCEDURE Same*(as: Symbol; flags: SET): BOOLEAN;
  641. BEGIN
  642. IF TraceSame THEN TRACE("Scope",name) END;
  643. IF (as = NIL) OR ~(as IS Scope) THEN RETURN FALSE END;
  644. WITH as: Scope DO
  645. IF ~symbols.Same(as.symbols, flags) THEN RETURN FALSE END;
  646. IF ~instances.Same(as.instances, flags) THEN RETURN FALSE END;
  647. IF ~channels.Same(as.channels, flags) THEN RETURN FALSE END;
  648. IF ~types.Same(as.types, flags) THEN RETURN FALSE END;
  649. IF ~ports.Same(as.ports, flags) THEN RETURN FALSE END;
  650. END;
  651. RETURN Same^(as, flags)
  652. END Same;
  653. PROCEDURE FindSymbol(CONST name: ARRAY OF CHAR; traverse: BOOLEAN): Symbol;
  654. VAR symbol: Symbol;
  655. BEGIN
  656. symbol := symbols.ByName(name);
  657. IF (symbol = NIL) & (scope # NIL) & traverse THEN RETURN scope.FindSymbol(name,TRUE)
  658. ELSE RETURN symbol;
  659. END;
  660. END FindSymbol;
  661. PROCEDURE NewInstance*(CONST name: ARRAY OF CHAR; type: Type): Instance;
  662. VAR instance: Instance;
  663. BEGIN
  664. NEW(instance, name, SELF, type);
  665. instances.AddInstance(instance);
  666. symbols.AddSymbol(instance);
  667. RETURN instance
  668. END NewInstance;
  669. (* generate a new channel, may be overwritten by implementations if a non-default channel object has to be installed *)
  670. PROCEDURE NewChannel*(): Channel;
  671. VAR channel: Channel; name: Name;
  672. BEGIN
  673. name := "@Channel"; Basic.AppendNumber(name,channels.Length());
  674. NEW(channel,name,SELF);
  675. channels.AddChannel(channel);
  676. symbols.AddSymbol(channel);
  677. RETURN channel;
  678. END NewChannel;
  679. (* generate a new port, may be overwritten by implementations if a non-default port object has to be installed *)
  680. PROCEDURE NewPort*(CONST name: ARRAY OF CHAR; direction: LONGINT; adr: LONGINT): Port;
  681. VAR port: Port;
  682. BEGIN
  683. NEW(port, name,SELF, direction,adr);
  684. ports.AddPort(port);
  685. symbols.AddSymbol(port);
  686. RETURN port
  687. END NewPort;
  688. (* generate a new type, may be overwritten by implementations if a non-default type object has to be installed *)
  689. PROCEDURE NewType*(CONST name: ARRAY OF CHAR): Type;
  690. VAR type: Type;
  691. BEGIN
  692. NEW(type,name,SELF);
  693. types.AddType(type);
  694. symbols.AddSymbol(type);
  695. RETURN type
  696. END NewType;
  697. PROCEDURE ForEachInstanceDo*(method: InstanceMethod): BOOLEAN;
  698. VAR i: LONGINT; instance: Instance; type: Type;
  699. BEGIN
  700. FOR i := 0 TO instances.Length()-1 DO
  701. instance := instances.GetInstance(i);
  702. IF ~method(instance) THEN RETURN FALSE END;
  703. END;
  704. (*
  705. FOR i := 0 TO types.Length()-1 DO
  706. type := types.GetType(i);
  707. IF ~type.ForEachInstanceDo(method) THEN RETURN FALSE END
  708. END;
  709. *)
  710. RETURN TRUE
  711. END ForEachInstanceDo;
  712. PROCEDURE ForEachTypeDo*(method: TypeMethod): BOOLEAN; (* used for linking *)
  713. VAR type: Type; i: LONGINT;
  714. BEGIN
  715. FOR i := 0 TO types.Length()-1 DO
  716. type := types.GetType(i);
  717. IF ~method(type) THEN RETURN FALSE END;
  718. IF ~type.ForEachTypeDo(method) THEN RETURN FALSE END; (* subtypes *)
  719. END;
  720. RETURN TRUE
  721. END ForEachTypeDo;
  722. (*
  723. PROCEDURE Link*(diagnostics: Diagnostics.Diagnostics; codeUnit, dataUnit: LONGINT): BOOLEAN;
  724. VAR type: Type; i: LONGINT;
  725. BEGIN
  726. FOR i := 0 TO types.Length()-1 DO
  727. type := types.GetType(i);
  728. IF type.instances.Length()=0 THEN
  729. IF ~type.LinkType(diagnostics, codeUnit, dataUnit) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  730. ELSE
  731. type.SetDataMemorySize(0);
  732. END;
  733. IF ~type.Link(diagnostics, codeUnit, dataUnit) THEN RETURN FALSE END; (* subtypes ? *)
  734. END;
  735. RETURN TRUE
  736. END Link;
  737. *)
  738. END Scope;
  739. (*
  740. definition of a (virtual) computing node (processor)
  741. - represented by ACTOR or ASSEMBLY (-> virtual) in source code
  742. - represented as processor (if ACTOR) and as network or processors (if ASSEMBLY) in hardware
  743. *)
  744. Type*=OBJECT (Scope)
  745. VAR
  746. devices-: DeviceList;
  747. modules-: ModuleList; (* for linking / compiling *)
  748. instructionMemorySize-, dataMemorySize-: LONGINT; (* sizes in units *)
  749. capabilities-: SET;
  750. PROCEDURE Same*(as: Symbol; flags: SET): BOOLEAN;
  751. BEGIN
  752. IF TraceSame THEN TRACE("Type",name) END;
  753. IF (as = NIL) OR ~(as IS Type) THEN RETURN FALSE END;
  754. WITH as: Type DO
  755. IF ~devices.Same(as.devices, flags) THEN RETURN FALSE END;
  756. IF (CheckModules IN flags) & ~modules.Same(as.modules, flags) THEN RETURN FALSE END;
  757. IF (instructionMemorySize # as.instructionMemorySize) THEN RETURN FALSE END;
  758. IF (dataMemorySize # as.dataMemorySize) THEN RETURN FALSE END;
  759. IF (capabilities # as.capabilities) THEN RETURN FALSE END;
  760. END;
  761. RETURN TRUE (*RETURN Same^(as, flags)*)
  762. END Same;
  763. PROCEDURE & InitType*(CONST name: ARRAY OF CHAR; scope: Scope);
  764. BEGIN
  765. InitScope(name,scope,scope.specification);
  766. ASSERT(specification # NIL);
  767. instructionMemorySize := defaultInstructionMemorySize;
  768. dataMemorySize := defaultDataMemorySize;
  769. NEW(devices,4);
  770. NEW(modules,4);
  771. SELF.scope := scope;
  772. capabilities := {};
  773. END InitType;
  774. PROCEDURE AddCapability*(capability: LONGINT);
  775. BEGIN
  776. INCL(capabilities, capability);
  777. END AddCapability;
  778. PROCEDURE SetInstructionMemorySize*(value: LONGINT);
  779. BEGIN instructionMemorySize := value
  780. END SetInstructionMemorySize;
  781. PROCEDURE SetDataMemorySize*(value: LONGINT);
  782. BEGIN dataMemorySize := value
  783. END SetDataMemorySize;
  784. (* generate a new device, may be overwritten by implementations if a non-default device object has to be installed *)
  785. PROCEDURE NewDevice*(CONST name: ARRAY OF CHAR; adr: LONGINT): Device;
  786. VAR device: Device;
  787. BEGIN
  788. NEW(device,name,SELF, adr);
  789. devices.AddDevice(device);
  790. symbols.AddSymbol(device);
  791. RETURN device;
  792. END NewDevice;
  793. PROCEDURE NewModule*(CONST moduleName, fileName: ARRAY OF CHAR): Module;
  794. VAR module: Module;
  795. BEGIN
  796. NEW(module, moduleName, SELF, fileName);
  797. modules.AddModule(module);
  798. symbols.AddSymbol(module);
  799. RETURN module;
  800. END NewModule;
  801. (*
  802. PROCEDURE ThisPort(CONST name: ARRAY OF CHAR): Port;
  803. VAR type: Type; port:Port; i: LONGINT;
  804. BEGIN
  805. (*! suboptimal, replace by two-staged version *)
  806. FOR i := 0 TO subTypes.Length()-1 DO
  807. type := subTypes.GetType(i);
  808. port := type.ports.ByName(name);
  809. IF port # NIL THEN RETURN port END;
  810. END;
  811. RETURN NIL
  812. END ThisPort;
  813. *)
  814. (* moved to compiler driver
  815. PROCEDURE LinkType*(diagnostics: Diagnostics.Diagnostics; codeUnit, dataUnit: LONGINT): BOOLEAN;
  816. VAR
  817. fileName, codeFileName, dataFileName: Files.FileName;
  818. code, data: Linker.Arrangement; linker: GenericLinker.Linker;
  819. module: Module;
  820. linkRoot,msg: SyntaxTree.String;
  821. i: LONGINT;
  822. logFile: Files.File; linkerLog: Files.Writer;
  823. BEGIN
  824. NEW (code, 0);
  825. NEW (data, 0);
  826. NEW (linker, diagnostics, linkerLog, FALSE (* useAll *), FALSE (* stripInitCodes *), code, data);
  827. GetFullName(msg,NIL);
  828. Strings.Append(msg,".log");
  829. logFile := Files.New(msg);
  830. IF logFile # NIL THEN NEW(linkerLog,logFile,0) ELSE logFile := NIL END;
  831. GetFullName(linkRoot,NIL);
  832. Strings.Append(linkRoot,".@BodyStub");
  833. linker.SetLinkRoot(linkRoot);
  834. FOR i := 0 TO modules.Length()-1 DO
  835. module := modules.GetModule(i);
  836. Linker.ReadObjectFile(module.name, "",ObjectFileExtension,linker);
  837. END;
  838. (* do linking after having read in all blocks to account for potential constraints *)
  839. IF ~linker.error THEN linker.Link; END;
  840. instructionMemorySize := MAX(code.SizeInBits() DIV codeUnit, instructionMemorySize);
  841. dataMemorySize := MAX(data.SizeInBits() DIV dataUnit, dataMemorySize);
  842. GetFullName(fileName,NIL);
  843. Files.JoinExtension(fileName,CodeFileExtension,codeFileName);
  844. Files.JoinExtension(fileName,DataFileExtension,dataFileName);
  845. IF ~linker.error THEN
  846. Linker.WriteOutputFile (code, codeFileName, linker, Linker.WriteTRMCodeFile);
  847. Linker.WriteOutputFile (data, dataFileName, linker, Linker.WriteTRMDataFile);
  848. GetFullName(msg,NIL); Strings.Append(msg," successfully linked");
  849. IF linkerLog # NIL THEN linkerLog.Update; Files.Register(logFile) END;
  850. IF specification.log # NIL THEN specification.log.String(msg); specification.log.Ln END;
  851. ELSE
  852. msg := "could not link ";
  853. Strings.Append(msg,linkRoot);
  854. FOR i := 0 TO modules.Length()-1 DO
  855. module := modules.GetModule(i);
  856. Strings.Append(msg," "); Strings.Append(msg,module.name);
  857. END;
  858. diagnostics.Error("",Streams.Invalid, msg);
  859. END;
  860. RETURN ~linker.error
  861. END LinkType;
  862. *)
  863. PROCEDURE Read(r: Streams.Reader): BOOLEAN;
  864. VAR port: Port; module: Module; device: Device; i,number: LONGINT;
  865. channel: Channel; instance: Instance; type: Type;
  866. BEGIN
  867. IF ~r.GetInteger(i,FALSE) OR (index # i) OR
  868. ~CheckItem(r,"name") OR ~GetString(r,name) OR
  869. ~CheckItem(r,"instructionMemorySize") OR ~r.GetInteger(instructionMemorySize,FALSE) OR
  870. ~CheckItem(r,"dataMemorySize") OR ~r.GetInteger(dataMemorySize,FALSE) OR
  871. ~CheckItem(r,"capabilities") OR ~GetSet(r,capabilities) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  872. IF ~CheckItem(r,"types") OR ~r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  873. FOR i := 0 TO number-1 DO
  874. type := NewType("");
  875. IF ~type.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  876. END;
  877. IF ~CheckItem(r,"instances") OR ~r.GetInteger(number,FALSE)
  878. THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END
  879. END;
  880. FOR i := 0 TO number-1 DO
  881. instance := NewInstance("",NIL);
  882. IF ~instance.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  883. END;
  884. IF ~CheckItem(r,"ports")OR ~ r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  885. FOR i := 0 TO number-1 DO
  886. port := NewPort("",0,0);
  887. IF ~port.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  888. END;
  889. IF ~CheckItem(r,"modules")OR ~ r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  890. FOR i := 0 TO number-1 DO
  891. module := NewModule("","");
  892. IF ~module.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  893. END;
  894. IF ~CheckItem(r,"devices")OR ~ r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  895. FOR i := 0 TO number-1 DO
  896. device := NewDevice("",0);
  897. IF ~device.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  898. END;
  899. IF ~CheckItem(r,"channels") OR ~ r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  900. FOR i := 0 TO number-1 DO
  901. channel := NewChannel();
  902. IF ~channel.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  903. END;
  904. RETURN TRUE
  905. END Read;
  906. PROCEDURE Write*(w: Streams.Writer; indent: LONGINT);
  907. VAR port: Port; device: Device; module: Module; instance: Instance; channel: Channel; type: Type; i: LONGINT;
  908. BEGIN
  909. Indent(w,indent); INC(indent);
  910. w.Int(index,1);
  911. w.String(" name="); w.String(name);
  912. w.String(" instructionMemorySize="); w.Int(instructionMemorySize,1);
  913. w.String(" dataMemorySize="); w.Int(dataMemorySize,1);
  914. w.String(" capabilities="); WriteSet(w, capabilities);
  915. w.Ln;
  916. (* sub types first because of potential delegates on ports *)
  917. Indent(w,indent); w.String("types=");w.Int(types.Length(),1); w.Ln;
  918. FOR i := 0 TO types.Length()-1 DO
  919. type := types.GetType(i);
  920. type.Write(w,indent+1);
  921. END;
  922. Indent(w,indent);
  923. w.String("instances=");w.Int(instances.Length(),1); w.Ln;
  924. FOR i := 0 TO instances.Length()-1 DO
  925. instance := instances.GetInstance(i);
  926. instance.Write(w,indent+1);
  927. END;
  928. Indent(w,indent);
  929. w.String("ports=");w.Int(ports.Length(),1); w.Ln;
  930. FOR i := 0 TO ports.Length()-1 DO
  931. port := ports.GetPort(i);
  932. port.Write(w,indent+1);
  933. END;
  934. Indent(w,indent);
  935. w.String("modules="); w.Int(modules.Length(),1); w.Ln;
  936. FOR i := 0 TO modules.Length()-1 DO
  937. module := modules.GetModule(i);
  938. module.Write(w,indent+1);
  939. END;
  940. Indent(w,indent);
  941. w.String("devices="); w.Int(devices.Length(),1); w.Ln;
  942. FOR i := 0 TO devices.Length()-1 DO
  943. device := devices.GetDevice(i);
  944. device.Write(w,indent+1);
  945. END;
  946. Indent(w,indent);
  947. w.String("channels=");w.Int(channels.Length(),1); w.Ln;
  948. FOR i := 0 TO channels.Length()-1 DO
  949. channel := channels.GetChannel(i);
  950. channel.Write(w,indent+1);
  951. END;
  952. w.Update;
  953. END Write;
  954. END Type;
  955. TypeList*= OBJECT(Basic.List)
  956. PROCEDURE GetType*(i: LONGINT): Type;
  957. VAR a: ANY;
  958. BEGIN
  959. a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Type) END
  960. END GetType;
  961. PROCEDURE AddType(a: Type);
  962. BEGIN a.index := Length(); Add(a);
  963. END AddType;
  964. PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Type;
  965. VAR a: Type; i: LONGINT;
  966. BEGIN
  967. FOR i := 0 TO Length()-1 DO
  968. a := GetType(i);
  969. IF (a # NIL) & (a.name = name) THEN RETURN a END;
  970. END;
  971. RETURN NIL
  972. END ByName;
  973. PROCEDURE Same(as: TypeList; flags: SET): BOOLEAN;
  974. VAR i: LONGINT; left, right: Type;
  975. BEGIN
  976. IF as.Length() # Length() THEN RETURN FALSE END;
  977. FOR i := 0 TO Length()-1 DO
  978. left := GetType(i);
  979. right := as.GetType(i);
  980. IF ~left.Same(right, flags) THEN RETURN FALSE END;
  981. END;
  982. RETURN TRUE
  983. END Same;
  984. END TypeList;
  985. (*
  986. channel defines the channel between ports
  987. - defined by CONNECT in source code
  988. - represented as FIFO in hardware
  989. *)
  990. Channel*=OBJECT (Symbol)
  991. VAR
  992. in-, out-: PortInstance;
  993. fifoSize-: LONGINT;
  994. widthInBits-: LONGINT;
  995. index-: LONGINT; (* useful for implementations that emulate channels (simulator) *)
  996. PROCEDURE Same*(as: Symbol; flags: SET): BOOLEAN;
  997. BEGIN
  998. IF TraceSame THEN TRACE("Channel",name) END;
  999. IF (as = NIL) OR ~(as IS Channel) THEN RETURN FALSE END;
  1000. WITH as: Channel DO
  1001. IF ~in.instance.Same(as.in.instance, flags) THEN RETURN FALSE END;
  1002. IF ~in.port.Same(as.in.port, flags) THEN RETURN FALSE END;
  1003. IF ~out.instance.Same(as.out.instance, flags) THEN RETURN FALSE END;
  1004. IF ~out.port.Same(as.out.port, flags) THEN RETURN FALSE END;
  1005. IF widthInBits # as.widthInBits THEN RETURN FALSE END;
  1006. IF index # as.index THEN RETURN FALSE END;
  1007. END;
  1008. RETURN Same^(as, flags)
  1009. END Same;
  1010. PROCEDURE & InitChannel(CONST name: ARRAY OF CHAR; scope: Scope);
  1011. BEGIN
  1012. InitSymbol(name,scope);
  1013. fifoSize := defaultFifoSize;
  1014. widthInBits := defaultChannelWidth;
  1015. in.port := NIL; in.instance := NIL;
  1016. out.port := NIL; out.instance := NIL;
  1017. SELF.index := -1;
  1018. END InitChannel;
  1019. PROCEDURE ConnectIn*(instance: Instance; port: Port);
  1020. BEGIN in.port := port; in.instance := instance;
  1021. END ConnectIn;
  1022. PROCEDURE ConnectOut*(instance: Instance; port: Port);
  1023. BEGIN out.port := port; out.instance := instance;
  1024. END ConnectOut;
  1025. PROCEDURE SetFifoSize*(size: LONGINT);
  1026. BEGIN fifoSize := size
  1027. END SetFifoSize;
  1028. PROCEDURE SetWidth*(width: LONGINT);
  1029. BEGIN widthInBits := width
  1030. END SetWidth;
  1031. PROCEDURE Read(r: Streams.Reader): BOOLEAN;
  1032. VAR s: Name; i: LONGINT;
  1033. BEGIN
  1034. IF ~r.GetInteger(i,FALSE) OR (i#index) OR
  1035. ~CheckItem(r,"name") OR ~GetString(r,name) OR
  1036. ~CheckItem(r,"outInstance") OR ~ GetString(r,s) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1037. IF s#"NIL" THEN out.instance := scope.instances.ByName(s) END;
  1038. IF ~CheckItem(r,"outPort") OR ~GetString(r,s) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1039. IF s#"NIL" THEN out.port := out.instance.instanceType.ports.ByName(s) END;
  1040. IF ~CheckItem(r,"inInstance") OR ~ GetString(r,s) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1041. IF s#"NIL" THEN in.instance := scope.instances.ByName(s) END;
  1042. IF ~CheckItem(r,"inPort")OR ~GetString(r,s) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1043. IF s#"NIL" THEN in.port := in.instance.instanceType.ports.ByName(s) END;
  1044. IF ~CheckItem(r,"size")OR ~r.GetInteger(i,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1045. fifoSize := i;
  1046. IF ~CheckItem(r,"width")OR ~r.GetInteger(i,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1047. widthInBits := i;
  1048. RETURN TRUE
  1049. END Read;
  1050. PROCEDURE Write*(w: Streams.Writer; indent: LONGINT);
  1051. BEGIN
  1052. Indent(w,indent);
  1053. w.Int(index,1);
  1054. w.String(" name="); w.String(name);
  1055. w.String(" outInstance="); IF out.instance = NIL THEN w.String("NIL") ELSE w.String(out.instance.name) END;
  1056. w.String(" outPort="); IF out.port = NIL THEN w.String("NIL") ELSE w.String(out.port.name) END;
  1057. w.String(" inInstance="); IF in.instance = NIL THEN w.String("NIL") ELSE w.String(in.instance.name) END;
  1058. w.String(" inPort="); IF in.port = NIL THEN w.String("NIL") ELSE w.String(in.port.name) END;
  1059. w.String(" size="); w.Int(fifoSize,1);
  1060. w.String(" width="); w.Int(widthInBits,1);
  1061. w.Ln;w.Update;
  1062. END Write;
  1063. END Channel;
  1064. ChannelList*= OBJECT(Basic.List)
  1065. PROCEDURE GetChannel*(i: LONGINT): Channel;
  1066. VAR a: ANY;
  1067. BEGIN
  1068. a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Channel) END
  1069. END GetChannel;
  1070. PROCEDURE AddChannel*(a: Channel);
  1071. BEGIN a.index := Length(); Add(a);
  1072. END AddChannel;
  1073. PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Channel;
  1074. VAR a: Channel; i: LONGINT;
  1075. BEGIN
  1076. FOR i := 0 TO Length()-1 DO
  1077. a := GetChannel(i);
  1078. IF (a # NIL) & (a.name = name) THEN RETURN a END;
  1079. END;
  1080. RETURN NIL
  1081. END ByName;
  1082. PROCEDURE ByPort*(port: Port): Channel;
  1083. VAR a: Channel; i: LONGINT;
  1084. BEGIN
  1085. FOR i := 0 TO Length()-1 DO
  1086. a := GetChannel(i);
  1087. IF (a # NIL) & (a.in.port = port) OR (a.out.port=port) THEN RETURN a END;
  1088. END;
  1089. RETURN NIL
  1090. END ByPort;
  1091. PROCEDURE Same(as: ChannelList; flags: SET): BOOLEAN;
  1092. VAR i: LONGINT; left, right: Channel;
  1093. BEGIN
  1094. IF as.Length() # Length() THEN RETURN FALSE END;
  1095. FOR i := 0 TO Length()-1 DO
  1096. left := GetChannel(i);
  1097. right := as.GetChannel(i);
  1098. IF ~left.Same(right, flags) THEN RETURN FALSE END;
  1099. END;
  1100. RETURN TRUE
  1101. END Same;
  1102. END ChannelList;
  1103. (*
  1104. a specification is a collection of actors together with factory procedures to build hardware
  1105. - represented as IMPORT in source code
  1106. - to build hardware scripts generating hardware
  1107. *)
  1108. Specification*=OBJECT (Scope) (* specification object including hardware factory *)
  1109. VAR
  1110. instructionSet-: Name;
  1111. diagnostics-: Diagnostics.Diagnostics;
  1112. log-: Streams.Writer;
  1113. supportedDevices-: DeviceList;
  1114. imports-: SymbolList;
  1115. frequencyDivider-: LONGINT;
  1116. PROCEDURE AddDevice*(CONST name: ARRAY OF CHAR; adr: HUGEINT);
  1117. VAR device: Device;
  1118. BEGIN
  1119. NEW(device, name, SELF, LONGINT(adr)); supportedDevices.AddDevice(device);
  1120. END AddDevice;
  1121. PROCEDURE Same*(as: Symbol; flags: SET): BOOLEAN;
  1122. VAR i: LONGINT;
  1123. BEGIN
  1124. IF TraceSame THEN TRACE("SameSpecification", name) END;
  1125. IF (as = NIL) OR ~(as IS Specification) THEN RETURN FALSE END;
  1126. WITH as: Specification DO
  1127. IF as.instructionSet # instructionSet THEN RETURN FALSE END;
  1128. IF ~imports.Same(as.imports,flags) THEN RETURN FALSE END;
  1129. IF frequencyDivider # as.frequencyDivider THEN RETURN FALSE END;
  1130. END;
  1131. RETURN Same^(as, flags);
  1132. END Same;
  1133. PROCEDURE DefineDevices*(system: Global.System);
  1134. VAR i: LONGINT; device: Device;
  1135. BEGIN
  1136. FOR i := 0 TO supportedDevices.Length()-1 DO
  1137. device := supportedDevices.GetDevice(i);
  1138. system.AddCapability(Basic.MakeString(device.name));
  1139. END;
  1140. END DefineDevices;
  1141. PROCEDURE & Init*(CONST name: ARRAY OF CHAR; diagnostics: Diagnostics.Diagnostics; log: Streams.Writer);
  1142. VAR device: Device;
  1143. BEGIN
  1144. InitScope(name,NIL,SELF);
  1145. instructionSet := "UNDEFINED";
  1146. NEW(supportedDevices,4);
  1147. SELF.diagnostics := diagnostics;
  1148. SELF.log := log;
  1149. AddDevice("DDR", 0FFCAH);
  1150. AddDevice("RS232",0FFFFFFC4H);
  1151. AddDevice("LCD", 0FFFFFFC8H);
  1152. AddDevice("LEDDigits", 0FFFFFFC8H);
  1153. AddDevice("CF", 0FFFFFFCCH);
  1154. AddDevice("LED", 0FFFFFFC7H);
  1155. AddDevice("TIMER", 0FFFFFFC6H);
  1156. (*AddDevice("PORT",0FF10H); *)
  1157. AddDevice("PORT", 0FFFFFFE0H);
  1158. AddDevice("Switch", 0FFFFFFC7H);
  1159. AddDevice("Wheel", 0FFFFFFCAH);
  1160. AddDevice("PersistentSwitch", 0FFFFFFCBH);
  1161. AddDevice("Motor",0FFFFFFCEH);
  1162. AddDevice("BraceletSPI",0FFFFFFD2H);
  1163. AddDevice("GPI",0FFFFFFD6H);
  1164. AddDevice("GPO",0FFFFFFD6H);
  1165. AddDevice("WDT", 0FFFFFFD8H); (*watch dog timer*)
  1166. AddDevice("SPI", 0FFFFFFD4H); (*ROBOT SPI on ML510*)
  1167. NEW(imports,4);
  1168. frequencyDivider := 1;
  1169. END Init;
  1170. (*! this is a bit quick and dirty, think about general concepts of such parameters *)
  1171. PROCEDURE SetFrequencyDivider*(divider: LONGINT);
  1172. BEGIN frequencyDivider := divider
  1173. END SetFrequencyDivider;
  1174. PROCEDURE AddImport*(CONST name: ARRAY OF CHAR);
  1175. VAR import: Specification;
  1176. BEGIN
  1177. IF imports.ByName(name) = NIL THEN
  1178. import := LoadSpecification(name,NIL,NIL);
  1179. IF import # NIL THEN imports.Add(import); symbols.Add(import) END;
  1180. END;
  1181. END AddImport;
  1182. PROCEDURE SetInstructionSet*(CONST instructionSet: ARRAY OF CHAR);
  1183. BEGIN
  1184. COPY(instructionSet,SELF.instructionSet);
  1185. END SetInstructionSet;
  1186. PROCEDURE Write*(w: Streams.Writer; indent: LONGINT);
  1187. VAR type: Type; channel: Channel; i: LONGINT; instance: Instance;port: Port; import: Symbol;
  1188. BEGIN
  1189. Indent(w,indent);w.String("name="); w.String(name); w.Ln;
  1190. INC(indent);
  1191. Indent(w,indent); w.String("instructionSet="); w.String(instructionSet); w.Ln;
  1192. Indent(w,indent); w.String("frequencyDivider="); w.Int(frequencyDivider,1); w.Ln;
  1193. Indent(w,indent); w.String("imports="); w.Int(imports.Length(),1); w.Ln;
  1194. FOR i := 0 TO imports.Length()-1 DO
  1195. import := imports.GetSymbol(i);
  1196. Indent(w,indent+1); w.String(import.name); w.Ln;
  1197. END;
  1198. Indent(w,indent); w.String("types=");w.Int(types.Length(),1); w.Ln;
  1199. FOR i := 0 TO types.Length()-1 DO
  1200. type := types.GetType(i);
  1201. type.Write(w,indent+1);
  1202. END;
  1203. (* sub types first because of potential delegates on ports *)
  1204. Indent(w,indent); w.String("instances=");w.Int(instances.Length(),1); w.Ln;
  1205. FOR i := 0 TO instances.Length()-1 DO
  1206. instance := instances.GetInstance(i);
  1207. instance.Write(w,indent+1);
  1208. END;
  1209. Indent(w,indent); w.String("ports=");w.Int(ports.Length(),1); w.Ln;
  1210. FOR i := 0 TO ports.Length()-1 DO
  1211. port := ports.GetPort(i);
  1212. port.Write(w,indent+1);
  1213. END;
  1214. Indent(w,indent); w.String("channels=");w.Int(channels.Length(),1); w.Ln;
  1215. FOR i := 0 TO channels.Length()-1 DO
  1216. channel := channels.GetChannel(i);
  1217. channel.Write(w,indent+1);
  1218. END;
  1219. w.Update;
  1220. END Write;
  1221. PROCEDURE Read*(r: Streams.Reader): BOOLEAN;
  1222. VAR i, number: LONGINT; type: Type;
  1223. instance: Instance; port: Port; channel: Channel; importName: Name;
  1224. BEGIN
  1225. IF ~CheckItem(r,"name") OR ~GetString(r,name) OR
  1226. ~CheckItem(r,"instructionSet") OR ~GetString(r,instructionSet) OR
  1227. ~CheckItem(r,"frequencyDivider") OR ~r.GetInteger(frequencyDivider,FALSE) OR
  1228. ~CheckItem(r,"imports") OR ~r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1229. FOR i := 0 TO number-1 DO
  1230. IF ~GetString(r,importName) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1231. AddImport(importName);
  1232. END;
  1233. IF ~CheckItem(r,"types") OR ~r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1234. FOR i := 0 TO number-1 DO
  1235. type := NewType("");
  1236. IF ~type.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1237. END;
  1238. IF ~CheckItem(r,"instances") OR ~r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1239. FOR i := 0 TO number-1 DO
  1240. instance := NewInstance("",NIL);
  1241. IF ~instance.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1242. END;
  1243. IF ~CheckItem(r,"ports")OR ~r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1244. FOR i := 0 TO number-1 DO
  1245. port := NewPort("",0,0);
  1246. IF ~port.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1247. END;
  1248. IF ~CheckItem(r,"channels") OR ~r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1249. FOR i := 0 TO number-1 DO
  1250. channel := NewChannel();
  1251. IF ~channel.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1252. END;
  1253. RETURN TRUE
  1254. END Read;
  1255. PROCEDURE GetPortAddress*(number: LONGINT): LONGINT;
  1256. BEGIN
  1257. RETURN BasePortAddress+2*number;
  1258. END GetPortAddress;
  1259. PROCEDURE Emit*(): BOOLEAN; (* to be overwritten by implementers *)
  1260. VAR w: Files.Writer; f: Files.File; fileName: Files.FileName; msg: Name;
  1261. BEGIN
  1262. FlattenNetwork(SELF);
  1263. Files.JoinExtension(SELF.name,SpecificationFileExtension,fileName);
  1264. f := Files.New(fileName);
  1265. IF f # NIL THEN
  1266. NEW(w,f,0);
  1267. Write(w,0);
  1268. w.Update;
  1269. Files.Register(f);
  1270. msg := "Wrote Active Cells specification to file "; Strings.Append(msg, fileName);
  1271. IF log # NIL THEN log.String(msg); log.Ln; END;
  1272. RETURN TRUE
  1273. ELSE
  1274. diagnostics.Error(fileName,Streams.Invalid, "could not generate file");
  1275. IF TraceError THEN HALT(100) ELSE RETURN FALSE END
  1276. END;
  1277. END Emit;
  1278. END Specification;
  1279. (*
  1280. PROCEDURE ReadHugeint(r: Streams.Reader; VAR x: HUGEINT): BOOLEAN;
  1281. VAR low, high: LONGINT;
  1282. BEGIN
  1283. IF r.GetInteger(high, FALSE) & r.GetInteger(low, FALSE) THEN
  1284. x := high * 100000000H + low;
  1285. RETURN TRUE
  1286. ELSE
  1287. RETURN FALSE
  1288. END
  1289. END ReadHugeint;
  1290. PROCEDURE WriteHugeint(r: Streams.Writer; x: HUGEINT);
  1291. VAR low, high: LONGINT;
  1292. BEGIN
  1293. low := SHORT(x); high := SHORT(x DIV 100000000H);
  1294. r.Int(high,1); r.String(" "); r.Int(low,1);
  1295. END WriteHugeint;
  1296. *)
  1297. PROCEDURE Indent(w: Streams.Writer; indent: LONGINT);
  1298. BEGIN
  1299. WHILE indent > 0 DO
  1300. w.String(" ");
  1301. DEC(indent);
  1302. END;
  1303. END Indent;
  1304. PROCEDURE CheckItem(VAR r: Streams.Reader; CONST name: ARRAY OF CHAR): BOOLEAN;
  1305. VAR i: LONGINT; ch: CHAR; b: BOOLEAN;
  1306. BEGIN
  1307. i := 0;
  1308. b := r.GetChar(ch);
  1309. WHILE (r.res=Streams.Ok) & (ch # "=") DO
  1310. IF name[i] # ch THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
  1311. INC(i);
  1312. r.Char(ch);
  1313. END;
  1314. RETURN TRUE
  1315. END CheckItem;
  1316. PROCEDURE GetString(VAR r: Streams.Reader; VAR name: ARRAY OF CHAR): BOOLEAN;
  1317. VAR c: CHAR;
  1318. BEGIN
  1319. c := r.Peek();
  1320. IF r.GetString(name) THEN RETURN TRUE
  1321. ELSE RETURN (name[0]=0X) & (c="'") OR (c='"')
  1322. END;
  1323. END GetString;
  1324. PROCEDURE GetSet(VAR r: Streams.Reader; VAR set: SET): BOOLEAN;
  1325. VAR int: LONGINT;
  1326. BEGIN
  1327. IF r.GetInteger(int, FALSE) THEN set := SYSTEM.VAL(SET, int); RETURN TRUE ELSE RETURN FALSE END;
  1328. END GetSet;
  1329. PROCEDURE WriteSet(VAR r: Streams.Writer; set: SET);
  1330. VAR int: LONGINT;
  1331. BEGIN
  1332. int := SYSTEM.VAL(LONGINT, set);
  1333. r.Int(int,1);
  1334. END WriteSet;
  1335. (**
  1336. Load an ActiveCells specification
  1337. name - specification name, with or without suffix ".spec"
  1338. *)
  1339. PROCEDURE LoadSpecification*(CONST name: ARRAY OF CHAR; diagnostics: Diagnostics.Diagnostics; log: Streams.Writer): Specification;
  1340. VAR fileName: Files.FileName; spec: Specification; f: Files.File; r: Files.Reader;
  1341. BEGIN
  1342. COPY(name,fileName);
  1343. Strings.Append(fileName,".spec");
  1344. f := Files.Old(fileName);
  1345. (*
  1346. IF f = NIL THEN
  1347. COPY(name, fileName);
  1348. f := Files.Old(fileName);
  1349. END;
  1350. *)
  1351. IF f = NIL THEN IF log # NIL THEN log.String("could not load specification "); log.String(name); log.Ln END; RETURN NIL END;
  1352. NEW(spec, "", diagnostics, log);
  1353. NEW(r,f,0);
  1354. IF spec.Read(r) THEN
  1355. RETURN spec
  1356. ELSE
  1357. RETURN NIL
  1358. END;
  1359. END LoadSpecification;
  1360. PROCEDURE ReadSpecification*(context: Commands.Context);
  1361. VAR fileName: Files.FileName; r: Files.Reader; specification: Specification;f : Files.File; b: BOOLEAN; diagnostics: Diagnostics.StreamDiagnostics;
  1362. BEGIN
  1363. b := context.arg.GetString(fileName);
  1364. NEW(diagnostics, context.error);
  1365. specification := LoadSpecification(fileName, diagnostics, context.out);
  1366. IF specification # NIL THEN
  1367. specification.Write(context.out,0);
  1368. END;
  1369. END ReadSpecification;
  1370. PROCEDURE CompareSpecification*(context: Commands.Context);
  1371. VAR fileName: Files.FileName; spec1, spec2: Specification; b: BOOLEAN;
  1372. BEGIN
  1373. b := context.arg.GetString(fileName);
  1374. spec1 := LoadSpecification(fileName, NIL, context.error);
  1375. IF spec1 = NIL THEN context.error.String("could not load specification "); context.error.String(fileName); RETURN END;
  1376. b := context.arg.GetString(fileName);
  1377. spec2 := LoadSpecification(fileName, NIL, context.error);
  1378. IF spec2 = NIL THEN context.error.String("could not load specification "); context.error.String(fileName); RETURN END;
  1379. IF spec1.Same(spec2, {}) THEN context.out.String("Specifications are equal") ELSE context.out.String("specifications are not equal"); END;
  1380. END CompareSpecification;
  1381. (*
  1382. (**
  1383. Load an ActiveCells specification
  1384. platformId - string ID of the platform to use
  1385. name - specification name
  1386. *)
  1387. PROCEDURE LoadSpecification*(CONST platformId: ARRAY OF CHAR; CONST name: ARRAY OF CHAR; diagnostics: Diagnostics.Diagnostics; log: Streams.Writer): Specification;
  1388. VAR
  1389. platform: PlatformDesc;
  1390. fileName: Files.FileName;
  1391. mod: Modules.Module;
  1392. res: WORD;
  1393. msg: ARRAY 8 OF CHAR;
  1394. BEGIN
  1395. Strings.Concat("Fox",platformId,fileName);
  1396. IF Modules.ModuleByName(fileName) = NIL THEN (* if platform module is not loaded - try to load it *)
  1397. mod := Modules.ThisModule(fileName,res,msg);
  1398. END;
  1399. COPY(name,fileName);
  1400. Strings.Append(fileName,".spec");
  1401. platform := GetPlatform(platformId); ASSERT(platform # NIL);
  1402. RESULT := platform.specLoader(fileName,diagnostics,log);
  1403. RETURN RESULT;
  1404. END LoadSpecification;
  1405. (** Register an ActiveCells hardware platform *)
  1406. PROCEDURE RegisterPlatform*(platformDesc: PlatformDesc);
  1407. VAR i: LONGINT;
  1408. BEGIN
  1409. ASSERT(platformDesc # NIL);
  1410. ASSERT(platformDesc.platformId # NIL);
  1411. ASSERT(platformDesc.specLoader # NIL);
  1412. i := 0;
  1413. WHILE (i < platforms.Length()) & (platforms.Get(i)(PlatformDesc).platformId^ # platformDesc.platformId^) DO
  1414. INC(i);
  1415. END;
  1416. IF i < platforms.Length() THEN RETURN; END; (* do not allow registering same platform twice! *)
  1417. platforms.Add(platformDesc);
  1418. D.String("registered ActiveCells hardware platform "); D.String(platformDesc.platformId^); D.Ln;
  1419. END RegisterPlatform;
  1420. (** Get an ActiveCells hardware platform descriptor given the platform ID string *)
  1421. PROCEDURE GetPlatform*(CONST platformId: ARRAY OF CHAR): PlatformDesc;
  1422. VAR i: LONGINT;
  1423. BEGIN
  1424. i := 0;
  1425. WHILE (i < platforms.Length()) & (platforms.Get(i)(PlatformDesc).platformId^ # platformId) DO
  1426. INC(i);
  1427. END;
  1428. IF i < platforms.Length() THEN
  1429. RETURN platforms.Get(i)(PlatformDesc);
  1430. ELSE
  1431. RETURN platform;
  1432. END;
  1433. END GetPlatform;
  1434. PROCEDURE LoadSpecificationDefault(CONST name: ARRAY OF CHAR; diagnostics: Diagnostics.Diagnostics; log: Streams.Writer): Specification;
  1435. VAR r: Files.Reader; specification: Specification; f: Files.File;
  1436. BEGIN
  1437. specification := NIL;
  1438. f := Files.Old(name);
  1439. IF f # NIL THEN NEW(r,f,0); NEW(specification,"",diagnostics,log);
  1440. IF ~specification.Read(r) THEN specification := NIL END;
  1441. END;
  1442. RETURN specification
  1443. END LoadSpecificationDefault;
  1444. *)
  1445. PROCEDURE GetSymbol*(scope: Scope; CONST name: ARRAY OF CHAR): Symbol;
  1446. VAR scopeName: Name; i,j: LONGINT; symbol: Symbol; first: BOOLEAN;
  1447. BEGIN
  1448. i := 0; first := TRUE;
  1449. WHILE (scope # NIL) & (name[i] # 0X) DO
  1450. j := 0;
  1451. WHILE (name[i] # 0X) & (name[i] # ".") DO
  1452. scopeName[j] := name[i];
  1453. INC(i); INC(j);
  1454. END;
  1455. scopeName[j] := 0X; INC(i);
  1456. (*
  1457. D.String("find symbol : "); D.String(scopeName); D.Ln;
  1458. *)
  1459. symbol := scope.FindSymbol(scopeName, first); first := FALSE;
  1460. IF (symbol # NIL) & (symbol IS Scope) THEN scope := symbol(Scope)
  1461. ELSE scope := NIL
  1462. END;
  1463. END;
  1464. IF name[i] # 0X THEN RETURN NIL ELSE RETURN symbol END;
  1465. END GetSymbol;
  1466. PROCEDURE Clone*(symbol: Symbol): Symbol;
  1467. BEGIN
  1468. RETURN symbol;
  1469. (* does nothing -- for compatibility with ActiveCells2 *)
  1470. END Clone;
  1471. PROCEDURE FlattenNetwork*(scope: Scope);
  1472. VAR instance,subInstance,newInstance: Instance; oldChannel,channel: Channel;
  1473. instances: InstanceList; channels: ChannelList;
  1474. i, j: LONGINT; name: SyntaxTree.String;
  1475. port: Port;
  1476. PROCEDURE FlattenPortInstance(VAR pi: PortInstance);
  1477. VAR name: Name; port, prevPort: Port; instance: Instance;
  1478. BEGIN
  1479. IF pi.port # NIL THEN
  1480. port := pi.port.delegate.port;
  1481. IF port # NIL THEN
  1482. instance := pi.port.delegate.instance;
  1483. ASSERT(instance # NIL);
  1484. COPY(pi.instance.name,name);
  1485. (* iteratively resolve port delegation and build local instance name *)
  1486. WHILE port # NIL DO
  1487. prevPort := port;
  1488. ASSERT(instance # NIL);
  1489. Strings.Append(name,"."); Strings.Append(name,instance.name);
  1490. instance := port.delegate.instance;
  1491. port := port.delegate.port;
  1492. END;
  1493. port := prevPort;
  1494. instance := instances.ByName(name);
  1495. ASSERT(port # NIL);
  1496. ASSERT(instance # NIL);
  1497. pi.instance := instance;
  1498. pi.port := port;
  1499. END;
  1500. END;
  1501. END FlattenPortInstance;
  1502. PROCEDURE EmbedInstance(instance: Instance; VAR subInstance: Instance): Instance;
  1503. VAR name: Name; newInstance: Instance; i: LONGINT; parameter,newParameter: Parameter;
  1504. BEGIN
  1505. COPY(instance.name, name); Strings.Append(name,"."); Strings.Append(name,subInstance.name);
  1506. newInstance := instances.ByName(name);
  1507. IF newInstance = NIL THEN
  1508. NEW(newInstance, name, scope, subInstance.instanceType);
  1509. FOR i := 0 TO subInstance.parameters.Length()-1 DO
  1510. parameter := subInstance.parameters.GetParameter(i);
  1511. newParameter := newInstance.AddParameter(parameter.name);
  1512. newParameter.index := parameter.index;
  1513. newParameter.parameterType := parameter.parameterType;
  1514. newParameter.integer := parameter.integer;
  1515. newParameter.boolean := parameter.boolean;
  1516. END;
  1517. END;
  1518. RETURN newInstance
  1519. END EmbedInstance;
  1520. BEGIN
  1521. IF scope.instances.Length()=0 THEN RETURN END;
  1522. NEW(instances,4); NEW(channels,4);
  1523. FOR i := 0 TO scope.channels.Length()-1 DO
  1524. (* copy local channels one-to-one *)
  1525. oldChannel := scope.channels.GetChannel(i);
  1526. channels.AddChannel(oldChannel);
  1527. END;
  1528. FOR i := 0 TO scope.instances.Length()-1 DO
  1529. instance := scope.instances.GetInstance(i);
  1530. IF instance.instanceType.instances.Length() # 0 THEN
  1531. FlattenNetwork(instance.instanceType);
  1532. FOR j := 0 TO instance.instanceType.instances.Length()-1 DO
  1533. subInstance := instance.instanceType.instances.GetInstance(j);
  1534. newInstance := EmbedInstance(instance, subInstance);
  1535. instances.AddInstance(newInstance)
  1536. END;
  1537. FOR j := 0 TO instance.instanceType.channels.Length()-1 DO
  1538. oldChannel := instance.instanceType.channels.GetChannel(j);
  1539. (* do not copy name: duplicates! *)
  1540. channel := scope.NewChannel();
  1541. channel.ConnectIn(oldChannel.in.instance, oldChannel.in.port);
  1542. channel.ConnectOut(oldChannel.out.instance, oldChannel.out.port);
  1543. channel.SetFifoSize(oldChannel.fifoSize);
  1544. channel.SetWidth(oldChannel.widthInBits);
  1545. channel.in.instance := EmbedInstance(instance, channel.in.instance);
  1546. channel.out.instance := EmbedInstance(instance, channel.out.instance);
  1547. channels.AddChannel(channel);
  1548. END;
  1549. ELSE
  1550. (* copy one-to-one *)
  1551. instances.AddInstance(instance);
  1552. END;
  1553. END;
  1554. FOR i := 0 TO channels.Length()-1 DO
  1555. channel := channels.GetChannel(i);
  1556. FlattenPortInstance(channel.in);
  1557. FlattenPortInstance(channel.out);
  1558. END;
  1559. FOR i := 0 TO scope.ports.Length()-1 DO
  1560. port := scope.ports.GetPort(i);
  1561. FlattenPortInstance(port.delegate);
  1562. END;
  1563. scope.instances := instances;
  1564. scope.channels := channels;
  1565. END FlattenNetwork;
  1566. PROCEDURE NormalizeName*(CONST src: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR);
  1567. VAR i: LONGINT; ch: CHAR;
  1568. BEGIN
  1569. i := 0;
  1570. REPEAT
  1571. ch := src[i];
  1572. CASE ch OF
  1573. ".", "@", "[", "]": dest[i] := "0";
  1574. ELSE
  1575. dest[i] := ch
  1576. END;
  1577. INC(i);
  1578. UNTIL ch = 0X;
  1579. END NormalizeName;
  1580. (* write a string and replace dots by the underscore character *)
  1581. PROCEDURE WriteName*(w: Streams.Writer; scope: Scope; CONST name, suffix: ARRAY OF CHAR);
  1582. VAR n: ARRAY 256 OF CHAR;
  1583. BEGIN
  1584. IF scope # NIL THEN scope.GetFullName(n,NIL); ELSE n := "" END;
  1585. IF name # "" THEN
  1586. IF n # "" THEN Strings.Append(n,".") END;
  1587. Strings.Append(n,name);
  1588. END;
  1589. NormalizeName(n,n);
  1590. IF suffix # "" THEN
  1591. ASSERT(n# "");
  1592. Strings.Append(n,"_"); Strings.Append(n,suffix)
  1593. END;
  1594. w.String(n);
  1595. END WriteName;
  1596. (*
  1597. PROCEDURE InitMod;
  1598. BEGIN
  1599. NEW(platforms,3);
  1600. NEW(platform);
  1601. platform.platformId := Strings.NewString("DEFAULT");
  1602. platform.specLoader := LoadSpecificationDefault;
  1603. END InitMod;
  1604. BEGIN
  1605. InitMod;
  1606. *)
  1607. END FoxActiveCells.
  1608. FoxActiveCells.ReadSpecification Test.spec ~
  1609. FSTools.CopyFiles TL.spec => Test.spec ~
  1610. FoxActiveCells.CompareSpecification Test TL ~~
  1611. System.FreeDownTo FoxActiveCells ~