StaticImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Barth, January 13, 1987 2:04:01 pm PST
DIRECTORY Core, CoreClasses, CoreFlat, CoreOps, CoreProperties, HashTable, Static, TerminalIO;
StaticImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreFlat, CoreOps, CoreProperties, HashTable, 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: BOOLFALSE];
CountLeafConnections: PUBLIC PROC [root: Core.CellType, eachWireCount: ConnectionCountProc, cutSet: CoreFlat.CutSet ← NIL] = {
CheckPublicCount: PROC [wire: Core.Wire] = {
publicInfo: WireInfo ← NARROW[HashTable.Fetch[publicTable, wire].value];
IF HashTable.Fetch[publicVisit, wire].found THEN RETURN;
IF NOT HashTable.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[HashTable.Fetch[publicTable, publicWire].value];
IF publicInfo=NIL THEN {
Check[thisCell, thisFlatCell, thisInstance];
publicInfo ← NARROW[HashTable.Fetch[publicTable, publicWire].value];
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] = {
[] ← HashTable.Insert[publicTable, wire, NEW[WireInfoRec ← [count: 1]]];
};
CoreOps.VisitRootAtomics[cell.public, InsertLeafPublic];
};
cell.class=CoreClasses.recordCellClass => {
InsertRecordPublic: PROC [wire: Core.Wire] = {
[] ← HashTable.Insert[publicTable, wire, NEW[WireInfoRec]];
};
CheckInternalCount: PROC [wire: Core.Wire] = {
internalInfo: WireInfo ← NIL;
IF HashTable.Fetch[publicTable, wire].found THEN RETURN;
IF HashTable.Fetch[visitCheck, wire].found THEN RETURN;
IF NOT HashTable.Insert[visitCheck, wire, $Visited] THEN ERROR;
internalInfo ← NARROW[HashTable.Fetch[internalTable, wire].value];
eachWireCount[internalInfo.count, rct.internal, wire, FALSE, cell, internalInfo.unconnectedOK];
};
rct: CoreClasses.RecordCellType ← NARROW[cell.data];
internalTable: HashTable.Table ← HashTable.Create[];
visitCheck: HashTable.Table ← HashTable.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 HashTable.Fetch[visitCompute, publicWire].found THEN RETURN;
IF NOT HashTable.Insert[visitCompute, publicWire, $Visited] THEN ERROR;
publicInfo ← GetPublicInfo[publicWire, rct[i].type, [CoreFlat.ExtendPath[flatCell.path, i, rct], 0], rct[i]];
actualInfo ← NARROW[HashTable.Fetch[internalTable, actualWire].value];
IF actualInfo=NIL THEN {
actualInfo ← NARROW[HashTable.Fetch[publicTable, actualWire].value];
IF actualInfo=NIL THEN {
actualInfo ← NEW[WireInfoRec];
IF NOT HashTable.Insert[internalTable, actualWire, actualInfo] THEN ERROR;
};
};
actualInfo.count ← actualInfo.count + publicInfo.count;
};
visitCompute: HashTable.Table ← HashTable.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];
[] ← HashTable.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: HashTable.Table ← HashTable.Create[];
publicTable: HashTable.Table ← HashTable.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 HashTable.Fetch[cellTypeVisit, cell].found THEN RETURN;
IF NOT HashTable.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] = {
[] ← HashTable.Insert[publicTable, wire, $Public];
};
CheckWireCount: PROC [wire: Core.Wire] = {
wireInfo: WireInfo ← NARROW[HashTable.Fetch[internalTable, wire].value];
publicWire: BOOL ← HashTable.Fetch[publicTable, wire].found;
IF HashTable.Fetch[visitCheck, wire].found THEN RETURN;
IF NOT HashTable.Insert[visitCheck, wire, $Visited] THEN ERROR;
eachWireCount[wireInfo.count, rct.internal, wire, publicWire, cell, wireInfo.unconnectedOK];
};
rct: CoreClasses.RecordCellType ← NARROW[cell.data];
publicTable: HashTable.Table ← HashTable.Create[];
internalTable: HashTable.Table ← HashTable.Create[];
visitCheck: HashTable.Table ← HashTable.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 HashTable.Fetch[visitCompute, publicWire].found THEN RETURN;
IF NOT HashTable.Insert[visitCompute, publicWire, $Visited] THEN ERROR;
actualInfo ← NARROW[HashTable.Fetch[internalTable, actualWire].value];
actualInfo.count ← actualInfo.count + 1;
};
visitCompute: HashTable.Table ← HashTable.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: HashTable.Table ← HashTable.Create[]; -- Marks analyzed cells
IF cutSet=NIL THEN cutSet ← NARROW[CoreProperties.GetCellTypeProp[root, staticCutSetProp]];
Check[root];
};
PropagateUnconnectedOK: PROC [wire: Core.Wire, internalTable: HashTable.Table, publicTable: HashTable.Table ← 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[HashTable.Fetch[internalTable, wire].value];
IF wireInfo=NIL THEN {
IF publicTable#NIL THEN wireInfo ← NARROW[HashTable.Fetch[publicTable, wire].value];
IF wireInfo=NIL THEN {
wireInfo ← NEW[WireInfoRec];
IF NOT HashTable.Store[internalTable, wire, wireInfo] THEN ERROR;
};
};
wireInfo.unconnectedOK ← wireInfo.unconnectedOK OR ok;
};
};
END.