DIRECTORY AMBridge, AMModel, AMTypes, BackStop, BrineIO, CD, CDOps, CDSequencer, CDSequencerExtras, CDViewer, Core, CoreCDUser, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, CoreStructuralComparison, GList, Interpreter, InterpreterOps, IO, List, PopUpButtons, ProcessProps, PWCLCoreFlatExtras, PWCore, PWCoreLichen, RefTab, Rope, SimpleMailer, Sisyph, StructuredStreams, SymTab, TerminalIO, UnparserBuffer, UserProfile, ViewerClasses, ViewerTools, WorldVM; PWCoreLichenImpl: CEDAR PROGRAM IMPORTS AMBridge, AMModel, AMTypes, BackStop, BrineIO, CD, CDOps, CDSequencer, CDSequencerExtras, CDViewer, CoreCDUser, CoreClasses, CoreFlat, CoreIO, CoreOps, CoreProperties, CoreStructuralComparison, GList, InterpreterOps, IO, List, PopUpButtons, ProcessProps, PWCLCoreFlatExtras, PWCore, RefTab, Rope, SimpleMailer, Sisyph, StructuredStreams, SymTab, TerminalIO, UnparserBuffer, UserProfile, ViewerTools, WorldVM EXPORTS PWCoreLichen SHARES PWCore = BEGIN OPEN CC:CoreClasses, CF:CoreFlat, CFE:PWCLCoreFlatExtras, CO:CoreOps, CP:CoreProperties, CSC:CoreStructuralComparison, PUB:PopUpButtons, 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; TV: TYPE ~ AMBridge.TV; BadRoot: PUBLIC SIGNAL [root: CellType] ~ CODE; Message: PUBLIC SIGNAL [msg: ROPE] ~ CODE; FoundProblems: PUBLIC SIGNAL [source, extracted: CellType] ~ CODE; MsgFailed: SIGNAL ~ CODE; SourceInfo: TYPE ~ REF SourceInfoPrivate; SourceInfoPrivate: TYPE ~ RECORD [layout: CD.Object, sourceCT: CellType, liKey: INT, extractedToSource, sourceToExtracteds: RefTab.Ref]; CompareData: TYPE ~ REF CompareDataPrivate; CompareDataPrivate: TYPE ~ RECORD [ context: Context, vsp: CSC.ViewStatsPair, hd: HighlightData, extractedToSourceInfo: RefTab.Ref, chops: REF INT, chop: BOOL _ FALSE --stacked via lambda-binding-- ]; wideTransistorTolerances: PUBLIC TransistorTolerances ~ CoreStructuralComparison.wideTransistorTolerances; tightTransistorTolerances: PUBLIC TransistorTolerances ~ CoreStructuralComparison.tightTransistorTolerances; FormatTolerances: PUBLIC PROC [ttols: TransistorTolerances] RETURNS [ROPE] ~ {RETURN CoreStructuralComparison.FormatTolerances[ttols]}; OtherRole: ARRAY Role OF Role = [A: B, B: A]; Extracted: Role ~ B; Source: Role ~ A; RoleDescriptions: CSC.RoleNames _ ALL["uninitialized"]; HighlightData: TYPE = REF HighlightDataPrivate; HighlightDataPrivate: TYPE = RECORD [ design: CD.Design _ NIL, viewer: ViewerClasses.Viewer _ NIL, ii: CD.Instance _ NIL ]; compareResults: ATOM = CoreIO.RegisterProperty[CP.RegisterUnprintableProperty[$PWCoreLichenCompareResults], WriteNil, ReadNil]; --I have to have a read proc because of expensive existing files with the written crock in them. I have to have a write proc because I can't register only a read proc, and there are expensive existing data structures (at November 19, 1987 5:31:56 pm PST). globKeyProp: ATOM = CoreIO.RegisterProperty[CP.RegisterUnprintableProperty[$PWCoreLichenImplGlobalKey], WriteNil, ReadNil]; doneProp: ATOM ~ CP.RegisterUnprintableProperty[$PWCoreLichenImplDone]; kindName: ARRAY CSC.MismatchKind OF ROPE ~ ["Stuck", "Difference", "Transitor shape mismatch"]; transistorTolerancesProp: PUBLIC ATOM ~ CP.RegisterProperty[$LichenTransistorTolerances]; chopProp: ATOM ~ CP.RegisterProperty[$PWCoreLichenChop]; check: BOOL _ TRUE; autoHack: BOOL _ FALSE; mayQuitEarly: BOOL _ TRUE; globKey: REF INT _ NEW [INT _ 1]; trace: PUBLIC SymTab.Ref _ SymTab.Create[case: TRUE]; StatsCmd: PROC [cmd: CDSequencer.Command] = {DisplayStats[]}; cmdTTols: TransistorTolerances _ wideTransistorTolerances; CompareCmd: PROC [cmd: CDSequencer.Command] --CDSequencer.CommandProc-- = { abort: REF BOOL ~ NEW [BOOL _ FALSE]; Inner: PROC ~ { CompareOne: CoreCDUser.EachRootCellTypeProc ~ { name: ROPE = CO.GetCellTypeName[root]; allOK: BOOL; {TerminalIO.PutF["Extracting and comparing %g.\n", IO.rope[name]]; allOK _ Compare[root, [cmd.design], cmdTTols !BadRoot => GOTO badrut]; TerminalIO.PutRope["Done extracting and comparing "]; TerminalIO.PutRope[name]; TerminalIO.PutRope[IF allOK THEN "; no new errors discovered.\n" ELSE "; some new errors discovered.\n"]; EXITS badrut => TerminalIO.PutRope["... that's not a valid root (there's no layout attached)!\n"]}; quit _ abort^; }; [] _ CoreCDUser.EnumerateSelectedCellTypes[cmd.design, CompareOne, Sisyph.mode]; }; CDSequencer.UseAbortFlag[cmd.design, abort]; TerminalIO.PutF["For PWCoreLichen, mayQuitEarly=%g, automorphismHack=%g, top transistor tolerances=%g\n", [boolean[GetQuitEarly[]]], [boolean[GetAutomorphismHack[]]], [rope[FormatTolerances[cmdTTols]]] ]; ProcessProps.AddPropList[List.PutAssoc[$AbortBool, abort, NIL], Inner]; }; ForgetCmd: PROC [cmd: CDSequencer.Command] --CDSequencer.CommandProc-- = { abort: REF BOOL ~ NEW [BOOL _ FALSE]; Inner: PROC ~ { ForgetOne: CoreCDUser.EachRootCellTypeProc ~ { name: ROPE = CO.GetCellTypeName[root]; TerminalIO.PutF["Forgetting comparisons for subtree rooted at %g.\n", IO.rope[name]]; ForgetComparisons[root]; quit _ abort^; }; [] _ CoreCDUser.EnumerateSelectedCellTypes[cmd.design, ForgetOne, Sisyph.mode]; }; CDSequencer.UseAbortFlag[cmd.design, abort]; ProcessProps.AddPropList[List.PutAssoc[$AbortBool, abort, NIL], Inner]; }; GlobalForgetCmd: PROC [cmd: CDSequencer.Command] --CDSequencer.CommandProc-- = { GlobalForget[]; TerminalIO.PutF["All previous results from Lichen have been forgotten\n"]; RETURN}; SetAutomorphismHackCmd: PROC [cmd: CDSequencer.Command] ~ { SELECT cmd.key FROM $PWCoreLichenEnableAutomorphismHack => SetAutomorphismHack[TRUE]; $PWCoreLichenDisableAutomorphismHack => SetAutomorphismHack[FALSE]; ENDCASE => ERROR; -- invalid command key !!! TerminalIO.PutF["Lichen now %gs automorphisms in graphs\n", IO.rope[IF GetAutomorphismHack[] THEN "accept" ELSE "reject"]]; }; SetQuitEarlyCmd: PROC [cmd: CDSequencer.Command] ~ { SELECT cmd.key FROM $PWCoreLichenEnableQuitEarly => SetQuitEarly[TRUE]; $PWCoreLichenDisableQuitEarly => SetQuitEarly[FALSE]; ENDCASE => ERROR; -- invalid command key !!! TerminalIO.PutF["Lichen now %g quit early\n", IO.rope[IF GetQuitEarly[] THEN "may" ELSE "may not"]]; }; SetTolerancesCmd: PROC [cmd: CDSequencer.Command] ~ { ENABLE TerminalIO.UserAbort => CONTINUE; SELECT cmd.key FROM $PWCoreLichenWideTolerances => cmdTTols _ wideTransistorTolerances; $PWCoreLichenTightTolerances => cmdTTols _ tightTransistorTolerances; $PWCoreLichenReadTolerances => { rope: ROPE ~ TerminalIO.RequestRope["Top transistor tolerances (e.g., \"length: 1.5, width: 2.0\"): "]; cmdTTols _ RefineTolerances[rope, cmdTTols]; }; ENDCASE => ERROR; -- invalid command key !!! TerminalIO.PutRope[Rope.Cat["PWCoreLichen top transistor tolerances are now ", FormatTolerances[cmdTTols], "\n"]]; }; PrintConstraintsCmd: PROC [cmd: CDSequencer.Command] --CDSequencer.CommandProc-- = { abort: REF BOOL ~ NEW [BOOL _ FALSE]; Inner: PROC ~ { PrintPerCellType: CoreCDUser.EachRootCellTypeProc ~ { extracted: CellType ~ PWCore.LayoutInfo[root].extractedCT; name: ROPE = CO.GetCellTypeName[extracted]; constraints: RefTab.Ref ~ GetConstraints[extracted]; PerConstraint: PROC [key, val: REF ANY] RETURNS [quit: BOOL _ FALSE] ~ { constraint: RefTab.Ref ~ NARROW[val]; sep: ROPE _ NIL; PerWire: PROC [key, val: REF ANY] RETURNS [quit: BOOL _ FALSE] ~ { wire: Core.Wire ~ NARROW[key]; TerminalIO.PutRope[sep]; TerminalIO.PutRope[CO.GetFullWireName[extracted.public, wire]]; sep _ ", "; quit _ abort^}; TerminalIO.PutRope["\t"]; [] _ constraint.Pairs[PerWire]; TerminalIO.PutRope[";\n"]; quit _ abort^}; IF constraints=NIL OR constraints.GetSize=0 THEN TerminalIO.PutF["No commonality constraints for %g.\n", IO.rope[name]] ELSE { TerminalIO.PutF["Commonality constraints of %g:\n", IO.rope[name]]; [] _ constraints.Pairs[PerConstraint]; TerminalIO.PutRope["\t.\n"]; }; quit _ abort^}; [] _ CoreCDUser.EnumerateSelectedCellTypes[cmd.design, PrintPerCellType, Sisyph.mode]; }; CDSequencer.UseAbortFlag[cmd.design, abort]; ProcessProps.AddPropList[List.PutAssoc[$AbortBool, abort, NIL], Inner]; }; TraceProc: PROC [viewer: PUB.Viewer, instanceData, classData, key: REF ANY] --PUB.PopUpButtonProc-- ~ { sel: ROPE ~ ViewerTools.GetSelectionContents[]; SELECT key FROM $AddTrace => { IF sel.Length[] = 0 THEN GOTO Usage; [] _ trace.Store[sel, $trace]; TerminalIO.PutF["Lichen also tracing %g\n", [rope[sel]]]}; $RemTrace => { IF sel.Length[] = 0 THEN GOTO Usage; [] _ trace.Delete[sel]; TerminalIO.PutF["Lichen not tracing %g\n", [rope[sel]]]}; $ClearTraces => { trace.Erase[]; TerminalIO.PutRope["Lichen not tracing anything\n"]}; $ListTraces => { first: BOOL _ TRUE; ListTrace: PROC [key, val: REF ANY] RETURNS [quit: BOOL _ FALSE] --SymTab.EachPairAction-- ~ { name: ROPE ~ NARROW[key]; IF first THEN first _ FALSE ELSE TerminalIO.PutRope[", "]; TerminalIO.PutRope[name]; RETURN}; TerminalIO.PutF["Lichen tracing %g names: ", [integer[trace.GetSize]]]; IF trace.Pairs[ListTrace] THEN ERROR; TerminalIO.PutRope["\n"]}; ENDCASE => ERROR; -- invalid command key !!! EXITS Usage => TerminalIO.PutRope["Invoke with a vertex name in the current Tioga selection\n"] }; traceButtonClass: PUB.Class ~ PUB.MakeClass[[ proc: TraceProc, choices: LIST[ [$AddTrace, "Add Tioga selection to the set of traced names"], [$ListTraces, "List the set of traced names"], [$RemTrace, "Remove Tioga selection from the set of traced names"], [$ClearTraces, "Clear the set of traced names"], ] ]]; traceButton: PUB.Viewer ~ traceButtonClass.Instantiate[viewerInfo: [name: "PWCL Trace"]]; TrackProfile: PROC [reason: UserProfile.ProfileChangeReason] --UserProfile.ProfileChangedProc-- = { cmdTTols _ RefineTolerances[UserProfile.Line["PWCoreLichen.TopTolerances", ""], wideTransistorTolerances]; RETURN}; DisplayStats: PUBLIC PROC ~ {CSC.DisplayStats[]}; ForgetComparisons: PUBLIC PROC [root: CellType] ~ { seen: RefTab.Ref ~ RefTab.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, compareResults, NIL]; CP.PutCellTypeProp[cell, doneProp, 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}; GetAutomorphismHack: PUBLIC PROC RETURNS [enabled: BOOL] = {enabled _ autoHack}; SetQuitEarly: PUBLIC PROC [may: BOOL] ~ {mayQuitEarly _ may}; GetQuitEarly: PUBLIC PROC RETURNS [may: BOOL] ~ {may _ mayQuitEarly}; GlobalForget: PUBLIC PROC ~ {globKey _ NEW [INT _ globKey^+1]; RETURN}; Compare: PUBLIC PROC [root: CellType, context: Context, ttols: TransistorTolerances _ wideTransistorTolerances] RETURNS [allOK: BOOL _ TRUE] = { ENABLE FoundProblems => allOK _ FALSE; cd: CompareData ~ NEW [CompareDataPrivate _ [context, CSC.CreateViewStatsPair[], NEW [HighlightDataPrivate _ []], RefTab.Create[], NEW [INT _ 0] ]]; sent: BOOL; info: SimpleMailer.SendMessageInfo; RecursiveCompare[root: root, cd: cd, ttols: ttols]; [sent, info] _ SimpleMailer.SendMessage[ from: "PWCoreLichen", to: LIST["Spreitzer.pa"], subject: CO.GetCellTypeName[root].Concat[" View Statistics"], body: IO.PutFR["chops: %g\n", [integer[cd.chops^]]] .Concat[CSC.FmtViewStatsPair[cd.vsp, RoleDescriptions]]]; IF (NOT sent) OR info # ok THEN SIGNAL MsgFailed; RETURN}; CompareForTheRestOfUs: PUBLIC PROC [root: CellType, design: CD.Design, precision: REAL _ 0.90] RETURNS [allOK: BOOL _ TRUE] = { ttols: TransistorTolerances; SELECT precision FROM >=1.0 => ttols _ tightTransistorTolerances; <= 0.000001 => ttols _ wideTransistorTolerances; ENDCASE => { ttols _ NEW[CoreStructuralComparison.TransistorTolerancesPrivate]; ttols[length] _ [precision, 1/precision]; ttols[width] _ [precision, 1/precision]; }; allOK _ Compare[root, [design], ttols]; }; RecursiveCompare: PROC [root: CellType, cd: CompareData, ttols: TransistorTolerances] = { extractedToSourceInfo: RefTab.Ref ~ NARROW[CP.GetCellTypeProp[root, compareResults]]; sameKey: BOOL ~ WITH CP.GetCellTypeProp[root, globKeyProp] SELECT FROM x: REF INT => x^ = globKey^, ENDCASE => FALSE; layoutAtom: ATOM = 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 sameKey AND extractedToSourceInfo#NIL => { IF extractedToSourceInfo#cd.extractedToSourceInfo THEN MergeRefTabs[cd.extractedToSourceInfo, extractedToSourceInfo]; RETURN}; layoutAtom#NIL => { done: BOOL ~ SELECT CP.GetCellTypeProp[root, doneProp] FROM NIL => FALSE, $TRUE => TRUE, ENDCASE => ERROR; source: CellType ~ root; extracted: CellType; extractedToSource, sourceToExtracteds: RefTab.Ref; layout: CD.Object; liKey: INT; IF abort^ THEN RETURN; CSC.PushTimer[$PWCore]; {ENABLE UNWIND => CSC.PopTimer[$PWCore]; [layout: layout, extractedCT: extracted, extractedToSource: extractedToSource, key: liKey] _ PWCore.LayoutInfo[source]; sourceToExtracteds _ ReverseRefTab[extractedToSource]}; CSC.PopTimer[$PWCore]; IF NOT cd.extractedToSourceInfo.Insert[extracted, NEW [SourceInfoPrivate _ [layout, source, liKey, extractedToSource, sourceToExtracteds]]] THEN ERROR; IF abort^ THEN RETURN; IF cd.chop THEN cd.chops^ _ cd.chops^ + 1 ELSE IF done THEN cd.chop _ TRUE ELSE MatchLeaves[extracted, source, sourceToExtracteds, layout, liKey, ttols, cd, abort]; IF abort^ THEN RETURN; CP.PutCellTypeProp[root, compareResults, cd.extractedToSourceInfo]; CP.PutCellTypeProp[root, globKeyProp, globKey]; CP.PutCellTypeProp[root, doneProp, $TRUE]; }; root.class=CC.recordCellClass => SIGNAL BadRoot[root]; ENDCASE => { cd.context.path.recastCount _ cd.context.path.recastCount+1; RecursiveCompare[CO.Recast[root], cd, ttols]; RETURN}; }; MergeRefTabs: PROC [to, from: RefTab.Ref] ~ { MovePair: PROC [key, val: REF ANY] RETURNS [quit: BOOL _ FALSE] ~ {[] _ to.Insert[key, val]; RETURN}; [] _ from.Pairs[MovePair]; RETURN}; SourceSubtree: PROC [data: REF ANY, instance: CC.CellInstance, path: CF.InstancePath, ttols: TransistorTolerances] RETURNS [CSC.SubtreeAns] --CSC.SubtreeSpec-- = { cd: CompareData ~ NARROW[data]; oldChop: BOOL ~ cd.chop; ct: CellType _ instance.type; recastCount: NAT _ 0; DO SELECT CP.GetCellTypeProp[ct, chopProp] FROM NIL => NULL; $TRUE => cd.chop _ TRUE; ENDCASE => ERROR; IF GetLayoutAtom[ct]#NIL THEN { subData: CompareData ~ NEW [CompareDataPrivate _ cd^]; subData.context.path _ CFE.LowerFlatCell[[path, recastCount], cd.context.path]; RecursiveCompare[ct, subData, ttols !BadRoot => ERROR]; GOTO Dun}; IF ct.class.recast=NIL THEN { IF ct.class#CC.recordCellClass THEN GOTO Dun; RETURN [[NIL, [NIL], IF cd.chop AND ~oldChop THEN Pop ELSE NIL]]}; ct _ CO.Recast[ct]; REPEAT Dun => RETURN [[ct, CSC.CreateParallelMapper[ct, instance.type], IF cd.chop AND ~oldChop THEN Pop ELSE NIL]]; ENDLOOP; }; Pop: PROC [data: REF ANY] ~ {cd: CompareData ~ NARROW[data]; cd.chop _ FALSE; RETURN}; GetLayoutAtom: PROC [cellType: CellType] RETURNS [ATOM] ~ {RETURN [NARROW[CP.GetCellTypeProp[cellType, PWCore.layoutAtomProp]]]}; EnumData: TYPE ~ REF EnumDataPrivate; EnumDataPrivate: TYPE ~ RECORD [ si: SourceInfo, finish: RefTab.Ref _ NIL ]; ExtractedSubtree: PROC [data: REF ANY, instance: CC.CellInstance, path: CF.InstancePath, ttols: TransistorTolerances] RETURNS [CSC.SubtreeAns] --CSC.SubtreeSpec-- = { cd: CompareData ~ NARROW[data]; ct: CellType _ instance.type; DO si: SourceInfo ~ NARROW[cd.extractedToSourceInfo.Fetch[ct].val]; IF check THEN TRUSTED { source: CellType ~ LOOPHOLE[PWCore.GetPWCoreExtractedCTKey[ct]]; sourced: BOOL ~ source#LOOPHOLE[0] AND GetLayoutAtom[source]#NIL; IF hardNosed AND source#LOOPHOLE[0] AND ~sourced THEN ct _ ct; IF sourced # (si#NIL) THEN ERROR}; IF si#NIL THEN RETURN [[si.sourceCT, [EnumerateSourceToExtracteds, NEW [EnumDataPrivate _ [si, IF ct#instance.type THEN CO.CreateBindingTable[ct.public, instance.type.public] ELSE NIL]]]]]; IF ct.class.recast=NIL THEN { IF ct.class#CC.recordCellClass THEN RETURN [[ct, CSC.CreateParallelMapper[ct, instance.type]]]; RETURN [[NIL, [NIL]]]}; ct _ CO.Recast[ct]; ENDLOOP; }; hardNosed: BOOL _ FALSE; EnumerateSourceToExtracteds: PROC [data: REF ANY, Consume: CSC.MapConsumer] ~ { ed: EnumData ~ NARROW[data]; si: SourceInfo ~ ed.si; seen: RefTab.Ref ~ RefTab.Create[]; PerFrom: PROC [wire: Wire] RETURNS [subWires: BOOL _ TRUE, quit: BOOL _ FALSE] --CO.EachWireProc-- ~ { IF wire.size#0 THEN RETURN; IF seen.Fetch[wire].found THEN RETURN; IF NOT seen.Insert[wire, $T] THEN ERROR; {extracteds: CSC.Element ~ NARROW[si.sourceToExtracteds.Fetch[wire].val]; ProduceTos: PROC [Consume: CSC.ToConsumer] ~ { FOR dl: CSC.Element _ extracteds, dl.rest WHILE dl#NIL DO WITH dl.first SELECT FROM dw: CSC.DescendantWire => { IF dw.flatCell.path.length#0 THEN ERROR; {it: Wire ~ IF ed.finish=NIL THEN dw.wire ELSE NARROW[ed.finish.Fetch[dw.wire].val]; IF it=NIL THEN ERROR; Consume[it]}}; ENDCASE => ERROR; wire _ wire; ENDLOOP; RETURN}; IF extracteds=NIL THEN ERROR; Consume[wire, ProduceTos]; RETURN}}; IF CO.VisitWireSeq[si.sourceCT.public, PerFrom] THEN ERROR; RETURN}; namesOfCellTypesToIgnore: SymTab.Ref _ SymTab.Create[case: FALSE]; MatchLeaves: PROC [extractedRoot, sourceRoot: CellType, sourceToExtracteds: RefTab.Ref, layout: CD.Object, liKey: INT, ttols: TransistorTolerances, cd: CompareData, abort: REF BOOL] = { GiveHints: PROC [Consume: PROC [ds: ARRAY CSC.Role OF CSC.Descendant]] --HintsGiver-- = { PassPair: PROC [key, val: REF ANY] RETURNS [quit: BOOL _ FALSE] --EachPairProc-- = { sourcePublic: Wire = NARROW[key]; extractedPublics: Element = NARROW[val]; ds: ARRAY CSC.Role OF CSC.Descendant; ds[Extracted] _ extractedPublics.first; ds[Source] _ NEW [CF.FlatWireRec _ [wireRoot: public, wire: sourcePublic]]; Consume[ds]; }; [] _ sourceToExtracteds.Pairs[PassPair]; }; ii: CD.Instance _ NIL; didQuitEarly: REF BOOL ~ NEW [BOOL _ FALSE]; contexized: BOOL _ FALSE; Contexize: PROC ~ { IF contexized THEN RETURN; contexized _ TRUE; IF cd.hd.viewer=NIL THEN { cd.hd.design _ CDOps.CreateDesign[CD.FetchTechnology[$cmosB]]; cd.hd.viewer _ CDViewer.CreateViewer[cd.hd.design]; }; IF cd.hd.ii=NIL OR cd.hd.ii.ob#layout THEN { IF cd.hd.ii#NIL THEN CDOps.RemoveInstance[cd.hd.design, cd.hd.ii, FALSE]; CDOps.IncludeInstance[cd.hd.design, cd.hd.ii _ NEW [CD.InstanceRep _ [ob: layout]]]; cd _ cd}; CoreCDUser.SetDesignRootCellType[cd.context.design, sourceRoot]; CoreCDUser.SetDesignRootCellType[cd.hd.design, extractedRoot]; CoreCDUser.SetRootCellTypeDecoration[sourceRoot, Sisyph.mode.decoration]; CoreCDUser.SetRootCellTypeDecoration[extractedRoot, PWCore.extractMode.decoration]; RETURN}; PrintWork: PROC [to: IO.STREAM, which: Role, subset: BOOL, root, other: CellType, ds: ElementList, Ans: CSC.QueryAnswerer] = { 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)[cd, instance, flatCell.path, ttols].leafType#NIL]; }; Annotate: PROC [subject: CFE.Descendant, to: IO.STREAM] = { PrintDL: PROC [which: CellType, 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[which, x^], x: REF CF.InstancePath => CF.InstancePathRope[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 ~ IF Ans#NIL THEN Ans[which, subject] ELSE [NIL, NIL]; IF dlp # [NIL, NIL] THEN { IF dlp[which].rest # NIL THEN { to.PutRope["&"]; PrintDL[root, dlp[which], subject]; }; to.PutRope["~"]; PrintDL[other, dlp[OtherRole[which]], 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; }; 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]]; PrintNeighborhood: PROC [to: IO.STREAM, which: Role, subset: BOOL] = { other: Role ~ OtherRole[which]; PrintWork[to, which, subset, cts[which], cts[other], colorElts[which], Ans]}; 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]; }; 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]; }; Ignore: PROC = {IF cellTypeName.Length[] > 0 THEN [] _ namesOfCellTypesToIgnore.Store[cellTypeName, $TRUE] ELSE ERROR--can't do it, you turkey--}; IF cellTypeName.Length[] > 0 AND namesOfCellTypesToIgnore.Fetch[cellTypeName].found THEN RETURN; CSC.PushTimer[$debug]; {ENABLE UNWIND => CSC.PopTimer[$debug]; 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[Source] # NIL THEN FindType[colorElts[Source], cts[Source]] ELSE FindType[colorElts[Extracted], cts[Extracted]]; TerminalIO.PutF["**** Doomed from the start in %g: you have %g layout %gs and %g in the source\n", [rope[cellTypeName]], [integer[GList.Length[colorElts[Extracted]]]], [rope[type]], [integer[GList.Length[colorElts[Source]]]]]; Message["Read 'em and weep"]; } ELSE { fws: FlatWireRecList _ NIL; TerminalIO.PutF["*** %g %gbetween layout and source for %g:\n", IO.rope[kindName[kind]], [rope[IF msg # NIL THEN Rope.Cat["(", msg, ") "] ELSE NIL]], IO.rope[cellTypeName]]; TerminalIO.PutF["\tlayout\t=> %g\n", IO.rope[ElementsToRope[colorElts[Extracted], cts[Extracted]]]]; TerminalIO.PutF["\tsource\t=> %g\n", IO.rope[ElementsToRope[colorElts[Source], cts[Source]]]]; Contexize[]; FOR role: Role IN Role DO clearFirst: BOOL _ TRUE; FOR elts: ElementList _ colorElts[role], 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 => CoreCDUser.HighlightFlatCellType[root: roots[role], flatCell: [di^, 0], clearFirst: clearFirst]; dw: CSC.DescendantWire => CoreCDUser.HighlightFlatWire[root: roots[role], flatWire: dw^, clearFirst: clearFirst]; ENDCASE => ERROR; clearFirst _ FALSE; ENDLOOP; ENDLOOP; ENDLOOP; Message["Joe Bob sez check it out"]; cd _ cd}; }; CSC.PopTimer[$debug]}; PerDroppedConnection: PROC [role: Role, subroot: Core.CellType, public, actual: CF.FlatWire] ~ { PrintNeighborhood: PROC [to: IO.STREAM, subset: BOOL] = { PrintWork[to, role, subset, subroot, NIL, LIST[LIST[actual]], NIL]}; Message[IO.PutFR["*** Dropped connection below %g %g between public %g and actual %g", IO.rope[RoleDescriptions[role]], [rope[CO.GetCellTypeName[subroot]]], [rope[CF.WirePathRope[subroot, public^]]], IO.rope[CF.WirePathRope[subroot, actual^]]]]; aok _ FALSE}; PerBogusMerge: PROC [role: Role, subroot: Core.CellType, w1, w2: CF.FlatWire, from: REF CF.InstancePath] ~ { PrintNeighborhood: PROC [to: IO.STREAM, subset: BOOL] = { PrintWork[to, role, subset, subroot, NIL, LIST[LIST[w1], LIST[w2]], NIL]}; Message[IO.PutFR["*** Wires %g and %g in %g %g not consistent with fusion by source at or below %g", [rope[CF.WirePathRope[subroot, w1^]]], [rope[CF.WirePathRope[subroot, w2^]]], [rope[RoleDescriptions[role]]], [rope[CO.GetCellTypeName[subroot]]], [rope[CF.InstancePathRope[subroot, from^]]] ]]; aok _ FALSE}; roots: CSC.CellTypePair _ ALL[extractedRoot]; stss: CSC.SubtreeSpecPair _ ALL[ExtractedSubtree]; mss: CSC.MergeSpecPair _ ALL[MergeByPinsAndFuseTransistors]; specVal: REF ANY ~ CP.InheritCellTypeProp[sourceRoot, transistorTolerancesProp]; oldChop: BOOL ~ cd.chop; ttolsCopied: BOOL _ FALSE; aok: BOOL _ TRUE; roots[Source] _ sourceRoot; stss[Source] _ SourceSubtree; mss[Source] _ CSC.MergeNothing; ttols _ RefineTolerances[specVal, ttols]; cd.chop _ FALSE; IF NOT (CSC.FlattenAndCompare[RoleDescriptions, roots, stss, mss, GiveHints, NIL, PerMismatch, PerDroppedConnection, PerBogusMerge, NIL, trace, autoHack, mayQuitEarly, didQuitEarly, abort, ttols, cd.vsp, cd].isomorphic AND aok) THEN FoundProblems[sourceRoot, extractedRoot]; cd.chop _ oldChop; RETURN}; RefineTolerances: PUBLIC PROC [propval: REF ANY, inherit: TransistorTolerances] RETURNS [ttols: TransistorTolerances] ~ { IF propval=NIL THEN RETURN [inherit]; WITH propval SELECT FROM x: ROPE => { specRef: REF TolerancesSpec; specTV: TV; errorRope: ROPE; noResult: BOOL; [specTV, errorRope, noResult] _ Evaluate[Rope.Cat["[", x, "]"], CODE[TolerancesSpec]]; IF errorRope.Length#0 OR noResult THEN ERROR; TRUSTED {specRef _ NARROW[AMBridge.RefFromTV[specTV]]}; ttols _ NEW [CSC.TransistorTolerancesPrivate _ [ length: IF specRef.length#0 THEN Normalize[specRef.length] ELSE inherit[length], width: IF specRef.width#0 THEN Normalize[specRef.width] ELSE inherit[width] ]]; RETURN}; ENDCASE => ERROR}; Normalize: PROC [x: REAL] RETURNS [CSC.Tolerance] ~ { RETURN [SELECT x FROM >= 1.0 => [1.0/x, x], > 0.0 => [x, 1.0/x], ENDCASE => ERROR]}; MergeByPinsAndFuseTransistors: PROC [ data: REF ANY, parent: Core.CellType, recastOfSubroot: BOOL, 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, Depublicize: CSC.Depublicizer] --MergeSpec-- = {cd: CompareData ~ NARROW[data]; nFused: NAT _ 0; si: SourceInfo ~ IF NOT recastOfSubroot THEN NARROW[cd.extractedToSourceInfo.Fetch[parent].val] ELSE NIL; 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]; rl1: REF INT ~ NARROW[CoreProperties.GetCellTypeProp[ci1.type, CC.lengthProp]]; rl2: REF INT ~ NARROW[CoreProperties.GetCellTypeProp[ci2.type, CC.lengthProp]]; IF t1.type=t2.type AND (rl1=rl2 OR rl1#NIL AND rl2#NIL AND rl1^=rl2^) 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[[], ci1, parent]], NEW [CF.InstancePath _ CF.AddInstance[[], 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 check AND ((si#NIL) # (PWCore.GetPWCoreExtractedCTKey[parent]#0 AND NOT recastOfSubroot)) THEN ERROR; IF si#NIL THEN { MergeExtracted: PROC [key, val: REF ANY] RETURNS [quit: BOOL _ FALSE] --EachPairProc-- = { sourcePublic: Wire = NARROW[key]; extractedPublics: Element = NARROW[val]; IF extractedPublics.rest # NIL THEN { Consume[extractedPublics]; IF msgFusionBySource THEN { sent: BOOL; info: SimpleMailer.SendMessageInfo; exts: ROPE _ NIL; FOR eps: Element _ extractedPublics, eps.rest WHILE eps#NIL DO ep: CSC.DescendantWire ~ NARROW[eps.first]; IF ep.flatCell.path.length#0 THEN ERROR; exts _ exts.Cat["\nExtracted public wire: ", FmtNames[parent.public, ep.wire]]; ENDLOOP; [sent, info] _ SimpleMailer.SendMessage[from: "PWCoreLichen", to: LIST["Spreitzer.pa"], subject: "Fusion by source", otherHeader: IO.PutFR["Source cell type: %g\nExtracted cell type: %g\nSource public wire: %g%g", [rope[CO.InheritCellTypeName[si.sourceCT]]], [rope[CO.InheritCellTypeName[parent]]], [rope[FmtNames[si.sourceCT.public, sourcePublic]]], [rope[exts]] ]]; IF (NOT sent) OR info # ok THEN SIGNAL MsgFailed}; }; }; DiscardSpurriousPublic: PROC [ext: Core.Wire] ~ { src: Core.Wire ~ NARROW[si.extractedToSource.Fetch[ext].val]; IF src=NIL THEN Depublicize[ext]; RETURN}; [] _ si.sourceToExtracteds.Pairs[MergeExtracted]; CO.VisitRootAtomics[parent.public, DiscardSpurriousPublic]; data _ data; }; }; fused: ATOM = CoreIO.RegisterProperty[CP.RegisterUnprintableProperty[$PWCoreLichenTransistorFused], WriteNil, ReadNil]; debug: BOOL _ FALSE; msgFusionBySource: BOOL _ FALSE; FmtNames: PROC [root, wire: Core.Wire] RETURNS [fmt: ROPE] ~ { n: INT _ 0; FOR ns: LIST OF ROPE _ CO.GetFullWireNames[root, wire], ns.rest WHILE ns#NIL DO SELECT n _ n + 1 FROM 1 => fmt _ ns.first; 2 => fmt _ fmt.Cat["(aka ", ns.first]; >2 => fmt _ fmt.Cat[", ", ns.first]; ENDCASE => ERROR; ENDLOOP; IF n > 1 THEN fmt _ fmt.Concat[")"]}; 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; }; ReverseRefTab: PROC [fwd: RefTab.Ref] RETURNS [bkwd: RefTab.Ref] = { CopyPair: PROC [key, val: REF ANY] RETURNS [quit: BOOL _ FALSE] --RefTab.EachPairProc-- = { wfrom: Wire = NARROW[key]; wto: Wire = NARROW[val]; lfrom: Element _ NARROW[bkwd.Fetch[wto].val]; lfrom _ CONS[NEW [CF.FlatWireRec _ [wireRoot: public, wire: wfrom]], lfrom]; [] _ bkwd.Store[wto, lfrom]; }; bkwd _ RefTab.Create[]; [] _ fwd.Pairs[CopyPair]; }; CreateParallelTable: PROC [w1, w2: Wire] RETURNS [RefTab.Ref] ~ { table: RefTab.Ref ~ RefTab.Create[]; PerPair: PROC [actualWire, publicWire: Wire] RETURNS [subWires: BOOL _ TRUE, quit: BOOL _ FALSE] ~ { IF NOT table.Insert[actualWire, publicWire] THEN ERROR; }; IF CO.VisitBinding[w1, w2, PerPair] THEN ERROR; RETURN [table]}; GetConstraints: PUBLIC PROC [subroot: CellType] RETURNS [RefTab.Ref] ~ {RETURN CSC.GetConstraints[subroot]}; 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; Evaluate: PROC [ rope: ROPE, target: AMTypes.Type _ AMTypes.nullType, context: AMModel.Context _ NIL-- NIL means use AMModel.RootContext[LocalWorld[]]--, symbolsList: Interpreter.SymbolsList _ NIL-- look here first for name to TV lookup--, abort: Interpreter.AbortClosure _ [NIL, NIL]-- default is to never abort--] RETURNS [result: TV _ NIL, errorRope: ROPE _ NIL, noResult: BOOL _ FALSE] = { inner: PROC = { result _ InterpreterOps.Eval[ tree: InterpreterOps.ParseExpr[expr: Rope.Cat["& _ ", rope], errout: errorStream], head: InterpreterOps.NewEvalHead[ context: context, specials: symbolsList, helpFatalClosure: [MyHelpFatal, errorStream], abortClosure: abort], target: target ! FatalInterpreterError => {errorStream.PutRope[msg]; CONTINUE}]; RETURN}; errorStream: IO.STREAM _ IO.ROS[]; IF context = NIL THEN TRUSTED {context _ AMModel.RootContext[WorldVM.LocalWorld[]]}; IF symbolsList = NIL THEN symbolsList _ LIST[SymTab.Create[]]; errorStream.PutRope[BackStop.Call[inner]]; errorRope _ IO.RopeFromROS[errorStream]; noResult _ (result = AMTypes.GetEmptyTV[]); RETURN}; FatalInterpreterError: ERROR [msg: ROPE] ~ CODE; MyHelpFatal: InterpreterOps.HelpFatal = { ERROR FatalInterpreterError[msg]; }; HashPath: RefTab.HashProc ~ { path: REF CF.InstancePath = NARROW[key]; RETURN[CF.InstancePathHash[path^]]; }; EqualPath: RefTab.EqualProc ~ { p1: REF CF.InstancePath = NARROW[key1]; p2: REF CF.InstancePath = NARROW[key2]; RETURN[CF.InstancePathEqual[p1^, p2^]]; }; WriteNil: CoreIO.PropWriteProc ~ {BrineIO.WriteID[stream, "a"]; BrineIO.WriteAtom[stream, $Foo]}; ReadNil: CoreIO.PropReadProc ~ { id: ROPE ~ BrineIO.ReadID[stream]; a: ATOM ~ BrineIO.ReadAtom[stream]; IF NOT (id.Equal["a"] AND a=$Foo) THEN ERROR; RETURN [NIL]}; RoleDescriptions[Source] _ "source"; RoleDescriptions[Extracted] _ "layout"; UserProfile.CallWhenProfileChanges[TrackProfile]; CDSequencerExtras.RegisterCommand[key: $PWCoreLichenCompare, proc: CompareCmd, queue: doQueue]; CDSequencerExtras.RegisterCommand[key: $PWCoreLichenForgetComparison, proc: ForgetCmd, queue: doQueue]; CDSequencerExtras.RegisterCommand[key: $PWCoreLichenForgetAllComparisons, proc: GlobalForgetCmd, queue: doQueue]; CDSequencerExtras.RegisterCommand[key: $PWCoreLichenEnableAutomorphismHack, proc: SetAutomorphismHackCmd, queue: doQueue]; CDSequencerExtras.RegisterCommand[key: $PWCoreLichenDisableAutomorphismHack, proc: SetAutomorphismHackCmd, queue: doQueue]; CDSequencerExtras.RegisterCommand[key: $PWCoreLichenEnableQuitEarly, proc: SetQuitEarlyCmd, queue: doQueue]; CDSequencerExtras.RegisterCommand[key: $PWCoreLichenDisableQuitEarly, proc: SetQuitEarlyCmd, queue: doQueue]; CDSequencerExtras.RegisterCommand[key: $PWCoreLichenWideTolerances, proc: SetTolerancesCmd, queue: doQueue]; CDSequencerExtras.RegisterCommand[key: $PWCoreLichenTightTolerances, proc: SetTolerancesCmd, queue: doQueue]; CDSequencerExtras.RegisterCommand[key: $PWCoreLichenReadTolerances, proc: SetTolerancesCmd, queue: doQueue]; CDSequencerExtras.RegisterCommand[key: $PWCoreLichenDisplayStats, proc: StatsCmd, queue: doQueue]; CDSequencerExtras.RegisterCommand[key: $PWCoreLichenPrintConstraints, proc: PrintConstraintsCmd, queue: doQueue]; END. RPWCoreLichenImpl.mesa Copyright Σ 1986, 1987 by Xerox Corporation. All rights reversed. Created by Bertrand Serlet, July 14, 1986 5:49:00 pm PDT Bertrand Serlet, May 5, 1988 10:40:04 pm PDT Last tweaked by Mike Spreitzer on March 4, 1989 2:34:15 pm PST Barth, April 16, 1987 11:54:55 pm PDT Louis Monier March 30, 1988 11:55:43 am PST Jean-Marc Frailong December 10, 1987 7:18:00 pm PST Don Curry July 20, 1988 7:40:18 am PDT Types & globals We need them in this order because SourceSubtree would side-effect the data-structure created from extractedRoot if it came second. ChipNDale command interface Public Utilities The real stuff Interpreter interface (for tolerance specifications) PROC [data: REF, head: EvalHead, parent: Tree, msg: ROPE]; CoreFlat extensions (should be moved there) CoreIO hacks (to be removed someday) Initialization Κ)ž– "cedar" style˜code™KšœB™BKšœ5Οk™8Kšœ,™,K™>K™%K™+K™3K™&—K˜š ˜ Kšœ.˜.Kšœ3˜5Kšœd˜dKšœ$œ$˜JKšœ*˜*KšœŒ˜Œ—K˜šΡblnœœ˜Kšœ0œ¨œΌ˜ŸKšœ ˜Kšœ ˜K˜—Kšœœœœ œœ œœœœœ˜Εhead™Kš œœœœœ ˜/Kšœ œœ ˜Kšœ œœ ˜$Kšœ œœ ˜Kšœœœ˜šœœ œ˜K˜K˜—KšΟnœœœœ˜/Kš Ÿœœœœœ˜*KšŸ œœœ!œ˜BšŸ œœœ˜K˜—Kšœ œœ˜)š œœœ œ$œ5˜ˆK˜—Kšœ œœ˜+šœœœ˜#K˜Kšœœ˜Kšœ˜K˜"Kšœœœ˜KšœœœΟc˜1Kšœ˜K˜—KšœœJ˜jKšœœK˜lK˜š Ÿœœœœœ˜JKšœœ3˜<—K˜š Ÿ œœœ ŸœŸœ˜-K˜—šŸ œ Ÿœ ˜&Kš ƒ™ƒK˜—šŸœœ œ˜7K˜—Kšœœœ˜/šœœœ˜%Kšœœ œ˜Kšœœ˜#Kšœœ ˜K˜K˜—KšœœœO €˜€Kšœ œœœM˜{šœ œœ4˜GK˜—š œ œœœœ7˜_K˜—Kšœœœœ/˜Yšœ œœ%˜8K˜—Kšœœœ˜Kšœ œœ˜Kšœœœ˜Kš œ œœœœ˜!Kšœœ"œ˜5—šœ™KšŸœœ/˜=K˜Kšœ:˜:K˜šŸ œœ œ˜KKš œœœœœœ˜%šŸœœ˜šŸ œ%˜/Kšœœœ˜&Kšœœ˜ Kšœ3œ ˜BKšœ9œ ˜FKšœ5˜5Kšœ˜Kšœœœ!œ$˜iKšœ^˜cK˜K˜—KšœP˜PK˜—Kšœ,˜,KšœΜ˜ΜKšœ:œ ˜GK˜—K˜šŸ œœ œ˜JKš œœœœœœ˜%šŸœœ˜šŸ œ%˜.Kšœœœ˜&KšœFœ ˜UKšœ˜K˜K˜—KšœO˜OK˜—Kšœ,˜,Kšœ:œ ˜GK˜—K˜šŸœœ œ˜PJšœ˜JšœJ˜JKšœ˜—K˜šŸœœ˜;šœ ˜Kšœ;œ˜AKšœ<œ˜CKšœœ ˜,—Kš œ<œœœ œ ˜{Kšœ˜—K˜šŸœœ˜4šœ ˜Kšœ-œ˜3Kšœ.œ˜5Kšœœ ˜,—Kš œ.œœœœ ˜dKšœ˜—K˜šŸœœ˜5Kšœœ˜(šœ ˜KšœC˜CKšœE˜E˜ Kšœœ]˜gKšœ,˜,K˜—Kšœœ ˜,—Kšœr˜rKšœ˜—K˜šŸœœ œ˜TKš œœœœœœ˜%šŸœœ˜šŸœ%˜5Kšœ:˜:Kšœœœ˜+Kšœ4˜4šŸ œœ œœœœœ˜HKšœœ˜%Kšœœœ˜šŸœœ œœœœœ˜BKšœœ˜Kšœ˜Kšœœ*˜?K˜ K˜—Kšœ˜Kšœ˜Kšœ˜K˜—Kšœ œœ˜+Kšœ9œ ˜Kšœ˜Kšœ4œ ˜CKšœ&˜&Kšœ˜K˜—K˜—KšœV˜VK˜—Kšœ,˜,Kšœ:œ ˜GK˜—K˜š Ÿ œœ œ'œœ œ˜gKšœœ&˜/šœ˜šœ˜Kšœœœ˜$Kšœ˜Kšœ:˜:—šœ˜Kšœœœ˜$Kšœ˜Kšœ9˜9—šœ˜Kšœ˜Kšœ5˜5—šœ˜Kšœœœ˜šŸ œœ œœœœœ œ˜^Kšœœœ˜Kšœœ œœ˜:Kšœ˜Kšœ˜—KšœG˜GKšœœœ˜%Kšœ˜—Kšœœ ˜,—š˜KšœY˜Y—Kšœ˜—K˜šœœ œ ˜-Kšœ˜šœ œ˜K˜>K˜.K˜CK˜0K˜—K˜—K˜Kšœ œI˜YK˜•StartOfExpansion- -- [reason: UserProfile.ProfileChangeReason]šŸ œœ+ "œ˜cKšœj˜jKšœ˜——™šŸ œœœœ˜1K˜—šŸœœœ˜3K˜#š Ÿœœœœœ!œœ œœœœœœœœ œ˜™Kšœœœ˜&Kšœœœœ˜+Kšœ'œ˜.Kšœ!œ˜(Kš œœœ œœœa˜’K˜—Kšœ$˜$Kšœ˜K˜—šŸœœœ œ˜HK˜—š Ÿœœœœ œ˜PK˜—KšŸ œœœœ˜=K˜Kš Ÿ œœœœœ˜EK˜Kš Ÿ œœœœœœ˜G—™š Ÿœœœ\œ œœ˜Kšœœ˜&Kš œœ!œœ/œœ ˜”Kšœœ˜ Kšœ#˜#Kšœ3˜3˜(Kšœ˜Kšœœ˜Kšœ œ2˜=šœœ+˜3Kšœœ.˜9——Kš œœœ œœ ˜1Kšœ˜K˜—šŸœœœœœ œ œœ˜Kšœ˜šœ ˜Kšœ+˜+Kšœ0˜0šœ˜ Kšœœ7˜BKšœ)˜)Kšœ(˜(K˜——Kšœ'˜'Kšœ˜K˜—šŸœœC˜YKšœ$œœ(˜Uš œ œœœ$œ˜FKšœœœ˜Kšœœ˜—Kšœ œ˜'š œœœœ"œ˜CKšœœœ˜Kšœœœœ˜—Kšœœœ˜šœœ˜šœœœ˜*Kšœ0œ?˜uKšœ˜—šœ œ˜šœœœœ!˜;Kšœœ˜ Kšœ œ˜Kšœœ˜—Kšœ˜Kšœ˜Kšœ2˜2Kšœœ˜Kšœœ˜ Kšœœœ˜šœ˜Kšœœœœ˜(Kšœw˜wKšœ7˜7—Kšœ˜Kš œœ,œWœœ˜—Kšœœœ˜Kšœ œ˜)Kšœœœ œ˜!KšœU˜YKšœœœ˜KšœA˜CKšœ-˜/Kšœ(˜*K˜—Kšœ œœ˜6šœ˜ Kšœ<˜Kšœœœœ˜"—Kšœœœœ.œœœœ5œœ˜½šœœœ˜Kš œ œœœœ+˜_Kšœœœ˜—Kšœœ ˜Kšœ˜—K˜Kšœ œœ˜K˜—š ŸœœœœŸœœ˜OKšœœ˜Kšœ˜K˜#šŸœœœ œœœœ œ˜fKšœ œœ˜Kšœœœ˜&Kšœœœœ˜(Kšœ œ œ(˜IšŸ œœŸœœ˜.š œœœœ˜9šœ œ˜šœœ˜Kšœœœ˜(Kš œ œ œœ œœ˜TKšœœœœ˜Kšœ˜—Kšœœ˜—Kšœ ˜ Kšœ˜—Kšœ˜—Kšœ œœœ˜Kšœ˜Kšœ˜ —Kšœœ+œœ˜;Kšœ˜K˜—šœ;œ˜BK˜—š Ÿ œœOœœ7œœ˜ΉšŸ œœŸœœœœœœ œ˜YšŸœœ œœœœœ œ˜TKšœœ˜!Kšœœ˜(Kš œœœœœ ˜%Kšœ'˜'Kšœ œœ7˜KKšœ ˜ K˜—Kšœ(˜(K˜—Kšœœ œ˜Kš œœœœœœ˜,Kšœ œœ˜šŸ œœ˜Kšœ œœ˜Kšœ œ˜šœœœ˜Kšœ"œ˜>K˜3K˜—šœ œœœ˜,Kšœ œœ.œ˜IKšœ/œœ˜TK˜ —Kšœ@˜@Kšœ>˜>KšœI˜IKšœS˜SKšœ˜—šŸ œœœœœ*Ÿœœ˜~šŸœœ œœ&œœœœ œ˜’Kšœ œœœœ9œœ/œ˜ͺK˜—š Ÿœœ œœœ˜;šŸœœ)œ˜IKšœœœ˜K˜šœœœ˜*š œ œœœœ$œ˜DKšœœ œœ˜2šœ œ œ˜%Kšœœ œ˜-Kšœœœœ˜9Kšœœ˜—K˜—Kšœ˜—K˜K˜—šœ œ˜Kšœœ œ˜Kšœœœœ˜Kšœœœœ˜?Kšœœ˜—Kšœœœœœœœœ˜Ešœœœœ˜šœœœ˜K˜Kšœ#˜#K˜—K˜Kšœ&œ˜+K˜—K˜—šŸœœ˜šŸ œœ œ œ˜1Kšœ2˜5K˜—Kšœ1˜1Kš œœœ(œ œ˜OKšœ˜—K˜&K˜K˜—šŸ œ˜šœ˜Kšœœœ˜Kšœœ˜Kšœœ˜Kšœ œ ˜KšŸœœ˜Kšœ ˜—K˜Kšœœœ˜5š Ÿœœœœœ˜FK˜KšœM˜M—šŸœœœœ˜,Kš œœœ œœœ7˜bK˜"Kšœœ˜$Kšœ!œ˜'K˜—šŸ œœœœ˜'Kš œœœ œœœ7˜bK˜Kšœœ˜%Kšœ!œ˜(K˜—Kš Ÿœœœœ:œ œ˜’Kšœœ4œœ˜`Kšœ˜Kšœœœœ˜'šœœ˜šŸœœ%œœ˜Ešœœ˜!Kšœœœ ˜*Kš œœœœœ-˜lKšœœ˜—K˜—Kš œœœœœ*œ0˜ŠKšœβ˜βKšœ˜K˜—šœ˜Kšœœ˜Kšœ@œœœœœœœ˜­Kšœ%œ=˜dKšœ%œ7˜^K˜ šœ œ˜Kšœ œœ˜šœ0œœ˜Fšœ)œ œ˜@šœ œ˜Kšœœ{˜‚Kšœœj˜qKšœœ˜—Kšœ œ˜Kšœ˜—Kšœ˜—Kšœ˜—Kšœ$˜$Kšœ ˜ —Kšœ˜Kšœ˜—šŸœœ6œ˜`š Ÿœœœœ œ˜9Kš œ%œœœ œ˜D—Kš œœMœ%œ#œ#œœ#˜υKšœœ˜ —š Ÿ œœ.œœœ˜lš Ÿœœœœ œ˜9Kš œ%œœœœœ˜J—Kš œœaœ%œEœ#œ'˜§Kšœœ˜ —Kšœœœ˜-Kšœœœ˜2Kšœœœ ˜Kšœœœ ˜+Kšœœœ˜(KšœO˜OKšœ˜—Kš œBœ<œXœ+œd˜οKš œœœ œœ ˜2—K˜—K˜—šŸœœ˜1Kšœœ&˜=Kšœœœ˜!Kšœ˜—Kšœ1˜1Kšœ9˜;K˜ K˜—K˜KšœœœœO˜wKšœœœ˜Kšœœœ˜ K˜—šŸœœœœ˜>Kšœœ˜ šœœœœœ'œœ˜Ošœ ˜Kšœ˜K˜&K˜$Kšœœ˜—Kšœ˜—Kšœœ˜%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˜—šŸ œœœ˜DšŸœœ œœœœœ œ˜[KšœΟdœ œ˜Kšœ‘œ œ˜Kšœ‘œ œ ‘œ˜-Kš œ‘œœœœ)‘œ‘œ˜LKšœ‘œ‘œ˜K˜—K˜K˜K˜K˜—šŸœœœ˜AK˜$šŸœœ œ œœœœ˜dKšœœ&œœ˜7K˜—Kšœœœœ˜/Kšœ ˜K˜—Kš Ÿœœœœœœ˜lK˜šŸ œœœœŸœœœœœ˜fKšœ˜Kšœ ˜ Kšœ œœ ˜Kšœ ˜ K˜Kšœœ˜K˜——™4šŸœ˜šœ˜Kšœœ˜ Kšœ(˜(Kšœ 4œ˜SKšœ' *œ˜UKšœ#œœ œ˜K—Kšœ œœ œœ œœ˜MšΟbœœ˜šœ˜KšœR˜Ršœ!˜!Kšœ˜Kšœ˜Kšœ-˜-Kšœ˜—K˜Kšœ6œ˜A—Kšœ˜—Kš œ œœœœ˜"Kšœ œœœ7˜TKšœœœœ˜>Kšœ*˜*Kšœ œ˜(Kšœ+˜+Kšœ˜K˜—šŸœœœœ˜0K˜—šŸ œ˜)Kšœœ%œ™:Kšœ˜!K˜——™+šŸœ˜Kšœœœœ˜(Kšœœ˜#K˜K˜—šŸ œ˜Kšœœœœ˜'Kšœœœœ˜'Kšœœ˜'K˜——™$šŸœ˜Kšœ;œ˜B—šŸœ˜šœ˜Kšœœ˜"Kšœœ˜#Kš œœœœœœ˜-Kšœ˜——K˜—™Kšœ$˜$Kšœ'˜'K˜1Kšœ_˜_Kšœg˜gKšœq˜qKšœz˜zKšœ{˜{Kšœl˜lKšœm˜mKšœl˜lKšœm˜mKšœl˜lKšœb˜bKšœq˜qK˜—K˜Kšœ˜—…—*Ί