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: BOOLFALSE;
CompareCmd: PROC [cmd: CDSequencer.Command] --CDSequencer.CommandProc-- = {
abort: REF BOOL ~ NEW [BOOLFALSE];
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: NATLAST[NAT], parent: CellType ← NIL, flatParent: CF.FlatCellTypeRec ← [], data: REF ANYNIL] --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 [BOOLFALSE];
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: BOOLFALSE] --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 [BOOLFALSE];
PerMismatch: PROC
[
msg: ROPENIL,
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: BOOLTRUE;
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: BOOLTRUE;
MergeByPinsAndFuseTransistors: PROC
[
original, parent: Core.CellType,
path: CF.InstancePath,
EnumerateInstances: PROC [Consume: PROC [ci: CC.CellInstance] RETURNS [stop: BOOLFALSE]],
IdentifyActual: PROC [ci: CC.CellInstance, actual: Core.Wire, describe: BOOLFALSE] 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: BOOLFALSE] = {
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: BOOLFALSE] = {
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: BOOLFALSE] --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: BOOLFALSE;
ElementsToRope: PROC [elts: ElementList, root: CellType] RETURNS [rope: ROPENIL] = {
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: ROPENIL;
WHILE elts#NIL DO
parts: Element ← elts.first;
this: ROPENIL;
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: BOOLFALSE] --HashTable.EachPairProc-- = {
wfrom: Wire = NARROW[key];
wto: Wire = NARROW[value];
lfrom: Element ← NARROW[bkwd.Fetch[wto].value];
lfromCONS[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: ROPENIL] = {
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.