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]]]]; 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. €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. 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. 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. Command Procs Extracts selected layout, checks connectivity of public wires, and highlights any disconnected ones. AddInstance: CoreGeometry.EachInstanceProc = { Transforms instance and tacks it onto instances. instances _ CONS[CoreGeometry.Transform[trans: trans, instance: instance], instances] }; instances: CoreGeometry.Instances _ NIL; [] _ CoreGeometry.EnumerateAllGeometry[decoration: decoration, cell: cell, wire: wires.first, eachInstance: AddInstance] SinixOps.HighlightDesign[design: design, highlight: SinixOps.HighLightListInst[instances: instances]] Bagness Procs Returns the top-level plus subpin bagness of a record cell wire. Fuses top-level geometry onto topLevelBagness. Adds subpins' bagness of transformed publicWire to bagness. Fetches the appropriate bagness information of wire, if cached. Otherwise, returns empty bagList. Returns a copy of the bagness of wire's pins with the specified transformation applied to each pin. Adds bin to bag. Nodeness Procs Tacks the specified bagness information onto public's existing bagness information. Takes the top-level bagness of a disconnected public wire and prunes away all but the pins. Inserts instance into pinTab. Deletes instance from pinTab and returns TRUE iff instance was present. Determines nodeness of a recordCellType cell. Internal disconnectivity raises the SIGNAL InternalDisconnection. Checks connectivity of wire. Determines nodeness of transistorCellType cell. Assumes that a transistor contains no disconnected wires. Returns the nodeness of cell, caching the information if necessary. Initialization Κ Χ˜codešœ™Kšœ<™˜šœ˜K–[text: ROPE]šœ?˜?Kš˜Kšœ˜—Kšœ˜—K–6[t1: ROPE _ NIL, t2: ROPE _ NIL, t3: ROPE _ NIL]šœx˜xKšœœ2˜NKš˜K˜—Kšœ˜—K–[text: ROPE]šœB˜Bšœ ˜šœ˜KšœE˜E—šœ˜šŸ œ#™.™0K–E[trans: D2Orient.Transformation, instance: CoreGeometry.Instance]šœ œE™UK™——Kšœ$œ™(KšœQ˜Qšœ%œ œ˜šœ ˜'Kšœ œ˜KšœO˜OKšœW˜Wšœœ ˜4Kšœ œ˜ KšœT˜TK˜—K˜—šœ !˜'Kšœœ˜———šœœ˜KšœT˜Z—K˜——Kšœ)œ ˜;KšœQ˜QK˜—K˜—šŸœ˜#K˜—šŸœ˜$šœj™jKšœD˜JK˜—K˜—šŸ œœ˜$™Cšœœ˜&Kšœ=˜=—šœ2œ œ˜Išœ%œœ  ˜UKšœ˜—Kšœ˜—šœ ˜šœ#˜#KšœP˜P—šœ ˜ Kšœœ+˜5Kšœœ˜&Kšœ@œ ˜PKšœL˜LKšœDœœ.˜‰K˜—šœ ˜$Kšœœ˜Kšœ˜Kšœ˜Kšœœ˜&Kšœ2œ ˜AKšœ&˜&Kšœ5œœ/˜{KšœU˜Ušœœœ˜Kšœ]˜]šœ7œ˜TK–$[x: RefTab.Ref, key: RefTab.Key]šœ œ5˜HKšœ œ˜ Kšœš˜šKš˜—K˜—Kšœ˜——KšœœL˜`KšœO˜OK˜———™Kšœœ)˜=šœ˜Kšœ˜Kšœ(˜(Kšœ/˜/Kšœ˜Kšœ˜K˜—–x[key: ROPE, proc: Commander.CommandProc, doc: ROPE _ NIL, clientData: REF ANY _ NIL, interpreted: BOOL _ TRUE]šœ˜KšœO˜O—K˜—Kšœ˜—…—.^CΩ