PWCoreLichenImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reversed.
Created by Bertrand Serlet, July 14, 1986 5:49:00 pm PDT
Bertrand Serlet, July 15, 1986 2:10:29 am PDT
Mike Spreitzer March 11, 1987 3:27:00 pm PST
Last tweaked by Mike Spreitzer on March 24, 1987 3:30:14 pm PST
DIRECTORY CD, CDCommandOps, CDDirectory, CDInstances, CDOps, CDSequencer, CDViewer, Core, CoreClasses, CoreFlat, CoreOps, CoreProperties, CoreStructuralComparison, GList, HashTable, IO, List, ProcessProps, PWCLCoreFlatExtras, PWCore, PWCoreLichen, Rope, SinixOps, Sisyph, StructuredStreams, TerminalIO, UnparserBuffer, ViewerClasses;
PWCoreLichenImpl:
CEDAR
PROGRAM
IMPORTS CD, CDCommandOps, CDDirectory, CDInstances, CDOps, CDSequencer, CDViewer, CoreClasses, CoreFlat, CoreOps, CoreProperties, CoreStructuralComparison, GList, HashTable, IO, List, ProcessProps, PWCLCoreFlatExtras, PWCore, Rope, SinixOps, Sisyph, StructuredStreams, TerminalIO, UnparserBuffer
EXPORTS PWCoreLichen
SHARES PWCore =
BEGIN OPEN CC: CoreClasses, CF: CoreFlat, CFE: PWCLCoreFlatExtras, CO: CoreOps, CP: CoreProperties, CSC: CoreStructuralComparison, PWCoreLichen, SS: StructuredStreams, UB: UnparserBuffer;
FlatWireRecList: TYPE = LIST OF CF.FlatWireRec;
Element: TYPE = CSC.Element;
ElementList: TYPE = CSC.ElementList;
ActualID: TYPE = CSC.ActualID;
Role: TYPE ~ CSC.Role;
OtherRole: ARRAY Role OF Role = [A: B, B: A];
Extracted: Role ~ A;
Source: Role ~ B;
RoleDescriptions:
ARRAY Role
OF
ROPE = [B: "source", A: "extracted"];
We need them in this order because ExtractedSubtree would side-effect the data-structure created from sourceRoot if it came second.
HighlightData: TYPE = REF HighlightDataPrivate;
HighlightDataPrivate:
TYPE =
RECORD [
design: CD.Design,
viewer: ViewerClasses.Viewer
];
sourceToExtractedsKey: ATOM = CP.RegisterProperty[$PWCoreLichenSourceToExtracteds, CP.Props[[CP.propPrint, CP.PropDontPrint]]];
compared: ATOM = CP.RegisterProperty[$PWCoreLichenCompared, CP.Props[[CP.propPrint, CP.PropDontPrint]]];
kindName: ARRAY CSC.MismatchKind OF ROPE ~ ["Stuck", "Difference", "Transitor shape mismatch"];
hd: HighlightData ← NIL;
autoHack: BOOL ← FALSE;
CompareCmd:
PROC [cmd: CDSequencer.Command]
--CDSequencer.CommandProc-- = {
abort: REF BOOL ~ NEW [BOOL ← FALSE];
Inner:
PROC ~ {
selected: CD.InstanceList ~ CDInstances.OnlySelected[CDOps.InstList[cmd.design]];
IF selected = NIL THEN TerminalIO.PutF["You %ldo%l realize you have nothing selected, don't you?\n", [rope["e"]], [rope["E"]]];
FOR insts:
CD.InstanceList ← selected, insts.rest
WHILE insts #
NIL
DO
inst: CD.Instance = insts.first;
TerminalIO.PutF["Extracting and comparing %g.\n", [rope[CDOps.InstRope[inst]]]];
{objName: ROPE = CDDirectory.Name[inst.ob];
cx: Sisyph.Context = Sisyph.Create[cmd.design];
root: CellType = Sisyph.ExtractSchematicByName[objName, cx];
Compare[root];
TerminalIO.PutF["Done extracting and comparing.\n"];
}ENDLOOP;
};
CDSequencer.UseAbortFlag[cmd.design, abort];
ProcessProps.AddPropList[List.PutAssoc[$AbortBool, abort, NIL], Inner];
};
ForgetCmd:
PROC [cmd: CDSequencer.Command]
--CDSequencer.CommandProc-- = {
selected: CD.InstanceList ~ CDInstances.OnlySelected[CDOps.InstList[cmd.design]];
IF selected = NIL THEN TerminalIO.PutF["You %ldo%l realize you have nothing selected, don't you?\n", [rope["e"]], [rope["E"]]];
FOR insts:
CD.InstanceList ← selected, insts.rest
WHILE insts #
NIL
DO
inst: CD.Instance = insts.first;
TerminalIO.PutF["Forgetting comparisons for subtree rooted at %g.\n", [rope[CDOps.InstRope[inst]]]];
{objName: ROPE = CDDirectory.Name[inst.ob];
cx: Sisyph.Context = Sisyph.Create[cmd.design];
root: CellType = Sisyph.ExtractSchematicByName[objName, cx];
ForgetComparisons[root];
}ENDLOOP;
TerminalIO.PutF["Done forgetting comparisons.\n"];
};
EnableAutomorphismHack:
PROC [cmd: CDSequencer.Command]
--CDSequencer.CommandProc-- = {
SetAutomorphismHack[TRUE];
};
DisableAutomorphismHack:
PROC [cmd: CDSequencer.Command]
--CDSequencer.CommandProc-- = {
SetAutomorphismHack[FALSE];
};
ForgetComparisons:
PUBLIC
PROC [root: CellType] ~ {
seen: HashTable.Table ~ HashTable.Create[];
Clearit:
PROC [cell: CellType, target:
CF.FlatCellTypeRec ←
CF.allFlatCells, flatCell:
CF.FlatCellTypeRec ← [], instance:
CF.CellInstance ←
NIL, index:
NAT ←
LAST[
NAT], parent: CellType ←
NIL, flatParent:
CF.FlatCellTypeRec ← [], data:
REF
ANY ←
NIL]
--CF.UnboundFlatCellProc-- ~ {
IF seen.Fetch[cell].found THEN RETURN;
IF NOT seen.Insert[cell, $Seen] THEN ERROR;
CP.PutCellTypeProp[cell, compared, NIL];
IF cell.class.recast#NIL OR cell.class=CC.recordCellClass THEN CF.NextUnboundCellType[cell, target, flatCell, instance, index, parent, flatParent, data, Clearit];
};
Clearit[cell: root, flatCell: [[]]];
};
SetAutomorphismHack: PUBLIC PROC [enabled: BOOL] = {autoHack ← enabled};
Compare:
PUBLIC
PROC [root: CellType] = {
key: REF ANY = CP.GetCellTypeProp[root, compared];
layoutAtom: ATOM = PWCore.GetLayoutAtom[root];
abort:
REF
BOOL ~
WITH ProcessProps.GetProp[$AbortBool]
SELECT
FROM
x: REF BOOL => x,
ENDCASE => NEW [BOOL ← FALSE];
IF abort^ THEN RETURN;
SELECT
TRUE
FROM
key = $TRUE => RETURN; -- already done
layoutAtom#
NIL => {
indirectObj: CD.Object = PWCore.Layout[root];
layoutCellType: CellType = PWCore.CorrespondingCellType[indirectObj];
layoutData: PWCore.LayoutData = NARROW[layoutCellType.data];
source, extracted: CellType;
extractedToSource: HashTable.Table;
IF abort^ THEN RETURN;
[sourceCellType: source, extractedCellType: extracted, extractedToSource: extractedToSource] ← PWCore.LayoutCellTypeInfo[layoutCellType];
IF abort^ THEN RETURN;
MatchLeaves[extracted, source, extractedToSource, indirectObj, layoutData.mode.decoration, hd, abort];
IF abort^ THEN RETURN;
CP.PutCellTypeProp[root, compared, $TRUE];
};
root.class=CC.recordCellClass => ERROR;
ENDCASE => Compare[CO.Recast[root]];
};
SourceSubtree:
PROC [instance:
CC.CellInstance, path:
CF.InstancePath]
RETURNS [leafType: CellType]
--CSC.SubtreeSpec-- = {
ct: CellType ← instance.type;
DO
IF PWCore.GetLayoutAtom[ct] # NIL THEN RETURN [ct];
IF ct.class.recast = NIL THEN RETURN [IF ct.class # CC.recordCellClass THEN ct ELSE NIL];
ct ← CO.Recast[ct];
ENDLOOP;
};
ExtractedSubtree:
PROC [instance:
CC.CellInstance, path:
CF.InstancePath]
RETURNS [leafType: CellType]
--CSC.SubtreeSpec-- = {
ct: CellType ← instance.type;
DO
IF ct.class = PWCore.layoutClass
THEN {
sourceCellType: CellType = PWCore.LayoutCellTypeInfo[ct].sourceCellType;
Compare[sourceCellType];
RETURN [sourceCellType];
};
IF ct.class.recast = NIL THEN RETURN [IF ct.class # CC.recordCellClass THEN ct ELSE NIL];
ct ← CO.Recast[ct];
ENDLOOP;
};
Signal:
SIGNAL [msg:
ROPE] =
CODE;
-- to give the possibility to continue
namesOfCellTypesToIgnore: HashTable.Table ← HashTable.Create[equal: HashTable.RopeEqualModCase, hash: HashTable.HashRopeModCase];
MatchLeaves:
PROC [extractedRoot, sourceRoot: CellType, extractedToSource: HashTable.Table, indirectObj:
CD.Object, decoration: SinixOps.Decoration, hd: HighlightData, abort:
REF
BOOL] = {
extractedRoot ← FuseTransistors[extractedRoot]; -- Patch good enough for now
{
sourceToExtracteds: HashTable.Table = ReverseHashTable[extractedToSource];
roots: ARRAY Role OF CellType ~ [A: extractedRoot, B: sourceRoot];
GiveHints:
PROC [
Consume:
PROC [ds:
ARRAY
CSC.Role
OF
CSC.Descendant]]
--HintsGiver-- = {
PassPair:
PROC [key, value:
REF
ANY]
RETURNS [quit:
BOOL ←
FALSE]
--EachPairProc-- = {
sourcePublic: Wire = NARROW[key];
extractedPublics: Element = NARROW[value];
Consume[[extractedPublics.first, NEW [CF.FlatWireRec ← [wireRoot: public, wire: sourcePublic]]]];
};
[] ← sourceToExtracteds.Pairs[PassPair];
};
ii: CD.Instance ← NIL;
didQuitEarly: REF BOOL ~ NEW [BOOL ← FALSE];
PerMismatch:
PROC
[
msg: ROPE ← NIL,
kind: CSC.MismatchKind,
cts: CSC.CellTypePair,
colorElts: CSC.ColorElts,
Ans: CSC.QueryAnswerer
] --CSC.MismatchConsumer--
= {
cellTypeName: ROPE = CO.GetCellTypeName[cts[Source]];
Ignore: PROC = {IF cellTypeName.Length[] > 0 THEN [] ← namesOfCellTypesToIgnore.Store[cellTypeName, $TRUE] ELSE ERROR--can't do it, you turkey--};
PrintCircuits:
PROC [to:
IO.
STREAM] = {
IF NOT SS.IsAnSS[to] THEN to ← SS.Create[UB.NewInittedHandle[[margin: 50, output: [stream[to]]]]];
to.PutRope["Circuits are: "];
PrintNeighborhood[to, Source, FALSE];
PrintNeighborhood[to, Extracted, FALSE];
};
PrintNeighborhoods:
PROC [to:
IO.
STREAM] = {
IF NOT SS.IsAnSS[to] THEN to ← SS.Create[UB.NewInittedHandle[[margin: 50, output: [stream[to]]]]];
to.PutRope["Neighborhoods are: "];
PrintNeighborhood[to, Source, TRUE];
PrintNeighborhood[to, Extracted, TRUE];
};
PrintNeighborhood:
PROC [to:
IO.
STREAM, which: Role, subset:
BOOL] = {
root: CellType ~ cts[which];
ds: ElementList ~ colorElts[which];
other: Role = OtherRole[which];
CutTest:
PROC [cutData:
REF
ANY, root, cellType: CellType, flatCell:
CF.FlatCellTypeRec, instance:
CC.CellInstance]
RETURNS [
BOOL]
--CFE.CutMembershipTester-- = {
RETURN [instance # NIL AND (SELECT which FROM Source => SourceSubtree, Extracted => ExtractedSubtree, ENDCASE => ERROR)[instance, flatCell.path] # NIL];
};
Annotate:
PROC [subject:
CFE.Descendant, to:
IO.
STREAM] = {
PrintDL:
PROC [which: Role, dls: Element, except:
CSC.Descendant] = {
first: BOOL ← TRUE;
to.PutRope["{"];
FOR dls ← dls, dls.rest
WHILE dls #
NIL
DO
IF except =
NIL
OR
NOT
CSC.DescendantEqual[except, dls.first]
THEN {
IF first THEN first ← FALSE ELSE to.PutRope[", "];
to.PutRope[
WITH dls.first
SELECT
FROM
x: CF.FlatWire => CF.WirePathRope[cts[which], x^],
x: REF CF.InstancePath => CF.InstancePathRope[cts[which], x^],
ENDCASE => ERROR];
};
ENDLOOP;
to.PutRope["}"];
};
WITH subject
SELECT
FROM
x: CF.FlatWire => NULL;
x: REF CF.InstancePath => NULL;
x: CF.FlatCellType => subject ← NEW [CF.InstancePath ← x.path];
ENDCASE => ERROR;
{dlp: CSC.Pair ~ Ans[which, subject];
IF dlp # [
NIL,
NIL]
THEN {
IF dlp[which].rest #
NIL
THEN {
to.PutRope["&"];
PrintDL[which, dlp[which], subject];
};
to.PutRope["~"];
PrintDL[other, dlp[other], NIL];
};
}};
Printit:
PROC = {
WithFilter:
PROC [filter:
CFE.Filter] ~
TRUSTED {
CFE.FlatPrint[root, filter, to, Annotate, [CutTest]];
};
to.PutRope[RoleDescriptions[which].Concat[": "]];
IF subset THEN CFE.MakeNeighborhoodFilter[ds, WithFilter] ELSE WithFilter[NIL];
};
PrintObject[to, Printit, always, " "];
to ← to;
};
IF cellTypeName.Length[] > 0 AND namesOfCellTypesToIgnore.Fetch[cellTypeName].found THEN RETURN;
IF didQuitEarly^
THEN {
FindType:
PROC [elts: ElementList, root: CellType]
RETURNS [
ROPE] ~ {
WITH elts.first.first
SELECT
FROM
dw: CSC.DescendantWire => RETURN ["wire"];
di: CSC.DescendantCellInstance => RETURN [CO.GetCellTypeName[CF.ResolveFlatCellType[root, [di^]].cellType]];
ENDCASE => ERROR;
};
type: ROPE ~ IF colorElts[A] # NIL THEN FindType[colorElts[A], cts[A]] ELSE FindType[colorElts[B], cts[B]];
TerminalIO.PutF["**** Doomed from the start in %g: you have %g extracted %gs and %g in the source\n", [rope[cellTypeName]], [integer[GList.Length[colorElts[Extracted]]]], [rope[type]], [integer[GList.Length[colorElts[Source]]]]];
Signal["Read 'em and weep"];
}
ELSE {
fws: FlatWireRecList ← NIL;
TerminalIO.PutF["*** %g %gbetween extracted and source for %g:\n", IO.rope[kindName[kind]], [rope[IF msg # NIL THEN Rope.Cat["(", msg, ") "] ELSE NIL]], IO.rope[cellTypeName]];
TerminalIO.PutF["\textracted\t=> %g\n", IO.rope[ElementsToRope[colorElts[Extracted], cts[Extracted]]]];
TerminalIO.PutF["\tsource\t=> %g\n", IO.rope[ElementsToRope[colorElts[Source], cts[Source]]]];
FOR elts: ElementList ← colorElts[Extracted], elts.rest
UNTIL elts =
NIL
DO
FOR parts: Element ← elts.first, parts.rest
UNTIL parts =
NIL
DO
WITH parts.first
SELECT
FROM
di: CSC.DescendantCellInstance => NULL;
dw: CSC.DescendantWire => fws ← CONS[dw^, fws];
ENDCASE => ERROR;
ENDLOOP;
ENDLOOP;
{highlight: BOOL = fws # NIL;
IF highlight
THEN {
IF ii=NIL THEN ii ← CDInstances.NewInstI[ob: indirectObj];
IF ii=NIL THEN ii ← NEW [CD.InstanceRep ← [ob: indirectObj]];
IF hd=
NIL
THEN {
hd ← NEW [HighlightDataPrivate ← []];
hd.design ← CDOps.CreateDesign[CD.FetchTechnology[$cmosB]];
hd.viewer ← CDViewer.CreateViewer[hd.design];
};
CDOps.IncludeInstance[hd.design, ii];
SinixOps.HighlightNets[decoration, hd.design, ii, cts[Extracted], fws];
};
Signal["Joe Bob sez check it out"];
IF highlight
THEN {
SinixOps.HighlightDesign[hd.design, NIL];
};
};
};
};
CP.PutCellTypeProp[extractedRoot, sourceToExtractedsKey, sourceToExtracteds];
IF NOT CSC.FlattenAndCompare[RoleDescriptions, [extractedRoot, sourceRoot], [ExtractedSubtree, SourceSubtree], [MergeByPinsAndFuseTransistors, CSC.MergeNothing], GiveHints, NIL, PerMismatch, NIL, autoHack, mayQuitEarly, didQuitEarly, abort].isomorphic THEN Signal["Done with that cell type"];
}};
mayQuitEarly: BOOL ← TRUE;
MergeByPinsAndFuseTransistors:
PROC
[
original, parent: Core.CellType,
path: CF.InstancePath,
EnumerateInstances: PROC [Consume: PROC [ci: CC.CellInstance] RETURNS [stop: BOOL ← FALSE]],
IdentifyActual: PROC [ci: CC.CellInstance, actual: Core.Wire, describe: BOOL ← FALSE] RETURNS [ActualID],
Consume: CSC.MergeConsumer] =
{nFused: NAT ← 0;
fkey: REF ~ NEW [ROPE ← "fused"];
FuseTransistors:
PROC = {
Describe:
PROC [ci:
CC.CellInstance]
RETURNS [description:
ROPE] = {
ip: CF.InstancePath = CF.AddInstance[CF.nullInstancePath, ci, parent];
description ← CF.InstancePathRope[parent, ip];
};
CheckChild:
PROC [ci:
CC.CellInstance]
RETURNS [stop:
BOOL ←
FALSE] = {
IF ci.type.class # CC.transistorCellClass THEN RETURN;
{ci1: CC.CellInstance = ci;
g1: ActualID = IdentifyActual[ci1, ci1.actual[0], debug];
c1a: ActualID = IdentifyActual[ci1, ci1.actual[1], debug];
c1b: ActualID = IdentifyActual[ci1, ci1.actual[2], debug];
CheckOthers:
PROC [ci:
CC.CellInstance]
RETURNS [stop:
BOOL ←
FALSE] = {
IF ci.type.class # CC.transistorCellClass OR CP.GetCellInstanceProp[ci, fused] = fkey THEN RETURN;
IF ci = ci1 THEN RETURN [TRUE];
{ci2: CC.CellInstance = ci;
g2: ActualID = IdentifyActual[ci2, ci2.actual[0], debug];
IF g1.id = g2.id
THEN {
c2a: ActualID = IdentifyActual[ci2, ci2.actual[1], debug];
c2b: ActualID = IdentifyActual[ci2, ci2.actual[2], debug];
IF c1a.id=c2a.id
AND c1b.id=c2b.id
OR c1a.id=c2b.id
AND c1b.id=c2a.id
THEN {
t1: CC.Transistor = NARROW [ci1.type.data];
t2: CC.Transistor = NARROW [ci2.type.data];
IF t1.type=t2.type
AND t1.length=t2.length
THEN {
IF debug THEN TerminalIO.PutF["%g || %g\n", [rope[Describe[ci1]]], [rope[Describe[ci2]]]];
CP.PutCellInstanceProp[ci2, fused, fkey];
nFused ← nFused + 1;
Consume[
LIST[
NEW [CF.InstancePath ← CF.AddInstance[path, ci1, parent]],
NEW [CF.InstancePath ← CF.AddInstance[path, ci2, parent]]]];
}
ELSE IF debug THEN TerminalIO.PutF["%g # %g\n", [rope[Describe[ci1]]], [rope[Describe[ci2]]]];
}
ELSE
IF debug
THEN {
TerminalIO.PutF["%g[%g, %g] # ", [rope[Describe[ci1]]], [rope[c1a.description]], [rope[c1b.description]]];
TerminalIO.PutF["%g[%g, %g]\n", [rope[Describe[ci2]]], [rope[c2a.description]], [rope[c2b.description]]];
};
}
ELSE IF debug THEN TerminalIO.PutF["%g.gate~%g # %g.gate~%g\n", [rope[Describe[ci1]]], [rope[g1.description]], [rope[Describe[ci2]]], [rope[g2.description]]];
}};
EnumerateInstances[CheckOthers];
}};
EnumerateInstances[CheckChild];
IF nFused # 0
THEN {
TerminalIO.PutF["*** PWCoreLichen: %g pairwise transistor fusions in CellType %g.\n", [integer[nFused]], [rope[CO.GetCellTypeName[parent]]]];
};
};
FuseTransistors[];
IF path.length = 0
THEN {
sourceToExtracteds: HashTable.Table = NARROW[CP.GetCellTypeProp[original, sourceToExtractedsKey]];
MergeExtracted:
PROC [key, value:
REF
ANY]
RETURNS [quit:
BOOL ←
FALSE]
--EachPairProc-- = {
sourcePublic: Wire = NARROW[key];
extractedPublics: Element = NARROW[value];
IF extractedPublics.rest # NIL THEN Consume[extractedPublics];
};
[] ← sourceToExtracteds.Pairs[MergeExtracted];
};
};
fused: ATOM = CP.RegisterProperty[$PWCoreLichenTransistorFused, CP.Props[[CP.propPrint, CP.PropDontPrint]]];
debug: BOOL ← FALSE;
ElementsToRope:
PROC [elts: ElementList, root: CellType]
RETURNS [rope:
ROPE ←
NIL] = {
FmtPart:
PROC [part:
REF
ANY]
RETURNS [
ROPE] ~ {
RETURN [
WITH part
SELECT
FROM
fi: REF CF.InstancePath => CF.InstancePathRope[root, fi^],
fw: CF.FlatWire => CF.WirePathRope[root, fw^],
ENDCASE => ERROR]};
sep: ROPE ← NIL;
WHILE elts#
NIL
DO
parts: Element ← elts.first;
this: ROPE ← NIL;
IF parts.rest = NIL THEN this ← FmtPart[parts.first]
ELSE {
sep: ROPE ← "{";
WHILE parts #
NIL
DO
this ← this.Cat[sep, FmtPart[parts.first]];
parts ← parts.rest;
sep ← ", ";
ENDLOOP;
this ← this.Concat["}"];
};
rope ← rope.Cat[sep, this];
elts ← elts.rest;
sep ← ", ";
ENDLOOP;
rope ← rope;
};
FuseTransistors: PROC [recordCell: CellType] RETURNS [new: CellType] = {
oldData, newData, data: CC.RecordCellType;
nb, fused: NAT ← 0;
IF recordCell.class#CC.recordCellClass THEN RETURN [recordCell];
oldData ← NARROW [recordCell.data];
data ← NEW [CC.RecordCellTypeRec[oldData.size]];
data.internal ← oldData.internal;
FOR i: NAT IN [0 .. data.size) DO data[i] ← oldData[i] ENDLOOP;
FOR i: NAT IN [0 .. data.size) DO
IF data[i]=NIL THEN LOOP;
data[i].type ← FuseTransistors[data[i].type];
IF data[i].type.class#CC.transistorCellClass THEN LOOP;
FOR j: NAT IN [0 .. i) DO
IF data[j]=NIL THEN LOOP;
IF data[j].type.class#CC.transistorCellClass THEN LOOP;
IF data[i].actual[0]=data[j].actual[0] AND ((data[i].actual[1]=data[j].actual[1] AND data[i].actual[2]=data[j].actual[2]) OR (data[i].actual[2]=data[j].actual[1] AND data[i].actual[1]=data[j].actual[2])) THEN {
t1: CC.Transistor ← NARROW [data[i].type.data];
t2: CC.Transistor ← NARROW [data[j].type.data];
IF t1.type=t2.type AND t1.length=t2.length THEN {
data[i] ← CC.CreateInstance[
actual: data[i].actual,
type: CC.CreateTransistor[
args: [type: t1.type, length: t1.length, width: t1.width + t2.width],
props: data[i].type.properties
],
props: data[i].properties
];
data[j] ← NIL;
fused ← fused + 1;
};
};
ENDLOOP;
ENDLOOP;
IF fused=0 THEN RETURN [recordCell];
TerminalIO.PutF["*** Lichen for PWCore.Get: fused %g transistors.\n", IO.int[fused]];
new ← CO.CreateCellType[CC.recordCellClass, recordCell.public, NEW [CC.RecordCellTypeRec[data.size-fused]], NIL, recordCell.properties];
newData ← NARROW [new.data];
newData.internal ← data.internal;
FOR i: NAT IN [0 .. data.size) DO
IF data[i]=NIL THEN LOOP;
newData[nb] ← data[i]; nb ← nb + 1;
ENDLOOP;
};
ReverseHashTable:
PROC [fwd: HashTable.Table]
RETURNS [bkwd: HashTable.Table] = {
CopyPair:
PROC [key, value:
REF
ANY]
RETURNS [quit:
BOOL ←
FALSE]
--HashTable.EachPairProc-- = {
wfrom: Wire = NARROW[key];
wto: Wire = NARROW[value];
lfrom: Element ← NARROW[bkwd.Fetch[wto].value];
lfrom ← CONS[NEW [CF.FlatWireRec ← [wireRoot: public, wire: wfrom]], lfrom];
[] ← bkwd.Store[wto, lfrom];
};
bkwd ← HashTable.Create[];
[] ← fwd.Pairs[CopyPair];
bkwd ← bkwd;
};
HashPath:
PROC [ra:
REF
ANY]
RETURNS [hash:
CARDINAL]
--HashTable.HashProc-- = {
path: REF CF.InstancePath = NARROW[ra];
hash ← CF.InstancePathHash[path^];
};
EqualPath:
PROC [r1, r2:
REF
ANY]
RETURNS [eq:
BOOL]
--HashTable.EqualProc-- = {
p1: REF CF.InstancePath = NARROW[r1];
p2: REF CF.InstancePath = NARROW[r2];
eq ← CF.InstancePathEqual[p1^, p2^];
};
PrintObject:
PROC [to:
IO.
STREAM,
PrintIt:
PROC, cond:
UB.BreakCondition ← width, sep:
ROPE ←
NIL] = {
SS.Bp[to, cond, step, sep];
SS.Begin[to];
PrintIt[!UNWIND => SS.End[to]];
SS.End[to];
};
step: NAT ← 3;
Start:
PROC = {
CDCommandOps.RegisterWithMenu[
menu: $ProgramMenu,
entry: "Sisyph Extract design & structurally compare to layout",
doc: "Select an instance of an object which is the schematic for the root of an interesting subtree of a design; then invoke this function. It will chop that subtree up into a smaller subtrees at CD.Objects/Core.CellTypes that are attached by PWCore. Each subtree will be flattened, and structural comparison will be done in Core between the Core that comes from the root schematic and the core that comes from extracting the ChipNDale.",
proc: CompareCmd
];
CDCommandOps.RegisterWithMenu[
menu: $ProgramMenu,
entry: "Forget comparison results in subtree",
doc: "For every Core.CellType in the subtrees rooted at the selections (which must be schematics with layout attached via PWCore), forget whether structural comparison has been done on it",
proc: ForgetCmd
];
CDCommandOps.RegisterWithMenu[
menu: $ProgramMenu,
entry: "Enable Automorphism Hack",
doc: "The automorphism hack is one of two ways to make structural comparison succeed despite (non-trivial (i.e., other than the identity, which technically is an automorphism, but is not problematic for PWCoreLichen)) automorphism in the circuit being compared. Enabling this hack leads to fewer false failures, at the expense of perhaps more obscure reporting of true failures.",
proc: EnableAutomorphismHack
];
CDCommandOps.RegisterWithMenu[
menu: $ProgramMenu,
entry: "Disable Automorphism Hack",
doc: "The automorphism hack is one of two ways to make structural comparison succeed despite (non-trivial (i.e., other than the identity, which technically is an automorphism, but is not problematic for PWCoreLichen)) automorphism in the circuit being compared. Enabling this hack leads to fewer false failures, at the expense of perhaps more obscure reporting of true failures.",
proc: DisableAutomorphismHack
];
};
Start[];
END.