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.
���ˆ��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
�Ê��–
"cedar" style˜�code™K™%K™?—K˜�KšÏk	œ~œŒ˜•K˜�šÑbnxœœ˜$KšœpœT˜ÍKšœ<˜CKšœ"˜(Kšœ˜—K˜�Kšœœœœœ
œœg˜­K˜�Kšœœœ˜'Kšœœœ6˜SK˜�Kš	œ
œœœœ˜K˜�KšÏnœœœ˜ K˜�KšŸœœœ<œ˜aKšŸ
œœœRœ˜pK˜�Kšœ	œ"˜/Kš	œ	œœœœ˜4K˜�KšŸœœœœ)˜FK˜�Kšœ	œ˜'Kšœœ!˜5K˜�šŸœœœ˜+Kšœ(˜(—K˜�šœ
œœ˜)šœ˜Kšœ,˜,Kšœœœ˜,—K˜
K˜
—K˜�šœœœ˜)Kšœ&˜&Kšœœœ˜,—K˜�Kšœœ)˜FKšœœ$˜FKšœœP˜mK˜�Kšœœœœ˜*Kš	œœœ.œœ˜XK˜�Kšœœ˜K˜�Kšœ
œ8˜IKšœœ˜)Kšœœ%˜0K˜�Kšœœœ˜K˜�š
Ÿœœ.œœœ˜_šœ,œœ˜BKš
œœœ œœ˜kKšœ˜—šœœ˜šœœ˜Kšœ˜Kšœ
œœ˜$Kšœœ˜"Kšœ
œœ˜#Kšœœ˜Kšœ˜Kšœ˜—Kšœœœ˜,—Kšœœ&˜5Kšœ˜—K˜�šŸœœœ œ!œœœ#Ÿ
œœœœÏcœœœœ˜•K˜Kšœ˜Kšœœœ˜&šœœœ'œ˜LK˜Kšœ˜—Kšœœ&˜EK˜Kšœœœ+˜FKšœœœ˜šœœ˜Kšœ
œœœ˜1Kš
œœœœœ
˜@—šœœœœ˜Kšœ
œœœ˜1Kšœœ˜$—šœœ1œ˜CKš	œœ3œœœ˜ZKšœ
œ˜—šœœœ˜šœœ˜Kšœ ˜ Kšœ4˜4Kšœœ
œ ˜6Kšœ˜Kšœbœ˜gK˜—K˜Kšœ;˜=Kšœ+˜+šœœœ˜K˜)Kšœ˜šŸœœ˜'šœœœ˜*Kšœœœ*˜D˜K˜Kšœ"˜"K˜—Kšœœœ˜!Kš
œœœœœ˜@K˜K˜—K˜—KšŸœœŸœœ œœœ˜jKšŸœœ=œœœœ˜|Kšœ
œœ˜šŸœœ œ˜1Kšœœœ˜$Kšœœ!œ
˜GKšœœœœ˜=šœœœ˜)Kšœœœ˜$Kšœœ!œ
˜GKš
œœœœœ˜FKšœœ(˜5˜K˜6K˜2—K˜K˜(Kšœœ˜Kšœ˜—Kšœ˜—šŸœœ˜K˜šœœ˜/šœœ˜Kšœœ#˜4K˜—Kšœ˜—šœœ˜7K˜Kšœ˜—Kšœ˜Kšœ˜—Kšœ0˜2Kšœœœ˜"Kšœ˜Kšœœ/ /œ˜Kšœ
œ˜K˜—K˜—šœ˜Kšœœœ˜*Kšœ˜—Kš
œœœœœ˜JKšœœ˜Kšœœœ˜#KšœG˜GKšœP˜PK˜š
Ÿœœœœ&œ˜všŸœœ˜*š
œœœœœ˜:KšœœœœE˜^šœœœ˜&Kšœœœ)˜8šœœ˜K˜K˜Kšœ0œ˜4Kšœ˜—Kšœœœœ˜)K˜Kšœœœ˜-K˜—K˜—K˜—Kšœ(˜*Kšœ˜—š$Ÿœœœœœ!œœ	œœœœœœœœœœ œ˜¾Kšœ4˜4Kš	œœœ&œœ˜ZKšœ	œœ˜#Kšœœœœœœœœ˜\šœ	œ˜šŸœœŸœœœœœœ˜_š
œœœœœœ˜HKšœœœ˜Kšœ˜—K˜—š
Ÿœœ=œœœ˜uKšœœ˜8Kšœœœœœ
œœœœ˜YKšœœ
œœ<œœ˜kKšœ˜—šŸœœ˜$Kšœ9˜9Kšœœ˜šœ
œ˜šœ˜Kšœœœ˜(K˜—Kšœ%˜%Kšœœ˜—Kšœœœœ˜šœœœ˜+Kšœ9˜9Kšœœœœ˜šœœœ˜šœ
œ˜šœ˜Kšœœœ˜(K˜—Kšœœ˜%Kšœœ˜—K˜—Kšœ$˜$Kšœœœœ˜Kšœ˜—K˜—šŸœœ˜%Kšœœ9˜QK˜"K•StartOfExpansion‹[fn: Asserting.Term, val: Asserting.Term, inAdditionTo: Asserting.Assertions, args: Asserting.Terms _ NIL, mayMute: BOOL _ FALSE]šœUœ˜[Kšœ˜—KšŸœœœ˜3šœœœ˜'Kš
œœœ*œœ˜oKšœ<˜<—Kšœi˜kKšœ!œKœœœ
œ˜ÄK˜—šœ˜Kšœœ˜Kšœœ(˜HKšœœœ"˜1Kšœ/œœ˜XKšœœœ,˜Hšœœ˜K˜K˜Kšœ˜Kšœ0œ˜4Kšœ˜—K˜&K˜šŸ
œœœœŸ
œ œ˜LKšœœ˜"Kšœœ˜š
Ÿ
œœœœ œ˜1Kšœœ˜ Kšœœ˜:Kšœœœœ˜Kšœœ"œœ˜3Kšœ%˜%Kšœœœœ˜Kšœœœ)˜9Kš
œœ.œœœ˜DKšœ˜	—šœœ˜Kšœ˜Kšœœœœ˜K˜Kšœ˜—Kšœ˜—K˜#šŸœœ˜+Kšœœ˜:Kšœ#œ˜*šœœœ˜Kšœœ˜2šœœ˜Kšœœœœœœ˜3Kšœœ˜#KšœœœœR˜vKšœœœœR˜vKšœ-˜4——Kšœœœ˜,Kšœœœœ˜Kšœ%˜%Kšœœœœ˜KšœœœœœœW˜²Kšœ˜	—Kšœœœœ˜)K˜šœœœ˜Kšœ>˜>Kšœ>˜>Kšœ,˜,Kšœ5˜5K˜—Kšœœœœ1˜DKšœR˜RKšœœœ˜#Kšœ0˜2Kšœœœ˜+Kšœ˜—Kšœ	œœ˜&Kšœ˜—Kšœ,œ˜1Kš
œœœœœœœ˜VKšœœœ˜!Kšœ˜K˜K˜#šŸ
œœ˜&Kšœœ:˜RKšœ#˜#Kšœœœœ˜šœœœ˜"Kšœœœœ˜)šœ"˜,˜
Kšœ5œ˜;Kšœ˜—šœ˜Kšœœœ˜K˜šœ$œœ˜8Kšœœ˜&Kšœœœ˜!Kšœœ	œ˜Kšœ)˜)Kšœ˜—Kšœœœ˜˜K˜K˜Kšœ˜K˜—K˜Kšœ˜—Kšœœ˜—Kšœ˜—Kšœ˜—Kšœœ/˜6Kšœ˜K˜K˜šœŸœœ˜"šœ
œ
œœ˜)KšœœF˜SKšœ˜Kšœ&˜&K˜—Kšœ˜—Kšœ œ˜'Kšœ!œœ˜.Kšœ@˜@Kš
œœœ,œœ˜qKšœ*˜,K˜Kšœ˜Kšœ˜Kšœ˜—K˜�šŸœœœ˜,K˜&Kšœœ˜šŸœœœœœœ˜<Kšœ_œœ˜K˜—Kšœ#œ˜)Kšœœ˜$Kšœ.˜0šœ3œœ˜RKšœ+œ˜2Kšœ˜—Kšœ˜—K˜�šŸœœ˜,K˜K˜Kšœ˜šœ	˜Kšœ*˜*Kšœ'˜'Kšœœ˜—Kšœ˜—K˜�šŸœœ'˜1šœ
œ
˜˜Kšœœ˜+Kšœœ˜-—K˜—Kšœœœœ!˜PKšœœœœ"˜QKšœ˜Kšœ˜—K˜�šŸ
œœ˜#Kšœœœœ˜šœœ˜Kšœ˜K˜$Kšœœœœ˜#Kšœ˜—Kšœ˜Kšœ˜—K˜�šŸ	œœ˜#šœœ˜K˜K˜K˜
Kšœ
˜K˜—K˜šœœ˜/K˜0Kšœ˜—Kšœ˜—K˜�šŸ	œœ,˜;Kšœœ˜Kšœœ˜Kšœœœ"˜2Kšœ˜—K˜�šŸœœœœ˜@K˜šœœœœ˜,šœ˜Kšœœ!œ˜4Kšœœœ˜—K˜—š˜Kšœœœ˜6Kšœœœœ˜Kšœœœ˜K˜Kšœ˜	—K˜�—šŸœœœœ˜XK˜*šŸ	œœ˜%Kšœœ˜&šœœœ˜Kšœœ˜;Kšœœœœ6œœ˜ZKšœœœœ˜0—Kšœ˜—Kšœ-˜/Kšœ˜—K˜�šŸœœ$˜6Kšœ!œ˜8Kšœ˜—K˜�šŸœœ#œ˜OKšœœ	œœ"˜;Kšœœœœœœœ	œœ˜KKšœ˜—K˜�šŸœœœœ˜IKšœœ4˜@Kšœ˜—K˜�š
Ÿœœœ> œœ˜¢Kšœœ1˜NKšœ 
œ˜#šœœ˜Kšœ#œ"œ'˜qšœ˜Kšœ+˜+Kš	œœœœœ$˜[K˜—Kšœœ˜—Kšœœ˜#Kšœœœœ˜Kšœœ
œœœœ˜7Kšœ˜—K˜�š
Ÿœœœ 
œœ˜`Kšœœ1˜NKšœœ%œœœœœ˜XKšœ˜—K˜�šŸœœœ
œ˜<šŸœœ" œ˜OKšœ1œ
˜BKšœœ
˜Kšœ˜—Kšœœ˜KšœC˜CKšœ˜—K˜�Kšœœ>˜[K˜�šŸœœœ˜IKšœœœ˜$Kšœ ˜ K˜Kšœ˜—K˜�šŸœœŸœœ˜RšŸ	œœ˜%Kšœ˜Kšœ˜—Kšœœ(˜/Kšœ˜—K˜�KšœœD˜dK˜�šŸœœœ˜LJšœœœ
˜$šœœ	˜J˜	J˜	J˜	Jšœœ˜—Kšœ˜—K˜�šŸœœŸœœ˜UšŸ	œœ˜%Kšœœœ˜'šœœœ˜Kšœœ+˜8Kšœœ+˜8Kšœœ)˜6Kšœœ-˜:Kšœ˜K˜—Kšœ˜—Kšœœ(˜/Kšœ˜Kšœ˜Kšœ˜K˜—K˜�šŸ
œœ	œœœœœ˜BKšœ
œ˜šœœ	œ˜2Kš	œ
œ	œœ
œ%˜SKšœ˜—Kšœ˜—K˜�šŸœœœœ˜CKšœ	œ$œœ˜=Kšœœ˜Kšœ	œ$œœ˜=šœ
œ˜šœœ˜Kš	œœœ>œœ˜fKš	œœœ=œœ˜dšœœ˜Kšœ˜šœœ˜K˜K˜K˜Kšœœ˜—Kšœ˜Kšœ˜—Kšœœ˜#K˜—Kšœœœ	˜>—Kšœ˜—K˜�šŸ	œœ
œœœ	œœ˜CKšœ
œœ 8œ˜aK˜Kšœ
œœ˜—K˜�KšŸœœ
œœœœ	œœœœ˜YK˜�šŸœœ˜Kšœœ6˜LKšœœ&œ!˜`K˜—K˜�K˜K˜�Kšœ˜—�…—����WD��sÝ��