123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- (** Active Cells Runtime Base Code for Variations of ActiveCellsRuntime Implementations
- Felix Friedrich, ETH Zürich, 2015
- *)
- module ActiveCellsRuntime;
- import
- system, Heaps, Modules, Diagnostics, Strings, Objects;
- const
- EnableTrace* = true;
- type
- (* do not inherit from this object -- not supported. This object contains hidden fields instantiated by the compiler that would be lost. *)
- Cell* = object (* must be exported for compiler *)
- var
- c: any;
- end Cell;
- Context*= object
-
- procedure Allocate*(scope: any; var c: any; t: Modules.TypeDesc; const name: array of char; isCellNet, isEngine: boolean);
- end Allocate;
-
- procedure AddPort*(c: any; var p: any; const name: array of char; inout: set; width: longint);
- end AddPort;
- procedure AddPortArray*(c: any; var ports: any; const name: array of char; inout: set; width: longint; const lens: array of longint);
- end AddPortArray;
- procedure AddStaticPortArray*(c: any; var ports: array of any; const name: array of char; inout: set; width: longint);
- end AddStaticPortArray;
- procedure AddPortIntegerProperty*(p: any; const name: array of char; value: longint);
- end AddPortIntegerProperty;
- procedure AddFlagProperty*(c: any; const name: array of char);
- end AddFlagProperty;
- procedure AddStringProperty*(c: any; const name: array of char; const value: array of char);
- end AddStringProperty;
- procedure AddIntegerProperty*(c: any; const name: array of char; value: longint);
- end AddIntegerProperty;
- procedure FinishedProperties*(c: any);
- end FinishedProperties;
- procedure Connect*(outPort, inPort: any; depth: longint);
- end Connect;
- procedure Delegate*(netPort: any; cellPort: any);
- end Delegate;
- procedure Start*(c: any; proc: procedure{DELEGATE});
- end Start;
- procedure Send*(p: any; value: longint);
- end Send;
- procedure Receive*(p: any; var value: longint);
- end Receive;
-
- end Context;
-
- Launcher* = object
- var
- proc: procedure {DELEGATE};
- context: Context;
- finished: boolean;
-
- procedure & Init*(context: Context);
- begin
- self.context := context;
- proc := nil;
- finished := false;
- end Init;
-
- procedure Start*(p: procedure{DELEGATE}; doWait: boolean);
- begin{EXCLUSIVE}
- proc := p;
- await(~doWait or finished);
- end Start;
-
- begin{ACTIVE,EXCLUSIVE}
- await(proc # nil);
- proc;
- finished := true;
- end Launcher;
-
- procedure GetContext(): Context;
- begin
- return Objects.ActiveObject()(Launcher).context;
- end GetContext;
-
- procedure AllocateOnContext(context: Context;scope: Cell; var c: Cell; tag: address; const name: array of char; isCellnet, isEngine: boolean);
- var
- a: any;
- typeInfo: Modules.TypeDesc;
- s, ac: any;
- begin
- (* allocation of cells must use the tag provided, it contains all internally stored metadata *)
- Heaps.NewRec(a, tag, false);
- system.get(tag-4,typeInfo);
- if EnableTrace then trace(scope, c, typeInfo, name, isCellnet, isEngine); end;
-
- if scope # nil then s := scope.c else s := nil end;
- if c # nil then ac := c.c else ac := nil end;
- c := a(Cell);
- context.Allocate(s, ac, typeInfo, name, isCellnet, isEngine);
- c.c := ac;
- end AllocateOnContext;
-
- procedure Allocate*(scope: Cell; var c: Cell; tag: address; const name: array of char; isCellnet, isEngine: boolean);
- begin
- AllocateOnContext(GetContext(), scope, c, tag, name, isCellnet, isEngine);
- end Allocate;
- procedure AddPort*(c: Cell; var p: any; const name: array of char; inout: set; width: longint);
- begin
- if EnableTrace then trace(c,p,name, inout, width); end;
- GetContext().AddPort(c.c, p, name, inout, width);
- end AddPort;
- procedure AddPortArray*(c: Cell; var ports: any; const name: array of char; inout: set; width: longint; const lens: array of longint);
- begin
- if EnableTrace then trace(name, inout, width, len(lens)); end;
- GetContext().AddPortArray(c.c, ports, name, inout, width, lens);
- end AddPortArray;
- procedure AddStaticPortArray*(c: Cell; var ports: array of any; const name: array of char; inout: set; width: longint);
- begin
- if EnableTrace then trace(name, inout, width, len(ports)); end;
- GetContext().AddStaticPortArray(c.c, ports, name, inout, width);
- end AddStaticPortArray;
- procedure AddPortIntegerProperty*(p: any; const name: array of char; value: longint);
- begin
- if EnableTrace then trace(p, name, value); end;
- GetContext().AddPortIntegerProperty(p,name,value);
- end AddPortIntegerProperty;
- procedure AddFlagProperty*(c: Cell; const name: array of char);
- begin
- if EnableTrace then trace(c, name); end;
- GetContext().AddFlagProperty(c.c, name);
- end AddFlagProperty;
- procedure AddStringProperty*(c: Cell; const name: array of char; var newValue: array of char; const value: array of char);
- begin
- if EnableTrace then trace(c, name, newValue, value); end;
- copy(value, newValue);
- GetContext().AddStringProperty(c.c, name, value);
- end AddStringProperty;
- procedure AddIntegerProperty*(c: Cell; const name: array of char; var newValue: longint; value: longint);
- begin
- if EnableTrace then trace(c, name, newValue, value); end;
- newValue := value;
- GetContext().AddIntegerProperty(c.c, name, value);
- end AddIntegerProperty;
- procedure FinishedProperties*(c: Cell);
- begin
- if EnableTrace then trace(c); end;
- GetContext().FinishedProperties(c.c);
- end FinishedProperties;
- procedure Connect*(outPort, inPort: any; depth: longint);
- begin
- if EnableTrace then trace(outPort, inPort, outPort, inPort, depth); end;
- GetContext().Connect(outPort, inPort, depth);
- end Connect;
- procedure Delegate*(netPort: any; cellPort: any);
- begin
- if EnableTrace then trace(netPort, cellPort); end;
- GetContext().Delegate(netPort, cellPort);
- end Delegate;
- procedure Start*(c: Cell; proc: procedure{DELEGATE});
- begin
- if EnableTrace then trace(c, proc); end;
- GetContext().Start(c.c, proc);
- end Start;
-
- procedure Send*(p: any; value: longint);
- begin
- GetContext().Send(p, value);
- end Send;
- procedure Receive*(p: any; var value: longint);
- begin
- GetContext().Receive(p, value);
- end Receive;
- type
- Module = pointer to record
- next: Module;
- checked, imports: boolean;
- m: Modules.Module
- end;
-
- procedure Find(root: Module; m: Modules.Module): Module;
- begin
- while (root # nil) & (root.m # m) do root := root.next end;
- return root
- end Find;
- procedure Imports(root, m: Module; const name: array of char): boolean;
- var i: longint;
- begin
- if ~m.checked then
- if m.m.name # name then
- i := 0;
- while i # len(m.m.module) do
- if (m.m.module[i].name = name) or Imports(root, Find(root, m.m.module[i]), name) then
- m.imports := true; i := len(m.m.module)
- else
- inc(i)
- end
- end
- else
- m.imports := true
- end;
- m.checked := true
- end;
- return m.imports
- end Imports;
- (*! caution: this is not thread safe -- must be moved to Modules.Mod *)
- procedure CopyModules(): Module;
- var firstm, lastm, c: Module; m: Modules.Module;
- begin
- new(firstm); firstm.next := nil; lastm := firstm;
- m := Modules.root;
- while m # nil do
- new(c); c.checked := false; c.imports := false; c.m := m;
- c.next := nil; lastm.next := c; lastm := c;
- m := m.next
- end;
- return firstm.next
- end CopyModules;
- procedure FreeDownTo(const modulename: array of char): longint;
- var
- root, m: Module; res: longint;
- nbrOfUnloadedModules : longint;
- msg: array 32 of char;
- begin
- nbrOfUnloadedModules := 0;
- root := CopyModules();
- m := root;
- while m # nil do
- if Imports(root, m, modulename) then
- Modules.FreeModule(m.m.name, res, msg);
- if res # 0 then
- (*context.error.String(msg);*)
- else
- inc(nbrOfUnloadedModules);
- end
- end;
- m := m.next
- end;
- return nbrOfUnloadedModules;
- end FreeDownTo;
-
- procedure Execute*( const cellNet: array of char; context: Context; diagnostics: Diagnostics.Diagnostics);
- type
- StartProc = procedure{DELEGATE}();
-
- Starter = object
- var
- p: StartProc;
- c: Cell;
- procedure & InitStarter(proc: address; scope: Cell);
- var startProcDesc: record proc: address; selfParam: address; end;
- begin
- startProcDesc.proc := proc;
- startProcDesc.selfParam := scope;
- system.move(address of startProcDesc, address of p, 2 * size of address);
- c := scope;
- end InitStarter;
- procedure P;
- begin
- Start(c, p)
- end P;
- end Starter
-
- var
- moduleName, typeName: array 256 of char;
- m: Modules.Module;
- typeInfo: Modules.TypeDesc;
- i, res: longint;
- str: array 256 of char;
- scope: Cell;
- unloaded: longint;
- starter: Starter;
- launcher: Launcher;
- begin
- i := Strings.IndexOfByte2(".",cellNet);
- if i = -1 then
- diagnostics.Error("",Diagnostics.Invalid,Diagnostics.Invalid, "cellNet malformed");
- end;
- Strings.Copy(cellNet,0,i,moduleName);
- Strings.Copy(cellNet,i+1,Strings.Length(cellNet)-Strings.Length(moduleName),typeName);
- unloaded := FreeDownTo(moduleName);
- if unloaded > 0 then
- (*param.ctx.Information("", Diagnostics.Invalid,Diagnostics.Invalid,"unloaded " & unloaded & " modules")*)
- end;
- m := Modules.ThisModule(moduleName,res,str);
- if m = nil then
- (*
- param.ctx.Error("",Diagnostics.Invalid,HdlBackend.ErrNotFound,'failed to load module "' & moduleName & '"');
- *)
- end;
- typeInfo := Modules.ThisType(m,typeName);
- if typeInfo = nil then
- (*
- param.ctx.Error("",Diagnostics.Invalid,HdlBackend.ErrNotFound,'failed to find cellnet type "' & param.architectureName & '" in module "' & moduleName & '"');
- return nil;
- *)
- end;
- assert(len(typeInfo.procedures) = 1);
- assert(typeInfo.procedures[0].name^ = "@Body");
- (* allocate the top level cellnet *)
- AllocateOnContext(context, nil,scope,typeInfo.tag,typeName,true,false);
- assert(scope # nil);
- assert(scope.c # nil);
- new(starter, typeInfo.procedures[0].address, scope);
- new(launcher, context);
- launcher.Start(starter.P, true);
- end Execute;
- end ActiveCellsRuntime.
|