DIRECTORY CD, CDBasics, CDCells, CDSymbolicObjects, Core, CoreClasses, CoreDirectory, CoreFlat, CoreGeometry, CoreOps, CoreProperties, CoreRoute, DABasics, IO, PWCore, RefTab, Rope, Route, RouteUtil, RTBasic, RTCoreUtil, SC, SCInstUtil, SCNetUtil, SCPrivate, SCUtil, Sinix, TerminalIO; SCGetStructureImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDSymbolicObjects, CoreDirectory, CoreFlat, CoreGeometry, CoreOps, CoreProperties, CoreRoute, IO, PWCore, RefTab, Rope, RouteUtil, RTBasic, RTCoreUtil, SC, SCInstUtil, SCNetUtil, SCUtil, Sinix, TerminalIO EXPORTS SCPrivate SHARES SC = BEGIN debug: BOOLEAN _ FALSE; DefineRect: PROC [obRect: SC.Rect, min, max, depth: INT, side: CoreGeometry.Side] RETURNS [pinRect: SC.Rect] ~ { SELECT side FROM bottom => pinRect _ [min, obRect.y1, max, obRect.y1 + depth]; right => pinRect _ [obRect.x2 - depth, min, obRect.x2, max]; top => pinRect _ [min, obRect.y2 - depth, max, obRect.y2]; left => pinRect _ [obRect.x2, min, obRect.x2 + depth, max]; ENDCASE; }; CreateObject: PROC [handle: SC.Handle, class: SCPrivate.CompClass, ob: CD.Object, cellType: Core.CellType] RETURNS [object: SCPrivate.Object] ~ { PinEnum: CoreGeometry.EachWirePinProc = { IF (side=top OR side=bottom) AND layer=branchLayer THEN { rect: SC.Rect = DefineRect[obRect, min, max, branchWidth, side]; name: Rope.ROPE = CoreOps.GetShortWireName[wire]; IF side=none THEN ERROR; pinList _ CONS [NEW[SCPrivate.ObjectPinRec _ [name: name, pinPos: [side, 0, (max+min)/2], publicWire: wire, rect: rect, layer: layer, equivClass: name]], pinList]; numPins _ numPins + 1; }; }; branchLayer: CD.Layer = handle.rules.rowRules.branchLayer; -- shortcut branchWidth: INT = handle.rules.rowRules.branchWidth; -- shortcut name: Rope.ROPE = CoreOps.GetCellTypeName[cellType]; -- will be object name obRect: CD.Rect; pinList: LIST OF SCPrivate.ObjectPin _ NIL; -- used to build the object pins numPins: NAT _ 0; -- always the size of pinList pins: SCPrivate.ObjectPins; -- stored in the object decoration: CoreGeometry.Decoration = NARROW[handle.parms, SCPrivate.Parms].mode.decoration; IF ob=NIL THEN ERROR SC.Error[callingError, Rope.Cat["No CD object for CellType ", name]]; obRect _ CD.InterestRect[ob]; [] _ CoreGeometry.EnumerateNonOverlappingSides[decoration, cellType, PinEnum]; pins _ NEW[SCPrivate.ObjectPinsRec[numPins]]; -- just the right size FOR i: NAT IN [0..numPins) DO -- put the pins in the object structure pins[i] _ pinList.first; pinList _ pinList.rest; ENDLOOP; object _ NEW[SCPrivate.ObjectRec _ [name: name, size: RTBasic.XYToPQ[horizontal, CDBasics.SizeOfRect[obRect]], orgin: RTBasic.XYToPQ[horizontal, CDBasics.BaseOfRect[obRect]], numPins: numPins, pins: pins, typeClass: class, numTimesUsed: 0, cdOb: ob, cellType: cellType]]; }; DefineFtType: PROCEDURE [handle: SC.Handle, name: Rope.ROPE] RETURNS [object: SCPrivate.Object] = { parms: SCPrivate.Parms = NARROW[handle.parms]; cellType: Core.CellType = CoreDirectory.Fetch[parms.libName, name]; -- get from library IF cellType=NIL THEN ERROR SC.Error[callingError, Rope.Cat["FeedThru object not found in library: ", name]]; -- quite deadly... object _ CreateObject[handle, ft, PWCore.Layout[cellType], cellType]; }; DefinePowerType: PROCEDURE [handle: SC.Handle, name: Rope.ROPE] RETURNS [object: SCPrivate.Object] = { parms: SCPrivate.Parms = NARROW[handle.parms]; cellType: Core.CellType = CoreDirectory.Fetch[parms.libName, name]; -- get from library IF cellType=NIL THEN ERROR SC.Error[callingError, Rope.Cat["Power object not found in library: ", name]]; -- quite deadly... object _ CreateObject[handle, logic, PWCore.Layout[cellType], cellType]; -- make power connection cells logic cells }; DefineIOType: PROCEDURE [handle: SC.Handle] RETURNS [object: SCPrivate.Object] = { mode: Sinix.Mode = NARROW[handle.parms, SCPrivate.Parms].mode; ob: CD.Object _ BuildIOObject[handle]; cellType: Core.CellType = NARROW [Sinix.Extract[ob, mode, NIL, NIL].result]; [] _ CoreOps.SetCellTypeName[cellType, "--IO Object--"]; -- documentation only... object _ CreateObject[handle, io, ob, cellType]; }; BuildIOObject: PROCEDURE [handle: SC.Handle] RETURNS [object: CD.Object] = { minSize: SC.Number = handle.rules.rowRules.branchWidth; symInst: CD.Instance; object _ CDCells.CreateEmptyCell[]; symInst _ RouteUtil.Include[object, CDSymbolicObjects.CreateSegment[length: minSize], [minSize, 0], CDSymbolicObjects.OrientFromDirection[south]]; CDSymbolicObjects.SetLayer[symInst, handle.rules.rowRules.branchLayer]; CDSymbolicObjects.SetName[symInst, "io"]; CDCells.SetInterestRect[design: NIL, cell: object, r: [0, 0, minSize, minSize]]; -- set interestRect of cell RTBasic.RepositionCell[object]; }; GetStructure: PUBLIC PROCEDURE [handle: SC.Handle, flattenCellType: RTCoreUtil.FlattenCellTypeProc] RETURNS [done: BOOL _ TRUE] ~ { InternalWireProc: RTCoreUtil.FlatWireProc ~ { [] _ SCNetUtil.DefineNet[handle, NEW [CoreFlat.FlatWireRec _ flatWire]]; }; ExternalWireProc: RTCoreUtil.FlatWireProc ~ { pathName: Rope.ROPE = CoreRoute.LabelFlatWire[root, flatWire]; -- for port instance names instance: SCPrivate.Instance _ SCUtil.FindInstance[handle, pathName]; net: SCPrivate.Net = SCNetUtil.FindPublicNet[handle, flatWire.wire]; IF instance # NIL THEN { -- this is an error, signal and return, net already tested SC.Signal[callingError, Rope.Cat["Duplicate port name: ", CoreRoute.LabelFlatWire[root, flatWire], ", object: ", parms.portObject.name]]; RETURN; }; net.externNet _ TRUE; net.publicWire _ flatWire.wire; IF SCUtil.IsPowerName[handle, CoreOps.GetShortWireName[flatWire.wire]] THEN RETURN; -- nothing more to do FOR side: DABasics.Side IN [bottom .. right] DO IF NOT WireOnSide[side, flatWire.wire] THEN LOOP; -- not interesting instance _ SCInstUtil.DefineInstance[handle, pathName, parms.portObject, pathName]; SCNetUtil.AddConnection[handle, net, instance, parms.portObject.pins.p[0], 0, externalPin]; instance.fnlSide _ side; instance.fnlPos _ GetIOPosition[side, flatWire.wire.properties, usePositions]; ENDLOOP; IF instance = NIL THEN { -- no side restriction, leave the pin free to move instance _ SCInstUtil.DefineInstance[handle, pathName, parms.portObject, pathName]; SCNetUtil.AddConnection[handle, net, instance, parms.portObject.pins.p[0], 0, externalPin]; }; }; InstanceProc: RTCoreUtil.FlatInstanceProc ~ { EachPublic: PROC [publicWire: Core.Wire] = { pinName: Rope.ROPE = CoreOps.GetShortWireName[publicWire]; flatWire: CoreFlat.FlatWire; net: SCPrivate.Net; thisPin: SCPrivate.ObjectPin; IF SCUtil.IsPowerName[handle, pinName] THEN RETURN; -- nothing to do flatWire _ NARROW [RefTab.Fetch[bindings, publicWire].val]; net _ SCNetUtil.FindNet[handle, flatWire]; -- get the net thisPin _ SCUtil.FindPin[object, pinName]; -- get the pin IF thisPin=NIL THEN { -- Error case: signal & return, net already handled SC.Signal[callingError, Rope.Cat["Pin not found: ", pinName, Rope.Cat[" on component: ", instance.name, ", type: ", object.name]]]; RETURN; }; IF Rope.Equal["Vdd", net.name] THEN hasVddConnection _ TRUE; IF Rope.Equal["Gnd", net.name] THEN hasGndConnection _ TRUE; FOR pinIndex: NAT IN [0 .. object.numPins) DO -- add all pins for wire to net objPin: SCPrivate.ObjectPin = object.pins.p[pinIndex]; IF objPin#NIL AND objPin.publicWire=thisPin.publicWire THEN SCNetUtil.AddConnection[handle, net, instance, objPin, pinIndex, compPin]; ENDLOOP; }; instance: SCPrivate.Instance; pathName: Rope.ROPE _ CoreFlat.InstancePathRope[root, flatCellType.path]; object: SCPrivate.Object _ NARROW [RefTab.Fetch[objectTable, cell].val]; IF object = NIL THEN { -- create the new object object _ CreateObject[handle, logic, PWCore.Layout[cell], cell]; [] _ RefTab.Insert[objectTable, cell, object]; }; instance _ SCInstUtil.DefineInstance[handle, pathName, object, NIL]; SCInstUtil.DefineSourceInstance[handle, NEW [CoreFlat.FlatCellTypeRec _ flatCellType], instance]; CoreOps.VisitRootAtomics[cell.public, EachPublic]; GetLogicProperties[instance, properties]; }; root: Core.CellType = handle.coreCellType; hasVddConnection, hasGndConnection: BOOLEAN _ FALSE; usePositions: BOOL _ RTCoreUtil.GetCoreBoolProp[root, SC.usePublicPositionsProp, FALSE]; objectTable: RefTab.Ref _ RefTab.Create[]; -- temporary table cell -> Object parms: SCPrivate.Parms _ NARROW[handle.parms]; structureData: SCPrivate.StructureData _ NEW [SCPrivate.StructureDataRec _ [ instances: NEW [SCPrivate.InstancesRec _ [inst: NEW [SCPrivate.InstsOb]]], nets: RefTab.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash], sourceInstances: RefTab.Create[equal: CoreFlat.FlatCellTypeEqual, hash: CoreFlat.FlatCellTypeHash] ]]; handle.structureData _ structureData; parms.portObject _ DefineIOType[handle]; parms.ftObject _ DefineFtType[handle, "feedthru"]; parms.vddObject _ DefinePowerType[handle, "vdd"]; parms.gndObject _ DefinePowerType[handle, "gnd"]; TerminalIO.PutRope["Getting structure description . . .\n"]; RTCoreUtil.Flatten[root, flattenCellType, ExternalWireProc, InternalWireProc, InstanceProc, SC.interestingProperties]; IF hasVddConnection THEN DoPower[handle, "Vdd", parms.vddObject, "Vdd"]; IF hasGndConnection THEN DoPower[handle, "Gnd", parms.gndObject, "Gnd"]; DoBuses[handle, left]; DoBuses[handle, right]; TerminalIO.PutF["Statistics: \n instances: %g, wires: %g, public wires: %g cells: %g\n", IO.int[structureData.instances.numLogics], IO.int[RefTab.GetSize[structureData.nets]], IO.int[structureData.instances.numIOs], IO.int[RefTab.GetSize[objectTable]]]; IF debug THEN SCUtil.WriteStructure[handle]; }; DoPower: PROC [handle: SC.Handle, instanceName: Rope.ROPE, object: SCPrivate.Object, wireName: Rope.ROPE] ~ { instance: SCPrivate.Instance _ SCInstUtil.DefineInstance[handle, instanceName, object, NIL]; net: SCPrivate.Net _ SCNetUtil.FindPublicNet[handle, CoreOps.FindWire[handle.coreCellType.public, wireName]]; SCNetUtil.AddConnection[handle, net, instance, object.pins.p[0], 0, compPin]; SCNetUtil.AddConnection[handle, net, instance, object.pins.p[1], 1, compPin]; }; DoBuses: PROCEDURE [handle: SC.Handle, lRSide: RTBasic.LRSide] = { layoutData: SCPrivate.LayoutData = NARROW[handle.layoutData]; wireName: Rope.ROPE = layoutData.powerBuses[lRSide].name; net: SCPrivate.Net _ SCNetUtil.FindPublicNet[handle, CoreOps.FindWire[handle.coreCellType.public, wireName]]; layoutData.powerBuses[lRSide].net _ net; }; GetLogicProperties: PROCEDURE [instance: SCPrivate.Instance, properties: Core.Properties] = { EachProperty: PROC [prop: ATOM, val: REF ANY] ~ { SELECT prop FROM SC.rowProp => instance.fnlRow _ NARROW[val, REF INT]^; SC.positionProp => instance.fnlPos _ NARROW[val, REF INT]^; ENDCASE; }; CoreProperties.Enumerate[properties, EachProperty]; }; WireOnSide: PROC [side: DABasics.Side, wire: Core.Wire] RETURNS [onSide: BOOL _ FALSE] ~ { ProcProps: PROC [prop: ATOM, val: REF ANY] ~ { SELECT prop FROM SC.bottomSideProp => IF side = bottom THEN onSide _ TRUE; SC.rightSideProp => IF side = right THEN onSide _ TRUE; SC.topSideProp => IF side = top THEN onSide _ TRUE; SC.leftSideProp => IF side = left THEN onSide _ TRUE; ENDCASE; }; CoreProperties.Enumerate[wire.properties, ProcProps]; }; GetIOPosition: PROC [side: DABasics.Side, properties: Core.Properties, usePositions: BOOL] RETURNS [position: INT _ 0] ~ { ProcProps: PROC [prop: ATOM, val: REF ANY] ~ { SELECT prop FROM SC.bottomPositionProp => IF side = bottom THEN position _ NARROW[val, REF INT]^; SC.rightPositionProp => IF side = right THEN position _ NARROW[val, REF INT]^; SC.topPositionProp => IF side = top THEN position _ NARROW[val, REF INT]^; SC.leftPositionProp => IF side = left THEN position _ NARROW[val, REF INT]^; ENDCASE; }; IF usePositions THEN CoreProperties.Enumerate[properties, ProcProps]; }; DestroyStructure: PUBLIC PROC [handle: SC.Handle] ~ { EachInst: SCInstUtil.EachInstanceProc ~ { IF instance.pinNets#NIL THEN FOR i: NAT IN [0..instance.pinNets.size) DO -- destroy pinNets instance.pinNets[i]^ _ []; instance.pinNets[i] _ NIL; ENDLOOP; instance.pinNets _ NIL; instance.ftNet _ NIL; instances.inst[instance.num] _ NIL; instance.object.pins _ NIL; instance.object.cdOb _ NIL; instance.object.cellType _ NIL; }; EachNet: RefTab.EachPairAction ~ { -- destroy the net thoroughly net: SCPrivate.Net _ NARROW [val]; netPin: SCPrivate.NetPin _ net.pins; WHILE netPin#NIL DO -- destroy the list of pins thoroughly next: SCPrivate.NetPin = netPin.link; netPin^ _ []; netPin _ next; ENDLOOP; net^ _ []; }; structureData: SCPrivate.StructureData = NARROW[handle.structureData]; instances: SCPrivate.Instances = structureData.instances; [] _ SCInstUtil.EnumerateAllInstances[handle, EachInst]; RefTab.Erase[structureData.sourceInstances]; [] _ RefTab.Pairs[structureData.nets, EachNet]; RefTab.Erase[structureData.nets]; structureData^ _ []; handle.structureData _ NIL; }; END. SCGetStructureImpl.mesa Copyright Σ 1986, 1987 by Xerox Corporation. All rights reserved. Last Edited by: Preas, September 9, 1985 10:06:38 am PDT Jean-Marc Frailong October 14, 1987 5:58:31 pm PDT Frank Bowers February 3, 1986 5:41:01 pm PST Preas, July 21, 1987 5:19:57 pm PDT get design data by reading Core connectivity and ChipnDale cells Object creation Build an SCPrivate object from the components. Either ob=PWCore.Layout[cellType], or cellType=Sinix.Extract[ob, handle.parms.mode] The handle is used to compute the pins. Only pins along top and bottom that are in the branchLayer are saved: they are the ones to which nets connect... This pin fits the requirements Define a feedthrough-type object Define an object used to connect nets to power supplies Define an IO-type object. This is the only case where the CD object is not derived as the layout for the CellType. The CD object is built explicitly, and the cellType is obtained by explicit extraction (sigh...) Build the special CD IO object (real messy...) Structure management PROC [flatWire: CoreFlat.FlatWireRec] RETURNS [quit: BOOL _ FALSE]; PROC [flatWire: CoreFlat.FlatWireRec] RETURNS [quit: BOOL _ FALSE]; Make a pin for each side the pin is restricted to PROC [flatCellType: CoreFlat.FlatCellTypeRec, cell: Core.CellType, bindings: CoreFlat.Bindings, properties: Core.Properties] RETURNS [quit: BOOL _ FALSE]; do binding of public to actual; this is clumsy because of change to Core Geometry Set up the private data Get auxilliary components Do the real work Connect to power cells Fix up the bus widths based on connectivity We are now finished... Make a new power connection Define a power bus in the handle layoutData Propagate row & position requirement from source Core properties to the Instance RETURNS TRUE if wire is restricted to side Find position for wire on side Destroy the SC structureData field in order to remove all circularities for GC The following fields are assumed to be destroyed before: netDat, pinsOnChan, segsInChan, pinList, edgeList. Check that it is so... Κ m˜codešœ™KšœB™B—šœ5Οk™8K™2Kšœ)™,Kšœ ™#—K˜K™@K˜š ˜ Kšœœ?œ?˜”—K˜šΟnœœ˜!Kšœœsœ8œ3˜μKšœ ˜Kšœœ˜K˜Kšœœœ˜—head™š ž œœ œœœ œ ˜pšœ˜Kšœ=˜=Kšœ<˜˜>Kšœ?˜?Kšœ@˜@Kšœ˜—K˜K˜—š ž œ œ œœœ˜cK™ Kšœœ˜.KšœD ˜WKš œ œœœœP ˜KšœE˜EK˜K˜—š žœ œ œœœ˜fK™7Kšœœ˜.KšœD ˜WKš œ œœœœM ˜|KšœI *˜sK˜K˜—šž œ œ œ œ˜RKš œ œΟbœœ;œZ™ΣKšœœ%˜>Kšœœ ˜&Kšœœœœ ˜LKšœ9 ˜QKšœ0˜0J˜J˜—š ž œ œ œ œ œ ˜LKšœœœ™.Kšœ œ,˜7Kšœ œ ˜Kšœ#˜#Kšœ’˜’KšœG˜GKšœ)˜)Kšœ œ. ˜lKšœ˜Kšœ˜——™šž œœ œ œ:œœœ˜ƒšžœ˜-Kšœ"œœœ™CKšœ!œ$˜HKšœ˜—šžœ˜-Kšœ"œœœ™CKšœœ, ˜YKšœE˜EKšœD˜Dšœ œœ :˜SKšœ‡˜‰Kšœ˜Kšœ˜—Kšœœ˜Kšœ˜KšœEœœ ˜išœœ˜/Kšœ1™1Kš œœ!œœ ˜DKšœS˜SKšœ[˜[Kšœ˜KšœN˜NKšœ˜—šœ œœ 2˜KKšœS˜SKšœ[˜[K˜—K˜—šž œ!˜-Kšœyœœœ™ššž œœ˜,Kšœœ(˜:Kšœ˜Kšœ˜Kšœ˜Kšœ%œœ ˜DKšœR™RKšœ œ*˜;Kšœ+ ˜9Kšœ+ ˜9šœ œœ 3˜IKšœ‚˜„Kšœ˜Kšœ˜—Kšœœœ˜™Nšžœ!˜)šœœœœœœœ ˜[Kšœ1œ˜5Kšœ˜—Kšœœœ"œ˜SKšœœœœ˜WKšœ˜—šžœ ˜@Kšœœ˜"Kšœ$˜$šœœœ &˜:Kšœ%˜%Kšœ ˜ Kšœ˜Kšœ˜—Kšœ‚™‚Kšœ ˜ Kšœ˜—Kšœ)œ˜FKšœ9˜9Kšœ9˜9Kšœ,˜,Kšœ/˜/Kšœ!˜!Kšœ˜Kšœœ˜Kšœ˜K˜—Kšœ˜—…—1ςFu