<> <> DIRECTORY Asserting USING [Assertions, Assertion, Terms, RelnOf, TermsOf, ToAssertions, Assert, Test], AssertingIO, Atom, Basics, DFUtilities, FS, IO, LichenDataStructure, LichenOps, List, RedBlackTree, RedBlackTreeExtras, Rope; LichenRead: CEDAR PROGRAM IMPORTS Asserting, AssertingIO, Atom, DFUtilities, FS, IO, LichenDataStructure, LichenOps, List, RedBlackTree, RedBlackTreeExtras, Rope EXPORTS LichenOps = BEGIN OPEN Asserting, LichenDataStructure, LichenOps; DFTest: PROC [dfName: ROPE] = BEGIN PerItem: PROC [item: REF ANY] RETURNS [stop: BOOL _ FALSE] = {Log["%g\n", IO.refAny[item]]}; from: IO.STREAM _ FS.StreamOpen[dfName]; Log["\nTesting DF file %g\n", IO.rope[dfName]]; DFUtilities.ParseFromStream[in: from, proc: PerItem, filter: [comments: TRUE]]; from.Close[]; Log["\nDone testing DF file %g\n", IO.rope[dfName]]; END; EasyOpen: PROC [fileName: ROPE] RETURNS [stream: IO.STREAM] = {stream _ FS.StreamOpen[fileName]}; ReadDesign: PROC [dfName: ROPE, keepAll: BOOL _ FALSE] RETURNS [design: Design] = BEGIN NonGrok: PROC [context: REF ANY, source: Source, assn: Assertion] = { WITH context SELECT FROM design: Design => { CheckIgnore[source, LIST[RelnOf[assn], $Design]]; IF keepAll THEN design.other _ CONS[assn, design.other]; }; cellType: CellType => { CheckIgnore[source, LIST[RelnOf[assn], $CellType, $Design]]; IF keepAll THEN Warn[source, "Can't represent assertion %g about %g's name", IO.refAny[assn], IO.rope[GlobalCellTypeName[cellType]]]; }; ENDCASE => ERROR; }; ReadFrom: PROC [dfName: ROPE, usingList: REF DFUtilities.UsingList] = BEGIN assns: Assertions _ NIL; dir, dfShort: ROPE _ NIL; s: Source; DiscardAssns: PROC = {FOR assns _ assns, assns.rest WHILE assns # NIL DO NonGrok[design, s, assns.first] ENDLOOP}; DesignAssns: PROC = {FOR assns _ assns, assns.rest WHILE assns # NIL DO WITH RelnOf[assns.first] SELECT FROM a: ATOM => SELECT a FROM $Design, $CreatingUser, $CreationTime, $CreationSite, $Version, $DerivingProgram, $Source => NULL --absorb accounting information, because it'll become invalid--; $DesignName => {r: ROPE _ NARROW[TermsOf[assns.first].first]; design.name _ r}; ENDCASE => NonGrok[design, s, assns.first]; ENDCASE => NonGrok[design, s, assns.first]; ENDLOOP}; PerItem: PROC [item: REF ANY] RETURNS [stop: BOOL _ FALSE] = BEGIN WITH item SELECT FROM di: REF DFUtilities.DirectoryItem => {dir _ di.path1; DesignAssns[]}; fi: REF DFUtilities.FileItem => { verless: ROPE _ DFUtilities.RemoveVersionNumber[dir.Cat[fi.name]]; IF NOT DFUtilities.SearchUsingList[file: verless, list: usingList].found THEN assns _ NIL ELSE { typeName: Naming _ ["?"]; ct: CellType _ NIL; FOR assns _ assns, assns.rest WHILE assns # NIL DO assn: Assertion _ assns.first; WITH RelnOf[assn] SELECT FROM a: ATOM => SELECT a FROM $CellType => { IF ct # NIL THEN Warn[s, "Multiple CellTypes for file %g in %g", IO.rope[fi.name], IO.rope[dfName]]; ct _ NEW [CellTypeRep _ [design: design, names: [], file: verless]]; typeName _ [NARROW[TermsOf[assn].first]]; FOR ctnas: Assertions _ ToAssertions[TermsOf[assn].rest], ctnas.rest WHILE ctnas # NIL DO ctna: Assertion _ ctnas.first; WITH RelnOf[ctna] SELECT FROM ia: ATOM => SELECT a FROM $G => typeName _ AddG[typeName, ctna, LIST[$CellType, $Design], ct]; $A => typeName _ AddA[typeName, ctna, LIST[$CellType, $Design], ct]; ENDCASE => NonGrok[ct, s, ctna]; ENDCASE => NonGrok[ct, s, ctna]; ENDLOOP; }; ENDCASE => NonGrok[design, s, assn]; ENDCASE => NonGrok[design, s, assn]; ENDLOOP; IF ct # NIL THEN { ct.names _ NamingNames[typeName]; AddCellType[ct]; } ELSE { IF NOT dfShort.Equal[fi.name, FALSE] THEN Warn[s, "Non-understood file entry: %g", IO.rope[fi.name]]; }; }; }; ii: REF DFUtilities.ImportsItem => {ReadFrom[ii.path1, IntUL[usingList, ii.list]]; DiscardAssns[]}; ii: REF DFUtilities.IncludeItem => {ReadFrom[ii.path1, usingList]; DiscardAssns[]}; ci: REF DFUtilities.CommentItem => assns _ AddAssn[ci.text, assns]; wi: REF DFUtilities.WhiteSpaceItem => NULL; ENDCASE => ERROR; END; IF usingList = NIL OR usingList.nEntries > 0 THEN { from: IO.STREAM _ FS.StreamOpen[dfName]; cp: FS.ComponentPositions; dfFull: ROPE; s _ [from, dfName]; [dfFull, cp, ] _ FS.ExpandName[dfName]; dfShort _ dfFull.Substr[start: cp.base.start, len: cp.ext.start+cp.ext.length-cp.base.start]; DFUtilities.ParseFromStream[in: from, proc: PerItem, filter: [comments: TRUE]]; from.Close[]; }; END; cp: FS.ComponentPositions; fullDFName: ROPE; [fullDFName, cp, ] _ FS.ExpandName[dfName]; design _ NEW [DesignRep _ [ name: fullDFName.Substr[start: cp.base.start, len: cp.base.length], cellTypesByName: RedBlackTree.Create[GetAliasKey, CompareAliases], cellTypesByAddress: RedBlackTree.Create[GetIDKey, CompareByAddress], allKept: keepAll ]]; ReadFrom[dfName: dfName, usingList: NIL]; END; AddCellType: PUBLIC PROC [ct: CellType] = { Insert[ct.design.cellTypesByName, ct.names, ct]; ct.design.cellTypesByAddress.Insert[ct, ct]; }; AddAssn: PROC [comment: ROPE, assns: Assertions] RETURNS [with: Assertions] = { in: IO.STREAM _ IO.RIS[comment]; char: CHAR; assn: Assertion; [] _ in.SkipWhitespace[flushComments: FALSE]; IF (char _ in.GetChar[]) # '- THEN ERROR; IF (char _ in.GetChar[]) # '- THEN ERROR; [] _ in.SkipWhitespace[]; IF in.EndOf[] THEN RETURN [assns]; IF (char _ in.GetChar[]) = '^ THEN { IF in.EndOf[] THEN RETURN [assns]; char _ in.GetChar[]; }; IF char # '( THEN RETURN [assns]; in.Backup['(]; assn _ AssertingIO.ReadAssn[in]; with _ CONS[assn, assns]; in.Close[]; }; IntUL: PROC [a, b: REF DFUtilities.UsingList] RETURNS [c: REF DFUtilities.UsingList] = { IF a = NIL AND b = NIL THEN RETURN [NIL]; IF b = NIL THEN RETURN [a]; DFUtilities.SortUsingList[b]; IF a = NIL THEN RETURN [b]; c _ NEW [DFUtilities.UsingList[MIN[a.nEntries, b.nEntries]]]; c.nEntries _ 0; FOR i: NAT IN [0 .. a.nEntries) DO found: BOOL _ DFUtilities.SearchUsingList[file: a[i].name, list: b].found; IF found THEN {c[c.nEntries] _ a[i]; c.nEntries _ c.nEntries + 1}; ENDLOOP; c _ c; }; ReadCellType: PROC [ct: CellType, privateToo: BOOL] = BEGIN from: IO.STREAM; currentlyPrivate: BOOL _ FALSE; s: Source; IF ct.publicKnown AND (ct.privateKnown OR NOT privateToo) THEN RETURN; s _ [from _ FS.StreamOpen[ct.file], ct.file]; DO assn: Assertion; NonGrok: PROC = { CheckIgnore[s, LIST[RelnOf[assn], $CellType]]; IF NOT ct.design.allKept THEN NULL ELSE IF currentlyPrivate THEN ct.otherPrivate _ CONS[assn, ct.otherPrivate] ELSE ct.otherPublic _ CONS[assn, ct.otherPublic]}; [] _ from.SkipWhitespace[]; IF from.EndOf[] THEN EXIT; assn _ AssertingIO.ReadAssn[from]; WITH RelnOf[assn] SELECT FROM a: ATOM => SELECT a FROM $PrivateFollows => {IF currentlyPrivate THEN Warn[s, "(PrivateFollows) seen more than once"]; currentlyPrivate _ TRUE}; ENDCASE; ENDCASE; IF currentlyPrivate AND NOT privateToo THEN EXIT; IF ct.publicKnown AND NOT currentlyPrivate THEN LOOP; WITH RelnOf[assn] SELECT FROM a: ATOM => SELECT a FROM $PrivateFollows => NULL; $CreatingUser, $CreationTime, $CreationSite, $Version, $DerivingProgram, $Source => NULL --absorb old audit trail--; $CellTypeName => {naming: Naming _ [NARROW[TermsOf[assn].first]]; FOR ctnas: Assertions _ ToAssertions[TermsOf[assn].rest], ctnas.rest WHILE ctnas # NIL DO ctna: Assertion _ ctnas.first; NonRep: PROC = { CheckIgnore[s, LIST[RelnOf[ctna], $CellTypeName, $CellType]]; IF ct.design.allKept THEN Warn[s, "Cant' represent assertion %g about %g's name", IO.refAny[ctna], IO.rope[GlobalCellTypeName[ct]]]; }; WITH RelnOf[ctna] SELECT FROM ia: ATOM => SELECT ia FROM $G => naming _ AddG[naming, ctna, LIST[$CellTypeName, $CellType], ct]; $A => naming _ AddA[naming, ctna, LIST[$CellTypeName, $CellType], ct]; ENDCASE => NonRep[]; ENDCASE => NonRep[]; ENDLOOP; InsistSameNames[ct.names, NamingNames[naming], ct.design]; }; $EC => {reln: ROPE _ NARROW[TermsOf[assn].first]; equivClass: ROPE _ NARROW[TermsOf[assn].rest.first]; IF NOT reln.Equal["Structure"] THEN { CheckIgnore[s, LIST[Atom.MakeAtom[reln], $EC, $CellType]]; IF NOT ct.design.allKept THEN NULL ELSE IF currentlyPrivate THEN ct.otherPrivate _ CONS[assn, ct.otherPrivate] ELSE ct.otherPublic _ CONS[assn, ct.otherPublic]; } ELSE IF ct.equivClass = implicitClass THEN ct.equivClass _ equivClass ELSE IF NOT equivClass.Equal[ct.equivClass] THEN Warn[s, "Multiple %g equivalence classes for %g: %g and %g", IO.rope[reln], IO.rope[GlobalCellTypeName[ct]], IO.rope[ct.equivClass], IO.rope[equivClass]]; }; $Ports => ReadPorts[ct, assn]; $PN => { portName: ROPE _ NARROW[TermsOf[assn].first]; netName: ROPE _ NARROW[TermsOf[assn].rest.first]; portIndex: NAT _ FindPort[ct.ports, portName]; IF portIndex = notFound THEN Warn[s, "CellType %g has no port named %g", IO.rope[GlobalCellTypeName[ct]], IO.refAny[portName]] ELSE ct.ports[portIndex].netNames _ CONS[netName, ct.ports[portIndex].netNames]; }; $N => ReadNet[ct, assn]; $CI => ReadCellInstance[ct, assn]; $InsidesUnspecified => { IF ct.parts # NIL THEN Warn[s, "Unspecified insides were specified for cell type %g", IO.rope[GlobalCellTypeName[ct]]]; }; ENDCASE => NonGrok[]; ENDCASE => NonGrok[]; ENDLOOP; IF ct.parts # NIL AND ct.mirror = NIL THEN AddWorld[ct]; ct.publicKnown _ TRUE; ct.privateKnown _ privateToo; from.Close[]; IF ExpansionKnown[ct] THEN { FOR pi: NAT IN [0 .. ct.ports.length) DO net: Vertex _ NIL; FOR nnl: RopeList _ ct.ports[pi].netNames, nnl.rest WHILE nnl # NIL DO n: Vertex _ NARROW[Lookup[ct.parts, nnl.first]]; SELECT TRUE FROM n = NIL => Err[[], "No net %g in cell type %g", IO.refAny[nnl.first], IO.rope[GlobalCellTypeName[ct]]]; net = NIL => net _ n; net # n => Err[[], "Multiple nets connected to port %g", IO.rope[GlobalPortName[ct, pi]]]; ENDCASE; ENDLOOP; ENDLOOP; }; END; InsistSameNames: PROC [n1, n2: Names, design: Design] = { st: SymbolTable _ RedBlackTree.Create[GetAliasKey, CompareAliases]; inBoth, in1, in2: ROPE _ NIL; Add: PROC [rl: RopeList, ns: ATOM] = { FOR rl _ rl, rl.rest WHILE rl # NIL DO a: Alias _ NEW [AliasRep _ [name: rl.first, thing: ns]]; st.Insert[a, a.name]; ENDLOOP; }; Remove: PROC [rl: RopeList, ns: ATOM] = { FOR rl _ rl, rl.rest WHILE rl # NIL DO n: RedBlackTree.Node _ st.Delete[rl.first]; SELECT TRUE FROM n = NIL => in2 _ AddName[in2, rl.first]; n # NIL => inBoth _ AddName[inBoth, rl.first]; ENDCASE => ERROR; ENDLOOP; }; NoteRest: PROC [ra: REF ANY] RETURNS [stop: BOOL] = { a: Alias _ NARROW[ra]; in1 _ AddName[in1, a.name]; stop _ FALSE; }; AddName: PROC [r, n: ROPE] RETURNS [nr: ROPE] = { SELECT TRUE FROM r = NIL => nr _ n; r # NIL => nr _ r.Cat[", ", n]; ENDCASE => ERROR; }; Add[n1.designed, $D]; Add[n1.unknown, $U]; Add[n1.progged, $P]; Remove[n2.designed, $D]; Remove[n2.unknown, $U]; Remove[n2.progged, $P]; st.EnumerateIncreasing[NoteRest]; IF in1 # NIL OR in2 # NIL THEN { Warn[[], "In design %g, CellType certainly named (%g) also named (%g) in DF file only and (%g) in cell file only", IO.rope[design.name], IO.rope[inBoth], IO.rope[in1], IO.rope[in2]]; }; }; ReadCellInstance: PROC [ct: CellType, assn: Assertion] = { instanceName: ROPE _ NARROW[TermsOf[assn].first]; typeName: ROPE _ NARROW[TermsOf[assn].rest.first]; instanceType: CellType _ NARROW[Lookup[ct.design.cellTypesByName, typeName]]; cv: Vertex; naming: Naming _ [instanceName]; IF ct.parts = NIL THEN { ct.parts _ RedBlackTree.Create[GetAliasKey, CompareAliases]; }; IF ct.mirror = NIL THEN AddWorld[ct]; cv _ NEW [VertexRep _ [ names: [], type: instanceType, parent: ct, class: cell]]; FOR cial: Assertions _ ToAssertions[TermsOf[assn].rest.rest], cial.rest WHILE cial # NIL DO cia: Assertion _ cial.first; NonGrok: PROC = { CheckIgnore[[], LIST[RelnOf[cia], $CI, $CellType]]; IF ct.design.allKept THEN cv.other _ CONS[cia, cv.other]; }; WITH RelnOf[cia] SELECT FROM a: ATOM => SELECT a FROM $G => naming _ AddG[naming, cia, LIST[$CI, $CellType], cv]; $A => naming _ AddA[naming, cia, LIST[$CI, $CellType], cv]; $CIC => { portIndex: NAT _ 0; EnsurePorts[instanceType]; FOR cicl: LORA _ TermsOf[cia], cicl.rest WHILE cicl # NIL DO cic: LORA _ NARROW[cicl.first]; portName: ROPE _ NARROW[cic.first]; netName: ROPE _ NARROW[cic.rest.first]; net: Vertex _ NARROW[Lookup[ct.parts, netName]]; IF NOT NamesInclude[instanceType.ports[portIndex].names, portName] THEN Err[[], "Cell instance connections not in order on %g.%g", IO.rope[GlobalCellTypeName[ct]], IO.rope[instanceName]]; Connect[cv, net, portIndex]; IF cic.rest.rest # NIL THEN Warn[[], "Extra cell instance connection info for %g.%g.%g", IO.rope[GlobalCellTypeName[ct]], IO.refAny[instanceName], IO.refAny[portName]]; portIndex _ portIndex + 1; ENDLOOP; IF portIndex # instanceType.ports.length THEN Warn[[], "Extra cell instance connections for %g.%g", IO.rope[GlobalCellTypeName[ct]], IO.refAny[instanceName]]; }; ENDCASE => NonGrok[]; ENDCASE => NonGrok[]; ENDLOOP; cv.names _ NamingNames[naming]; AddVertex[cv]; LinkInstance[cv]; }; AddWorld: PUBLIC PROC [ct: CellType] = BEGIN cv: Vertex; IF ct.ports = NIL THEN ERROR; ct.mirror _ cv _ NEW [VertexRep _ [names: [NIL, NIL, LIST[MirrorName]], type: ct, parent: ct, class: cell]]; <> <> FOR i: CARDINAL IN [0 .. ct.ports.length) DO port: Port _ ct.ports[i]; nv: Vertex _ NARROW[Lookup[ct.parts, ct.ports[i].netNames.first]]; Connect[cv, nv, i]; ENDLOOP; END; ReadNet: PROC [ct: CellType, assn: Assertion] = { netName: ROPE _ NARROW[TermsOf[assn].first]; nv: Vertex _ NEW [VertexRep _ [names: [], parent: ct, class: net]]; naming: Naming _ [netName]; IF ct.parts = NIL THEN { ct.parts _ RedBlackTree.Create[GetAliasKey, CompareAliases]; }; FOR nal: Assertions _ ToAssertions[TermsOf[assn].rest], nal.rest WHILE nal # NIL DO na: Assertion _ nal.first; NonGrok: PROC = { CheckIgnore[[], LIST[RelnOf[na], $N, $CellType]]; IF ct.design.allKept THEN nv.other _ CONS[na, nv.other]; }; WITH RelnOf[na] SELECT FROM a: ATOM => SELECT a FROM $G => naming _ AddG[naming, na, LIST[$N, $CellType], nv]; $A => naming _ AddA[naming, na, LIST[$N, $CellType], nv]; ENDCASE => NonGrok[]; ENDCASE => NonGrok[]; ENDLOOP; nv.names _ NamingNames[naming]; AddVertex[nv]; }; AddG: PROC [in: Naming, assn: Assertion, context: LORA, owner: REF ANY] RETURNS [out: Naming] = { gener: ATOM _ NARROW[TermsOf[assn].first]; out _ in; IF RelnOf[assn] # $G THEN ERROR; IF out.first = NIL THEN ERROR; SELECT gener FROM $D => out.designed _ CONS[out.first, out.designed]; $P => out.progged _ CONS[out.first, out.progged]; ENDCASE => { CheckIgnore[[], CONS[gener, CONS[$G, context]]]; IF KeepAll[owner] THEN Warn[[], "Unable to represent assertion %g about %g's name", IO.refAny[assn], IO.rope[GlobalName[owner, out]]]; }; out.first _ NIL; }; AddA: PROC [in: Naming, assn: Assertion, context: LORA, owner: REF ANY] RETURNS [out: Naming] = { out _ in; context _ CONS[$A, context]; IF RelnOf[assn] # $A THEN ERROR; FOR aliasList: LORA _ TermsOf[assn], aliasList.rest WHILE aliasList # NIL DO alias: LORA _ NARROW[aliasList.first]; newName: ROPE _ NARROW[alias.first]; known, designed: BOOL _ FALSE; FOR aal: Assertions _ ToAssertions[alias.rest], aal.rest WHILE aal # NIL DO aa: Assertion _ aal.first; NonRep: PROC [firstArg: BOOL] = { ctx: LORA _ CONS[RelnOf[aa], context]; IF firstArg THEN ctx _ CONS[TermsOf[aa].first, ctx]; CheckIgnore[[], ctx]; IF KeepAll[owner] THEN Warn[[], "Unable to represent assertion %g about name %g of %g", IO.refAny[aa], IO.rope[newName], IO.rope[GlobalName[owner, out]]]; }; WITH RelnOf[aa] SELECT FROM a: ATOM => SELECT a FROM $G => {gener: ATOM _ NARROW[TermsOf[aa].first]; SELECT gener FROM $D => designed _ known _ TRUE; $P => designed _ NOT (known _ TRUE); ENDCASE => NonRep[TRUE]; }; ENDCASE => NonRep[FALSE]; ENDCASE => NonRep[FALSE]; ENDLOOP; SELECT TRUE FROM NOT known => out.unknown _ CONS[newName, out.unknown]; designed => out.designed _ CONS[newName, out.designed]; ENDCASE => out.progged _ CONS[newName, out.progged]; ENDLOOP; }; NamingNames: PUBLIC PROC [naming: Naming] RETURNS [names: Names] = { names _ [designed: ReverseRopeList[naming.designed], unknown: ReverseRopeList[naming.unknown], progged: ReverseRopeList[naming.progged]]; IF naming.first # NIL THEN names.unknown _ CONS[naming.first, names.unknown]; }; ReverseRopeList: PROC [inHead: RopeList] RETURNS [outHead: RopeList] = { cur: RopeList _ inHead; prev: RopeList _ NIL; WHILE cur # NIL DO next: RopeList _ cur.rest; cur.rest _ prev; prev _ cur; cur _ next; ENDLOOP; outHead _ prev; }; ReadPorts: PROC [ct: CellType, assn: Assertion] = { len: NAT _ List.Length[TermsOf[assn]]; i: NAT _ 0; s: Socket _ NEW [SocketRep _ [ct, NullPortIndex]]; IF ct.ports # NIL THEN ERROR; ct.ports _ NEW [PortSeq[len]]; FOR psl: LORA _ TermsOf[assn], psl.rest WHILE psl # NIL DO portSpec: LORA _ NARROW[psl.first]; naming: Naming _ [NARROW[portSpec.first]]; ct.ports[i] _ []; s.portIndex _ i; FOR pal: Assertions _ ToAssertions[portSpec.rest], pal.rest WHILE pal # NIL DO pa: Assertion _ pal.first; NonGrok: PROC = { CheckIgnore[[], LIST[RelnOf[pa], $Ports, $CellType]]; IF ct.design.allKept THEN ct.ports[i].other _ CONS[pa, ct.ports[i].other]; }; WITH RelnOf[pa] SELECT FROM paa: ATOM => SELECT paa FROM $EC => { reln: ROPE _ NARROW[TermsOf[pa].first]; equivClass: ROPE _ NARROW[TermsOf[pa].rest.first]; IF reln.Equal["Structure"] THEN { IF ct.ports[i].equivClass = implicitClass THEN ct.ports[i].equivClass _ equivClass ELSE IF NOT ct.ports[i].equivClass.Equal[equivClass] THEN Warn[[], "Multiple Sturcture equivalence classes for port %g : %g and %g", IO.rope[GlobalPortName[ct, i]], IO.refAny[ct.ports[i].equivClass], IO.refAny[equivClass]]; }; }; $G => naming _ AddG[naming, pa, LIST[$Ports, $CellType], s]; $A => naming _ AddA[naming, pa, LIST[$Ports, $CellType], s]; ENDCASE => NonGrok[]; ENDCASE => NonGrok[]; ENDLOOP; ct.ports[i].names _ NamingNames[naming]; i _ i + 1; ENDLOOP; IF i # len THEN ERROR; }; Connect: PUBLIC PROC [cv, nv: Vertex, portIndex: PortIndex] = BEGIN e: Edge _ NEW [EdgeRep _ [ sides: [net: [nv, NIL, nv.lastEdge], cell: [cv, NIL, cv.lastEdge]], color: noColor, portIndex: portIndex]]; IF nv.lastEdge # NIL THEN nv.lastEdge.sides[net].next _ e ELSE nv.firstEdge _ e; IF cv.lastEdge # NIL THEN cv.lastEdge.sides[cell].next _ e ELSE cv.firstEdge _ e; nv.lastEdge _ cv.lastEdge _ e; END; EnsureAllIn: PUBLIC PROC [design: Design] = { PerType: PROC [ra: REF ANY] RETURNS [stop: BOOL] = { ct: CellType _ NARROW[ra]; EnsureParts[ct]; stop _ FALSE}; IF design.allKnown THEN RETURN; design.allKnown _ TRUE; RedBlackTreeExtras.StatelessEnumerateIncreasing[design.cellTypesByAddress, PerType, GetIDKey]; }; EnsurePorts: PUBLIC PROC [ct: CellType] = { IF NOT ct.publicKnown THEN ReadCellType[ct, FALSE]; IF ct.ports = NIL THEN ERROR; }; EnsureParts: PUBLIC PROC [ct: CellType] = { IF NOT ct.privateKnown THEN ReadCellType[ct, TRUE]; }; ExpansionKnown: PUBLIC PROC [ct: CellType] RETURNS [known: BOOL] = { known _ ct.parts # NIL OR ct.asArray # NIL; }; GetInternalStyle: PUBLIC PROC [ct: CellType] RETURNS [is: InternalStyle] = { is _ SELECT TRUE FROM ct.asArray # NIL => array, ct.parts # NIL => graph, ENDCASE => ERROR; }; NoteChange: PUBLIC PROC [ct: CellType] = { IF NOT (ct.publicKnown AND ct.privateKnown) THEN ERROR; ct.file _ NIL; ct.inittedFor _ 0;}; WriteAll: PUBLIC PROC [when: ROPE, a, b: CellType, hashTable: HashTable] = BEGIN Log["\n%g\n", IO.rope[when]]; WriteHashTable[hashTable]; WriteSymbolTable["A", a.parts]; WriteSymbolTable["B", b.parts]; Log["\nDone %g\n", IO.rope[when]]; END; WriteHashTable: PROC [hashTable: HashTable] = BEGIN Log["\nHashTable:\n"]; FOR hti: HashTableIndex _ hashTable.firstNonEmpty, hashTable[hti].nextNonEmpty WHILE hti # NullIndex DO hte: HashTableEntry _ hashTable[hti]; Log["%05d %4g %4g", IO.card[hti], IO.card[hte.count[A]], IO.card[hte.count[B]]]; Log[" %05d %5g %5g", IO.card[hte.newColor], IO.bool[hte.multicolored], IO.bool[hte.suspect]]; FOR v: Vertex _ hte.v, v.colorNext WHILE v # NIL DO Log[" %g.%g", IO.rope[graphIDToRope[v.graph]], IO.rope[PickAName[v.names]]]; ENDLOOP; Log["\n"]; ENDLOOP; END; WriteSymbolTable: PROC [graphID: ROPE, vertices: SymbolTable] = BEGIN WriteVertex: PROC [any: REF ANY] RETURNS [stop: BOOL] = BEGIN a: Alias _ NARROW[any]; v: Vertex _ NARROW[a.thing]; stop _ FALSE; IF PickAName[v.names] # a.name THEN RETURN; Log["(%05d)\t%05d\t%5g\t%5g\t%12g", IO.card[v.oldColor], IO.card[v.curColor], IO.bool[v.unique], IO.bool[v.suspect], IO.rope[PickAName[v.names]]]; IF v.equiv # NIL THEN Log["\t%g\n", IO.rope[PickAName[v.equiv.names]]] ELSE Log["\n"]; END; Log["\nGraph %g vertices:\n", IO.rope[graphID]]; vertices.EnumerateIncreasing[WriteVertex]; END; ignorable: Asserting.Assertions _ NIL; CheckIgnore: PROC [source: Source, what: LORA] = { IF NOT Asserting.Test[what.first, what.rest, ignorable] THEN Warn[source, "Unknown assertion %g", IO.refAny[what]]; }; AddIgnorance: PROC [spec: LORA, context: LORA] = { FOR spec _ spec, spec.rest WHILE spec # NIL DO WITH spec.first SELECT FROM a: ATOM => ignorable _ Asserting.Assert[a, context, ignorable]; l: LORA => AddIgnorance[l.rest, CONS[l.first, context]]; ENDCASE => ERROR; ENDLOOP; }; Start: PROC = { ignoreSpec: LORA _ NARROW[FS.StreamOpen["Lichen.ignorable"].GetRefAny[]]; AddIgnorance[ignoreSpec, NIL]; }; Start[]; END.