StructureFromCoreImpl:
CEDAR
PROGRAM
IMPORTS Asserting, CoreClasses, CoreFlat, CoreOps, CoreProperties, HashTable, IO, Rope, RopeHash, StructuralComparisonDataStructure
EXPORTS StructureFromCore
SHARES StructuralComparisonDataStructure =
BEGIN OPEN CC: CoreClasses, CO: CoreOps, CP: CoreProperties, CoreStructuralComparison, StructuralComparisonDataStructure;
implKey: ATOM = $StructureFromCoreImplInstance;
implVal: REF ROPE ← NEW [ROPE ← "New for this one"];
ColorerKey: ATOM = $CoreStructureColorer;
Colorer: TYPE = REF ColorerPrivate;
ColorerPrivate:
TYPE =
RECORD [
CellTypeColor: PROC [ct: Core.CellType] RETURNS [Color],
ColorPorts:
PROC [ct: Core.CellType,
SetColor:
PROC [Core.Wire, Color]]
Must set the color of each atom of the public wire.
];
wireColorKey:
ATOM =
CP.RegisterProperty[
$LichenStructureFromCoreImplWireColor,
CP.Props[[CP.propPrint, CP.PropDontPrint]]];
structureFromFlattenedCore:
ATOM =
CP.RegisterProperty[
$StructureFromFlattenedCore,
CP.Props[[CP.propPrint, CP.PropDontPrint]]];
structureFromUnflattenedCore:
ATOM =
CP.RegisterProperty[
$StructureFromUnflattenedCore,
CP.Props[[CP.propPrint, CP.PropDontPrint]]];
backHashKey: ATOM = $StructureFromCoreImplCellTypeToBackpointerHashtable;
structureToCore: ATOM = $StructureToCore;
emptyPath: CoreFlat.PackedPath = [];
GetGraph:
PUBLIC
PROC [cct: Core.CellType, internals, flatten:
BOOL]
RETURNS [sct: CellType] = {
raw: REF ANY;
colorer: Colorer ← NIL;
backHash: HashTable.Table;
flattenByAnotherName: BOOL = flatten;
structureFromCoreCellType: ATOM = IF flatten THEN structureFromFlattenedCore ELSE structureFromUnflattenedCore;
sct ← NIL;
DO
raw ← CP.GetCellClassProp[cct.class, ColorerKey];
IF raw #
NIL
THEN
WITH raw
SELECT
FROM
x: Colorer => colorer ← x;
ENDCASE;
raw ← CP.GetCellTypeProp[cct, structureFromCoreCellType];
IF raw #
NIL
THEN
WITH raw
SELECT
FROM
x: CellType => sct ← IF Asserting.FnVal[implKey, x.otherPublic] = implVal THEN x ELSE NIL;
ENDCASE => sct ← NIL;
IF sct # NIL THEN EXIT;
IF colorer # NIL THEN EXIT;
IF cct.class.recast = NIL THEN EXIT;
cct ← CO.Recast[cct];
ENDLOOP;
IF sct =
NIL
THEN {
seen: HashTable.Table = HashTable.Create[];
pi: PortIndex ← 0;
DefinePorts:
PROC [wire: Core.Wire]
RETURNS [subWires:
BOOL ←
TRUE, quit:
BOOL ←
FALSE]
--CO.EachWireProc-- = {
IF wire.size = 0
AND
NOT seen.Fetch[wire].found
THEN {
name: ROPE = UnionNames[CO.GetFullWireNames[cct.public, wire]];
sct.ports[pi] ← [
name: name,
color: GetWireColor[wire]
];
IF NOT seen.Insert[wire, $T] THEN ERROR;
pi ← pi + 1;
};
};
IF colorer = NIL THEN colorer ← defaultColorer;
sct ←
NEW [CellTypeRep ← [
name: GetCellTypeName[cct],
color: FilterColor[colorer.CellTypeColor[cct]],
ports: NEW [PortSeq[CO.WireBits[cct.public]]],
otherPublic: Asserting.AssertFn1[structureToCore, cct, Asserting.AssertFn1[implKey, implVal, NIL]]
]];
CP.PutCellTypeProp[cct, structureFromCoreCellType, sct];
colorer.ColorPorts[cct, SetWireColor];
[] ← CO.VisitWire[cct.public, DefinePorts];
IF pi # sct.ports.length THEN ERROR;
};
IF sct.internalsKnown OR NOT internals THEN RETURN;
sct.internalsKnown ← TRUE;
backHash ← HashTable.Create[hash: HashDescendant, equal: DescendantEqual];
sct.otherPrivate ← Asserting.AssertFn1[backHashKey, backHash, sct.otherPrivate];
{
Prefix:
PROC [path: CoreFlat.PackedPath]
RETURNS [prefix:
ROPE] = {
IF path.length=0 THEN RETURN [NIL];
prefix ← CoreFlat.PathRope[cct, path].Concat["/"];
};
BeforeExpand:
PROC [bindings: HashTable.Table, path: CoreFlat.PackedPath, cellType: Core.CellType] = {
DefineInternal:
PROC [key, value:
REF
ANY]
RETURNS [quit:
BOOL ←
FALSE]
--HashTable.EachPairAction-- = {
wb: CoreFlat.WireBind = NARROW[value];
IF wb.wire.size # 0 THEN RETURN;
{dw: DescendantWire = NEW [DescendantWirePrivate ← [wb.path, wb.wire]];
IF
NOT backHash.Fetch[dw].found
THEN {
iw: Core.Wire = wb.wire;
rct: CC.RecordCellType = NARROW[cellType.data];
name: ROPE = Prefix[dw.path].Concat[UnionNames[CO.GetFullWireNames[rct.internal, iw]]];
v: Vertex =
NEW [VertexRep ← [
name: name,
class: net,
other: Asserting.AssertFn1[structureToCore, dw, NIL]
]];
IF NOT backHash.Insert[dw, v] THEN ERROR;
AddPart[sct, v];
};
}};
[] ← bindings.Pairs[DefineInternal];
};
SeeInstance:
PROC [bindings: HashTable.Table, path: CoreFlat.PackedPath, instance:
CC.CellInstance]
RETURNS [flatten:
BOOL] = {
flatten ← flattenByAnotherName AND CO.ToBasic[instance.type].class = CC.recordCellClass;
IF flatten THEN RETURN;
{ci: CC.CellInstance = instance;
di: DescendantCellInstance = NEW [DescendantCellInstancePrivate ← [path, ci]];
name: ROPE = Prefix[path].Concat[CC.GetCellInstanceName[ci]];
type: CellType = GetGraph[ci.type, FALSE, FALSE];
v: Vertex =
NEW [VertexRep ← [
name: name,
class: cell,
type: type,
other: Asserting.AssertFn1[structureToCore, di, NIL]
]];
pi: PortIndex ← 0;
seen: HashTable.Table = HashTable.Create[];
SeeBinding:
PROC [actualWire, publicWire: Core.Wire]
RETURNS [subWires:
BOOL ←
TRUE, quit:
BOOL ←
FALSE]
--CO.EachWirePairProc-- = {
pw: Core.Wire = publicWire;
IF pw.size = 0
AND
NOT seen.Fetch[pw].found
THEN {
awb: CoreFlat.WireBind = NARROW[bindings.Fetch[actualWire].value];
adw: DescendantWire = NEW [DescendantWirePrivate ← [awb.path, awb.wire]];
nv: Vertex = GetStructure[sct, adw];
IF nv = NIL THEN ERROR;
Link[v, nv, type.ports[pi].color];
IF NOT seen.Insert[pw, $T] THEN ERROR;
pi ← pi + 1;
};
};
IF NOT backHash.Insert[di, v] THEN ERROR;
AddPart[sct, v];
[] ← CO.VisitBinding[ci.actual, ci.type.public, SeeBinding];
IF pi # type.ports.length THEN ERROR;
}};
CoreFlat.EnumerateLeaves[cct, SeeInstance, NIL, BeforeExpand, NIL]};
{pi: PortIndex ← 0;
seen: HashTable.Table = HashTable.Create[];
SetPortNet:
PROC [wire: Core.Wire]
RETURNS [subWires:
BOOL ←
TRUE, quit:
BOOL ←
FALSE]
--CO.EachWireProc-- = {
IF wire.size = 0
AND
NOT seen.Fetch[wire].found
THEN {
dw: DescendantWire = NEW [DescendantWirePrivate ← [emptyPath, wire]];
nv: Vertex = GetStructure[sct, dw];
IF nv = NIL THEN ERROR;
sct.ports[pi].net ← nv;
IF NOT seen.Insert[wire, $T] THEN ERROR;
pi ← pi + 1;
};
};
[] ← CO.VisitWire[cct.public, SetPortNet];
IF pi # sct.ports.length THEN ERROR;
};
AddMirror[sct];
sct ← sct;
};
ForgetGraph:
PUBLIC
PROC [sct: CellType] = {
cct: Core.CellType = GetCellType[sct];
EnumerateParts[sct, DestroyVertex, TRUE];
sct^ ← [];
CP.PutCellTypeProp[cct, structureFromFlattenedCore, NIL];
CP.PutCellTypeProp[cct, structureFromUnflattenedCore, NIL];
};
AddPart:
PROC [sct: CellType, v: Vertex] = {
v.nextPart ← sct.firstPart;
sct.firstPart ← v;
sct.size ← sct.size + 1};
Link:
PROC [cv, nv: Vertex, edgeColor: Color] = {
e: Edge =
NEW [EdgeRep ← [
sides: [
net: [v: nv, next: NIL, prev: nv.lastEdge],
cell: [v: cv, next: NIL, prev: cv.lastEdge]],
color: edgeColor]];
IF nv.lastEdge = NIL THEN nv.firstEdge ← e ELSE nv.lastEdge.sides[net].next ← e;
IF cv.lastEdge = NIL THEN cv.firstEdge ← e ELSE cv.lastEdge.sides[cell].next ← e;
nv.lastEdge ← cv.lastEdge ← e;
};
DestroyVertex:
PROC [v: Vertex] = {
WHILE v.firstEdge #
NIL
DO
e: Edge ← v.firstEdge;
v.firstEdge ← e.sides[v.class].next;
e.sides[v.class] ← [NIL, NIL, NIL];
ENDLOOP;
v^ ← [class: v.class];
};
AddMirror:
PROC [sct: CellType] = {
v: Vertex =
NEW [VertexRep ← [
name: " The Outside World! ",
class: cell,
type: sct,
isMirror: TRUE
]];
sct.mirror ← v;
FOR pi: PortIndex
IN [0 .. sct.ports.length)
DO
Link[v, sct.ports[pi].net, sct.ports[pi].color];
ENDLOOP;
};
SetWireColor:
PROC [wire: Core.Wire, color: Color] = {
CP.PutWireProp[wire, wireColorKey, NEW [Color ← color]];
};
GetWireColor:
PROC [wire: Core.Wire]
RETURNS [color: Color] = {
rc: REF Color = NARROW[CP.GetWireProp[wire, wireColorKey]];
color ← rc^;
};
GetCellType:
PUBLIC
PROC [sct: CellType]
RETURNS [cct: Core.CellType] = {
cct ← NARROW[Asserting.FnVal[structureToCore, sct.otherPublic]];
};
GetStructure:
PUBLIC
PROC [sct: CellType, core: Descendant]
RETURNS [v: Vertex] = {
backHash: HashTable.Table = NARROW[Asserting.FnVal[backHashKey, sct.otherPrivate]];
v ← NARROW[backHash.Fetch[core].value];
};
GetCore:
PUBLIC
PROC [v: Vertex]
RETURNS [core: Descendant] = {
core ← Asserting.FnVal[structureToCore, v.other];
};
HashDescendant:
PROC [ra:
REF
ANY]
RETURNS [hash:
CARDINAL] = {
org: Descendant = ra;
hash ←
WITH org
SELECT
FROM
x: DescendantWire => x.path.PathHash[] + RefHash[x.wire],
x: DescendantCellInstance => x.path.PathHash[] + RefHash[x.instance],
ENDCASE => ERROR;
};
DescendantEqual:
PROC [r1, r2:
REF
ANY]
RETURNS [equal:
BOOL] = {
o1: Descendant = r1;
o2: Descendant = r2;
equal ←
WITH o1
SELECT
FROM
x: DescendantWire =>
WITH o2
SELECT
FROM
y: DescendantWire => x.path.PathEqual[y.path] AND x.wire = y.wire,
ENDCASE => FALSE,
x: DescendantCellInstance =>
WITH o2
SELECT
FROM
y: DescendantCellInstance => x.path.PathEqual[y.path] AND x.instance = y.instance,
ENDCASE => FALSE,
ENDCASE => ERROR;
};
RefHash:
PROC [ra:
REF
ANY]
RETURNS [hash:
CARDINAL] =
INLINE {
ln: Basics.LongNumber ← [lc[LOOPHOLE[ra]]];
hash ← ln.lo + ln.hi;
};
defaultColorer: Colorer ← NEW [ColorerPrivate ← [DefaultCellTypeColor, DefaultColorPorts]];
DefaultCellTypeColor:
PROC [ct: Core.CellType]
RETURNS [color: Color] = {
name: ROPE ← CO.GetCellTypeName[ct];
color ← RopeHash.FromRope[name];
};
DefaultColorPorts:
PROC [ct: Core.CellType,
SetColor:
PROC [Core.Wire, Color]] = {
ColorPort:
PROC [wire: Core.Wire]
RETURNS [subWires:
BOOL ←
TRUE, quit:
BOOL ←
FALSE]
--CO.EachWireProc-- = {
IF wire.size = 0
THEN {
name: ROPE = UnionNames[CO.GetFullWireNames[ct.public, wire]];
SetColor[wire, RopeHash.FromRope[name]];
};
};
[] ← CO.VisitWire[ct.public, ColorPort];
};
transistorColorer: Colorer ← NEW [ColorerPrivate ← [TransistorCellTypeColor, ColorTransistorPorts]];
TransistorCellTypeColor:
PROC [ct: Core.CellType]
RETURNS [color: Color] = {
td: CC.Transistor = NARROW[ct.data];
color ←
SELECT td.type
FROM
nE => 36,
pE => 24,
nD => 33,
ENDCASE => ERROR;
};
ColorTransistorPorts:
PROC [ct: Core.CellType,
SetColor:
PROC [Core.Wire, Color]] = {
ColorPort:
PROC [wire: Core.Wire]
RETURNS [subWires:
BOOL ←
TRUE, quit:
BOOL ←
FALSE]
--CO.EachWireProc-- = {
IF wire.size = 0
THEN {
name: ROPE = CO.GetShortWireName[wire];
SetColor[wire,
SELECT
TRUE
FROM
name.Substr[len: 2].Equal["ch", FALSE] => channelColor,
name.Equal["gate", FALSE] => gateColor,
ENDCASE => ERROR
];
};
};
[] ← CO.VisitWire[ct.public, ColorPort];
};
gateColor: Color ← 47;
channelColor: Color ← 834;
UnionNames:
PROC [names:
LIST
OF
ROPE]
RETURNS [unioned:
ROPE] = {
unioned ← NIL;
FOR names ← names, names.rest
WHILE names #
NIL
DO
unioned ← IF unioned=NIL THEN names.first ELSE Rope.Cat[unioned, "|", names.first];
ENDLOOP;
unioned ← unioned;
};
GetCellTypeName:
PROC [cct: Core.CellType]
RETURNS [name:
ROPE] = {
IF (name ← CO.GetCellTypeName[cct]).Length[] # 0 THEN RETURN;
cct ← CO.ToBasic[cct];
IF (name ← CO.GetCellTypeName[cct]).Length[] # 0 THEN RETURN;
WITH cct.data
SELECT
FROM
t:
CC.Transistor => {
name ←
IO.PutFR[
"%g(%g/%g)",
[rope[
SELECT t.type
FROM
nE => "nE",
pE => "pE",
nD => "nD",
ENDCASE => ERROR]],
[integer[t.length]],
[integer[t.width]]];
[] ← CO.SetCellTypeName[cct, name];
};
ENDCASE => name ← IO.PutFR["%xB^", [cardinal[LOOPHOLE[cct]]]];
};
Start:
PROC = {
CP.PutCellClassProp[CC.transistorCellClass, ColorerKey, transistorColorer];
};
Start[];
END.