FoxActiveCells.Mod 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835
  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 ~