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: 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; }; }; WireInfo: TYPE = REF WireInfoRec; WireInfoRec: TYPE = RECORD [ count: INT _ 0, unconnectedOK: BOOL _ FALSE]; 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: BOOL _ FALSE] = { 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: BOOL _ FALSE] = { GetPublicInfo: PROC [publicWire: Core.Wire, thisCell: Core.CellType, thisFlatCell: CoreFlat.FlatCellTypeRec, thisInstance: CoreClasses.CellInstance] RETURNS [publicInfo: WireInfo, quit: BOOL _ FALSE] = { 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: BOOL _ FALSE] = { Check: PROC [cell: Core.CellType, flatCell: CoreFlat.FlatCellTypeRec _ CoreFlat.rootCellType, instance: CoreClasses.CellInstance _ NIL] RETURNS [quit: BOOL _ FALSE] = { 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]; }; 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. Κ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 New Practice Old Practice ΚŒ– "cedar" style˜codešœ™KšœB™BK™&K™.K™—KšΟk œR˜[K˜•StartOfExpansion[]šΟb œœ˜KšœC˜JKšœ˜Kšœœœ˜—K˜Kšœ œ ˜Kšœœ˜)Kšœ œ˜.K˜šΟn œœœœ˜JKšœ@˜@K˜ K˜K˜—š ŸœœHœœœ˜~Kšœœ@˜Jš œ œœœœ˜3Kšœ@˜@Kš˜—šœ˜Kšœœ(˜Cšœ œœ˜Kšœ œœ œ&˜Ošœ œœ˜Kšœ œ˜Kšœœ-œœ˜>K˜—K˜—Kšœ0œ˜6K˜—K˜K˜—Kšœ œœ ˜!šœ œœ˜Kšœœ˜Kšœœœ˜K˜—head™ šŸœœ˜/šœœœœ œœœ œ˜xKšœ:˜:Kšœ˜šœ˜Kšœ)˜)Kšœ/˜/Kšœœ˜—Kšœ˜K˜—K˜K˜—šŸœœœUœœœœ˜›šŸœ˜*šœ œ˜Kšœœ&˜CKšœ'œœ˜5Kšœœ,œœ˜=Kšœg˜gK˜—K˜—š Ÿœœxœœœœ˜¨š Ÿ œœ‚œœœ˜ΛKšœ œ,˜?šœ œœ˜Kšœ3˜3Kšœ œ,˜?Kšœ œœœ˜K˜—K˜—šœœ˜šœ+œ-œE˜‘šŸœœ˜,Kšœ&œ˜EK˜—Kšœ8˜8K˜—šœ+˜+šŸœœ˜.Kšœ&œ˜8K˜—šŸœ˜,šœ œ˜Kšœœ˜Kšœ'œœ˜5Kšœ&œœ˜4Kšœœ+œœ˜˜>K˜—šœ˜ šŸœ˜0Kšœ˜Kšœœœ˜!Kšœl˜lKšœ9˜9K˜—Kšœ/˜/Kšœœœ ˜