CompareOpsImpl:
CEDAR
PROGRAM
IMPORTS CompareOps, IO, OrderedSymbolTableRef, Rope, ViewerIO
EXPORTS CompareDataStructure, CompareOps =
BEGIN OPEN CompareDataStructure, CompareOps;
MirrorName: PUBLIC ROPE ← " world ";
log: IO.STREAM ← ViewerIO.CreateViewerStreams["Compare Log"].out;
Warn:
PUBLIC
PROC [source: Source, format:
ROPE, v1, v2, v3, v4, v5:
IO.Value ← [null[]]] = {
IF source.stream #
NIL
THEN {
log.PutRope["Before "];
IF source.name # NIL THEN log.PutRope[source.name];
log.PutF["[%g]: ", IO.int[source.stream.GetIndex[]]];
}
ELSE IF source.name # NIL THEN log.PutF["In %g: ", IO.rope[source.name]];
log.PutF[format, v1, v2, v3, v4, v5];
log.PutChar['\n];
};
Err:
PUBLIC
PROC [source: Source, format:
ROPE, v1, v2, v3, v4, v5:
IO.Value ← [null[]]] = {
IF source.stream #
NIL
THEN {
log.PutRope["Before "];
IF source.name # NIL THEN log.PutRope[source.name];
log.PutF["[%g]: ", IO.int[source.stream.GetIndex[]]];
}
ELSE IF source.name # NIL THEN log.PutF["In %g: ", IO.rope[source.name]];
log.PutF[format, v1, v2, v3, v4, v5];
log.PutChar['\n];
log.Flush[];
ERROR;
};
Log:
PUBLIC
PROC [format:
ROPE, v1, v2, v3, v4, v5:
IO.Value ← [null[]]] =
{log.PutF[format, v1, v2, v3, v4, v5]};
Fail:
PUBLIC
PROC [af: AssertionFamily, ao: FailableAssertionOp, format:
ROPE, v1, v2, v3, v4, v5:
IO.Value ← [null[]]] = {
SELECT ao
FROM
report => {log.PutF[format, v1, v2, v3, v4, v5]; log.PutRope["\n"]};
check => (SELECT af FROM normal => NotNormal, comparable => NotComparable, ENDCASE => ERROR)[IO.PutFR[format, v1, v2, v3, v4, v5]];
ENDCASE => ERROR
};
FlushLog: PUBLIC PROC = {log.Flush[]};
IsMirror:
PUBLIC
PROC [v: Vertex]
RETURNS [isMirror:
BOOL] =
{isMirror ← v = v.parent.mirror};
EnumerateNames:
PUBLIC
PROC [names: Names, consume:
PROC [name:
ROPE, class:
ATOM
--UNION[$designed, $unknown, $progged]--]] = {
Doit:
PROC [rl: RopeList, class:
ATOM] = {
FOR rl ← rl, rl.rest WHILE rl # NIL DO consume[rl.first, class] ENDLOOP;
};
Doit[names.designed, $designed];
Doit[names.unknown, $unknown];
Doit[names.progged, $progged];
};
NamesInclude:
PUBLIC
PROC [names: Names, name:
ROPE]
RETURNS [incl:
BOOL] = {
incl
←
RopeListIncludes[names.designed, name] OR
RopeListIncludes[names.unknown, name] OR
RopeListIncludes[names.progged, name];
};
AddVertex:
PUBLIC
PROC [v: Vertex] =
BEGIN
Insert[v.parent.parts, v.names, v];
SELECT v.class
FROM
net => v.parent.netCount ← v.parent.netCount + 1;
cell => v.parent.cellCount ← v.parent.cellCount + 1;
ENDCASE => ERROR;
END;
FindPort:
PUBLIC
PROC [ports: PortS, name:
ROPE]
RETURNS [portIndex:
NAT] = {
FOR i:
NAT
IN [0 .. ports.length)
DO
IF NamesInclude[ports[i].names, name] THEN RETURN [i];
ENDLOOP;
portIndex ← notFound;
};
RopeListIncludes:
PUBLIC
PROC [rl: RopeList, r:
ROPE]
RETURNS [found:
BOOL] = {
FOR rl ← rl, rl.rest
WHILE rl #
NIL
DO
IF rl.first.Equal[r] THEN RETURN [TRUE];
ENDLOOP;
found ← FALSE};
AddNames:
PUBLIC
PROC [ra:
REF
ANY
--UNION[Vertex, CellType]--, names: Names] = {
Work:
PROC [old: Names, byName: SymbolTable]
RETURNS [new: Names] = {
ReallyWork:
PROC [old, add: RopeList]
RETURNS [new: RopeList] = {
new ← old;
FOR add ← add, add.rest
WHILE add #
NIL
DO
a: Alias ← NEW [AliasRep ← [name: add.first, thing: ra]];
byName.Insert[a];
new ← CONS[add.first, new];
ENDLOOP;
};
new.designed ← ReallyWork[old.designed, names.designed];
new.unknown ← ReallyWork[old.unknown, names.unknown];
new.progged ← ReallyWork[old.progged, names.progged];
};
WITH ra
SELECT
FROM
ct: CellType => ct.names ← Work[ct.names, ct.design.cellTypesByName];
v: Vertex => v.names ← Work[v.names, v.parent.parts];
ENDCASE => ERROR;
};
Insert:
PUBLIC
PROC [st: SymbolTable, names: Names, val:
REF
ANY] = {
Work:
PROC [rl: RopeList] = {
FOR rl ← rl, rl.rest
WHILE rl #
NIL
DO
a: Alias ← NEW [AliasRep ← [name: rl.first, thing: val]];
st.Insert[a];
ENDLOOP;
};
Work[names.designed];
Work[names.unknown];
Work[names.progged];
};
Delete:
PUBLIC
PROC [st: SymbolTable, names: Names, val:
REF
ANY] = {
Work:
PROC [rl: RopeList] = {
FOR rl ← rl, rl.rest
WHILE rl #
NIL
DO
deld: REF ANY ← AntiAlias[st.Delete[rl.first]];
IF deld # val THEN ERROR;
ENDLOOP;
};
Work[names.designed];
Work[names.unknown];
Work[names.progged];
};
CompareRopes:
PUBLIC
PROC [r1, r2:
REF
ANY]
RETURNS [c: Basics.Comparison] =
BEGIN
c ← NARROW[r1, ROPE].Compare[NARROW[r2]];
END;
CompareNames:
PUBLIC
PROC [r1, r2:
REF
ANY]
RETURNS [c: Basics.Comparison] =
BEGIN
Key:
PROC [r:
REF
ANY]
RETURNS [k:
ROPE] = {
WITH r
SELECT
FROM
rr: ROPE => k ← rr;
a: Alias => k ← a.name;
ENDCASE => ERROR};
c ← Key[r1].Compare[Key[r2]];
END;
CompareByAddress:
PUBLIC
PROC [r1, r2:
REF
ANY]
RETURNS [c: Basics.Comparison] =
BEGIN
i1: INT ← LOOPHOLE[r1];
i2: INT ← LOOPHOLE[r2];
c ←
SELECT i1 - i2
FROM
<0 => less,
=0 => equal,
>0 => greater,
ENDCASE => ERROR;
END;
CompareVertices: PUBLIC PROC [r1, r2: REF ANY] RETURNS [c: Basics.Comparison] = CompareNames;
CompareECParentNet:
PUBLIC
PROC [r1, r2:
REF
ANY]
RETURNS [c: Basics.Comparison] =
BEGIN
Key:
PROC [r:
REF
ANY]
RETURNS [k: Vertex] = {
WITH r
SELECT
FROM
ec: ExtraConnection => k ← ec.parentNet;
v: Vertex => k ← v;
ENDCASE => ERROR};
c ← CompareByAddress[Key[r1], Key[r2]];
END;
CompareECSubCell:
PUBLIC
PROC [r1, r2:
REF
ANY]
RETURNS [c: Basics.Comparison] =
BEGIN
Key:
PROC [r:
REF
ANY]
RETURNS [k: Vertex] = {
WITH r
SELECT
FROM
ec: ExtraConnection => k ← ec.subCell;
v: Vertex => k ← v;
ENDCASE => ERROR};
c ← CompareByAddress[Key[r1], Key[r2]];
END;
CompareECChildNet:
PUBLIC
PROC [r1, r2:
REF
ANY]
RETURNS [c: Basics.Comparison] =
BEGIN
Key:
PROC [r:
REF
ANY]
RETURNS [k: Vertex] = {
WITH r
SELECT
FROM
ec: ExtraConnection => k ← ec.childNet;
v: Vertex => k ← v;
ENDCASE => ERROR};
c ← CompareByAddress[Key[r1], Key[r2]];
END;
CompareECSubCellThenChildNet:
PUBLIC
PROC [r1, r2:
REF
ANY]
RETURNS [c: Basics.Comparison] =
BEGIN
Key:
PROC [r:
REF
ANY]
RETURNS [k: ExtraConnection] = {
WITH r
SELECT
FROM
ec: ExtraConnection => k ← ec;
ENDCASE => ERROR};
k1: ExtraConnection ← Key[r1];
k2: ExtraConnection ← Key[r2];
IF (c ← CompareByAddress[k1.subCell, k2.subCell]) # equal THEN RETURN;
c ← CompareByAddress[k1.childNet, k2.childNet]
END;
Lookup:
PUBLIC
PROC [st: SymbolTable, key:
ROPE]
RETURNS [val:
REF
ANY] =
{val ← AntiAlias[st.Lookup[key]]};
AntiAlias:
PUBLIC
PROC [ra:
REF
ANY]
RETURNS [val:
REF
ANY] = {
FOR val ← ra, NARROW[val, Alias].thing WHILE (val # NIL) AND ISTYPE[val, Alias] DO NULL ENDLOOP;
};
GlobalCellTypeName:
PUBLIC
PROC [ct: CellType]
RETURNS [r:
ROPE] = {
r ← ct.design.name.Cat[".", PickAName[ct.names]]};
GlobalPortName:
PUBLIC
PROC [ct: CellType, portIndex: PortIndex]
RETURNS [r:
ROPE] = {
r ← GlobalCellTypeName[ct].Cat[".", PickAName[ct.ports[portIndex].names]]};
GlobalVertexName:
PUBLIC
PROC [v: Vertex]
RETURNS [r:
ROPE] = {
r ← GlobalCellTypeName[v.parent].Cat[".", PickAName[v.names]]};
GlobalName:
PUBLIC
PROC [ra:
REF
ANY, soFar: Naming ← [
NIL,
NIL]]
RETURNS [name:
ROPE] = {
nn: Names ← NamingNames[soFar];
name ← PickAName[nn];
WITH ra
SELECT
FROM
design: Design => NULL;
ct: CellType => name ← ct.design.name.Cat[".", name];
v: Vertex => name ← GlobalCellTypeName[v.type].Cat[".", name];
s: Socket => name ← GlobalCellTypeName[s.ct].Cat[".", name];
ENDCASE => ERROR;
};
KeepAll:
PUBLIC
PROC [ra:
REF
ANY]
RETURNS [keepAll:
BOOL] = {
keepAll ←
WITH ra
SELECT
FROM
d: Design => d.allKept,
ct: CellType => ct.design.allKept,
v: Vertex => v.type.design.allKept,
s: Socket => s.ct.design.allKept,
ENDCASE => ERROR};
PickAName:
PUBLIC
PROC [names: Names]
RETURNS [name:
ROPE] = {
Try:
PROC [rl: RopeList]
RETURNS [done:
BOOL] =
{IF done ← (rl # NIL) THEN name ← rl.first};
IF Try[names.designed] THEN RETURN;
IF Try[names.unknown] THEN RETURN;
IF Try[names.progged] THEN RETURN;
ERROR;
};
END.