StructureFromCoreImpl.Mesa
Barth, April 16, 1987 10:45:57 pm PDT
Last tweaked by Mike Spreitzer on June 23, 1989 10:56:45 am PDT
DIRECTORY Asserting, Atom, Basics, Core, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, CoreStructuralComparison, Histograms, IO, PWCLCoreFlatExtras, RefTab, Rope, RopeHash, StructuralComparisonDataStructure, StructuralComparisonOps, StructureColor, StructureFromCore;
StructureFromCoreImpl:
CEDAR
PROGRAM
IMPORTS Asserting, Atom, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, CoreStructuralComparison, Histograms, IO, RefTab, Rope, RopeHash, StructuralComparisonDataStructure, StructuralComparisonOps
EXPORTS StructureFromCore, CoreStructuralComparison, StructureColor
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 ROPE ← NEW [ROPE ← "New for this one"];
ColorerProp: PUBLIC ATOM = CP.RegisterProperty[$CoreStructureColorer];
Colorer: TYPE = StructureColor.Colorer;
ColorerPrivate: TYPE = StructureColor.ColorerPrivate;
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: BOOL ← TRUE;
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, ColorerProp]
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: BOOL ← FALSE]] ~ {};
IdentifyActual: PROC [ci: CoreClasses.CellInstance, actual: Core.Wire, describe: BOOL ← FALSE] RETURNS [ActualID] ~ {ERROR};
mergingDone: BOOL ← FALSE;
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:
NAT ←
LAST[
NAT], parent: Core.CellType ←
NIL, flatParent:
CF.FlatCellTypeRec ← [], data:
REF
ANY ←
NIL, 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:
BOOL ←
FALSE]] = {
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:
BOOL ←
FALSE]
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: BOOL ← TRUE;
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
ANY ←
NIL] = {
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: ROPE ← CO.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: INT ← NARROW[CoreProperties.GetCellTypeProp[cct, CoreClasses.lengthProp], REF INT]^;
transistorWidth: INT ← NARROW[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: BOOL ← TRUE;
DontRead: PROC [stream: IO.STREAM, prop: ATOM] RETURNS [value: REF ANY] ~ {RETURN [NIL]};
Start:
PROC = {
CP.PutCellClassProp[CC.transistorCellClass, ColorerProp, transistorColorer];
CP.PutCellClassProp[CC.transistorCellClass, TransCountsKey, NEW [TransCountsPrivate ← [1, 0]] ];
};
Start[];
END.