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]];
AddVertex[cv]; --AM1
LinkInstance[cv]; --AM2
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.