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"]; 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] = { { 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 _ 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; }; 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. ðPWCoreLichenImpl.mesa Copyright c 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 We need them in this order because ExtractedSubtree would side-effect the data-structure created from sourceRoot if it came second. extractedRoot _ FuseTransistors[extractedRoot]; -- Patch good enough for now IF ii=NIL THEN ii _ CDInstances.NewInstI[ob: indirectObj]; 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; }; Ê– "cedar" style˜code™Kšœ Ïmœ1™Kšžœžœ˜—K˜—Kšžœ˜—K˜K˜—šžœ žœž˜Kšœžœ žœ˜Kšœžœžœžœ˜Kšœžœžœžœ˜?Kšžœžœ˜—Kšœžœ˜%šžœžœžœžœ˜šžœžœžœ˜K˜Kšœ$˜$K˜—K˜Kšœžœ˜ K˜—K˜—šŸœžœ˜šŸ œžœ žœ žœ˜1Kšžœ2˜5K˜—Kšœ1˜1Kš žœžœžœ(žœ žœ˜OKšœ˜—K˜&K˜K˜—Kšžœžœ4žœžœ˜`šžœžœ˜šŸœžœ%žœžœ˜Ešžœžœž˜!Kšœžœžœ ˜*Kš œžœžœžœžœ-˜lKšžœžœ˜—K˜—Kš œžœžœžœžœ žœ ˜kKšœå˜åK˜K˜—šžœ˜Kšœžœ˜KšœCžœžœžœžœžœžœžœ˜°Kšœ(žœ=˜gKšœ%žœ7˜^šžœ5žœžœž˜Kšžœ)žœ žœž˜@šžœ žœž˜Kšœžœžœ˜'Kšœžœžœ ˜/Kšžœžœ˜—Kšžœ˜—Kšžœ˜—Kšœ žœ žœ˜šžœ žœ˜Kšžœžœžœ,™:Kš žœžœžœžœžœ"˜=šžœžœžœ˜Kšœžœ˜%Kšœžœ˜;K˜-K˜—K˜%KšœG˜GK˜—Kšœ#˜#šžœ žœ˜Kšœ$žœ˜)K˜—Kšœ˜K˜—Kšœ˜—KšžœK˜MKšžœžœžœ…žœžœžœ:žœ$˜¤K˜Kšœžœžœ˜—K˜šŸœž˜#šœ˜Kšœ ˜ Kšœžœ˜KšŸœžœŸœžœžœžœžœžœ˜\Kš Ÿœžœžœ,žœžœžœ ˜iKšŸœžœ˜—Kšœ žœ˜Kšœžœžœžœ ˜!šŸœžœ˜š Ÿœžœžœžœžœ˜DKšœžœžœ žœ˜FKšœžœ˜.K˜—š Ÿ œžœžœžœžœžœ˜GKšžœžœžœžœ˜6Kšœžœ˜Kšœ9˜9Kšœ:˜:Kšœ:˜:š Ÿ œžœžœžœžœžœ˜HKš žœžœžœžœ'žœžœ˜bKšžœ žœžœžœ˜Kšœžœ˜Kšœ9˜9šžœžœ˜Kšœ:˜:Kšœ:˜:š žœžœžœžœžœ˜LKšœžœžœ˜+Kšœžœžœ˜+šžœžœžœ˜1KšžœžœM˜ZKšžœ'˜)K˜šœžœ˜ Kšžœžœžœ!˜:Kšžœžœžœ#˜<—K˜—KšžœžœžœL˜^K˜—šžœžœžœ˜Kšœj˜jKšœi˜iKšœ˜—K˜—KšžœžœžœŒ˜žK˜—Kšœ ˜ K˜—Kšœ˜šžœ žœ˜Kšœožœ˜K˜—K˜—K˜šžœžœ˜Kšœ&žœžœ3˜bšŸœžœžœžœžœžœžœ œ˜\Kšœžœ˜!Kšœžœ˜*Kšžœžœžœ˜>K˜—Kšœ.˜.K˜—K˜Kš œžœžœ0žœžœ žœÏb œ˜lKšœžœžœ˜—K˜š Ÿœžœ%žœžœžœ˜Wš Ÿœžœžœžœžœžœ˜0šžœžœžœž˜Kšœžœžœžœ˜:Kšœžœ žœ˜.Kšžœžœ˜——Kšœžœžœ˜šžœžœžœ˜K˜Kšœžœžœ˜Kšžœžœžœ˜4šžœ˜Kšœžœ˜šžœ žœž˜K˜+K˜K˜ Kšžœ˜—K˜K˜—Kšœ˜Kšœ˜K˜ Kšžœ˜—K˜ K˜K˜—šŸœžœžœ™HKšœžœ™*Kšœ žœ™Kšžœžœžœžœ™@Kšœ žœ™#Kšœžœžœ"™0Kšœ!™!Kš žœžœžœžœžœ™?šžœžœžœž™!Kšžœ žœžœžœ™Kšœ-™-Kšžœžœžœžœ™7šžœžœžœ žœ™Kšžœ žœžœžœ™Kšžœžœžœžœ™7š žœ%žœ'žœ&žœ&žœ'žœ™ÒKšœžœžœ™/Kšœžœžœ™/šžœžœžœ™1šœ žœ™Kšœ™šœžœ™KšœF™FKšœ™Kšœ™—Kšœ™Kšœ™—Kšœ žœ™K™K™—K™—Kšžœ™—Kšžœ™—Kšžœ žœžœ™$Kšžœ7žœ ™UKš œžœžœ%žœžœ&žœ™ˆKšœ žœ ™Kšœ!™!šžœžœžœž™!Kšžœ žœžœžœ™Kšœ#™#Kšžœ™—K™—K˜šŸœžœžœ˜QšŸœžœžœžœžœžœžœ œ˜`KšœÏdœ žœ˜Kšœ¢œ žœ˜Kšœ¢œ žœ ¢œ ˜/Kš œ¢œžœžœžœ)¢œ¢œ˜LKšœ¢œ¢œ˜K˜—K˜K˜K˜ K˜—K˜šŸœžœžœžœžœžœ œ˜PKšœžœžœžœ˜'Kšœžœ˜"K˜—K˜šŸ œžœ žœžœžœžœ œ˜PKšœžœžœžœ˜%Kšœžœžœžœ˜%Kšœžœ˜$K˜—K˜šŸ œžœžœžœŸœžœžœžœžœ˜fKšžœ˜Kšžœ ˜ Kšœ žœžœ ˜Kšžœ ˜ K˜Kšœžœ˜—K˜šŸœžœ˜šœ˜K˜K˜@K˜¸Kšœ˜K˜—šœ˜K˜K˜.K˜½Kšœ˜K˜—šœ˜K˜K˜"K˜ýKšœ˜K˜—šœ˜K˜K˜#K˜ýKšœ˜K˜—K˜—K˜K˜K˜Kšžœ˜K™—…—Iòiñ