CoreCreateImpl.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
Bertrand Serlet, September 17, 1986 10:11:40 pm PDT
Barth, February 17, 1987 6:02:57 pm PST
Louis Monier May 1, 1986 4:50:13 pm PDT
Mike Spreitzer November 18, 1986 2:39:13 pm PST
DIRECTORY
Core, CoreClasses, CoreCreate, CoreOps, CoreProperties, HashTable, Rope;
CoreCreateImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreOps, CoreProperties, HashTable, Rope
EXPORTS CoreCreate =
BEGIN OPEN CoreCreate;
Wires
WireList: PUBLIC PROC [wrs: LIST OF WRNIL, name: ROPENIL, props: Properties ← NIL] RETURNS [newWire: Wire] = {
count: NAT ← 0;
FOR wrl: LIST OF WR ← wrs, wrl.rest UNTIL wrl=NIL DO
IF wrl.first#NIL THEN count ← count + 1;
ENDLOOP;
newWire ← CoreOps.CreateWires[count, name, props];
count ← 0;
FOR wrl: LIST OF WR ← wrs, wrl.rest UNTIL wrl=NIL DO
IF wrl.first#NIL THEN {
new: Wire ← WITH wrl.first SELECT FROM
wire: Wire   => wire,
rope: ROPE  => CoreOps.CreateWire[name: rope],
text: REF TEXT  => CoreOps.CreateWire[name: Rope.FromRefText[text]],
ENDCASE   => ERROR;
newWire[count] ← new;
count ← count + 1;
};
ENDLOOP;
};
Wires: PUBLIC PROC [wr1, wr2, wr3, wr4, wr5, wr6, wr7, wr8, wr9, wr10, wr11, wr12, wr13: WRNIL, name: ROPENIL, props: Properties ← NIL] RETURNS [Wire] = {
RETURN [WireList[LIST [wr1, wr2, wr3, wr4, wr5, wr6, wr7, wr8, wr9, wr10, wr11, wr12, wr13], name, props]];
};
Seq: PUBLIC PROC [name: ROPENIL, size: NAT, protoChild: Wire ← NIL] RETURNS [wire: Wire] = {
wire ← CoreOps.SetShortWireName[CoreOps.CreateWires[size], name];
IF protoChild=NIL THEN FOR i: NAT IN [0..size) DO
wire[i] ← CoreOps.CreateWire[];
ENDLOOP
ELSE FOR i: NAT IN [0..size) DO
wire[i] ← CoreOps.CopyWire[protoChild];
ENDLOOP;
};
Index: PUBLIC PROC [wr: WR, index: NAT] RETURNS [WR] = {
WITH wr SELECT FROM
wire: Wire   => RETURN [wire[index]];
rope: ROPE   => RETURN [CoreOps.Index[rope, index]];
text: REF TEXT  => RETURN [CoreOps.Index[Rope.FromRefText[text], index]];
ENDCASE   => ERROR
};
Range: PUBLIC PROC [wire: Wire, start, size: NAT, name: ROPENIL, props: Properties ← NIL] RETURNS [Wire] = {
RETURN [CoreOps.SubrangeWire[wire, start, size, name, props]];
};
Union: PUBLIC PROC [wr1, wr2, wr3, wr4, wr5, wr6, wr7, wr8, wr9, wr10, wr11, wr12, wr13: Wire ← NIL, name: ROPENIL, props: Properties ← NIL] RETURNS [wire: Wire] = {
wires: LIST OF Wire ← LIST [wr1, wr2, wr3, wr4, wr5, wr6, wr7, wr8, wr9, wr10, wr11, wr12, wr13];
count: NAT ← 0;
FOR wl: LIST OF Wire ← wires, wl.rest UNTIL wl=NIL DO
IF wl.first#NIL THEN count ← count + (IF wl.first.size=0 THEN 1 ELSE wl.first.size);
ENDLOOP;
wire ← CoreOps.CreateWires[count, name, props];
count ← 0;
FOR wl: LIST OF Wire ← wires, wl.rest UNTIL wl=NIL DO
IF wl.first#NIL THEN {
IF wl.first.size=0 THEN {
wire[count] ← wl.first;
count ← count+1;
}
ELSE {
FOR w: NAT IN [0..wl.first.size) DO
wire[count+w] ← wl.first[w];
ENDLOOP;
count ← count + wl.first.size;
};
};
ENDLOOP;
};
Cells
Instance: PUBLIC PROC [type: CellType, pa1, pa2, pa3, pa4, pa5, pa6, pa7, pa8, pa9, pa10, pa11, pa12, pa13: PA ← [], name: ROPENIL, props: Properties ← NIL] RETURNS [CellInstance] = {
revpas: LIST OF PANIL;
FOR pas: LIST OF PALIST [pa1, pa2, pa3, pa4, pa5, pa6, pa7, pa8, pa9, pa10, pa11, pa12, pa13], pas.rest UNTIL pas=NIL DO
IF pas.first#[] THEN revpas ← CONS [pas.first, revpas];
ENDLOOP;
RETURN [InstanceList[type: type, pas: revpas, name: name, props: props]];
};
instanceBindProp: ATOM ← CoreProperties.RegisterProperty[$CoreInstanceBind, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]];
This property temporarily stores a table of bindings of the form: public [Wire] -> actual [WR]
InstanceList: PUBLIC PROC [type: CellType, pas: LIST OF PANIL, name: ROPENIL, props: Properties ← NIL] RETURNS [instance: CellInstance] = {
pasTable: HashTable.Table ← HashTable.Create[];
instance ← CoreClasses.CreateInstance[actual: NIL, type: type, name: name, props: props];
We check pas is of the right type, to detect errors as soon as possible
FOR checkPas: LIST OF PA ← pas, checkPas.rest WHILE checkPas#NIL DO
pa: PA = checkPas.first;
pub: WRWITH pa.public SELECT FROM
wire: Wire   => wire,
rope: ROPE   => rope,
text: REF TEXT => Rope.FromRefText[text],
ENDCASE  => ERROR;
actual: WRWITH pa.actual SELECT FROM
wire: Wire   => wire,
rope: ROPE   => rope,
text: REF TEXT => Rope.FromRefText[text],
ENDCASE  => ERROR;
public: Wire ← FindWire[type.public, checkPas.first.public];
IF public=NIL THEN MakeError[
Rope.Cat[
"Could not find public '",
IF ISTYPE [pub, ROPE] THEN NARROW [pub] ELSE CoreOps.GetShortWireName[NARROW[pub]], "'"
],
CoreOps.GetCellTypeName[type]];
IF NOT HashTable.Store[pasTable, public, actual] THEN MakeError[
Rope.Cat[
"Binding list binds twice public '",
IF ISTYPE [pub, ROPE] THEN NARROW [pub] ELSE CoreOps.GetShortWireName[NARROW[pub]], "'"
],
CoreOps.GetCellTypeName[type]];
ENDLOOP;
CoreProperties.PutCellInstanceProp[on: instance, prop: instanceBindProp, value: pasTable];
};
CreateError: ERROR [msg: ROPE] = CODE;
MakeError: PROC [msg: ROPE, cellName: ROPE] = {
ERROR CreateError[Rope.Cat[msg, " in cell type '", cellName, "'"]];
};
CheckWellFormed: PROC [root: ROPE, wire: Wire, cellName: ROPE] = {
IF wire=NIL THEN MakeError[root, cellName];
FOR sub: NAT IN [0..wire.size) DO CheckWellFormed[root, wire[sub], cellName] ENDLOOP;
};
Cell: PUBLIC PROC [public: WireSeq, onlyInternal, internal: WireSeq ← NIL, instances: CellInstances, name: ROPENIL, props: Properties ← NIL] RETURNS [cellType: CellType] = {
SELECT TRUE FROM
internal=NIL AND onlyInternal=NIL  => internal ← public;
internal=NIL => internal ← CoreOps.UnionWire[public, onlyInternal];
onlyInternal=NIL => {};
ENDCASE  => MakeError["Both internal and onlyInternal are specified", name];
CheckWellFormed["Public is malformed", public, name];
CheckWellFormed["Internal is malformed", internal, name];
FOR instList: CellInstances ← instances, instList.rest UNTIL instList=NIL DO
CreateActual: PROC [public: Wire] RETURNS [actual: Wire] = {
searches in internal for a wire of the same name as the one passed in argument
FindByName: PROC [wire: Wire] RETURNS [actual: Wire] = {
actualName: ROPE ← CoreOps.GetShortWireName[wire];
actual ← FindWire[internal, wire];
IF actual#NIL THEN RETURN;
IF actualName#NIL THEN actual ← FindWire[internal, actualName];
IF actual#NIL THEN RETURN;
IF wire.size=0 THEN ActualError[];
actual ← wire;
FOR i: NAT IN [0 .. wire.size) DO
actual[i] ← FindByName[actual[i]];
ENDLOOP;
};
ActualError: PROC = {
MakeError[Rope.Cat["Public '", CoreOps.GetFullWireName[instance.type.public, public], "' of sub cell type '", CoreOps.GetCellTypeName[instance.type], "' has bad actual"], name];
};
act: WR;
actual ← NARROW [HashTable.Fetch[table: visitTab, key: public].value];
IF actual#NIL THEN RETURN; -- already done this part of the DAG
act ← HashTable.Fetch[table: pasTable, key: public].value;
IF act#NIL THEN {
some binding was explicitly required
actual ← FindWire[internal, act];
IF actual=NIL THEN WITH act SELECT FROM
wire: Wire => actual ← FindByName[wire];
rope: ROPE => MakeError[Rope.Cat["Actual with name '", rope, "' not found in internal"], name];
ENDCASE => ERROR;
} ELSE {
no explicitly required binding for this public
FOR pNames: LIST OF ROPE ← CoreOps.GetFullWireNames[instance.type.public, public], pNames.rest UNTIL pNames=NIL DO
actual ← FindWire[internal, pNames.first];
IF actual#NIL THEN EXIT;
REPEAT FINISHED => {
IF public.size=0 THEN ActualError[];
actual ← CoreOps.CreateWires[public.size];
FOR i: NAT IN [0 .. public.size) DO
actual[i] ← CreateActual[public[i]];
ENDLOOP;
};
ENDLOOP;
};
IF NOT HashTable.Insert[table: visitTab, key: public, value: actual] THEN ERROR;
};
instance: CellInstance ← instList.first;
visitTab: HashTable.Table ← HashTable.Create[]; -- Wire to Wire
pasTable: HashTable.Table ← NARROW[CoreProperties.GetCellInstanceProp[from: instance, prop: instanceBindProp]];
instance.actual ← CreateActual[instance.type.public];
FOR i: NAT IN [0..instance.actual.size) DO
IF NOT CoreOps.RecursiveMember[candidate: instance.actual[i], wire: internal] THEN
internal ← CoreOps.UnionWire[internal, CoreOps.CreateWire[LIST[instance.actual[i]]]];
ENDLOOP;
CoreProperties.PutCellInstanceProp[on: instance, prop: instanceBindProp, value: NIL];
ENDLOOP;
cellType ← CoreClasses.CreateRecordCell[public: public, internal: internal, instances: instances, name: name, props: props];
};
Transistor: PUBLIC PROC [type: TransistorType ← nE, length: NAT ← 2, width: NAT ← 4, name: ROPENIL, props: Properties ← NIL] RETURNS [cellType: CellType] = {
cellType ← CoreClasses.CreateTransistor[
args: [type: type, length: length, width: width],
name: name, props: props
];
};
SequenceCell: PUBLIC PROC [baseCell: CellType, count: NAT, sequencePorts: WireSeq ← NIL, flatSequencePorts: WireSeq ← NIL, stitchPorts: LIST OF PANIL, name: ROPENIL, props: Properties ← NIL] RETURNS [cellType: CellType] = {
FindTopWire: PROC [wr: WR] RETURNS [index: NAT] = {
FOR index IN [0..baseCell.public.size) DO
WITH wr SELECT FROM
wrwire: Wire => IF wrwire=baseCell.public[index] THEN RETURN;
wrrope: ROPE => IF Rope.Equal[wrrope, CoreOps.GetShortWireName[baseCell.public[index]]] THEN RETURN;
text: REF TEXT => IF Rope.Equal[Rope.FromRefText[text], CoreOps.GetShortWireName[baseCell.public[index]]] THEN RETURN;
ENDCASE => ERROR;
REPEAT FINISHED => ERROR; -- no such wire
ENDLOOP;
};
FindPorts: PROC [ports: WireSeq] RETURNS [set: CoreClasses.SequenceSet] = {
IF ports#NIL THEN {
set ← NEW[CoreClasses.SequenceSetRec[ports.size]];
FOR i: INT IN [0..ports.size) DO
sequenceName: ROPE ← CoreOps.GetShortWireName[ports[i]];
FOR w: NAT IN [0..baseCell.public.size) DO
IF ports[i]=baseCell.public[w] OR (sequenceName#NIL AND Rope.Equal[sequenceName, CoreOps.GetShortWireName[ baseCell.public[w]]]) THEN {
set[i] ← w;
EXIT;
};
REPEAT FINISHED => ERROR;
ENDLOOP;
ENDLOOP;
};
};
stitches: CoreClasses.StitchSet ← NIL;
seqCell: CoreClasses.SequenceCellType ← NIL;
IF stitchPorts#NIL THEN {
stitchCount: NAT ← 0;
FOR sps: LIST OF PA ← stitchPorts, sps.rest UNTIL sps=NIL DO
stitchCount ← stitchCount + 1;
ENDLOOP;
stitches ← NEW[CoreClasses.StitchSetRec[stitchCount]];
stitchCount ← 0;
FOR sps: LIST OF PA ← stitchPorts, sps.rest UNTIL sps=NIL DO
stitches[stitchCount].this ← FindTopWire[sps.first.public];
stitches[stitchCount].that ← FindTopWire[sps.first.actual];
stitchCount ← stitchCount + 1;
ENDLOOP;
};
seqCell ← NEW [CoreClasses.SequenceCellTypeRec ← [
base: baseCell,
count: count,
sequence: FindPorts[sequencePorts],
flatSequence: FindPorts[flatSequencePorts],
stitch: stitches]];
cellType ← CoreClasses.CreateSequence[args: seqCell, name: name, props: props];
};
FindWire: PUBLIC PROC [root: WireSeq, wr: WR] RETURNS [found: Wire ← NIL] = {
WITH wr SELECT FROM
wrwire: Wire => IF CoreOps.RecursiveMember[candidate: wrwire, wire: root] THEN found ← wrwire;
wrrope: ROPE => found ← CoreOps.FindWire[root, wrrope];
text: REF TEXT => found ← CoreOps.FindWire[root, Rope.FromRefText[text]];
ENDCASE => ERROR;
};
END.