StructureFromCoreImpl.Mesa
Barth, April 16, 1987 10:45:57 pm PDT
Last tweaked by Mike Spreitzer on May 10, 1989 10:45:49 am PDT
DIRECTORY Asserting, Atom, Basics, Core, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, CoreStructuralComparison, Histograms, IO, PWCLCoreFlatExtras, RefTab, Rope, RopeHash, StructuralComparisonDataStructure, StructuralComparisonOps, StructureFromCore;
StructureFromCoreImpl: CEDAR PROGRAM
IMPORTS Asserting, Atom, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, CoreStructuralComparison, Histograms, IO, RefTab, Rope, RopeHash, StructuralComparisonDataStructure, StructuralComparisonOps
EXPORTS StructureFromCore, CoreStructuralComparison
SHARES StructuralComparisonDataStructure
=
BEGIN OPEN CC: CoreClasses, CF: CoreFlat, CIO: CoreIO, CO: CoreOps, CP: CoreProperties, StructuralComparisonOps, CoreStructuralComparison, StructuralComparisonDataStructure;
ViewStats: TYPE ~ REF ViewStatsPrivate;
ViewStatsPrivate: PUBLIC TYPE ~ StructuralComparisonDataStructure.ViewStatsPrivate;
ATOMList: TYPE = LIST OF ATOM;
LosingConstraint: SIGNAL ~ CODE;
DroppedConnection: PUBLIC SIGNAL [subroot: Core.CellType, public, actual: DescendantWire] ~ CODE;
BogusMerge: PUBLIC SIGNAL [subroot: Core.CellType, w1, w2: DescendantWire, from: DescendantCellInstance] ~ CODE;
implKey: ATOM = $StructureFromCoreImplInstance;
implVal: REF ROPENEW [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.
];
TransCountsKey: ATOM = CP.RegisterProperty[
$StructureFromCoreImplTransistorCounts];
wireRepProp: ATOM = CIO.RegisterProperty[
CP.RegisterProperty[
$LichenStructureFromCoreImplWireReplacement,
CP.Props[[CP.propPrint, CP.PropDontPrint]]],
DontWrite,
DontRead];
wireColorKey: ATOM = CP.RegisterProperty[
$LichenStructureFromCoreImplWireColor,
CP.Props[[CP.propPrint, CP.PropDontPrint]]];
structureFromCorePrefix: ROPE = "StructureFromCore with SubtreeSpec=";
structureFromCorePrefixLength: INT = structureFromCorePrefix.Length[];
structureFromCoreFormat: ROPE = structureFromCorePrefix.Concat["%g(%g), MergeSpec=%g(%g), and internals=%g"];
SpecAndKeyList: TYPE = LIST OF SpecAndKey;
SpecAndKey: TYPE = RECORD [sts: SubtreeSpec, ms: MergeSpec, internals: BOOL, key: ATOM];
stsToKey: SpecAndKeyList ← NIL;
backHashKey: ATOM = $StructureFromCoreImplCellTypeToBackpointerHashtable;
structureToCore: ATOM = $StructureToCore;
depub: ATOM ~ $StructureFromCoreImplDepublicize;
debug: BOOLTRUE;
GetKeyForSpecs: PROC [sts: SubtreeSpec, ms: MergeSpec, internals: BOOL] RETURNS [key: ATOM] = {
FOR stks: SpecAndKeyList ← stsToKey, stks.rest WHILE stks # NIL DO
IF stks.first.sts=sts AND stks.first.ms=ms AND stks.first.internals=internals THEN RETURN [stks.first.key];
ENDLOOP;
key ← CP.RegisterProperty[
Atom.MakeAtom[IO.PutFR[
structureFromCoreFormat,
[cardinal[LOOPHOLE[sts, CARDINAL]]],
[refAny[NEW [SubtreeSpec ← sts]]],
[cardinal[LOOPHOLE[ms, CARDINAL]]],
[refAny[NEW [MergeSpec ← ms]]],
[boolean[internals]]
]],
CP.Props[[CP.propPrint, CP.PropDontPrint]]];
stsToKey ← CONS[[sts, ms, internals, key], stsToKey];
RETURN};
GetGraph: PUBLIC PROC [ttols: TransistorTolerances ← NIL, cct: Core.CellType, internals: BOOL, specData: REF ANY, sts: SubtreeSpec, ms: MergeSpec, SurveyPart: PROC [v: Vertex, core: REF ANY --UNION [Wire, CellInstance]--] ← NIL, vs: ViewStats ← NIL] RETURNS [sct: CellType] = {
original: Core.CellType = cct;
PushTimer[$getGraph];
{ENABLE UNWIND => PopTimer[$getGraph];
colorer: Colorer = WITH CP.InheritCellTypeProp[cct, ColorerKey] SELECT FROM
x: Colorer => x,
ENDCASE => defaultColorer;
structureFromCoreCellType: ATOM = GetKeyForSpecs[sts, ms, internals];
backHash: RefTab.Ref;
tc: TransCounts ← NARROW[CP.InheritCellTypeProp[cct, TransCountsKey]];
uncounted: BOOL ← tc=NIL;
IF internals THEN {
IF cct.class = CC.transistorCellClass THEN ERROR;
IF tc=NIL THEN tc ← NEW [TransCountsPrivate ← []] ELSE tc^ ← []}
ELSE IF tc=NIL THEN {
IF cct.class = CC.transistorCellClass THEN ERROR;
tc ← NEW [TransCountsPrivate ← []]};
WITH CP.GetCellTypeProp[cct, structureFromCoreCellType] SELECT FROM
x: CellType => sct ← IF Asserting.FnVal[implKey, x.otherPublic] = implVal THEN x ELSE NIL;
ENDCASE => sct ← NIL;
IF sct = NIL THEN {
sct ← NEW [CellTypeRep ← [
name: GetCellTypeName[original],
color: FilterColor[colorer.CellTypeColor[original]],
ports: NEW [PortSeq[CO.WireSeqBits[original.public]]],
transCounts: tc,
otherPublic: Asserting.AssertFn1[structureToCore, original, Asserting.AssertFn1[implKey, implVal, NIL]]
]];
sct.ports.length ← 0;
CP.PutCellTypeProp[original, structureFromCoreCellType, sct];
colorer.ColorPorts[original, SetWireColor];
IF NOT internals THEN {
wireToPort: RefTab.Ref = RefTab.Create[];
pi: PortIndex ← 0;
DefinePorts: PROC [wire: Core.Wire] = {
IF NOT wireToPort.Fetch[wire].found THEN {
name: ROPE = UnionNames[CO.GetFullWireNames[original.public, wire]];
sct.ports[pi] ← [
name: name,
color: GetWireColor[wire, noColor]
];
IF sct.ports[pi] = [] THEN ERROR;
IF NOT wireToPort.Insert[wire, NEW [PortIndex ← pi]] THEN ERROR;
pi ← pi + 1;
};
};
EnumerateInstances: PROC [Consume: PROC [ci: CoreClasses.CellInstance] RETURNS [stop: BOOLFALSE]] ~ {};
IdentifyActual: PROC [ci: CoreClasses.CellInstance, actual: Core.Wire, describe: BOOLFALSE] RETURNS [ActualID] ~ {ERROR};
mergingDone: BOOLFALSE;
Consume: PROC [ds: Element] --MergeConsumer-- ~ {
fw1: CF.FlatWire ~ NARROW[ds.first];
i1: PortIndex ← NARROW[wireToPort.Fetch[fw1.wire].val, REF PortIndex]^;
IF fw1.flatCell.path.length#0 OR sct.ports[i1]=[] THEN ERROR;
FOR ds ← ds.rest, ds.rest WHILE ds#NIL DO
fw2: CF.FlatWire ~ NARROW[ds.first];
i2: PortIndex ← NARROW[wireToPort.Fetch[fw2.wire].val, REF PortIndex]^;
IF fw2.flatCell.path.length#0 OR i1=i2 OR sct.ports[i2]=[] THEN ERROR;
IF i2<i1 THEN {it: PortIndex ← i1; i1 ← i2; i2 ← it};
sct.ports[i1] ← [
name: sct.ports[i1].name.Cat["|", sct.ports[i2].name],
color: sct.ports[i1].color + sct.ports[i2].color];
sct.ports[i2] ← [];
PostMerge[original, fw1.wire, fw2.wire];
mergingDone ← TRUE;
ENDLOOP;
RETURN};
FixPass: PROC ~ {
goodPI: PortIndex ← 0;
FOR pi: PortIndex IN [0 .. sct.ports.length) DO
IF sct.ports[pi]#[] THEN {
IF goodPI#pi THEN sct.ports[goodPI] ← sct.ports[pi];
goodPI ← goodPI+1};
ENDLOOP;
FOR badPI: PortIndex IN [goodPI .. sct.ports.length) DO
sct.ports[badPI] ← [];
ENDLOOP;
sct.ports.length ← goodPI;
RETURN};
CO.VisitRootAtomics[original.public, DefinePorts];
IF pi # sct.ports.size THEN ERROR;
sct.ports.length ← pi;
ms[specData, original, FALSE, EnumerateInstances, IdentifyActual, Consume, NIL--not implemented because not needed (right?)--];
IF mergingDone THEN FixPass[];
};
}
ELSE {
IF GetCellType[sct] # original THEN ERROR;
sct.transCounts ← tc};
IF sct.internalsKnown OR NOT internals THEN {PopTimer[$getGraph]; RETURN};
sct.internalsKnown ← TRUE;
{ENABLE UNWIND => ForgetGraph[sct];
backHash ← RefTab.Create[hash: HashDescendant, equal: DescendantEqual];
sct.otherPrivate ← Asserting.AssertFn1[backHashKey, backHash, sct.otherPrivate];
{
IntroduceWires: PROC [flatCell: CF.FlatCellTypeRec, wireRoot: CF.WireRoot, root: Core.Wire, bindings: CF.Bindings] = {
DefineInternal: PROC [wire: Core.Wire] = {
IF bindings = NIL OR NOT bindings.Fetch[wire].found THEN {
dw: CF.FlatWire = NEW [CF.FlatWireRec ← [flatCell: flatCell, wireRoot: wireRoot, wire: wire]];
IF NOT backHash.Fetch[dw].found THEN {
name: ROPE ~ CF.WirePathRope[root: original, wire: dw^];
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];
IF SurveyPart # NIL THEN SurveyPart[v, wire];
};
};
};
CO.VisitRootAtomics[root, DefineInternal];
};
Flatten: PROC [cell: Core.CellType, target: CF.FlatCellTypeRec ← CF.allFlatCells, flatCell: CF.FlatCellTypeRec ← [], instance: CF.CellInstance ← NIL, index: NATLAST[NAT], parent: Core.CellType ← NIL, flatParent: CF.FlatCellTypeRec ← [], data: REF ANYNIL, bindings: CF.Bindings ← NIL] --CF.BoundFlatCellProc-- = {
path: DescendantCellInstancePrivate = flatCell.path;
ans: SubtreeAns ~ IF path.length > 0 THEN sts[specData, instance, path, ttols] ELSE [NIL];
flatten: BOOL = ans.leafType = NIL;
rct: CC.RecordCellType ~ IF cell.class = CC.recordCellClass THEN NARROW[cell.data] ELSE NIL;
IF flatten THEN {
EnumerateInstances: PROC [Consume: PROC [ci: CC.CellInstance] RETURNS [stop: BOOLFALSE]] = {
IF cell.class = CC.recordCellClass THEN FOR i: NAT IN [0 .. rct.size) DO
IF Consume[rct[i]] THEN EXIT;
ENDLOOP;
};
IdentifyActual: PROC [ci: CoreClasses.CellInstance, actual: Core.Wire, describe: BOOLFALSE] RETURNS [ActualID] = {
dw: DescendantWire ~ NARROW[bindings.Fetch[actual].val];
IF dw # NIL THEN RETURN [[dw, IF describe THEN CF.WirePathRope[original, dw^] ELSE NIL]];
RETURN [[actual, IF describe THEN CF.WirePathRope[original, [flatCell: flatCell, wire: actual]] ELSE NIL]];
};
ConsumeMerge: PROC [ds: Element] = {
v: Vertex ← CanonizeAndGetStructure[sct, path, ds.first];
fw, sw: Core.Wire ← NIL;
WITH ds.first SELECT FROM
dw: DescendantWire => {
IF dw.flatCell.path.length#0 THEN ERROR;
fw ← dw.wire};
dci: DescendantCellInstance => v ← v;
ENDCASE => ERROR;
IF v=NIL THEN ERROR;
FOR ds ← ds.rest, ds.rest WHILE ds # NIL DO
w: Vertex ← CanonizeAndGetStructure[sct, path, ds.first];
IF w=NIL THEN ERROR;
IF fw#NIL THEN {
WITH ds.first SELECT FROM
dw: DescendantWire => {
IF dw.flatCell.path.length#0 THEN ERROR;
sw ← dw.wire};
dci: DescendantCellInstance => ERROR;
ENDCASE => ERROR;
PostMerge[cell, fw, sw]};
v ← MergeVertices[sct, v, w].merged;
IF v=NIL THEN ERROR;
ENDLOOP;
};
Depublicize: PROC [pw: Core.Wire] ~ {
dw: DescendantWire ~ NEW [CoreFlat.FlatWireRec ← [flatCell: flatCell, wire: pw]];
v: Vertex ~ GetStructure[sct, dw];
v.other ← Asserting.AssertFn1[fn: depub, val: $TRUE, inAdditionTo: v.other, mayMute: TRUE];
RETURN};
IgnoreDepublicity: PROC [pw: Core.Wire] ~ {RETURN};
IF cell.class=CC.recordCellClass THEN {
IF vs#NIL THEN vs.sizeDists[Original].ChangeTransformed[MAX[minbin, rct.size], MAX[minbin, rct.internal.size]];
IntroduceWires[flatCell, internal, rct.internal, bindings]};
CF.NextBoundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, bindings, Flatten];
ms[specData, cell, path.length=0 AND flatCell.recastCount#0, EnumerateInstances, IdentifyActual, ConsumeMerge, IF path.length=0 AND flatCell.recastCount=0 THEN Depublicize ELSE IgnoreDepublicity];
}
ELSE {
ci: CC.CellInstance = instance;
di: DescendantCellInstance = NEW [DescendantCellInstancePrivate ← path];
name: ROPE ~ CF.InstancePathRope[original, path];
type: CellType = GetGraph[ttols, ans.leafType, FALSE, specData, sts, MergeNothing, NIL];
itc: TransCounts ~ NARROW[CP.InheritCellTypeProp[cell, TransCountsKey]];
v: Vertex = NEW [VertexRep ← [
name: name,
class: cell,
type: type,
other: Asserting.AssertFn1[structureToCore, di, NIL]
]];
bounded: RefTab.Ref ~ RefTab.Create[];
pi: PortIndex ← 0;
SeeBinding: PROC [from: REF ANY, ProduceTos: ToProducer] --MapConsumer-- = {
leafPub: Core.Wire ~ NARROW[from];
theV: Vertex ← NIL;
PerInstPub: PROC [to: REF ANY] --ToConsumer-- ~ {
instPub: Core.Wire ~ NARROW[to];
adw: DescendantWire = NARROW[bindings.Fetch[instPub].val];
IF adw = NIL THEN ERROR;
IF NOT bounded.Insert[instPub, leafPub] THEN ERROR;
{nv: Vertex = GetStructure[sct, adw];
IF nv = NIL THEN ERROR;
IF theV=NIL THEN Link[v, theV ← nv, type.ports[pi].color]
ELSE IF (theV ← MergeVertices[sct, theV, nv].merged)=NIL THEN ERROR;
RETURN}};
IF leafPub.size=0 THEN {
ProduceTos[PerInstPub];
IF theV=NIL THEN ERROR;
pi ← pi + 1;
RETURN};
RETURN};
sats: RefTab.Ref ~ RefTab.Create[];
CheckBinding: PROC [instPub: Core.Wire] ~ {
adw: DescendantWire ~ NARROW[bindings.Fetch[instPub].val];
rep: Core.Wire ~ Canonize[instPub, FALSE];
IF rep#NIL THEN {
sat: DescendantWire ~ NARROW[sats.Fetch[rep].val];
SELECT TRUE FROM
sat=NIL => IF NOT sats.Insert[rep, adw] THEN ERROR;
CF.FlatWireEqual[sat, adw] => NULL;
adw.flatCell.path.length#0 OR NOT CO.RecursiveMember[original.public, adw.wire] => BogusMerge[original, adw, sat, di];
sat.flatCell.path.length#0 OR NOT CO.RecursiveMember[original.public, sat.wire] => BogusMerge[original, adw, sat, di];
ENDCASE => PostMerge[original, adw.wire, sat.wire]};
IF bounded.Fetch[instPub].found THEN RETURN;
IF adw = NIL THEN ERROR;
{nv: Vertex = GetStructure[sct, adw];
IF nv = NIL THEN ERROR;
IF nv.firstEdge#NIL OR NOT bounded.Insert[nv, instPub] THEN DroppedConnection[original, NEW [DescendantWirePrivate ← [flatCell: flatCell, wireRoot: public, wire: instPub]], adw];
RETURN}};
IF NOT backHash.Insert[di, v] THEN ERROR;
AddPart[sct, v];
IF itc#NIL THEN {
tc.flatTransistors ← tc.flatTransistors + itc.flatTransistors;
tc.flatTransMerges ← tc.flatTransMerges + itc.flatTransMerges;
tc.flatWires ← tc.flatWires + itc.flatWires;
tc.flatWireDels ← tc.flatWireDels + itc.flatWireDels;
}
ELSE IF vs#NIL THEN vs.missingTransistors ← vs.missingTransistors+1;
ans.publicInvMapEnumerator.Enumerate[ans.publicInvMapEnumerator.data, SeeBinding];
IF pi#type.ports.length THEN ERROR;
CO.VisitRootAtomics[ci.type.public, CheckBinding];
IF SurveyPart # NIL THEN SurveyPart[v, ci];
};
IF ans.Pop#NIL THEN ans.Pop[specData];
RETURN};
IntroduceWires[[], public, original.public, NIL];
Flatten[original, CF.allFlatCells, [], NIL, LAST[NAT], NIL, [], NIL, RefTab.Create[]];
IF sct.ports.length#0 THEN ERROR;
};
{pi: PortIndex ← 0;
seen: RefTab.Ref = RefTab.Create[];
SetPortNet: PROC [wire: Core.Wire] = {
dw: DescendantWire = NEW [DescendantWirePrivate ← [wireRoot: public, wire: wire]];
nv: Vertex = GetStructure[sct, dw];
IF nv = NIL THEN ERROR;
IF NOT seen.Fetch[nv].found THEN {
IF NOT seen.Insert[nv, $TRUE] THEN ERROR;
SELECT Asserting.FnVal[depub, nv.other] FROM
$TRUE => {
nv.other ← Asserting.Remove1[depub, $TRUE, nv.other, TRUE];
RETURN};
NIL => {
first: BOOLTRUE;
color: Color ← 0;
FOR ds: Element ← GetCore[nv], ds.rest WHILE ds # NIL DO
dw: DescendantWire = NARROW[ds.first];
IF dw.path.length # 0 THEN ERROR;
IF first THEN first ← FALSE;
color ← color + GetWireColor[dw.wire, 0];
ENDLOOP;
IF first THEN ERROR;
sct.ports[pi] ← [
name: nv.name,
net: nv,
color: FilterColor[color]
];
pi ← pi + 1;
RETURN};
ENDCASE => ERROR;
};
RETURN};
[] ← CO.VisitRootAtomics[original.public, SetPortNet];
sct.ports.length ← pi;
};
AddMirror[sct];
{CheckVertex: PROC [v: Vertex] ~ {
IF v.class=net AND v.firstEdge=NIL THEN {
IF debug THEN Log["Deleting lonely %g in %g.\n", [rope[v.name]], [rope[sct.name]]];
DeleteVertex[sct, v];
tc.flatWireDels ← tc.flatWireDels + 1;
};
RETURN};
sct.EnumerateParts[CheckVertex, FALSE];
IF sct.netCount < sct.ports.length THEN ERROR;
tc.flatWires ← tc.flatWires + (sct.netCount - sct.ports.length);
IF vs#NIL THEN vs.sizeDists[Reconciled].ChangeTransformed[MAX[minbin, sct.cellCount], MAX[minbin, sct.netCount]];
CP.PutCellTypeProp[cct, TransCountsKey, tc];
};
}};
PopTimer[$getGraph];
RETURN};
ForgetGraph: PUBLIC PROC [sct: CellType] = {
cct: Core.CellType = GetCellType[sct];
propsToRemove: ATOMList ← NIL;
FindPropsToRemove: PROC [prop: ATOM, val: REF ANYNIL] = {
IF structureFromCorePrefix.Equal[Atom.GetPName[prop].Substr[len: structureFromCorePrefixLength]] THEN propsToRemove ← CONS[prop, propsToRemove];
};
EnumerateParts[sct, DestroyVertex, TRUE];
sct^ ← CellTypeRep[destroyed: TRUE];
CP.Enumerate[cct.properties, FindPropsToRemove];
FOR propsToRemove ← propsToRemove, propsToRemove.rest WHILE propsToRemove # NIL DO
CP.PutCellTypeProp[cct, propsToRemove.first, NIL];
ENDLOOP;
RETURN};
AddPart: PROC [sct: CellType, v: Vertex] = {
v.nextPart ← sct.firstPart;
sct.firstPart ← v;
sct.size ← sct.size + 1;
SELECT v.class FROM
cell => sct.cellCount ← sct.cellCount + 1;
net => sct.netCount ← sct.netCount + 1;
ENDCASE => ERROR;
RETURN};
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;
RETURN};
DestroyVertex: PROC [v: Vertex] = {
IF v=NIL THEN RETURN;
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];
RETURN};
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;
RETURN};
PostMerge: PROC [cct: Core.CellType, w1, w2: Core.Wire] ~ {
w1 ← Canonize[w1, TRUE];
w2 ← Canonize[w2, TRUE];
IF w1#w2 THEN CP.PutWireProp[w1, wireRepProp, w2];
RETURN};
Canonize: PROC [w: Core.Wire, fix: BOOL] RETURNS [Core.Wire] ~ {
original: Core.Wire ~ w;
IF CP.GetWireProp[w, wireRepProp]=NIL THEN {
IF fix
THEN {CP.PutWireProp[w, wireRepProp, w]; RETURN [w]}
ELSE RETURN [NIL];
};
DO
v: Core.Wire ~ NARROW[CP.GetWireProp[w, wireRepProp]];
IF v=NIL THEN ERROR;
IF v=w THEN RETURN [w];
w ← v;
ENDLOOP};
GetCommonalityConstraints: PUBLIC PROC [subroot: Core.CellType] RETURNS [RefTab.Ref] ~ {
constraints: RefTab.Ref ~ RefTab.Create[];
PerAtomic: PROC [wire: Core.Wire] ~ {
cw: Core.Wire ~ Canonize[wire, FALSE];
IF cw#NIL THEN {
constraint: RefTab.Ref ← NARROW[constraints.Fetch[cw].val];
IF constraint=NIL AND NOT constraints.Insert[cw, constraint ← RefTab.Create[]] THEN ERROR;
IF NOT constraint.Insert[wire, wire] THEN ERROR}
ELSE wire ← wire};
CO.VisitRootAtomics[subroot.public, PerAtomic];
RETURN [constraints]};
SetWireColor: PROC [wire: Core.Wire, color: Color] = {
CP.PutWireProp[wire, wireColorKey, NEW [Color ← color]];
RETURN};
GetWireColor: PROC [wire: Core.Wire, default: Color] RETURNS [color: Color] = {
rc: REF Color = NARROW[CP.GetWireProp[wire, wireColorKey]];
color ← IF rc#NIL THEN rc^ ELSE IF default#noColor THEN default ELSE ERROR;
RETURN};
GetCellType: PUBLIC PROC [sct: CellType] RETURNS [cct: Core.CellType] = {
cct ← NARROW[Asserting.FnVal[structureToCore, sct.otherPublic]];
RETURN};
CanonizeAndGetStructure: PUBLIC PROC [sct: CellType, insert: DescendantCellInstancePrivate, core: --not necessarily canonical--Descendant] RETURNS [v: Vertex] = {
backHash: RefTab.Ref = NARROW[Asserting.FnVal[backHashKey, sct.otherPrivate]];
cd: --Canonized--Descendant ← core;
WITH core SELECT FROM
di: DescendantCellInstance => cd ← NEW [DescendantCellInstancePrivate ← CF.RaiseRootOfInstancePath[insert, di^]];
dw: DescendantWire => {
original: Core.CellType = GetCellType[sct];
cd ← NEW [CF.FlatWireRec ← CF.CanonizeWire[original, CF.RaiseRootOfFlatWire[insert, dw^]]];
};
ENDCASE => ERROR;
v ← NARROW[backHash.Fetch[cd].val];
IF v=NIL THEN RETURN;
FOR v ← v, v.better UNTIL v.better=NIL DO NULL ENDLOOP;
RETURN};
GetStructure: PUBLIC PROC [sct: CellType, core: --Canonized--Descendant] RETURNS [v: Vertex] = {
backHash: RefTab.Ref = NARROW[Asserting.FnVal[backHashKey, sct.otherPrivate]];
FOR v ← NARROW[backHash.Fetch[core].val], v.better UNTIL v.better = NIL DO NULL ENDLOOP;
RETURN};
GetCore: PUBLIC PROC [v: Vertex] RETURNS [core: Element] = {
Note: PROC [assertion: Asserting.Assertion] --Asserting.AssertionConsumer-- = {
d: Descendant = Asserting.FnVal[structureToCore, LIST[assertion]];
core ← CONS[d, core];
RETURN};
core ← NIL;
Asserting.EnumerateAssertionsAbout[structureToCore, v.other, Note];
RETURN};
defaultColorer: Colorer ← NEW [ColorerPrivate ← [DefaultCellTypeColor, DefaultColorPorts]];
DefaultCellTypeColor: PROC [ct: Core.CellType] RETURNS [color: Color] = {
name: ROPECO.GetCellTypeName[ct];
color ← RopeHash.FromRope[name];
color ← color * color;
RETURN};
DefaultColorPorts: PROC [ct: Core.CellType, SetColor: PROC [Core.Wire, Color]] = {
ColorPort: PROC [wire: Core.Wire] = {
SetColor[wire, RefHash[wire]];
RETURN};
[] ← CO.VisitRootAtomics[ct.public, ColorPort];
RETURN};
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;
RETURN};
ColorTransistorPorts: PROC [ct: Core.CellType, SetColor: PROC [Core.Wire, Color]] = {
ColorPort: PROC [wire: Core.Wire] = {
name: ROPE = CO.GetShortWireName[wire];
SetColor[wire, SELECT TRUE FROM
name.Equal[CC.transistorPortNames[ch1]] => channelColor,
name.Equal[CC.transistorPortNames[ch2]] => channelColor,
name.Equal[CC.transistorPortNames[gate]] => gateColor,
name.Equal[CC.transistorPortNames[Vdd]] => substrateColor,
ENDCASE => ERROR
];
RETURN};
[] ← CO.VisitRootAtomics[ct.public, ColorPort];
RETURN};
gateColor: Color ← 47;
channelColor: Color ← 834;
substrateColor: Color ← 99;
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;
RETURN};
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 => {
transistorLength: INTNARROW[CoreProperties.GetCellTypeProp[cct, CoreClasses.lengthProp], REF INT]^;
transistorWidth: INTNARROW[CoreProperties.GetCellTypeProp[cct, CoreClasses.widthProp], REF INT]^;
name ← IO.PutFR[
"%g(%g/%g)",
[rope[SELECT t.type FROM
nE => "nE",
pE => "pE",
nD => "nD",
ENDCASE => ERROR]],
[integer[transistorLength]],
[integer[transistorWidth]]];
[] ← CO.SetCellTypeName[cct, name];
};
ENDCASE => name ← IO.PutFR["%xH^", [cardinal[LOOPHOLE[cct]]]];
RETURN};
DontWrite: PROC [stream: IO.STREAM, prop: ATOM, value: REF ANY] ~ {
IF complain THEN SIGNAL LosingConstraint--can't survive CoreIO, so can't have constraints here--;
};
complain: BOOLTRUE;
DontRead: PROC [stream: IO.STREAM, prop: ATOM] RETURNS [value: REF ANY] ~ {RETURN [NIL]};
Start: PROC = {
CP.PutCellClassProp[CC.transistorCellClass, ColorerKey, transistorColorer];
CP.PutCellClassProp[CC.transistorCellClass, TransCountsKey, NEW [TransCountsPrivate ← [1, 0]] ];
};
Start[];
END.