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
Wires
WireList:
PUBLIC
PROC [wrs:
LIST
OF
WR ←
NIL, name:
ROPE ←
NIL, 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:
WR ←
NIL, name:
ROPE ←
NIL, 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:
ROPE ←
NIL, 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:
ROPE ←
NIL, 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:
ROPE ←
NIL, 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:
ROPE ←
NIL, props: Properties ←
NIL]
RETURNS [CellInstance] = {
revpas: LIST OF PA ← NIL;
FOR pas:
LIST
OF
PA ←
LIST [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
PA ←
NIL, name:
ROPE ←
NIL, 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:
WR ←
WITH pa.public
SELECT
FROM
wire: Wire => wire,
rope: ROPE => rope,
text: REF TEXT => Rope.FromRefText[text],
ENDCASE => ERROR;
actual:
WR ←
WITH 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:
ROPE ←
NIL, 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:
ROPE ←
NIL, 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
PA ←
NIL, name:
ROPE ←
NIL, 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;
};