PWCoreLichenImpl.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
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;
Types & globals
FlatWireRecList: TYPE = LIST OF CF.FlatWireRec;
Element: TYPE = CSC.Element;
ElementList: TYPE = CSC.ElementList;
ActualID: TYPE = CSC.ActualID;
Role: TYPE ~ CSC.Role;
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;
We need them in this order because SourceSubtree would side-effect the data-structure created from extractedRoot if it came second.
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];
ChipNDale command interface
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};
Public Utilities
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};
The real stuff
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;
Interpreter interface (for tolerance specifications)
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 = {
PROC [data: REF, head: EvalHead, parent: Tree, msg: ROPE];
ERROR FatalInterpreterError[msg];
};
CoreFlat extensions (should be moved there)
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^]];
};
CoreIO hacks (to be removed someday)
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]};
Initialization
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.