MODULE FoxActiveCells;
IMPORT SyntaxTree := FoxSyntaxTree, Basic := FoxBasic, Global := FoxGlobal, Files, Streams, D := Debugging, Diagnostics, Strings, Commands, GenericLinker, StaticLinker, SYSTEM, Modules;
CONST
In*= SyntaxTree.InPort; Out*= SyntaxTree.OutPort;
defaultInstructionMemorySize*=0;
defaultDataMemorySize *=2048;
defaultPortWidth *=32;
defaultFifoSize *=32;
defaultChannelWidth* = 32;
CodeFileExtension*="code";
DataFileExtension*="data";
SpecificationFileExtension*="spec";
ObjectFileExtension*="Gof";
VectorCapability*=Global.VectorCapability;
FloatingPointCapability*=Global.FloatingPointCapability;
TraceError=FALSE;
BasePortAddress=LONGINT(0FFFFFFE0H);
TraceSame= FALSE;
CheckModules= 0;
CheckParameters=1;
TYPE
Name*= ARRAY 256 OF CHAR;
PortInstance*=RECORD
instance-: Instance; port-: Port
END;
Symbol*=OBJECT
VAR name-: Name;
scope-: Scope;
PROCEDURE GetFullName*(VAR name: ARRAY OF CHAR; in: Scope);
PROCEDURE InScope(this,in : Scope): BOOLEAN;
BEGIN
WHILE (this # NIL) & (this # in) DO
this := this.scope;
END;
RETURN this # NIL
END InScope;
BEGIN
IF (SELF.scope # NIL) & ~InScope(in,SELF.scope) THEN
SELF.scope.GetFullName(name,in);
Strings.Append(name,".");
Strings.Append(name,SELF.name);
ELSE
COPY(SELF.name,name)
END;
END GetFullName;
PROCEDURE InitSymbol(CONST name: ARRAY OF CHAR; scope: Scope);
BEGIN
COPY(name,SELF.name);
SELF.scope := scope;
END InitSymbol;
PROCEDURE AppendToMsg*(VAR msg: ARRAY OF CHAR);
VAR name:Name;
BEGIN
GetFullName(name, NIL);
Strings.Append(msg, name);
END AppendToMsg;
PROCEDURE Same*(as: Symbol; flags: SET): BOOLEAN;
BEGIN
RETURN name = as.name
END Same;
END Symbol;
SymbolList*= OBJECT(Basic.List)
PROCEDURE GetSymbol*(i: LONGINT): Symbol;
VAR a: ANY;
BEGIN
a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Symbol) END
END GetSymbol;
PROCEDURE AddSymbol(a: Symbol);
BEGIN Add(a);
END AddSymbol;
PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Symbol;
VAR a: Symbol; i: LONGINT;
BEGIN
FOR i := 0 TO Length()-1 DO
a := GetSymbol(i);
IF (a # NIL) & (a.name = name) THEN RETURN a END;
END;
RETURN NIL
END ByName;
PROCEDURE Same(as: SymbolList; flags: SET): BOOLEAN;
VAR i: LONGINT; left, right: Symbol;
BEGIN
IF as.Length() # Length() THEN RETURN FALSE END;
FOR i := 0 TO Length()-1 DO
left := GetSymbol(i);
right := as.GetSymbol(i);
IF ~left.Same(right, flags) THEN RETURN FALSE END;
END;
RETURN TRUE
END Same;
END SymbolList;
Port*= OBJECT (Symbol)
VAR
direction-: LONGINT;
adr-: LONGINT;
width-: LONGINT;
delegate-: PortInstance;
index-: LONGINT;
PROCEDURE Same(as: Symbol; flags: SET): BOOLEAN;
BEGIN
IF TraceSame THEN TRACE("Port",name) END;
IF (as = NIL) OR ~(as IS Port) THEN RETURN FALSE END;
WITH as: Port DO
IF (direction # as.direction) OR (adr # as.adr) OR (width # as.width) THEN RETURN FALSE END;
END;
RETURN Same^(as, flags)
END Same;
PROCEDURE &InitPort*(CONST name: ARRAY OF CHAR; scope: Scope; direction: LONGINT; adr: LONGINT);
BEGIN
InitSymbol(name,scope);
SELF.direction := direction;
SELF.adr := adr;
width := defaultPortWidth;
delegate.instance := NIL;
index := -1;
END InitPort;
PROCEDURE SetWidth*(widthInBits: LONGINT);
BEGIN width := widthInBits
END SetWidth;
PROCEDURE Delegate*(instance: Instance; port: Port);
BEGIN
delegate.instance := instance; delegate.port := port
END Delegate;
PROCEDURE Write*(w: Streams.Writer; indent: LONGINT);
BEGIN
Indent(w,indent);
w.Int(index,1);
w.String(" name="); w.String(name);
w.String(" direction=");
IF direction = In THEN w.String("in ");
ELSIF direction=Out THEN w.String("out ");
END;
w.String(" adr="); w.Int(adr,1);
w.String(" width="); w.Int(width,1);
w.String(" delegateInstance=");
IF delegate.instance = NIL THEN
w.String("none")
ELSE
w.String(delegate.instance.name);
w.String(" delegatePort="); w.String(delegate.port.name);
END;
w.Ln;
w.Update;
END Write;
PROCEDURE Read*(r: Streams.Reader): BOOLEAN;
VAR s: Name; index: LONGINT;
BEGIN
IF ~r.GetInteger(index,FALSE) OR (index # SELF.index) OR ~CheckItem(r,"name") OR ~GetString(r,name)
OR ~CheckItem(r,"direction") OR ~GetString(r,s)
THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
IF s = "in" THEN direction := In
ELSIF s="out" THEN direction := Out
END;
IF ~CheckItem(r,"adr") OR ~r.GetInteger(adr,FALSE) OR
~CheckItem(r,"width") OR ~r.GetInteger(width,FALSE) OR
~CheckItem(r,"delegateInstance") OR ~GetString(r,s)
THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
IF s = "none" THEN delegate.instance := NIL
ELSE
delegate.instance := scope.instances.ByName(s);
ASSERT(delegate.instance # NIL);
IF ~CheckItem(r,"delegatePort") OR ~GetString(r,s) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
delegate.port := delegate.instance.type.ports.ByName(s);
END;
RETURN TRUE
END Read;
END Port;
PortList*= OBJECT(Basic.List)
PROCEDURE GetPort*(i: LONGINT): Port;
VAR a: ANY;
BEGIN
a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Port) END
END GetPort;
PROCEDURE AddPort(a: Port);
BEGIN a.index := Length(); Add(a);
END AddPort;
PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Port;
VAR a: Port; i: LONGINT;
BEGIN
FOR i := 0 TO Length()-1 DO
a := GetPort(i);
IF (a # NIL) & (a.name = name) THEN RETURN a END;
END;
RETURN NIL
END ByName;
PROCEDURE Same(as: PortList; flags: SET): BOOLEAN;
VAR i: LONGINT; left, right: Port;
BEGIN
IF as.Length() # Length() THEN RETURN FALSE END;
FOR i := 0 TO Length()-1 DO
left := GetPort(i);
right := as.GetPort(i);
IF ~left.Same(right, flags) THEN RETURN FALSE END;
END;
RETURN TRUE
END Same;
END PortList;
Device*= OBJECT (Symbol)
VAR
adr-: LONGINT;
index-: LONGINT;
PROCEDURE Same(as: Symbol; flags: SET): BOOLEAN;
BEGIN
IF TraceSame THEN TRACE("Device",name) END;
IF (as = NIL) OR ~(as IS Device) THEN RETURN FALSE END;
WITH as: Device DO
IF (adr # as.adr) OR (index # as.index) THEN RETURN FALSE END;
END;
RETURN Same^(as, flags)
END Same;
PROCEDURE &InitDevice*(CONST name: ARRAY OF CHAR; scope: Scope; adr: LONGINT);
BEGIN
InitSymbol(name,scope);
SELF.adr := adr;
index := -1;
END InitDevice;
PROCEDURE Write*(w:Streams.Writer; indent: LONGINT);
BEGIN
Indent(w,indent);
w.Int(index,1);
w.String(" name="); w.String(name); w.String(" adr="); w.Int(adr,1); w.Ln;
w.Update;
END Write;
PROCEDURE Read*(r: Streams.Reader): BOOLEAN;
VAR i: LONGINT;
BEGIN
RETURN r.GetInteger(i,FALSE) & (i=index) &
CheckItem(r,"name") & GetString(r,name) &
CheckItem(r,"adr") & r.GetInteger(adr,FALSE);
END Read;
END Device;
DeviceList*= OBJECT(Basic.List)
PROCEDURE GetDevice*(i: LONGINT): Device;
VAR a: ANY;
BEGIN
a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Device) END
END GetDevice;
PROCEDURE AddDevice(p: Device);
BEGIN
ASSERT(ByName(p.name) = NIL);
p.index := Length(); Add(p);
END AddDevice;
PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Device;
VAR a: Device; i: LONGINT;
BEGIN
FOR i := 0 TO Length()-1 DO
a := GetDevice(i);
IF (a # NIL) & (a.name = name) THEN RETURN a END;
END;
RETURN NIL
END ByName;
PROCEDURE Same(as: DeviceList; flags: SET): BOOLEAN;
VAR i: LONGINT; left, right: Device;
BEGIN
IF as.Length() # Length() THEN RETURN FALSE END;
FOR i := 0 TO Length()-1 DO
left := GetDevice(i);
right := as.GetDevice(i);
IF ~left.Same(right, flags) THEN RETURN FALSE END;
END;
RETURN TRUE
END Same;
END DeviceList;
Module*=OBJECT (Symbol)
VAR
fileName*: Files.FileName;
index-: LONGINT;
PROCEDURE Same(as: Symbol; flags: SET): BOOLEAN;
BEGIN
IF TraceSame THEN TRACE("Module",name) END;
IF (as = NIL) OR ~(as IS Module) THEN RETURN FALSE END;
WITH as: Module DO
IF (index # as.index) OR (fileName # as.fileName) THEN RETURN FALSE END;
END;
RETURN Same^(as, flags)
END Same;
PROCEDURE & InitModule(CONST name: ARRAY OF CHAR; scope: Scope; CONST fileName: ARRAY OF CHAR);
BEGIN
InitSymbol(name,scope);
COPY(name, SELF.name);
COPY(fileName, SELF.fileName);
index := -1;
END InitModule;
PROCEDURE Write*(w:Streams.Writer; indent: LONGINT);
BEGIN
Indent(w,indent);
w.Int(index,1);
w.String(" name="); w.String(name);
w.String(" filename="); w.String("'"); w.String(fileName); w.String("'");
w.Ln;
w.Update;
END Write;
PROCEDURE Read*(r: Streams.Reader): BOOLEAN;
VAR i: LONGINT;
BEGIN
RETURN r.GetInteger(i,FALSE) & (i=index) & CheckItem(r,"name") & GetString(r,name)
&CheckItem(r,"filename") & GetString(r,fileName);
END Read;
END Module;
ModuleList*= OBJECT(Basic.List)
PROCEDURE GetModule*(i: LONGINT): Module;
VAR a: ANY;
BEGIN
a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Module) END
END GetModule;
PROCEDURE AddModule(a: Module);
BEGIN a.index := Length(); Add(a);
END AddModule;
PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Module;
VAR a: Module; i: LONGINT;
BEGIN
FOR i := 0 TO Length()-1 DO
a := GetModule(i);
IF (a # NIL) & (a.name = name) THEN RETURN a END;
END;
RETURN NIL
END ByName;
PROCEDURE Same(as: ModuleList; flags: SET): BOOLEAN;
VAR i: LONGINT; left, right: Module;
BEGIN
IF as.Length() # Length() THEN RETURN FALSE END;
FOR i := 0 TO Length()-1 DO
left := GetModule(i);
right := as.GetModule(i);
IF ~left.Same(right, flags) THEN RETURN FALSE END;
END;
RETURN TRUE
END Same;
END ModuleList;
Parameter*=OBJECT (Symbol)
CONST
Boolean=0;Integer=1;
VAR
index-: LONGINT;
type-: SHORTINT;
integer-: LONGINT;
boolean-: BOOLEAN;
PROCEDURE Same(as: Symbol; flags: SET): BOOLEAN;
BEGIN
IF TraceSame THEN TRACE("Parameter",name) END;
IF (as = NIL) OR ~(as IS Parameter) THEN RETURN FALSE END;
WITH as: Parameter DO
IF (index # as.index) OR (type # as.type) OR (integer # as.integer) OR (as.boolean # boolean) THEN RETURN FALSE END;
END;
RETURN Same^(as, flags)
END Same;
PROCEDURE &Init(CONST name: ARRAY OF CHAR; scope: Scope);
BEGIN
InitSymbol(name,scope);
END Init;
PROCEDURE SetBoolean*(b: BOOLEAN);
BEGIN
type := Boolean; boolean := b
END SetBoolean;
PROCEDURE SetInteger*(i: LONGINT);
BEGIN
type := Integer; integer := i
END SetInteger;
PROCEDURE Write(w: Streams.Writer; indent: LONGINT);
VAR typeName: SyntaxTree.String;
BEGIN
Indent(w,indent);
w.Int(index,1);
w.String(" name="); w.String(name);
w.String(" type=");
IF type = Integer THEN w.String("INTEGER")
ELSIF type=Boolean THEN w.String("BOOLEAN")
END;
w.String(" value=");
IF type = Integer THEN w.Int(integer,1)
ELSIF type=Boolean THEN
IF boolean THEN w.String("TRUE") ELSE w.String("FALSE") END
END;
w.Ln;
w.Update;
END Write;
PROCEDURE Read(r: Streams.Reader): BOOLEAN;
VAR index: LONGINT; s: Name;
BEGIN
IF r.GetInteger(index,FALSE) & CheckItem(r,"name") & GetString(r,name)
&CheckItem(r,"type") & GetString(r,s) & CheckItem(r,"value") THEN
IF s= "INTEGER" THEN type := Integer
ELSIF s = "BOOLEAN" THEN type := Boolean
ELSE RETURN FALSE
END;
IF (type = Integer) & r.GetInteger(integer,FALSE) THEN
ELSIF (type=Boolean) & GetString(r,s) THEN
IF s="TRUE" THEN boolean := TRUE ELSE boolean := FALSE END;
ELSE RETURN FALSE
END;
ELSE RETURN FALSE
END;
RETURN TRUE
END Read;
END Parameter;
ParameterList*= OBJECT(Basic.List)
PROCEDURE GetParameter*(i: LONGINT): Parameter;
VAR a: ANY;
BEGIN
a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Parameter) END
END GetParameter;
PROCEDURE AddParameter(a: Parameter);
BEGIN a.index := Length(); Add(a);
END AddParameter;
PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Parameter;
VAR a: Parameter; i: LONGINT;
BEGIN
FOR i := 0 TO Length()-1 DO
a := GetParameter(i);
IF (a # NIL) & (a.name = name) THEN RETURN a END;
END;
RETURN NIL
END ByName;
PROCEDURE Same(as: ParameterList; flags: SET): BOOLEAN;
VAR i: LONGINT; left, right: Parameter;
BEGIN
IF as.Length() # Length() THEN RETURN FALSE END;
FOR i := 0 TO Length()-1 DO
left := GetParameter(i);
right := as.GetParameter(i);
IF ~left.Same(right, flags) THEN RETURN FALSE END;
END;
RETURN TRUE
END Same;
END ParameterList;
Instance*=OBJECT (Symbol)
VAR
type-: Type;
parameters-: ParameterList;
index-: LONGINT;
instructionMemorySize-, dataMemorySize-: LONGINT;
capabilities-: SET;
PROCEDURE Same(as: Symbol; flags: SET): BOOLEAN;
BEGIN
IF TraceSame THEN TRACE("Instance",name) END;
IF (as = NIL) OR ~(as IS Instance) THEN RETURN FALSE END;
WITH as: Instance DO
IF (index # as.index) THEN RETURN FALSE END;
IF ~type.Same(as.type, flags) THEN RETURN FALSE END;
IF (CheckParameters IN flags) & ~parameters.Same(as.parameters, flags) THEN RETURN FALSE END;
IF (instructionMemorySize # as.instructionMemorySize) THEN RETURN FALSE END;
IF (dataMemorySize # as.dataMemorySize) THEN RETURN FALSE END;
END;
RETURN Same^(as, flags)
END Same;
PROCEDURE IsEngine*(): BOOLEAN;
BEGIN
RETURN Global.EngineCapability IN capabilities
END IsEngine;
PROCEDURE &Init(CONST name: ARRAY OF CHAR; scope: Scope; c: Type);
BEGIN
InitSymbol(name,scope);
type := c;
index := -1; SELF.scope := scope; NEW(parameters,4);
ASSERT(scope # NIL);
SetType(c);
END Init;
PROCEDURE SetType(type: Type);
BEGIN
IF type # NIL THEN
SELF.type := type;
dataMemorySize := type.dataMemorySize;
capabilities := type.capabilities;
END;
END SetType;
PROCEDURE SetInstructionMemorySize*(value: LONGINT);
BEGIN instructionMemorySize := value
END SetInstructionMemorySize;
PROCEDURE SetDataMemorySize*(value: LONGINT);
BEGIN dataMemorySize := value
END SetDataMemorySize;
PROCEDURE AddParameter*(CONST name: ARRAY OF CHAR): Parameter;
VAR parameter: Parameter;
BEGIN
NEW(parameter,name,NIL); parameters.Add(parameter);
RETURN parameter
END AddParameter;
PROCEDURE Write(w: Streams.Writer; indent: LONGINT);
VAR typeName: Name; parameter: Parameter; i: LONGINT;
BEGIN
Indent(w,indent); INC(indent);
w.Int(index,1);
w.String(" name="); w.String(name);
type.GetFullName(typeName,scope);
w.String(" type="); w.String(typeName);
w.String(" instructionMemorySize="); w.Int(instructionMemorySize,1);
w.String(" dataMemorySize="); w.Int(dataMemorySize,1);
w.String(" capabilities="); WriteSet(w,capabilities);
w.Ln;
Indent(w,indent);
w.String("parameters=");w.Int(parameters.Length(),1); w.Ln;
FOR i := 0 TO parameters.Length()-1 DO
parameter := parameters.GetParameter(i);
parameter.Write(w,indent+1);
END;
w.Update;
END Write;
PROCEDURE Read(r: Streams.Reader): BOOLEAN;
VAR index: LONGINT; s: Name; symbol: Symbol; i,number: LONGINT; parameter: Parameter;
BEGIN
IF r.GetInteger(index,FALSE) & CheckItem(r,"name") & GetString(r,name) &
CheckItem(r,"type") & GetString(r,s) &
CheckItem(r,"instructionMemorySize") & r.GetInteger(instructionMemorySize,FALSE) &
CheckItem(r,"dataMemorySize") & r.GetInteger(dataMemorySize,FALSE) &
CheckItem(r,"capabilities") & GetSet(r,capabilities)
THEN
symbol := GetSymbol(scope,s);
IF symbol = NIL THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
SetType(symbol(Type));
IF ~CheckItem(r,"parameters") OR ~r.GetInteger(number,FALSE)
THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
FOR i := 0 TO number-1 DO
parameter := AddParameter("");
IF ~parameter.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
END;
RETURN TRUE
ELSE IF TraceError THEN HALT(100) ELSE RETURN FALSE END
END;
END Read;
PROCEDURE AppendToMsg(VAR msg: ARRAY OF CHAR);
VAR name:Name;
BEGIN
AppendToMsg^(msg);
type.GetFullName(name,NIL);
Strings.Append(msg," (");
Strings.Append(msg,name);
Strings.Append(msg,")");
END AppendToMsg;
END Instance;
InstanceList*= OBJECT(Basic.List)
PROCEDURE GetInstance*(i: LONGINT): Instance;
VAR a: ANY;
BEGIN
a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Instance) END
END GetInstance;
PROCEDURE AddInstance(a: Instance);
BEGIN a.index := Length(); Add(a);
END AddInstance;
PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Instance;
VAR a: Instance; i: LONGINT;
BEGIN
FOR i := 0 TO Length()-1 DO
a := GetInstance(i);
IF (a # NIL) & (a.name = name) THEN RETURN a END;
END;
RETURN NIL
END ByName;
PROCEDURE Same(as: InstanceList; flags: SET): BOOLEAN;
VAR i: LONGINT; left, right: Symbol;
BEGIN
IF as.Length() # Length() THEN RETURN FALSE END;
FOR i := 0 TO Length()-1 DO
left := GetInstance(i);
right := as.GetInstance(i);
IF ~left.Same(right, flags) THEN RETURN FALSE END;
END;
RETURN TRUE
END Same;
END InstanceList;
InstanceMethod*= PROCEDURE {DELEGATE} (instance: Instance): BOOLEAN;
TypeMethod*= PROCEDURE {DELEGATE} (type: Type): BOOLEAN;
Scope*=OBJECT (Symbol)
VAR
symbols-: SymbolList;
instances-: InstanceList;
channels-: ChannelList;
types-: TypeList;
ports-: PortList;
index-: LONGINT;
specification-: Specification;
PROCEDURE &InitScope(CONST name: ARRAY OF CHAR; scope: Scope; specification: Specification);
BEGIN
COPY(name,SELF.name); SELF.specification := specification;
NEW(instances,4); NEW(channels,4);
NEW(ports,4); NEW(types,4);
NEW(symbols,4);
index := -1;
END InitScope;
PROCEDURE Same(as: Symbol; flags: SET): BOOLEAN;
BEGIN
IF TraceSame THEN TRACE("Scope",name) END;
IF (as = NIL) OR ~(as IS Scope) THEN RETURN FALSE END;
WITH as: Scope DO
IF ~symbols.Same(as.symbols, flags) THEN RETURN FALSE END;
IF ~instances.Same(as.instances, flags) THEN RETURN FALSE END;
IF ~channels.Same(as.channels, flags) THEN RETURN FALSE END;
IF ~types.Same(as.types, flags) THEN RETURN FALSE END;
IF ~ports.Same(as.ports, flags) THEN RETURN FALSE END;
END;
RETURN Same^(as, flags)
END Same;
PROCEDURE FindSymbol(CONST name: ARRAY OF CHAR; traverse: BOOLEAN): Symbol;
VAR symbol: Symbol;
BEGIN
symbol := symbols.ByName(name);
IF (symbol = NIL) & (scope # NIL) & traverse THEN RETURN scope.FindSymbol(name,TRUE)
ELSE RETURN symbol;
END;
END FindSymbol;
PROCEDURE NewInstance*(CONST name: ARRAY OF CHAR; type: Type): Instance;
VAR instance: Instance;
BEGIN
NEW(instance, name, SELF, type);
instances.AddInstance(instance);
symbols.AddSymbol(instance);
RETURN instance
END NewInstance;
PROCEDURE NewChannel*(): Channel;
VAR channel: Channel; name: Name;
BEGIN
name := "@Channel"; Basic.AppendNumber(name,channels.Length());
NEW(channel,name,SELF);
channels.AddChannel(channel);
symbols.AddSymbol(channel);
RETURN channel;
END NewChannel;
PROCEDURE NewPort*(CONST name: ARRAY OF CHAR; direction: LONGINT; adr: LONGINT): Port;
VAR port: Port;
BEGIN
NEW(port, name,SELF, direction,adr);
ports.AddPort(port);
symbols.AddSymbol(port);
RETURN port
END NewPort;
PROCEDURE NewType*(CONST name: ARRAY OF CHAR): Type;
VAR type: Type;
BEGIN
NEW(type,name,SELF);
types.AddType(type);
symbols.AddSymbol(type);
RETURN type
END NewType;
PROCEDURE ForEachInstanceDo*(method: InstanceMethod): BOOLEAN;
VAR i: LONGINT; instance: Instance; type: Type;
BEGIN
FOR i := 0 TO instances.Length()-1 DO
instance := instances.GetInstance(i);
IF ~method(instance) THEN RETURN FALSE END;
END;
RETURN TRUE
END ForEachInstanceDo;
PROCEDURE ForEachTypeDo*(method: TypeMethod): BOOLEAN;
VAR type: Type; i: LONGINT;
BEGIN
FOR i := 0 TO types.Length()-1 DO
type := types.GetType(i);
IF ~method(type) THEN RETURN FALSE END;
IF ~type.ForEachTypeDo(method) THEN RETURN FALSE END;
END;
RETURN TRUE
END ForEachTypeDo;
END Scope;
Type*=OBJECT (Scope)
VAR
devices-: DeviceList;
modules-: ModuleList;
instructionMemorySize-, dataMemorySize-: LONGINT;
capabilities-: SET;
PROCEDURE Same(as: Symbol; flags: SET): BOOLEAN;
BEGIN
IF TraceSame THEN TRACE("Type",name) END;
IF (as = NIL) OR ~(as IS Type) THEN RETURN FALSE END;
WITH as: Type DO
IF ~devices.Same(as.devices, flags) THEN RETURN FALSE END;
IF (CheckModules IN flags) & ~modules.Same(as.modules, flags) THEN RETURN FALSE END;
IF (instructionMemorySize # as.instructionMemorySize) THEN RETURN FALSE END;
IF (dataMemorySize # as.dataMemorySize) THEN RETURN FALSE END;
IF (capabilities # as.capabilities) THEN RETURN FALSE END;
END;
RETURN Same^(as, flags)
END Same;
PROCEDURE & InitType*(CONST name: ARRAY OF CHAR; scope: Scope);
BEGIN
InitScope(name,scope,scope.specification);
ASSERT(specification # NIL);
instructionMemorySize := defaultInstructionMemorySize;
dataMemorySize := defaultDataMemorySize;
NEW(devices,4);
NEW(modules,4);
SELF.scope := scope;
capabilities := {};
END InitType;
PROCEDURE AddCapability*(capability: LONGINT);
BEGIN
INCL(capabilities, capability);
END AddCapability;
PROCEDURE SetInstructionMemorySize*(value: LONGINT);
BEGIN instructionMemorySize := value
END SetInstructionMemorySize;
PROCEDURE SetDataMemorySize*(value: LONGINT);
BEGIN dataMemorySize := value
END SetDataMemorySize;
PROCEDURE NewDevice*(CONST name: ARRAY OF CHAR; adr: LONGINT): Device;
VAR device: Device;
BEGIN
NEW(device,name,SELF, adr);
devices.AddDevice(device);
symbols.AddSymbol(device);
RETURN device;
END NewDevice;
PROCEDURE NewModule*(CONST moduleName, fileName: ARRAY OF CHAR): Module;
VAR module: Module;
BEGIN
NEW(module, moduleName, SELF, fileName);
modules.AddModule(module);
symbols.AddSymbol(module);
RETURN module;
END NewModule;
PROCEDURE Read(r: Streams.Reader): BOOLEAN;
VAR port: Port; module: Module; device: Device; i,number: LONGINT;
channel: Channel; instance: Instance; type: Type;
BEGIN
IF ~r.GetInteger(i,FALSE) OR (index # i) OR
~CheckItem(r,"name") OR ~GetString(r,name) OR
~CheckItem(r,"instructionMemorySize") OR ~r.GetInteger(instructionMemorySize,FALSE) OR
~CheckItem(r,"dataMemorySize") OR ~r.GetInteger(dataMemorySize,FALSE) OR
~CheckItem(r,"capabilities") OR ~GetSet(r,capabilities) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
IF ~CheckItem(r,"types") OR ~r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
FOR i := 0 TO number-1 DO
type := NewType("");
IF ~type.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
END;
IF ~CheckItem(r,"instances") OR ~r.GetInteger(number,FALSE)
THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END
END;
FOR i := 0 TO number-1 DO
instance := NewInstance("",NIL);
IF ~instance.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
END;
IF ~CheckItem(r,"ports")OR ~ r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
FOR i := 0 TO number-1 DO
port := NewPort("",0,0);
IF ~port.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
END;
IF ~CheckItem(r,"modules")OR ~ r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
FOR i := 0 TO number-1 DO
module := NewModule("","");
IF ~module.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
END;
IF ~CheckItem(r,"devices")OR ~ r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
FOR i := 0 TO number-1 DO
device := NewDevice("",0);
IF ~device.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
END;
IF ~CheckItem(r,"channels") OR ~ r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
FOR i := 0 TO number-1 DO
channel := NewChannel();
IF ~channel.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
END;
RETURN TRUE
END Read;
PROCEDURE Write*(w: Streams.Writer; indent: LONGINT);
VAR port: Port; device: Device; module: Module; instance: Instance; channel: Channel; type: Type; i: LONGINT;
BEGIN
Indent(w,indent); INC(indent);
w.Int(index,1);
w.String(" name="); w.String(name);
w.String(" instructionMemorySize="); w.Int(instructionMemorySize,1);
w.String(" dataMemorySize="); w.Int(dataMemorySize,1);
w.String(" capabilities="); WriteSet(w, capabilities);
w.Ln;
Indent(w,indent); w.String("types=");w.Int(types.Length(),1); w.Ln;
FOR i := 0 TO types.Length()-1 DO
type := types.GetType(i);
type.Write(w,indent+1);
END;
Indent(w,indent);
w.String("instances=");w.Int(instances.Length(),1); w.Ln;
FOR i := 0 TO instances.Length()-1 DO
instance := instances.GetInstance(i);
instance.Write(w,indent+1);
END;
Indent(w,indent);
w.String("ports=");w.Int(ports.Length(),1); w.Ln;
FOR i := 0 TO ports.Length()-1 DO
port := ports.GetPort(i);
port.Write(w,indent+1);
END;
Indent(w,indent);
w.String("modules="); w.Int(modules.Length(),1); w.Ln;
FOR i := 0 TO modules.Length()-1 DO
module := modules.GetModule(i);
module.Write(w,indent+1);
END;
Indent(w,indent);
w.String("devices="); w.Int(devices.Length(),1); w.Ln;
FOR i := 0 TO devices.Length()-1 DO
device := devices.GetDevice(i);
device.Write(w,indent+1);
END;
Indent(w,indent);
w.String("channels=");w.Int(channels.Length(),1); w.Ln;
FOR i := 0 TO channels.Length()-1 DO
channel := channels.GetChannel(i);
channel.Write(w,indent+1);
END;
w.Update;
END Write;
END Type;
TypeList*= OBJECT(Basic.List)
PROCEDURE GetType*(i: LONGINT): Type;
VAR a: ANY;
BEGIN
a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Type) END
END GetType;
PROCEDURE AddType(a: Type);
BEGIN a.index := Length(); Add(a);
END AddType;
PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Type;
VAR a: Type; i: LONGINT;
BEGIN
FOR i := 0 TO Length()-1 DO
a := GetType(i);
IF (a # NIL) & (a.name = name) THEN RETURN a END;
END;
RETURN NIL
END ByName;
PROCEDURE Same(as: TypeList; flags: SET): BOOLEAN;
VAR i: LONGINT; left, right: Type;
BEGIN
IF as.Length() # Length() THEN RETURN FALSE END;
FOR i := 0 TO Length()-1 DO
left := GetType(i);
right := as.GetType(i);
IF ~left.Same(right, flags) THEN RETURN FALSE END;
END;
RETURN TRUE
END Same;
END TypeList;
Channel*=OBJECT (Symbol)
VAR
in-, out-: PortInstance;
fifoSize-: LONGINT;
widthInBits-: LONGINT;
index-: LONGINT;
PROCEDURE Same(as: Symbol; flags: SET): BOOLEAN;
BEGIN
IF TraceSame THEN TRACE("Channel",name) END;
IF (as = NIL) OR ~(as IS Channel) THEN RETURN FALSE END;
WITH as: Channel DO
IF ~in.instance.Same(as.in.instance, flags) THEN RETURN FALSE END;
IF ~in.port.Same(as.in.port, flags) THEN RETURN FALSE END;
IF ~out.instance.Same(as.out.instance, flags) THEN RETURN FALSE END;
IF ~out.port.Same(as.out.port, flags) THEN RETURN FALSE END;
IF widthInBits # as.widthInBits THEN RETURN FALSE END;
IF index # as.index THEN RETURN FALSE END;
END;
RETURN Same^(as, flags)
END Same;
PROCEDURE & InitChannel(CONST name: ARRAY OF CHAR; scope: Scope);
BEGIN
InitSymbol(name,scope);
fifoSize := defaultFifoSize;
widthInBits := defaultChannelWidth;
in.port := NIL; in.instance := NIL;
out.port := NIL; out.instance := NIL;
SELF.index := -1;
END InitChannel;
PROCEDURE ConnectIn*(instance: Instance; port: Port);
BEGIN in.port := port; in.instance := instance;
END ConnectIn;
PROCEDURE ConnectOut*(instance: Instance; port: Port);
BEGIN out.port := port; out.instance := instance;
END ConnectOut;
PROCEDURE SetFifoSize*(size: LONGINT);
BEGIN fifoSize := size
END SetFifoSize;
PROCEDURE SetWidth*(width: LONGINT);
BEGIN widthInBits := width
END SetWidth;
PROCEDURE Read(r: Streams.Reader): BOOLEAN;
VAR s: Name; i: LONGINT;
BEGIN
IF ~r.GetInteger(i,FALSE) OR (i#index) OR
~CheckItem(r,"name") OR ~GetString(r,name) OR
~CheckItem(r,"outInstance") OR ~ GetString(r,s) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
IF s#"NIL" THEN out.instance := scope.instances.ByName(s) END;
IF ~CheckItem(r,"outPort") OR ~GetString(r,s) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
IF s#"NIL" THEN out.port := out.instance.type.ports.ByName(s) END;
IF ~CheckItem(r,"inInstance") OR ~ GetString(r,s) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
IF s#"NIL" THEN in.instance := scope.instances.ByName(s) END;
IF ~CheckItem(r,"inPort")OR ~GetString(r,s) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
IF s#"NIL" THEN in.port := in.instance.type.ports.ByName(s) END;
IF ~CheckItem(r,"size")OR ~r.GetInteger(i,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
fifoSize := i;
IF ~CheckItem(r,"width")OR ~r.GetInteger(i,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
widthInBits := i;
RETURN TRUE
END Read;
PROCEDURE Write*(w: Streams.Writer; indent: LONGINT);
BEGIN
Indent(w,indent);
w.Int(index,1);
w.String(" name="); w.String(name);
w.String(" outInstance="); IF out.instance = NIL THEN w.String("NIL") ELSE w.String(out.instance.name) END;
w.String(" outPort="); IF out.port = NIL THEN w.String("NIL") ELSE w.String(out.port.name) END;
w.String(" inInstance="); IF in.instance = NIL THEN w.String("NIL") ELSE w.String(in.instance.name) END;
w.String(" inPort="); IF in.port = NIL THEN w.String("NIL") ELSE w.String(in.port.name) END;
w.String(" size="); w.Int(fifoSize,1);
w.String(" width="); w.Int(widthInBits,1);
w.Ln;w.Update;
END Write;
END Channel;
ChannelList*= OBJECT(Basic.List)
PROCEDURE GetChannel*(i: LONGINT): Channel;
VAR a: ANY;
BEGIN
a := Get(i); IF a = NIL THEN RETURN NIL ELSE RETURN a(Channel) END
END GetChannel;
PROCEDURE AddChannel*(a: Channel);
BEGIN a.index := Length(); Add(a);
END AddChannel;
PROCEDURE ByName*(CONST name: ARRAY OF CHAR): Channel;
VAR a: Channel; i: LONGINT;
BEGIN
FOR i := 0 TO Length()-1 DO
a := GetChannel(i);
IF (a # NIL) & (a.name = name) THEN RETURN a END;
END;
RETURN NIL
END ByName;
PROCEDURE ByPort*(port: Port): Channel;
VAR a: Channel; i: LONGINT;
BEGIN
FOR i := 0 TO Length()-1 DO
a := GetChannel(i);
IF (a # NIL) & (a.in.port = port) OR (a.out.port=port) THEN RETURN a END;
END;
RETURN NIL
END ByPort;
PROCEDURE Same(as: ChannelList; flags: SET): BOOLEAN;
VAR i: LONGINT; left, right: Channel;
BEGIN
IF as.Length() # Length() THEN RETURN FALSE END;
FOR i := 0 TO Length()-1 DO
left := GetChannel(i);
right := as.GetChannel(i);
IF ~left.Same(right, flags) THEN RETURN FALSE END;
END;
RETURN TRUE
END Same;
END ChannelList;
Specification*=OBJECT (Scope)
VAR
instructionSet-: Name;
diagnostics-: Diagnostics.Diagnostics;
log-: Streams.Writer;
supportedDevices-: DeviceList;
imports-: SymbolList;
frequencyDivider-: LONGINT;
PROCEDURE AddDevice*(CONST name: ARRAY OF CHAR; adr: HUGEINT);
VAR device: Device;
BEGIN
NEW(device, name, SELF, LONGINT(adr)); supportedDevices.AddDevice(device);
END AddDevice;
PROCEDURE Same*(as: Symbol; flags: SET): BOOLEAN;
VAR i: LONGINT;
BEGIN
IF TraceSame THEN TRACE("SameSpecification", name) END;
IF (as = NIL) OR ~(as IS Specification) THEN RETURN FALSE END;
WITH as: Specification DO
IF as.instructionSet # instructionSet THEN RETURN FALSE END;
IF ~imports.Same(as.imports,flags) THEN RETURN FALSE END;
IF frequencyDivider # as.frequencyDivider THEN RETURN FALSE END;
END;
RETURN Same^(as, flags);
END Same;
PROCEDURE DefineDevices*(system: Global.System);
VAR i: LONGINT; device: Device;
BEGIN
FOR i := 0 TO supportedDevices.Length()-1 DO
device := supportedDevices.GetDevice(i);
system.AddCapability(Basic.MakeString(device.name));
END;
END DefineDevices;
PROCEDURE & Init*(CONST name: ARRAY OF CHAR; diagnostics: Diagnostics.Diagnostics; log: Streams.Writer);
VAR device: Device;
BEGIN
InitScope(name,NIL,SELF);
instructionSet := "UNDEFINED";
NEW(supportedDevices,4);
SELF.diagnostics := diagnostics;
SELF.log := log;
AddDevice("DDR", 0FFCAH);
AddDevice("RS232",0FFFFFFC4H);
AddDevice("LCD", 0FFFFFFC8H);
AddDevice("CF", 0FFFFFFCCH);
AddDevice("LED", 0FFFFFFC7H);
AddDevice("TIMER", 0FFFFFFC6H);
AddDevice("PORT", 0FFFFFFE0H);
AddDevice("Switch", 0FFFFFFC7H);
AddDevice("Motor",0FFFFFFCEH);
AddDevice("BraceletSPI",0FFFFFFD2H);
AddDevice("GPI",0FFFFFFD6H);
AddDevice("GPO",0FFFFFFD6H);
AddDevice("WDT", 0FFFFFFD8H);
AddDevice("SPI", 0FFFFFFD4H);
NEW(imports,4);
frequencyDivider := 1;
END Init;
PROCEDURE SetFrequencyDivider*(divider: LONGINT);
BEGIN frequencyDivider := divider
END SetFrequencyDivider;
PROCEDURE AddImport*(CONST name: ARRAY OF CHAR);
VAR import: Specification;
BEGIN
IF imports.ByName(name) = NIL THEN
import := LoadSpecification(name,NIL,NIL);
IF import # NIL THEN imports.Add(import); symbols.Add(import) END;
END;
END AddImport;
PROCEDURE SetInstructionSet*(CONST instructionSet: ARRAY OF CHAR);
BEGIN
COPY(instructionSet,SELF.instructionSet);
END SetInstructionSet;
PROCEDURE Write*(w: Streams.Writer; indent: LONGINT);
VAR type: Type; channel: Channel; i: LONGINT; instance: Instance;port: Port; import: Symbol;
BEGIN
Indent(w,indent);w.String("name="); w.String(name); w.Ln;
INC(indent);
Indent(w,indent); w.String("instructionSet="); w.String(instructionSet); w.Ln;
Indent(w,indent); w.String("frequencyDivider="); w.Int(frequencyDivider,1); w.Ln;
Indent(w,indent); w.String("imports="); w.Int(imports.Length(),1); w.Ln;
FOR i := 0 TO imports.Length()-1 DO
import := imports.GetSymbol(i);
Indent(w,indent+1); w.String(import.name); w.Ln;
END;
Indent(w,indent); w.String("types=");w.Int(types.Length(),1); w.Ln;
FOR i := 0 TO types.Length()-1 DO
type := types.GetType(i);
type.Write(w,indent+1);
END;
Indent(w,indent); w.String("instances=");w.Int(instances.Length(),1); w.Ln;
FOR i := 0 TO instances.Length()-1 DO
instance := instances.GetInstance(i);
instance.Write(w,indent+1);
END;
Indent(w,indent); w.String("ports=");w.Int(ports.Length(),1); w.Ln;
FOR i := 0 TO ports.Length()-1 DO
port := ports.GetPort(i);
port.Write(w,indent+1);
END;
Indent(w,indent); w.String("channels=");w.Int(channels.Length(),1); w.Ln;
FOR i := 0 TO channels.Length()-1 DO
channel := channels.GetChannel(i);
channel.Write(w,indent+1);
END;
w.Update;
END Write;
PROCEDURE Read*(r: Streams.Reader): BOOLEAN;
VAR i, number: LONGINT; type: Type;
instance: Instance; port: Port; channel: Channel; importName: Name;
BEGIN
IF ~CheckItem(r,"name") OR ~GetString(r,name) OR
~CheckItem(r,"instructionSet") OR ~GetString(r,instructionSet) OR
~CheckItem(r,"frequencyDivider") OR ~r.GetInteger(frequencyDivider,FALSE) OR
~CheckItem(r,"imports") OR ~r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
FOR i := 0 TO number-1 DO
IF ~GetString(r,importName) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
AddImport(importName);
END;
IF ~CheckItem(r,"types") OR ~r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
FOR i := 0 TO number-1 DO
type := NewType("");
IF ~type.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
END;
IF ~CheckItem(r,"instances") OR ~r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
FOR i := 0 TO number-1 DO
instance := NewInstance("",NIL);
IF ~instance.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
END;
IF ~CheckItem(r,"ports")OR ~r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
FOR i := 0 TO number-1 DO
port := NewPort("",0,0);
IF ~port.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
END;
IF ~CheckItem(r,"channels") OR ~r.GetInteger(number,FALSE) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
FOR i := 0 TO number-1 DO
channel := NewChannel();
IF ~channel.Read(r) THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
END;
RETURN TRUE
END Read;
PROCEDURE GetPortAddress*(number: LONGINT): LONGINT;
BEGIN
RETURN BasePortAddress+2*number;
END GetPortAddress;
PROCEDURE Emit*(): BOOLEAN;
VAR w: Files.Writer; f: Files.File; fileName: Files.FileName; msg: Name;
BEGIN
FlattenNetwork(SELF);
Files.JoinExtension(SELF.name,SpecificationFileExtension,fileName);
f := Files.New(fileName);
IF f # NIL THEN
NEW(w,f,0);
Write(w,0);
w.Update;
Files.Register(f);
msg := "Wrote Active Cells specification to file "; Strings.Append(msg, fileName);
IF log # NIL THEN log.String(msg); log.Ln; END;
RETURN TRUE
ELSE
diagnostics.Error(fileName,Diagnostics.Invalid, Diagnostics.Invalid,"could not generate file");
IF TraceError THEN HALT(100) ELSE RETURN FALSE END
END;
END Emit;
END Specification;
PROCEDURE Indent(w: Streams.Writer; indent: LONGINT);
BEGIN
WHILE indent > 0 DO
w.String(" ");
DEC(indent);
END;
END Indent;
PROCEDURE CheckItem(VAR r: Streams.Reader; CONST name: ARRAY OF CHAR): BOOLEAN;
VAR i: LONGINT; ch: CHAR; b: BOOLEAN;
BEGIN
i := 0;
b := r.GetChar(ch);
WHILE (r.res=Streams.Ok) & (ch # "=") DO
IF name[i] # ch THEN IF TraceError THEN HALT(100) ELSE RETURN FALSE END END;
INC(i);
r.Char(ch);
END;
RETURN TRUE
END CheckItem;
PROCEDURE GetString(VAR r: Streams.Reader; VAR name: ARRAY OF CHAR): BOOLEAN;
VAR c: CHAR;
BEGIN
c := r.Peek();
IF r.GetString(name) THEN RETURN TRUE
ELSE RETURN (name[0]=0X) & (c="'") OR (c='"')
END;
END GetString;
PROCEDURE GetSet(VAR r: Streams.Reader; VAR set: SET): BOOLEAN;
VAR int: LONGINT;
BEGIN
IF r.GetInteger(int, FALSE) THEN set := SYSTEM.VAL(SET, int); RETURN TRUE ELSE RETURN FALSE END;
END GetSet;
PROCEDURE WriteSet(VAR r: Streams.Writer; set: SET);
VAR int: LONGINT;
BEGIN
int := SYSTEM.VAL(LONGINT, set);
r.Int(int,1);
END WriteSet;
PROCEDURE LoadSpecification*(CONST name: ARRAY OF CHAR; diagnostics: Diagnostics.Diagnostics; log: Streams.Writer): Specification;
VAR fileName: Files.FileName; spec: Specification; f: Files.File; r: Files.Reader;
BEGIN
COPY(name,fileName);
Strings.Append(fileName,".spec");
f := Files.Old(fileName);
IF f = NIL THEN IF log # NIL THEN log.String("could not load specification "); log.String(name); log.Ln END; RETURN NIL END;
NEW(spec, "", diagnostics, log);
NEW(r,f,0);
IF spec.Read(r) THEN
RETURN spec
ELSE
RETURN NIL
END;
END LoadSpecification;
PROCEDURE ReadSpecification*(context: Commands.Context);
VAR fileName: Files.FileName; r: Files.Reader; specification: Specification;f : Files.File; b: BOOLEAN; diagnostics: Diagnostics.StreamDiagnostics;
BEGIN
b := context.arg.GetString(fileName);
NEW(diagnostics, context.error);
specification := LoadSpecification(fileName, diagnostics, context.out);
IF specification # NIL THEN
specification.Write(context.out,0);
END;
END ReadSpecification;
PROCEDURE CompareSpecification*(context: Commands.Context);
VAR fileName: Files.FileName; spec1, spec2: Specification; b: BOOLEAN;
BEGIN
b := context.arg.GetString(fileName);
spec1 := LoadSpecification(fileName, NIL, context.error);
IF spec1 = NIL THEN context.error.String("could not load specification "); context.error.String(fileName); RETURN END;
b := context.arg.GetString(fileName);
spec2 := LoadSpecification(fileName, NIL, context.error);
IF spec2 = NIL THEN context.error.String("could not load specification "); context.error.String(fileName); RETURN END;
IF spec1.Same(spec2, {}) THEN context.out.String("Specifications are equal") ELSE context.out.String("specifications are not equal"); END;
END CompareSpecification;
PROCEDURE GetSymbol*(scope: Scope; CONST name: ARRAY OF CHAR): Symbol;
VAR scopeName: Name; i,j: LONGINT; symbol: Symbol; first: BOOLEAN;
BEGIN
i := 0; first := TRUE;
WHILE (scope # NIL) & (name[i] # 0X) DO
j := 0;
WHILE (name[i] # 0X) & (name[i] # ".") DO
scopeName[j] := name[i];
INC(i); INC(j);
END;
scopeName[j] := 0X; INC(i);
symbol := scope.FindSymbol(scopeName, first); first := FALSE;
IF (symbol # NIL) & (symbol IS Scope) THEN scope := symbol(Scope)
ELSE scope := NIL
END;
END;
IF name[i] # 0X THEN RETURN NIL ELSE RETURN symbol END;
END GetSymbol;
PROCEDURE FlattenNetwork*(scope: Scope);
VAR instance,subInstance,newInstance: Instance; oldChannel,channel: Channel;
instances: InstanceList; channels: ChannelList;
i,j: LONGINT; name: SyntaxTree.String;
port: Port;
PROCEDURE FlattenPortInstance(VAR pi: PortInstance);
VAR name: Name; port, prevPort: Port; instance: Instance;
BEGIN
IF pi.port # NIL THEN
port := pi.port.delegate.port;
IF port # NIL THEN
instance := pi.port.delegate.instance;
ASSERT(instance # NIL);
COPY(pi.instance.name,name);
WHILE port # NIL DO
prevPort := port;
ASSERT(instance # NIL);
Strings.Append(name,"."); Strings.Append(name,instance.name);
instance := port.delegate.instance;
port := port.delegate.port;
END;
port := prevPort;
instance := instances.ByName(name);
ASSERT(port # NIL);
ASSERT(instance # NIL);
pi.instance := instance;
pi.port := port;
END;
END;
END FlattenPortInstance;
PROCEDURE EmbedInstance(instance: Instance; VAR subInstance: Instance): Instance;
VAR name: Name; newInstance: Instance; i: LONGINT; parameter,newParameter: Parameter;
BEGIN
COPY(instance.name, name); Strings.Append(name,"."); Strings.Append(name,subInstance.name);
newInstance := instances.ByName(name);
IF newInstance = NIL THEN
NEW(newInstance, name, scope, subInstance.type);
FOR i := 0 TO subInstance.parameters.Length()-1 DO
parameter := subInstance.parameters.GetParameter(i);
newParameter := newInstance.AddParameter(parameter.name);
newParameter.index := parameter.index;
newParameter.type := parameter.type;
newParameter.integer := parameter.integer;
newParameter.boolean := parameter.boolean;
END;
END;
RETURN newInstance
END EmbedInstance;
BEGIN
IF scope.instances.Length()=0 THEN RETURN END;
NEW(instances,4); NEW(channels,4);
FOR i := 0 TO scope.channels.Length()-1 DO
oldChannel := scope.channels.GetChannel(i);
channels.AddChannel(oldChannel);
END;
FOR i := 0 TO scope.instances.Length()-1 DO
instance := scope.instances.GetInstance(i);
IF instance.type.instances.Length() # 0 THEN
FlattenNetwork(instance.type);
FOR j := 0 TO instance.type.instances.Length()-1 DO
subInstance := instance.type.instances.GetInstance(j);
newInstance := EmbedInstance(instance, subInstance);
instances.AddInstance(newInstance)
END;
FOR j := 0 TO instance.type.channels.Length()-1 DO
oldChannel := instance.type.channels.GetChannel(j);
channel := scope.NewChannel();
channel.ConnectIn(oldChannel.in.instance, oldChannel.in.port);
channel.ConnectOut(oldChannel.out.instance, oldChannel.out.port);
channel.SetFifoSize(oldChannel.fifoSize);
channel.SetWidth(oldChannel.widthInBits);
channel.in.instance := EmbedInstance(instance, channel.in.instance);
channel.out.instance := EmbedInstance(instance, channel.out.instance);
channels.AddChannel(channel);
END;
ELSE
instances.AddInstance(instance);
END;
END;
FOR i := 0 TO channels.Length()-1 DO
channel := channels.GetChannel(i);
FlattenPortInstance(channel.in);
FlattenPortInstance(channel.out);
END;
FOR i := 0 TO scope.ports.Length()-1 DO
port := scope.ports.GetPort(i);
FlattenPortInstance(port.delegate);
END;
scope.instances := instances;
scope.channels := channels;
END FlattenNetwork;
PROCEDURE NormalizeName*(CONST src: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR);
VAR i: LONGINT; ch: CHAR;
BEGIN
i := 0;
REPEAT
ch := src[i];
CASE ch OF
".", "@", "[", "]": dest[i] := "0";
ELSE
dest[i] := ch
END;
INC(i);
UNTIL ch = 0X;
END NormalizeName;
PROCEDURE WriteName*(w: Streams.Writer; scope: Scope; CONST name, suffix: ARRAY OF CHAR);
VAR n: ARRAY 256 OF CHAR;
BEGIN
IF scope # NIL THEN scope.GetFullName(n,NIL); ELSE n := "" END;
IF name # "" THEN
IF n # "" THEN Strings.Append(n,".") END;
Strings.Append(n,name);
END;
NormalizeName(n,n);
IF suffix # "" THEN
ASSERT(n# "");
Strings.Append(n,"_"); Strings.Append(n,suffix)
END;
w.String(n);
END WriteName;
(*
PROCEDURE InitMod;
BEGIN
NEW(platforms,3);
NEW(platform);
platform.platformId := Strings.NewString("DEFAULT");
platform.specLoader := LoadSpecificationDefault;
END InitMod;
BEGIN
InitMod;
*)
END FoxActiveCells.
FoxActiveCells.ReadSpecification Test.spec ~
FSTools.CopyFiles TL.spec => Test.spec ~
FoxActiveCells.CompareSpecification Test TL ~~
SystemTools.FreeDownTo FoxActiveCells ~