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;
};
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"];
};
};
WireInfo: TYPE = REF WireInfoRec;
WireInfoRec:
TYPE =
RECORD [
count: INT ← 0,
unconnectedOK: BOOL ← FALSE];
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];
};
PropagateUnconnectedOK:
PROC [wire: Core.Wire, internalTable: RefTab.Ref, publicTable: RefTab.Ref ←
NIL, ok:
BOOL ←
FALSE] = {
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;
};
};
END.