StaticImpl.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Barth, January 13, 1987 2:04:01 pm PST
Bertrand Serlet March 30, 1987 10:01:05 pm PST
DIRECTORY Core, CoreClasses, CoreFlat, CoreOps, CoreProperties, RefTab, Static, TerminalIO;
StaticImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreFlat, CoreOps, CoreProperties, RefTab, TerminalIO
EXPORTS Static
= BEGIN OPEN Static;
staticProp: ATOM = $Static;
unconnectedOKAtom: ATOM = $UnconnectedOk;
staticCutSetProp: PUBLIC ATOM ← $StaticCutSet;
UnconnectedOK: PUBLIC PROC [wire: Core.Wire] RETURNS [same: Core.Wire] = {
CoreProperties.PutWireProp[wire, staticProp, unconnectedOKAtom];
same ← wire;
};
PropagateUnconnectedOK: PROC [wire: Core.Wire, internalTable: RefTab.Ref, publicTable: RefTab.Ref ← NIL, ok: BOOLFALSE] = {
ok ← ok OR CoreProperties.GetWireProp[wire, staticProp]=unconnectedOKAtom;
IF wire.size>0 THEN FOR i: NAT IN [0..wire.size) DO
PropagateUnconnectedOK[wire[i], internalTable, publicTable, ok];
ENDLOOP
ELSE {
wireInfo: WireInfo ← NARROW[RefTab.Fetch[internalTable, wire].val];
IF wireInfo=NIL THEN {
IF publicTable#NIL THEN wireInfo ← NARROW[RefTab.Fetch[publicTable, wire].val];
IF wireInfo=NIL THEN {
wireInfo ← NEW[WireInfoRec];
IF NOT RefTab.Store[internalTable, wire, wireInfo] THEN ERROR;
};
};
wireInfo.unconnectedOK ← wireInfo.unconnectedOK OR ok;
};
};
WireInfo: TYPE = REF WireInfoRec;
WireInfoRec: TYPE = RECORD [
count: INT ← 0,
unconnectedOK: BOOLFALSE];
New Practice
ConnectionCheck: PUBLIC ConnectionCheckProc = {
IF (NOT unconnectedOK) AND ((flatWire.wireRoot=public AND count<1) OR (NOT flatWire.wireRoot=public AND count<2)) THEN {
TerminalIO.PutRope[CoreFlat.WirePathRope[root, flatWire]];
TerminalIO.PutRope[" has "];
SELECT count FROM
0 => TerminalIO.PutRope["no connection"];
1 => TerminalIO.PutRope["only one connection"];
ENDCASE => ERROR;
TerminalIO.PutRope["\n"];
};
};
CountFlatConnections: PUBLIC PROC [root: Core.CellType, eachWireCount: ConnectionCheckProc, cutSet: CoreFlat.CutSet ← NIL] RETURNS [quit: BOOLFALSE] = {
CheckPublicCount: CoreOps.EachWireProc = {
IF wire.size=0 THEN {
publicInfo: WireInfo ← NARROW[RefTab.Fetch[publicTable, wire].val];
IF RefTab.Fetch[publicVisit, wire].found THEN RETURN;
IF NOT RefTab.Insert[publicVisit, wire, $Visited] THEN ERROR;
quit ← eachWireCount[root, [wireRoot: public, wire: wire], publicInfo.count, publicInfo.unconnectedOK];
};
};
Check: PROC [cell: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec ← CoreFlat.rootCellType, instance: CoreClasses.CellInstance ← NIL] RETURNS [quit: BOOLFALSE] = {
GetPublicInfo: PROC [publicWire: Core.Wire, thisCell: Core.CellType, thisFlatCell: CoreFlat.FlatCellTypeRec, thisInstance: CoreClasses.CellInstance] RETURNS [publicInfo: WireInfo, quit: BOOLFALSE] = {
publicInfo ← NARROW[RefTab.Fetch[publicTable, publicWire].val];
IF publicInfo=NIL THEN {
quit ← Check[thisCell, thisFlatCell, thisInstance];
publicInfo ← NARROW[RefTab.Fetch[publicTable, publicWire].val];
IF publicInfo=NIL THEN ERROR;
};
};
SELECT TRUE FROM
cell.class=CoreClasses.transistorCellClass OR cell.class=CoreClasses.unspecifiedCellClass OR CoreFlat.CutSetMemberResolved[flatCell, instance, cell, cutSet] => {
InsertLeafPublic: PROC [wire: Core.Wire] = {
[] ← RefTab.Insert[publicTable, wire, NEW[WireInfoRec ← [count: 1]]];
};
CoreOps.VisitRootAtomics[cell.public, InsertLeafPublic];
};
cell.class=CoreClasses.recordCellClass => {
InsertRecordPublic: PROC [wire: Core.Wire] = {
[] ← RefTab.Insert[publicTable, wire, NEW[WireInfoRec]];
};
CheckInternalCount: CoreOps.EachWireProc = {
IF wire.size=0 THEN {
internalInfo: WireInfo ← NIL;
IF RefTab.Fetch[publicTable, wire].found THEN RETURN;
IF RefTab.Fetch[visitCheck, wire].found THEN RETURN;
IF NOT RefTab.Insert[visitCheck, wire, $Visited] THEN ERROR;
internalInfo ← NARROW[RefTab.Fetch[internalTable, wire].val];
quit ← eachWireCount[root, [flatCell: flatCell, wire: wire], internalInfo.count, internalInfo.unconnectedOK];
};
};
rct: CoreClasses.RecordCellType ← NARROW[cell.data];
internalTable: RefTab.Ref ← RefTab.Create[];
visitCheck: RefTab.Ref ← RefTab.Create[];
CoreOps.VisitRootAtomics[cell.public, InsertRecordPublic];
FOR i: NAT IN [0..rct.size) DO
ComputeInternalCount: CoreOps.EachWirePairProc = {
actualInfo, publicInfo: WireInfo;
IF publicWire.size>0 THEN RETURN;
IF RefTab.Fetch[visitCompute, publicWire].found THEN RETURN;
IF NOT RefTab.Insert[visitCompute, publicWire, $Visited] THEN ERROR;
[publicInfo, quit] ← GetPublicInfo[publicWire, rct[i].type, [CoreFlat.ExtendPath[flatCell.path, i, rct], 0], rct[i]];
IF quit THEN RETURN;
actualInfo ← NARROW[RefTab.Fetch[internalTable, actualWire].val];
IF actualInfo=NIL THEN {
actualInfo ← NARROW[RefTab.Fetch[publicTable, actualWire].val];
IF actualInfo=NIL THEN {
actualInfo ← NEW[WireInfoRec];
IF NOT RefTab.Insert[internalTable, actualWire, actualInfo] THEN ERROR;
};
};
actualInfo.count ← actualInfo.count + publicInfo.count;
};
visitCompute: RefTab.Ref ← RefTab.Create[];
quit ← CoreOps.VisitBindingSeq[rct[i].actual, rct[i].type.public, ComputeInternalCount];
IF quit THEN RETURN;
ENDLOOP;
PropagateUnconnectedOK[rct.internal, internalTable, publicTable];
quit ← CoreOps.VisitWireSeq[rct.internal, CheckInternalCount];
};
ENDCASE => {
ComputePublicCount: CoreOps.EachWirePairProc = {
publicInfo: WireInfo;
IF publicWire.size>0 THEN RETURN;
[publicInfo, quit] ← GetPublicInfo[publicWire, thisCell, [flatCell.path, flatCell.recastCount+1], instance];
[] ← RefTab.Insert[publicTable, actualWire, publicInfo];
};
thisCell: Core.CellType ← CoreOps.Recast[cell];
quit ← IF thisCell=cell THEN Check[cell, flatCell, instance]
ELSE CoreOps.VisitBindingSeq[cell.public, thisCell.public, ComputePublicCount];
};
};
publicVisit: RefTab.Ref ← RefTab.Create[];
publicTable: RefTab.Ref ← RefTab.Create[]; -- Core.Wire to WireInfo
IF cutSet=NIL THEN cutSet ← NARROW[CoreProperties.GetCellTypeProp[root, staticCutSetProp]];
quit ← Check[root];
IF NOT quit THEN quit ← CoreOps.VisitWireSeq[root.public, CheckPublicCount];
};
CountHierarchicalConnections: PUBLIC PROC [root: Core.CellType, eachWireCount: ConnectionCheckProc, cutSet: CoreFlat.CutSet ← NIL] RETURNS [quit: BOOLFALSE] = {
Check: PROC [cell: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec ← CoreFlat.rootCellType, instance: CoreClasses.CellInstance ← NIL] RETURNS [quit: BOOLFALSE] = {
IF RefTab.Fetch[cellTypeVisit, cell].found THEN RETURN;
IF NOT RefTab.Insert[cellTypeVisit, cell, $Visited] THEN ERROR;
SELECT TRUE FROM
cell.class=CoreClasses.transistorCellClass OR cell.class=CoreClasses.unspecifiedCellClass OR CoreFlat.CutSetMemberResolved[flatCell, instance, cell, cutSet] => RETURN;
cell.class=CoreClasses.recordCellClass => {
InsertRecordPublic: PROC [wire: Core.Wire] = {
[] ← RefTab.Insert[publicTable, wire, $Public];
};
CheckWireCount: CoreOps.EachWireProc = {
IF wire.size=0 THEN {
wireInfo: WireInfo ← NARROW[RefTab.Fetch[internalTable, wire].val];
publicWire: BOOL ← RefTab.Fetch[publicTable, wire].found;
IF RefTab.Fetch[visitCheck, wire].found THEN RETURN;
IF NOT RefTab.Insert[visitCheck, wire, $Visited] THEN ERROR;
quit ← eachWireCount[root, [flatCell: flatCell, wireRoot: IF publicWire THEN public ELSE internal, wire: wire], wireInfo.count, wireInfo.unconnectedOK];
};
};
rct: CoreClasses.RecordCellType ← NARROW[cell.data];
publicTable: RefTab.Ref ← RefTab.Create[];
internalTable: RefTab.Ref ← RefTab.Create[];
visitCheck: RefTab.Ref ← RefTab.Create[];
PropagateUnconnectedOK[rct.internal, internalTable];
FOR i: NAT IN [0..rct.size) DO
ComputeInternalCount: CoreOps.EachWirePairProc = {
actualInfo: WireInfo;
IF publicWire.size>0 THEN RETURN;
IF RefTab.Fetch[visitCompute, publicWire].found THEN RETURN;
IF NOT RefTab.Insert[visitCompute, publicWire, $Visited] THEN ERROR;
actualInfo ← NARROW[RefTab.Fetch[internalTable, actualWire].val];
actualInfo.count ← actualInfo.count + 1;
};
visitCompute: RefTab.Ref ← RefTab.Create[];
IF CoreOps.VisitBindingSeq[rct[i].actual, rct[i].type.public, ComputeInternalCount] THEN ERROR;
quit ← Check[rct[i].type, [CoreFlat.ExtendPath[flatCell.path, i, rct], 0], rct[i]];
IF quit THEN RETURN;
ENDLOOP;
CoreOps.VisitRootAtomics[cell.public, InsertRecordPublic];
quit ← CoreOps.VisitWireSeq[rct.internal, CheckWireCount];
};
ENDCASE => {
new: Core.CellType ← CoreOps.Recast[cell];
quit ← IF cell=new THEN Check[cell, flatCell, instance]
ELSE Check[new, [flatCell.path, flatCell.recastCount+1], instance];
};
};
cellTypeVisit: RefTab.Ref ← RefTab.Create[]; -- Marks analyzed cells
IF cutSet=NIL THEN cutSet ← NARROW[CoreProperties.GetCellTypeProp[root, staticCutSetProp]];
quit ← Check[root];
};
Old Practice
CheckCount: PUBLIC ConnectionCountProc = {
IF (NOT unconnectedOK) AND ((public AND count<1) OR (NOT public AND count<2)) THEN {
TerminalIO.PutRope[CoreOps.GetFullWireName[wireRoot, wire]];
TerminalIO.PutRope[IF public THEN " of cell " ELSE " in cell "];
TerminalIO.PutRope[CoreOps.GetCellTypeName[cellType]];
TerminalIO.PutRope[" has "];
SELECT count FROM
0 => TerminalIO.PutRope["no connection"];
1 => TerminalIO.PutRope["only one connection"];
ENDCASE => ERROR;
TerminalIO.PutRope["\n"];
};
};
CountLeafConnections: PUBLIC PROC [root: Core.CellType, eachWireCount: ConnectionCountProc, cutSet: CoreFlat.CutSet ← NIL] = {
CheckPublicCount: PROC [wire: Core.Wire] = {
publicInfo: WireInfo ← NARROW[RefTab.Fetch[publicTable, wire].val];
IF RefTab.Fetch[publicVisit, wire].found THEN RETURN;
IF NOT RefTab.Insert[publicVisit, wire, $Visited] THEN ERROR;
eachWireCount[publicInfo.count, root.public, wire, TRUE, root, publicInfo.unconnectedOK];
};
Check: PROC [cell: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec ← CoreFlat.rootCellType, instance: CoreClasses.CellInstance ← NIL] = {
GetPublicInfo: PROC [publicWire: Core.Wire, thisCell: Core.CellType, thisFlatCell: CoreFlat.FlatCellTypeRec, thisInstance: CoreClasses.CellInstance] RETURNS [publicInfo: WireInfo] = {
publicInfo ← NARROW[RefTab.Fetch[publicTable, publicWire].val];
IF publicInfo=NIL THEN {
Check[thisCell, thisFlatCell, thisInstance];
publicInfo ← NARROW[RefTab.Fetch[publicTable, publicWire].val];
IF publicInfo=NIL THEN ERROR;
};
};
SELECT TRUE FROM
cell.class=CoreClasses.transistorCellClass OR cell.class=CoreClasses.unspecifiedCellClass OR CoreFlat.CutSetMemberResolved[flatCell, instance, cell, cutSet] => {
InsertLeafPublic: PROC [wire: Core.Wire] = {
[] ← RefTab.Insert[publicTable, wire, NEW[WireInfoRec ← [count: 1]]];
};
CoreOps.VisitRootAtomics[cell.public, InsertLeafPublic];
};
cell.class=CoreClasses.recordCellClass => {
InsertRecordPublic: PROC [wire: Core.Wire] = {
[] ← RefTab.Insert[publicTable, wire, NEW[WireInfoRec]];
};
CheckInternalCount: PROC [wire: Core.Wire] = {
internalInfo: WireInfo ← NIL;
IF RefTab.Fetch[publicTable, wire].found THEN RETURN;
IF RefTab.Fetch[visitCheck, wire].found THEN RETURN;
IF NOT RefTab.Insert[visitCheck, wire, $Visited] THEN ERROR;
internalInfo ← NARROW[RefTab.Fetch[internalTable, wire].val];
eachWireCount[internalInfo.count, rct.internal, wire, FALSE, cell, internalInfo.unconnectedOK];
};
rct: CoreClasses.RecordCellType ← NARROW[cell.data];
internalTable: RefTab.Ref ← RefTab.Create[];
visitCheck: RefTab.Ref ← RefTab.Create[];
CoreOps.VisitRootAtomics[cell.public, InsertRecordPublic];
FOR i: NAT IN [0..rct.size) DO
ComputeInternalCount: CoreOps.EachWirePairProc = {
actualInfo, publicInfo: WireInfo;
IF publicWire.size>0 THEN RETURN;
IF RefTab.Fetch[visitCompute, publicWire].found THEN RETURN;
IF NOT RefTab.Insert[visitCompute, publicWire, $Visited] THEN ERROR;
publicInfo ← GetPublicInfo[publicWire, rct[i].type, [CoreFlat.ExtendPath[flatCell.path, i, rct], 0], rct[i]];
actualInfo ← NARROW[RefTab.Fetch[internalTable, actualWire].val];
IF actualInfo=NIL THEN {
actualInfo ← NARROW[RefTab.Fetch[publicTable, actualWire].val];
IF actualInfo=NIL THEN {
actualInfo ← NEW[WireInfoRec];
IF NOT RefTab.Insert[internalTable, actualWire, actualInfo] THEN ERROR;
};
};
actualInfo.count ← actualInfo.count + publicInfo.count;
};
visitCompute: RefTab.Ref ← RefTab.Create[];
IF CoreOps.VisitBindingSeq[rct[i].actual, rct[i].type.public, ComputeInternalCount] THEN ERROR;
ENDLOOP;
PropagateUnconnectedOK[rct.internal, internalTable, publicTable];
CoreOps.VisitRootAtomics[rct.internal, CheckInternalCount];
};
ENDCASE => {
ComputePublicCount: CoreOps.EachWirePairProc = {
publicInfo: WireInfo;
IF publicWire.size>0 THEN RETURN;
publicInfo ← GetPublicInfo[publicWire, thisCell, [flatCell.path, flatCell.recastCount+1], instance];
[] ← RefTab.Insert[publicTable, actualWire, publicInfo];
};
thisCell: Core.CellType ← CoreOps.Recast[cell];
IF thisCell=cell THEN Check[cell, flatCell, instance]
ELSE IF CoreOps.VisitBindingSeq[cell.public, thisCell.public, ComputePublicCount] THEN ERROR;
};
};
publicVisit: RefTab.Ref ← RefTab.Create[];
publicTable: RefTab.Ref ← RefTab.Create[]; -- Core.Wire to WireInfo
IF cutSet=NIL THEN cutSet ← NARROW[CoreProperties.GetCellTypeProp[root, staticCutSetProp]];
Check[root];
CoreOps.VisitRootAtomics[root.public, CheckPublicCount];
};
CountDirectConnections: PUBLIC PROC [root: Core.CellType, eachWireCount: ConnectionCountProc, cutSet: CoreFlat.CutSet ← NIL] = {
Check: PROC [cell: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec ← CoreFlat.rootCellType, instance: CoreClasses.CellInstance ← NIL] = {
IF RefTab.Fetch[cellTypeVisit, cell].found THEN RETURN;
IF NOT RefTab.Insert[cellTypeVisit, cell, $Visited] THEN ERROR;
SELECT TRUE FROM
cell.class=CoreClasses.transistorCellClass OR cell.class=CoreClasses.unspecifiedCellClass OR CoreFlat.CutSetMemberResolved[flatCell, instance, cell, cutSet] => RETURN;
cell.class=CoreClasses.recordCellClass => {
InsertRecordPublic: PROC [wire: Core.Wire] = {
[] ← RefTab.Insert[publicTable, wire, $Public];
};
CheckWireCount: PROC [wire: Core.Wire] = {
wireInfo: WireInfo ← NARROW[RefTab.Fetch[internalTable, wire].val];
publicWire: BOOL ← RefTab.Fetch[publicTable, wire].found;
IF RefTab.Fetch[visitCheck, wire].found THEN RETURN;
IF NOT RefTab.Insert[visitCheck, wire, $Visited] THEN ERROR;
eachWireCount[wireInfo.count, rct.internal, wire, publicWire, cell, wireInfo.unconnectedOK];
};
rct: CoreClasses.RecordCellType ← NARROW[cell.data];
publicTable: RefTab.Ref ← RefTab.Create[];
internalTable: RefTab.Ref ← RefTab.Create[];
visitCheck: RefTab.Ref ← RefTab.Create[];
PropagateUnconnectedOK[rct.internal, internalTable];
FOR i: NAT IN [0..rct.size) DO
ComputeInternalCount: CoreOps.EachWirePairProc = {
actualInfo: WireInfo;
IF publicWire.size>0 THEN RETURN;
IF RefTab.Fetch[visitCompute, publicWire].found THEN RETURN;
IF NOT RefTab.Insert[visitCompute, publicWire, $Visited] THEN ERROR;
actualInfo ← NARROW[RefTab.Fetch[internalTable, actualWire].val];
actualInfo.count ← actualInfo.count + 1;
};
visitCompute: RefTab.Ref ← RefTab.Create[];
IF CoreOps.VisitBindingSeq[rct[i].actual, rct[i].type.public, ComputeInternalCount] THEN ERROR;
Check[rct[i].type, [CoreFlat.ExtendPath[flatCell.path, i, rct], 0], rct[i]];
ENDLOOP;
CoreOps.VisitRootAtomics[cell.public, InsertRecordPublic];
CoreOps.VisitRootAtomics[rct.internal, CheckWireCount];
};
ENDCASE => {
new: Core.CellType ← CoreOps.Recast[cell];
IF cell=new THEN Check[cell, flatCell, instance]
ELSE Check[new, [flatCell.path, flatCell.recastCount+1], instance];
};
};
cellTypeVisit: RefTab.Ref ← RefTab.Create[]; -- Marks analyzed cells
IF cutSet=NIL THEN cutSet ← NARROW[CoreProperties.GetCellTypeProp[root, staticCutSetProp]];
Check[root];
};
END.