CoreClassesImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Barth, March 23, 1987 1:04:31 pm PST
Spreitzer, January 10, 1986 4:08:14 pm PST
Bertrand Serlet October 19, 1986 2:43:33 pm PDT
Pradeep Sindhu April 30, 1986 9:35:06 pm PDT
Mike Spreitzer November 18, 1986 2:31:35 pm PST
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:
ROPE ←
NIL, props: Properties ←
NIL, giveNames:
BOOL ←
FALSE]
RETURNS [recordCell: CellType] = {
internals: HashTable.Table ← HashTable.Create[internal.size];
AddInInternals: CoreOps.EachWireProc = {[] ← HashTable.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 ~HashTable.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 ~HashTable.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: HashTable.Table, key:
REF]
RETURNS [value:
REF] = {
value ← HashTable.Fetch[table, key].value;
IF value=$None THEN value ← NIL;
};
Store:
PROC [table: HashTable.Table, key:
REF, value:
REF] = {
[] ← HashTable.Store[table, key, IF HashTable.Fetch[table, key].value=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 ← HashTable.Fetch[actualPossibleNames, actualWire].value;
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: HashTable.Table ← HashTable.Create[]; -- association actual -> possible name for the actual. $None indicates at least two different names.
existingNames: HashTable.Table ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.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:
ROPE ←
NIL, 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 HashTable), adds in table xToZ the pairs found by enumerating xToY and following in the yToZ table.
Compose:
PROC [xToY, yToZ, xToZ: HashTable.Table]
RETURNS [ok:
BOOL ←
TRUE, overWritten:
BOOL ←
FALSE] = {
EachX: HashTable.EachPairAction = {
found: BOOL;
z: HashTable.Value; [found, z] ← HashTable.Fetch[yToZ, value];
IF NOT found THEN {ok ← FALSE; quit ← TRUE; RETURN};
overWritten ← overWritten OR NOT HashTable.Store[xToZ, key, z];
};
ok ← NOT HashTable.Pairs[xToY, EachX];
};
CreatePermutedRecordCell:
PUBLIC
PROC [iconPublic: WireSeq, schCell: CellType, table: HashTable.Table, name:
ROPE ←
NIL, 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: HashTable.Table ← HashTable.Create[];
BEGIN
-- fill public and initialize schPublicsToRecordPublics
RegisterPublicMapping: CoreOps.EachWirePairProc = {
[] ← HashTable.Store[iconToRecord, actualWire, publicWire];
};
iconToRecord: HashTable.Table ← HashTable.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 [HashTable.Fetch[schPublicsToRecordPublics, schPublic].value];
IF actual#NIL THEN RETURN;
actual ← CoreOps.CreateWires[size: schPublic.size];
[] ← HashTable.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"];
PrintTransistor: CoreOps.PrintClassProc = {
tran: Transistor ← NARROW [data];
IO.PutF[out, "\n\ntype: %g, length: %g, width: %g", IO.rope[transistorTypeNames[tran.type]], IO.int[tran.length], IO.int[tran.width]];
};
CreateTransistor:
PUBLIC
PROC [args: TransistorRec, name:
ROPE ←
NIL, props: Properties ←
NIL]
RETURNS [cellType: CellType] = {
tranNames: ARRAY TransistorType OF ROPE ← ["nE", "pE", "nD"];
tranPublic: Wire ← CoreOps.CreateWire[
LIST[
CoreOps.CreateWire[name: "gate"],
CoreOps.CreateWire[name: "ch1"],
CoreOps.CreateWire[name: "ch2"]
]];
cellType ← CoreOps.CreateCellType[
class: transistorCellClass,
public: tranPublic,
data: NEW [TransistorRec ← args],
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] ← public^];
cellTypeName: ROPE ← CoreOps.GetCellTypeName[seqCell.base];
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:
ROPE ←
NIL, 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];
};