CoreClassesImpl.mesa
Copyright Ó 1985, 1987 by Xerox Corporation. All rights reserved.
Barth, April 16, 1987 4:22:27 pm PDT
Spreitzer, January 10, 1986 4:08:14 pm PST
Bertrand Serlet April 6, 1987 3:05:57 pm PDT
Pradeep Sindhu April 30, 1986 9:35:06 pm PDT
Mike Spreitzer February 27, 1987 3:44:24 pm PST
Christian Le Cocq April 28, 1987 2:39:45 pm PDT
DIRECTORY Core, CoreClasses, CoreOps, CoreProperties, GList, IO, RefTab, RefTabExtras, Rope;
CoreClassesImpl: CEDAR PROGRAM
IMPORTS CoreOps, CoreProperties, GList, IO, RefTab, RefTabExtras, Rope
EXPORTS CoreClasses =
BEGIN OPEN Core, CoreClasses;
Record
recordCellClass: PUBLIC CellClass ← CoreOps.SetClassPrintProc[NEW [CellClassRec ← [name: "Record", layersProps: FALSE]], PropRecordPrint];
PropRecordPrint: CoreOps.PrintClassProc = {
recordCellType: RecordCellType ← NARROW [data];
CoreOps.PrintIndent[indent, out];
IO.PutRope[out, "Internal wire:"];
CoreOps.PrintWire[recordCellType.internal, out, indent, level];
CoreOps.PrintIndent[indent, out];
IO.PutF[out, "%g instances", IO.int[recordCellType.size]];
FOR i: NAT IN [0 .. recordCellType.size) DO
instance: CellInstance = recordCellType.instances[i];
EachWirePair: CoreOps.EachWirePairProc = {
publicName: ROPE = CoreOps.GetFullWireName[instance.type.public, publicWire];
actualName: ROPE = CoreOps.GetFullWireName[recordCellType.internal, actualWire];
subWires ← CoreOps.GetShortWireName[publicWire]=NIL AND publicWire.size>0;
IF NOT subWires THEN IF Rope.Match["[*]", actualName]
THEN out.PutF[" %g: %g(%g^);", IO.rope[publicName], IO.rope[actualName], IO.int[LOOPHOLE[actualWire]]]
ELSE out.PutF[" %g: %g;", IO.rope[publicName], IO.rope[actualName]];
};
CoreOps.PrintIndent[indent, out];
IO.PutF[out, "CellInstance %g: %g", [rope[GetCellInstanceName[instance]]], [rope[CoreOps.GetCellTypeName[instance.type]]]];
CoreOps.PrintIndent[indent, out];
IO.PutRope[out, " Actual wire: "];
IF NOT CoreOps.Conform[instance.actual, instance.type.public] THEN out.PutF["\n*** Actual and Public do not conform\n"];
FOR j: NAT IN [0 .. instance.type.public.size) DO
[] ← CoreOps.VisitBinding[instance.actual[j], instance.type.public[j], EachWirePair];
ENDLOOP;
CoreProperties.PrintProperties[props: instance.properties, out: out, indent: 1, level: level];
ENDLOOP;
};
givenNameProp: ATOM ← CoreProperties.RegisterProperty[$GivenName, CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]];
CreateRecordCell: PUBLIC PROC [public: WireSeq, internal: WireSeq, instances: LIST OF CellInstance, name: ROPENIL, props: Properties ← NIL, giveNames: BOOLFALSE] RETURNS [recordCell: CellType] = {
internals: RefTab.Ref ← RefTab.Create[internal.size];
AddInInternals: CoreOps.EachWireProc = {[] ← RefTab.Store[internals, wire, wire]};
data: RecordCellType;
size: NAT ← GList.Length[instances];
data ← NEW [RecordCellTypeRec[size]];
size ← 0;
FOR i: NAT IN [0 .. internal.size) DO
[] ← CoreOps.VisitWire[internal[i], AddInInternals];
ENDLOOP;
FOR i: NAT IN [0 .. public.size) DO
IF ~RefTab.Fetch[internals, public[i]].found THEN ERROR; -- public public[i] is not part of internal
ENDLOOP;
FOR list: LIST OF CellInstance ← instances, list.rest WHILE list#NIL DO
data[size] ← list.first; size ← size+1;
IF NOT CoreOps.Conform[list.first.actual, list.first.type.public] THEN ERROR;
FOR i: NAT IN [0 .. list.first.actual.size) DO
IF ~RefTab.Fetch[internals, list.first.actual[i]].found THEN ERROR; -- actual list.first.actual[i] is not part of internal
ENDLOOP;
ENDLOOP;
data.internal ← internal;
IF giveNames THEN {
Fetch: PROC [table: RefTab.Ref, key: REF] RETURNS [value: REF] = {
value ← RefTab.Fetch[table, key].val;
IF value=$None THEN value ← NIL;
};
Store: PROC [table: RefTab.Ref, key: REF, value: REF] = {
[] ← RefTab.Store[table, key, IF RefTab.Fetch[table, key].val=NIL THEN value ELSE $None];
};
FindPossibleName: CoreOps.EachWirePairProc = {
value: REF;
name: ROPE ← CoreOps.GetShortWireName[publicWire];
IF CoreOps.GetShortWireName[actualWire]#NIL THEN RETURN;
IF name=NIL THEN RETURN;
value ← RefTab.Fetch[actualPossibleNames, actualWire].val;
IF value=$None THEN RETURN;
IF Rope.Equal[NARROW [value], name] THEN RETURN;
Store[actualPossibleNames, actualWire, name];
};
AddInExistingNames: CoreOps.EachWireProc = {
name: ROPE ← CoreOps.GetShortWireName[wire];
IF name=NIL THEN {
might be an actual
value: REF ← Fetch[actualPossibleNames, wire];
IF value=NIL THEN RETURN;
Store[existingNames, value, wire];
} ELSE Store[existingNames, name, wire];
};
AddName: CoreOps.EachWireProc = {
name: ROPE ← CoreOps.GetShortWireName[wire];
value: REF;
IF name#NIL THEN RETURN [subWires: FALSE];
value ← Fetch[actualPossibleNames, wire];
IF value=NIL OR Fetch[existingNames, value]#wire THEN RETURN;
CoreProperties.PutWireProp[wire, $GivenName, $GivenName];
[] ← CoreOps.SetShortWireName[wire, NARROW [value]];
};
actualPossibleNames: RefTab.Ref ← RefTab.Create[]; -- association actual -> possible name for the actual. $None indicates at least two different names.
existingNames: RefTab.Ref ← RefTab.Create[equal: RefTabExtras.EqualRope, hash: RefTabExtras.HashRope]; -- association name -> wire that will get that name. $None indicates a conflict
First pass visiting all bindings
FOR i: NAT IN [0 .. data.size) DO
[] ← CoreOps.VisitBinding[data[i].actual, data[i].type.public, FindPossibleName];
ENDLOOP;
Second Pass finding all short names to find conflicts
[] ← CoreOps.VisitWire[internal, AddInExistingNames];
Third pass affecting the names when appropriate
[] ← CoreOps.VisitWire[internal, AddName];
};
CoreOps.FlushNameCaches[internal];
recordCell ← CoreOps.CreateCellType[recordCellClass, public, data, name, props];
};
CreateInstance: PUBLIC PROC [actual: WireSeq, type: CellType, name: ROPENIL, props: Properties ← NIL] RETURNS [instance: CellInstance] = {
instance ← NEW [CellInstanceRec ← [actual: actual, type: type, properties: props]];
IF name#NIL THEN instance ← SetCellInstanceName[instance, name];
};
GetCellInstanceName: PUBLIC PROC [instance: CellInstance] RETURNS [name: ROPE] = {
name ← NARROW [CoreProperties.GetCellInstanceProp[instance, CoreOps.nameProp]];
};
SetCellInstanceName: PUBLIC PROC [instance: CellInstance, name: ROPE] RETURNS [sameInstance: CellInstance] = {
CoreProperties.PutCellInstanceProp[on: instance, prop: CoreOps.nameProp, value: name];
sameInstance ← instance;
};
CorrespondingActual: PUBLIC PROC [instance: CellInstance, public: Wire] RETURNS [actual: Wire ← NIL] = {
EachWirePair: CoreOps.EachWirePairProc = {
IF publicWire=public THEN {actual ← actualWire; quit ← TRUE};
};
[] ← CoreOps.VisitBinding[instance.actual, instance.type.public, EachWirePair];
};
This function (that could be in RefTab), adds in table xToZ the pairs found by enumerating xToY and following in the yToZ table.
Compose: PROC [xToY, yToZ, xToZ: RefTab.Ref] RETURNS [ok: BOOLTRUE, overWritten: BOOLFALSE] = {
EachX: RefTab.EachPairAction = {
found: BOOL;
z: RefTab.Val; [found, z] ← RefTab.Fetch[yToZ, val];
IF NOT found THEN {ok ← FALSE; quit ← TRUE; RETURN};
overWritten ← overWritten OR NOT RefTab.Store[xToZ, key, z];
};
ok ← NOT RefTab.Pairs[xToY, EachX];
};
CreatePermutedRecordCell: PUBLIC PROC [iconPublic: WireSeq, schCell: CellType, table: RefTab.Ref, name: ROPENIL, props: Properties ← NIL] RETURNS [recordCell: CellType] = {
AddInternal: PROC [wire: Wire] = {
IF NOT CoreOps.Member[internals, wire] THEN internals ← CONS [wire, internals];
};
internals: LIST OF Wire ← NIL;
public: Wire ← CoreOps.CopyWire[iconPublic];
actual: Wire;
schPublicsToRecordPublics: RefTab.Ref ← RefTab.Create[];
BEGIN -- fill public and initialize schPublicsToRecordPublics
RegisterPublicMapping: CoreOps.EachWirePairProc = {
[] ← RefTab.Store[iconToRecord, actualWire, publicWire];
};
iconToRecord: RefTab.Ref ← RefTab.Create[];
[] ← CoreOps.VisitBinding[iconPublic, public, RegisterPublicMapping];
FOR i: NAT IN [0 .. public.size) DO AddInternal[public[i]] ENDLOOP;
IF NOT Compose[table, iconToRecord, schPublicsToRecordPublics].ok THEN ERROR;
END;
BEGIN -- fill actual while filling schPublicsToRecordPublics
Map: PROC [schPublic: Wire] RETURNS [actual: Wire] = {
actual ← NARROW [RefTab.Fetch[schPublicsToRecordPublics, schPublic].val];
IF actual#NIL THEN RETURN;
actual ← CoreOps.CreateWires[size: schPublic.size];
[] ← RefTab.Store[schPublicsToRecordPublics, schPublic, actual];
FOR i: NAT IN [0 .. actual.size) DO actual[i] ← Map[schPublic[i]] ENDLOOP;
};
actual ← Map[schCell.public];
FOR i: NAT IN [0 .. actual.size) DO AddInternal[actual[i]] ENDLOOP;
END;
recordCell ← CreateRecordCell [public: public, internal: CoreOps.CreateWire[internals], instances: LIST [CreateInstance[actual, schCell]], name: name, props: props];
};
ReverseCellInstances: PUBLIC PROC [instances: CellInstances] RETURNS [rev: CellInstances ← NIL] = {
rev ← NARROW [GList.Reverse[instances]];
};
InstanceIndex: PUBLIC PROC [recordCell: CellType, instance: CellInstance] RETURNS [index: INT ← -1] = {
rct: RecordCellType ← NARROW [recordCell.data];
FOR i: NAT IN [0 .. rct.size) DO
IF rct[i]=instance THEN RETURN [i];
ENDLOOP;
};
Transistor
transistorCellClass: PUBLIC CellClass ← CoreOps.SetClassPrintProc[NEW [CellClassRec ← [name: "Transistor", layersProps: FALSE]], PrintTransistor];
transistorTypeNames: PUBLIC ARRAY TransistorType OF ROPE ← ["nE", "pE", "nD"];
transistorPortNames: PUBLIC ARRAY TransistorPort OF ROPE ← ["gate", "ch1", "ch2", "Vdd"];
lengthProp: PUBLIC ATOM ← $CoreTransistorLength;
widthProp: PUBLIC ATOM ← $CoreTransistorWidth;
PrintTransistor: CoreOps.PrintClassProc = {
tran: Transistor ← NARROW [data];
IO.PutF[out, "\n\ntype: %g", IO.rope[transistorTypeNames[tran.type]]];
};
CreateTransistor: PUBLIC PROC [type: TransistorType, length: INT ← -1, width: INT ← -1, name: ROPENIL, props: Properties ← NIL] RETURNS [cellType: CellType] = {
tranPublic: Wires ← NIL;
IF type=pE THEN tranPublic ← CONS[CoreOps.CreateWire[name: transistorPortNames[Vdd]], tranPublic];
tranPublic ← CONS[CoreOps.CreateWire[name: transistorPortNames[ch2]], tranPublic];
tranPublic ← CONS[CoreOps.CreateWire[name: transistorPortNames[ch1]], tranPublic];
tranPublic ← CONS[CoreOps.CreateWire[name: transistorPortNames[gate]], tranPublic];
cellType ← CoreOps.CreateCellType[
class: transistorCellClass,
public: CoreOps.CreateWire[tranPublic],
data: NEW [TransistorRec ← [type]],
name: name, props: props];
IF length#-1 THEN CoreProperties.PutCellTypeProp[cellType, lengthProp, NEW[INT ← length]];
IF width#-1 THEN CoreProperties.PutCellTypeProp[cellType, widthProp, NEW[INT ← width]];
};
Unspecified
unspecifiedCellClass: PUBLIC CellClass ← NEW [CellClassRec ← [name: "Unspecified", layersProps: FALSE]];
CreateUnspecified: PUBLIC PROC [public: WireSeq, name: ROPENIL, props: Properties ← NIL] RETURNS [cellType: CellType] = {
cellType ← CoreOps.CreateCellType[
class: unspecifiedCellClass,
public: public,
data: NIL,
name: name,
props: props];
};
Sequence
sequenceCellClass: PUBLIC CellClass ← CoreOps.SetClassPrintProc[NEW [CellClassRec ← [name: "Sequence", recast: RecastSequence, layersProps: FALSE]], PrintSequence];
PrintSequence: CoreOps.PrintClassProc = {
cell: SequenceCellType ← NARROW [data];
IO.PutF[out, "\n\nBase cell type: %g", IO.rope[CoreOps.GetCellTypeName[cell.base]]];
IO.PutF[out, ", count: %g", IO.int[cell.count]];
IO.PutRope[out, "\nsequence wires:"];
IF cell.sequence#NIL THEN FOR seq: NAT IN [0 .. cell.sequence.length) DO
IO.PutF[out, " %g", IO.rope[CoreOps.GetShortWireName[ cell.base.public[cell.sequence[seq]]]]];
ENDLOOP;
IO.PutRope[out, "\nflat sequence wires:"];
IF cell.flatSequence#NIL THEN FOR seq: NAT IN [0 .. cell.flatSequence.length) DO
IO.PutF[out, " %g", IO.rope[CoreOps.GetShortWireName[ cell.base.public[cell.flatSequence[seq]]]]];
ENDLOOP;
IO.PutRope[out, "\nstitch wires:"];
IF cell.stitch#NIL THEN FOR seq: NAT IN [0 .. cell.stitch.length) DO
IO.PutF[out, " [%g, &g]", IO.rope[CoreOps.GetShortWireName[ cell.base.public[cell.stitch[seq].this]]], IO.rope[CoreOps.GetShortWireName[ cell.base.public[cell.stitch[seq].that]]]];
ENDLOOP;
};
RecastSequence: RecastProc = {
seqCell: SequenceCellType ← NARROW[me.data];
public: Wire ← CoreOps.CopyWire[me.public];
newInternal: Wire ← NEW [WireRec[public.size+seqCell.count]];
instances: LIST OF CoreClasses.CellInstance ← NIL;
FOR w: NAT IN [0..public.size) DO
newInternal[w] ← public[w];
ENDLOOP;
FOR cell: NAT DECREASING IN [0..seqCell.count) DO
newWire: Wire ← NEW[WireRec[public.size]];
cellTypeName: ROPE ← CoreOps.GetCellTypeName[seqCell.base];
newWire.properties ← public.properties;
FOR i: NAT IN [0 .. public.size) DO newWire[i] ← public[i] ENDLOOP;
IF seqCell.sequence#NIL THEN FOR seqWire: NAT IN [0..seqCell.sequence.length) DO
seqElement: NAT ← seqCell.sequence[seqWire];
newWire[seqElement] ← newWire[seqElement][cell];
ENDLOOP;
IF seqCell.flatSequence#NIL THEN FOR seqWire: NAT IN [0..seqCell.flatSequence.length) DO
seqElement: NAT ← seqCell.flatSequence[seqWire];
size: NAT ← seqCell.base.public[seqElement].size;
actWire: Wire ← NEW[WireRec[size]];
FOR i: NAT IN [0..size) DO
actWire[i] ← newWire[seqElement][(size*cell)+i];
ENDLOOP;
newWire[seqElement] ← actWire;
ENDLOOP;
IF seqCell.stitch#NIL AND seqCell.count>1 AND cell<seqCell.count-1 THEN FOR seqWire: NAT IN [0..seqCell.stitch.length) DO
this: NAT ← seqCell.stitch[seqWire].this;
that: NAT ← seqCell.stitch[seqWire].that;
newWire[that] ← newInternal[public.size+cell+1][this] ← CoreOps.SetShortWireName[CoreOps.CopyWire[ seqCell.base.public[this]], NIL];
ENDLOOP;
instances ← CONS [CreateInstance[
actual: newWire,
type: seqCell.base,
name: IF cellTypeName=NIL THEN NIL ELSE IO.PutFR["%g%g", IO.rope[cellTypeName], IO.int[cell]]],
instances];
newInternal[public.size+cell] ← newWire;
ENDLOOP;
new ← CreateRecordCell[
public: public,
internal: newInternal,
instances: instances,
name: CoreOps.GetCellTypeName[me],
props: NIL];
};
CreateSequence: PUBLIC PROC [args: SequenceCellType, name: ROPENIL, props: Properties ← NIL] RETURNS [cellType: CellType] = {
public: Wire ← CoreOps.CopyWire[args.base.public];
IF args.sequence#NIL THEN FOR seq: NAT IN [0..args.sequence.length) DO
wire: Wire ← public[args.sequence[seq]];
newWire: Wire ← NEW[WireRec[args.count]];
FOR i: NAT IN [0 .. args.count) DO
newWire[i] ← CoreOps.SetShortWireName[CoreOps.CopyWire[wire], NIL];
ENDLOOP;
public[args.sequence[seq]] ← CoreOps.SetShortWireName[newWire, CoreOps.GetShortWireName[wire]];
ENDLOOP;
IF args.flatSequence#NIL THEN FOR seq: NAT IN [0..args.flatSequence.length) DO
wire: Wire ← public[args.flatSequence[seq]];
newSeqLength: NAT ← args.count * wire.size;
newSeq: Wire ← NEW[WireRec[newSeqLength]];
IF wire.size=0 THEN ERROR;
FOR i: NAT IN [0..newSeqLength) DO
newSeq[i] ← CoreOps.SetShortWireName[CoreOps.CopyWire[wire[0]], NIL];
ENDLOOP;
public[args.flatSequence[seq]] ← CoreOps.SetShortWireName[newSeq, CoreOps.GetShortWireName[wire]];
ENDLOOP;
cellType ← CoreOps.CreateCellType[
class: sequenceCellClass,
public: public,
data: args,
name: name,
props: props];
};
END.