NodenessImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Bruce Wagar August 17, 1987 3:21:01 pm PDT
Bertrand Serlet September 14, 1987 0:11:34 am PDT
Implementation of the wire connectivity programs.
DIRECTORY
Bagness, BasicTime, CD, CDCommandOps, CDEnvironment, CDOps, CDSequencer, Commander, CommandTool, Core, CoreClasses, CoreGeometry, CoreOps, CoreProperties, FileNames, IO, Nodeness, PW, RefTab, Rope, RoutingCheck, Sinix, SinixOps, TerminalIO, ViewerIO;
NodenessImpl: CEDAR PROGRAM
IMPORTS
Bagness, BasicTime, CDCommandOps, CDEnvironment, CDOps, Commander, CommandTool, CoreClasses, CoreGeometry, CoreOps, CoreProperties, FileNames, IO, PW, RefTab, Rope, RoutingCheck, Sinix, SinixOps, TerminalIO, ViewerIO
EXPORTS
Nodeness
= BEGIN OPEN Nodeness;
Nodeness Property
The nodeness property is stored on a CellType under the key $Nodeness.
Its value is a list of NodenessItems, one for each (Decoration, TouchProc) pair.
NodenessItem: TYPE = RECORD[
decoration: Decoration,
touch: TouchProc,
nodeness: Wires
];
NodenessItems: TYPE = LIST OF NodenessItem;
Bagness Property
The bagness property is stored on a public wire of a CellType under the key $Bagness.
Its value is a list of BagnessItems, one for each (Decoration, TouchProc) pair for which the wire is disconnected.
BagnessItem: TYPE = RECORD[
decoration: Decoration,
touch: TouchProc,
bagness: BagList
];
BagnessItems: TYPE = LIST OF BagnessItem;
Command Procs
CheckConnectivityCommand: Commander.CommandProc = {
argv: CommandTool.ArgumentVector ← CommandTool.Parse[cmd: cmd, starExpand: FALSE
! CommandTool.Failed => {msg ← errorMsg; GO TO failed}];
instances: CD.InstanceList;
design: CD.Design;
file, shortName: ROPE;
out: IO.STREAM;
mode: Sinix.Mode;
cell: CellType;
nodeness: Wires;
IF argv.argc#2 THEN {msg ← Rope.Cat["Incorrect syntax.\n", commandProcDoc]; GO TO failed};
file ← CDEnvironment.FindFile[argv[1], ".dale"];
shortName ← FileNames.GetShortName[file];
design ← PW.OpenDesign[file];
RoutingCheck.Check[design]; -- check all routing cells
out ← ViewerIO.CreateViewerStreams[
name: IO.PutFR["Connectivity check of %g.", IO.rope[shortName]],
backingFile: Rope.Cat[Rope.Substr[shortName, 0, Rope.Length[shortName]-5], ".cclog"]
].out;
instances ← CDOps.InstList[design];
IF instances=NIL OR instances.rest#NIL THEN ERROR;
mode ← SinixOps.GetExtractMode[tech: design.technology];
cell ← NARROW [Sinix.Extract[instances.first.ob, mode].result];
IO.PutF[out, "Checking connectivity of %g.\n", IO.rope[CoreOps.GetCellTypeName[cellType: cell]]];
nodeness ← GetNodeness[decoration: mode.decoration, touch: mode.touchProc, cell: cell !
InternalDisconnection => {
name: ROPENIL;
name ← CoreOps.GetFullWireName[root: NARROW [cell.data, CoreClasses.RecordCellType].internal, wire: wire !
ANY => {
IO.Put[out, IO.rope["<ERROR in CoreOps.GetFullWireName>"]]; CONTINUE
}
];
IO.PutF[out, "SIGNAL: Wire %g in cell %g is disconnected internally.\n", IO.rope[name], IO.rope[CoreOps.GetCellTypeName[cellType: cell]]];
RESUME
}
];
IF nodeness = NIL
THEN
IO.PutF[out, "Cell %g contains no disconnected public wires.\n", IO.rope[CoreOps.GetCellTypeName[cellType: cell]]]
ELSE {
IO.PutF[out, "Cell %g contains the following disconnected public wires:\n", IO.rope[CoreOps.GetCellTypeName[cellType: cell]]];
FOR wires: Wires ← nodeness, wires.rest UNTIL wires = NIL DO
IO.PutF[out, " %g's pins are in %g bags.\n", IO.rope[CoreOps.GetFullWireName[root: cell.public, wire: wires.first]], IO.int[Bagness.BagCount[bagList: GetBagnessProp[decoration: mode.decoration, touch: mode.touchProc, wire: wires.first]]]];
ENDLOOP;
};
IO.Close[out];
EXITS
failed => {result ← $Failure};
};
CheckConnectivity: PROC [command: CDSequencer.Command] = {
Extracts selected layout, checks connectivity of public wires, and highlights any disconnected ones.
design: CD.Design = command.design;
mode: Sinix.Mode = SinixOps.GetExtractMode[tech: design.technology];
decoration: Decoration = mode.decoration;
touch: TouchProc = mode.touchProc;
disconnectedInternals: LIST OF RECORD[cell: CellType, wire: Wire] ← NIL;
root, cell: CellType;
trans: Transformation;
[root: root, cell: cell, trans: trans] ← SinixOps.SelectedCellType[design: design, mode: mode];
IF root # NIL THEN {
nodeness: Wires ← GetNodeness[decoration: decoration, touch: touch, cell: cell !
InternalDisconnection => {
TerminalIO.PutRopes[t1: "SIGNAL: Wire ", t2: CoreOps.GetFullWireName[root: NARROW[cell.data, CoreClasses.RecordCellType].internal, wire: wire !
ANY => {
TerminalIO.PutRope[text: "<ERROR in CoreOps.GetFullWireName>"];
CONTINUE
}
]];
TerminalIO.PutRopes[t1: " in cell ", t2: CoreOps.GetCellTypeName[cellType: cell], t3: " is disconnected internally.\n"];
disconnectedInternals ← CONS[[cell: cell, wire: wire], disconnectedInternals];
RESUME
}
];
TerminalIO.PutRope[text: CoreOps.GetCellTypeName[cellType: cell]];
IF nodeness = NIL
THEN
TerminalIO.PutRope[text: " contains no disconnected public wires.\n"]
ELSE {
AddInstance: CoreGeometry.EachInstanceProc = {
Transforms instance and tacks it onto instances.
instances ← CONS[CoreGeometry.Transform[trans: trans, instance: instance], instances]
};
instances: CoreGeometry.Instances ← NIL;
TerminalIO.PutRope[text: " contains the following disconnected public wires:\n"];
FOR wires: Wires ← nodeness, wires.rest UNTIL wires = NIL DO
TerminalIO.PutRopes[t1: " ", t2: CoreOps.GetFullWireName[root: cell.public, wire: wires.first]];
TerminalIO.PutF1[format: "'s pins are in %g bags.\n", value: IO.int[Bagness.BagCount[bagList: GetBagnessProp[decoration: decoration, touch: touch, wire: wires.first]]]];
[] ← CoreGeometry.EnumerateAllGeometry[decoration: decoration, cell: cell, wire: wires.first, eachInstance: AddInstance]
ENDLOOP;
TerminalIO.PutRope[text: " ** End List **\n"];
SinixOps.HighlightDesign[design: design, highlight: SinixOps.HighLightListInst[instances: instances]]
}
}
};
Bagness Procs
RecordWireBagness: PROC [decoration: Decoration, touch: TouchProc, recordCell: CoreClasses.RecordCellType, wire: Wire] RETURNS [bagness: BagList] = {
Returns the top-level plus subpin bagness of a record cell wire.
FuseTopLevelInstance: CoreGeometry.EachInstanceProc = {
Fuses top-level geometry onto topLevelBagness.
topLevelBagness ← Bagness.FuseInstance[bagList: topLevelBagness, instance: instance, touch: touch]
};
topLevelBagness: BagList ← Bagness.CreateBagList[];
[] ← CoreGeometry.EnumerateGeometry[decoration: decoration, wire: wire, eachInstance: FuseTopLevelInstance];
bagness ← Bagness.CreateBagList[];
FOR i: NAT IN [0..recordCell.size) DO -- determine bagness of subpins
AddSubPins: CoreOps.EachWirePairProc = {
Adds subpins' bagness of transformed publicWire to bagness.
IF actualWire = wire THEN
bagness ← Bagness.FuseBagList[bagList1: GetTransformedBagness[decoration: decoration, touch: touch, cell: instanceCell, wire: publicWire, trans: trans], bagList2: bagness, touch: touch]
};
cellInstance: CoreClasses.CellInstance = recordCell[i];
trans: Transformation = CoreGeometry.GetTrans[decoration: decoration, cellInstance: cellInstance];
instanceCell: CellType = cellInstance.type;
[] ← CoreOps.VisitBinding[actual: cellInstance.actual, public: instanceCell.public, eachWirePair: AddSubPins]
ENDLOOP;
bagness ← Bagness.FuseBagList[bagList1: topLevelBagness, bagList2: bagness, touch: touch]
};
GetBagnessProp: PROC [decoration: Decoration, touch: TouchProc, wire: Wire] RETURNS [BagList]= {
Fetches the appropriate bagness information of wire, if cached. Otherwise, returns empty bagList.
FOR items: BagnessItems ← NARROW[CoreProperties.GetWireProp[from: wire, prop: $Bagness]], items.rest UNTIL items = NIL DO
IF items.first.decoration = decoration AND items.first.touch = touch THEN -- found
RETURN [items.first.bagness]
ENDLOOP;
RETURN [Bagness.CreateBagList[]]
};
GetTransformedBagness: PROC [decoration: Decoration, touch: TouchProc, cell: CellType, wire: Wire, trans: Transformation] RETURNS [BagList] = {
Returns a copy of the bagness of wire's pins with the specified transformation applied to each pin.
IF CoreOps.Member[wires: GetNodeness[decoration: decoration, touch: touch, cell: cell], wire: wire]
THEN -- fetch from public's properties
RETURN [Bagness.TransformBagList[bagList: GetBagnessProp[decoration: decoration, touch: touch, wire: wire], trans: trans]]
ELSE { -- enumerate a trivial one
AddPin: CoreGeometry.EachInstanceProc = {
Adds bin to bag.
bag ← Bagness.InsertInstance[bag: bag, instance: CoreGeometry.Transform[trans: trans, instance: instance]]
};
bag: Bag ← Bagness.CreateBag[];
[] ← CoreGeometry.EnumeratePins[decoration: decoration, public: wire, eachInstance: AddPin];
RETURN [Bagness.InsertBag[bagList: Bagness.CreateBagList[], bag: bag]]
}
};
Nodeness Procs
InternalDisconnection: PUBLIC SIGNAL [decoration: Decoration, touch: TouchProc, cell: CellType, wire: Wire] = CODE;
PutBagnessProp: PROC [public: Wire, decoration: Decoration, touch: TouchProc, bagness: BagList] = {
Tacks the specified bagness information onto public's existing bagness information.
bagnessItem: BagnessItem ← [decoration: decoration, touch: touch, bagness: bagness];
bagnessItems: BagnessItems ← NARROW[CoreProperties.GetWireProp[from: public, prop: $Bagness]];
bagnessItems ← CONS[bagnessItem, bagnessItems];
CoreProperties.PutWireProp[on: public, value: bagnessItems, prop: $Bagness]
};
PruneNonPins: PROC [decoration: Decoration, public: Wire, bagness: BagList] RETURNS [BagList] = {
Takes the top-level bagness of a disconnected public wire and prunes away all but the pins.
InsertPin: CoreGeometry.EachInstanceProc = {
Inserts instance into pinTab.
[] ← Bagness.InstTabInsert[instTab: pinTab, inst: instance]
};
DeletePin: Bagness.InstKeepProc = {
Deletes instance from pinTab and returns TRUE iff instance was present.
RETURN [Bagness.InstTabDelete[instTab: pinTab, inst: instance]]
};
pinTab: Bagness.InstTab ← Bagness.InstTabCreate[];
[] ← CoreGeometry.EnumeratePins[decoration: decoration, public: public, eachInstance: InsertPin];
RETURN [Bagness.PruneInstances[bagList: bagness, keep: DeletePin]]
};
RecordNodeness: NodenessProc = {
Determines nodeness of a recordCellType cell. Internal disconnectivity raises the SIGNAL InternalDisconnection.
RecordWireNodeness: PROC [wire: Wire] = {
Checks connectivity of wire.
bagness: BagList ← RecordWireBagness[decoration: decoration, touch: touch, recordCell: recordCell, wire: wire];
bagCount: NAT ← Bagness.BagCount[bagList: bagness];
internallyDisconnected: BOOLFALSE;
IF bagCount > 1 THEN -- wire is disconnected
IF CoreOps.RecursiveMember[wire: cell.public, candidate: wire]
THEN { -- disconnected wire is public
newBagCount: NAT;
bagness ← PruneNonPins[decoration: decoration, public: wire, bagness: bagness];
internallyDisconnected ← (newBagCount ← Bagness.BagCount[bagList: bagness]) # bagCount;
IF newBagCount > 1 THEN { -- pins are disconnected
nodeness ← CONS[wire, nodeness];
PutBagnessProp[public: wire, decoration: decoration, touch: touch, bagness: bagness]
}
}
ELSE -- disconnected wire is internal
internallyDisconnected ← TRUE;
IF internallyDisconnected THEN
SIGNAL InternalDisconnection[decoration: decoration, touch: touch, cell: cell, wire: wire]
};
recordCell: CoreClasses.RecordCellType = NARROW[cell.data];
CoreOps.VisitRootAtomics[root: recordCell.internal, eachWire: RecordWireNodeness]
};
TrivialNodeness: NodenessProc = {};
TransistorNodeness: NodenessProc = {
Determines nodeness of transistorCellType cell. Assumes that a transistor contains no disconnected wires.
RETURN [TrivialNodeness[decoration: decoration, touch: touch, cell: cell]]
};
GetNodeness: PUBLIC NodenessProc = {
Returns the nodeness of cell, caching the information if necessary.
nodenessItems: NodenessItems ← NARROW[
CoreProperties.GetCellTypeProp[from: cell, prop: $Nodeness]];
FOR items: NodenessItems ← nodenessItems, items.rest UNTIL items = NIL DO
IF items.first.decoration = decoration AND items.first.touch = touch THEN -- cached
RETURN [items.first.nodeness]
ENDLOOP;
SELECT cell.class FROM
CoreClasses.transistorCellClass =>
nodeness ← TransistorNodeness[decoration: decoration, touch: touch, cell: cell];
CoreClasses.recordCellClass => {
name: ROPE = CoreOps.GetCellTypeName[cellType: cell];
time: BasicTime.GMT = BasicTime.Now[];
TerminalIO.PutF1[format: "Checking connectivity of %g\n", value: IO.rope[name]];
nodeness ← RecordNodeness[decoration: decoration, touch: touch, cell: cell];
TerminalIO.PutF[format: "Connectivity checked of %g (%g sec.)\n", v1: IO.rope[name], v2: IO.int[BasicTime.Period[time, BasicTime.Now[]]]]
};
ENDCASE => { -- recast and recurse
name: ROPE = cell.class.name;
recastCell: CellType;
recastNodeness: Wires;
time: BasicTime.GMT = BasicTime.Now[];
TerminalIO.PutF1[format: "Recasting %g\n", value: IO.rope[name]];
recastCell ← CoreOps.Recast[me: cell];
TerminalIO.PutF[format: "%g recasted (%g sec.)\n", v1: IO.rope[name], v2: IO.int[BasicTime.Period[time, BasicTime.Now[]]]];
recastNodeness ← GetNodeness[decoration: decoration, touch: touch, cell: recastCell];
IF recastNodeness # NIL THEN {
table: RefTab.Ref ← CoreOps.CreateBindingTable[wire1: recastCell.public, wire2: cell.public];
FOR recastWires: Wires ← recastNodeness, recastWires.rest UNTIL recastWires = NIL DO
wire: Wire ← NARROW[RefTab.Fetch[x: table, key: recastWires.first].val];
nodeness ← CONS[wire, nodeness];
PutBagnessProp[public: wire, decoration: decoration, touch: touch, bagness: GetBagnessProp[decoration: decoration, touch: touch, wire: recastWires.first]]
ENDLOOP
}
};
nodenessItems ← CONS[[decoration: decoration, touch: touch, nodeness: nodeness], nodenessItems];
CoreProperties.PutCellTypeProp[on: cell, prop: $Nodeness, value: nodenessItems]
};
Initialization
commandProcDoc: ROPE ← "Checks connectivity of a .dale file";
CDCommandOps.RegisterWithMenu[
menu: $OtherProgramMenu,
entry: "Extract and Check Connectivity",
doc: "checks connectivity of selected object",
proc: CheckConnectivity,
key: $CheckConnectivity];
Commander.Register[
key: "CheckConnectivity", proc: CheckConnectivityCommand, doc: commandProcDoc];
END.