<> <> <> <> <<>> <> <<>> 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; <> <> <> <<>> NodenessItem: TYPE = RECORD[ decoration: Decoration, touch: TouchProc, nodeness: Wires ]; NodenessItems: TYPE = LIST OF NodenessItem; <> <> <> <<>> BagnessItem: TYPE = RECORD[ decoration: Decoration, touch: TouchProc, bagness: BagList ]; BagnessItems: TYPE = LIST OF BagnessItem; <> 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: ROPE _ NIL; name _ CoreOps.GetFullWireName[root: NARROW [cell.data, CoreClasses.RecordCellType].internal, wire: wire ! ANY => { IO.Put[out, IO.rope[""]]; 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] = { <> 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: ""]; 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 { <> <> <> <<};>> <> 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"]; <> } } }; <> RecordWireBagness: PROC [decoration: Decoration, touch: TouchProc, recordCell: CoreClasses.RecordCellType, wire: Wire] RETURNS [bagness: BagList] = { <> FuseTopLevelInstance: CoreGeometry.EachInstanceProc = { <> 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 = { <> 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]= { <> 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] = { <> 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 = { <> 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]] } }; <> InternalDisconnection: PUBLIC SIGNAL [decoration: Decoration, touch: TouchProc, cell: CellType, wire: Wire] = CODE; PutBagnessProp: PROC [public: Wire, decoration: Decoration, touch: TouchProc, bagness: BagList] = { <> 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] = { <> InsertPin: CoreGeometry.EachInstanceProc = { <> [] _ Bagness.InstTabInsert[instTab: pinTab, inst: instance] }; DeletePin: Bagness.InstKeepProc = { <> 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 = { <> RecordWireNodeness: PROC [wire: Wire] = { <> bagness: BagList _ RecordWireBagness[decoration: decoration, touch: touch, recordCell: recordCell, wire: wire]; bagCount: NAT _ Bagness.BagCount[bagList: bagness]; internallyDisconnected: BOOL _ FALSE; 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 = { <> RETURN [TrivialNodeness[decoration: decoration, touch: touch, cell: cell]] }; GetNodeness: PUBLIC NodenessProc = { <> 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] }; <> 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.