<> <> <> <> DIRECTORY Atom, CD, CDBasics, Core, CoreClasses, CoreFlat, CoreGeometry, CoreOps, CoreProperties, CoreRoute, CoreRouteFlat, DABasics, IO, PWCore, RefTab, Rope, Route, Sisyph, SymTab, TerminalIO; CoreRouteFlatImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CoreFlat, CoreGeometry, CoreOps, CoreProperties, CoreRoute, IO, PWCore, RefTab, Sisyph, SymTab, TerminalIO EXPORTS CoreRouteFlat = BEGIN <> Structure: TYPE = CoreRouteFlat.Structure; Instance: TYPE = CoreRouteFlat.Instance; TwoInstances: TYPE = RECORD[i0,i1: Instance]; CellType: TYPE = Core.CellType; Atoms: TYPE = LIST OF ATOM; LeafProc: TYPE = PROC[ flatCell: CoreFlat.FlatCellTypeRec, instance: CoreClasses.CellInstance, bindings: CoreFlat.Bindings, -- cell.public to flatWires wrt root position: CD.Position]; layDeco: CoreGeometry.Decoration _ PWCore.extractMode.decoration; schDeco: CoreGeometry.Decoration _ Sisyph.mode.decoration; <> ComparePosition: PROC [pos1, pos2: CD.Position] RETURNS [BOOL] = { RETURN[IF pos1.y = pos2.y THEN pos1.x <= pos2.x ELSE pos1.y < pos2.y]}; FlattenToLayout: PUBLIC PROC[ root: CellType, propKeys: Atoms _ NIL, properties: Core.Properties _ NIL ] RETURNS [structure: Structure] = { EachLeaf: LeafProc = { instName: Rope.ROPE _ CoreFlat.CellTypePathRope[root, flatCell]; schObj: CD.Object _ CoreGeometry.GetObject[schDeco, instance.type]; inst: Instance _ NEW[CoreRouteFlat.InstanceRec _ [ name: instName, flatCell: NEW[CoreFlat.FlatCellTypeRec _ flatCell], position: position, schIR: CD.InterestRect[schObj], layObject: PWCore.Layout[instance.type], props: CopyProps[instance.properties, instance.type.properties, propKeys]]]; actuals: RefTab.Ref _ CoreOps.CreateBindingTable[instance.type.public, instance.actual]; structure.instances.rest _ CONS[inst, structure.instances.rest]; -- root always first FOR list:LIST OF Instance_structure.instances.rest, list.rest WHILE list#NIL AND list.rest#NIL DO IF ComparePosition[list.first.position, list.rest.first.position] THEN EXIT ELSE [list.first, list.rest.first] _ TwoInstances[list.rest.first, list.first] ENDLOOP; FOR side: DABasics.Side IN DABasics.Side DO instPins: CoreRoute.WirePins _ CoreRoute.LayPins[instance.type, side]; <> FOR instPins _ instPins, instPins.rest WHILE instPins#NIL DO wp: CoreRoute.WirePin _ instPins.first; pin: CoreRouteFlat.Pin _ [range: [wp.min, wp.max], side: side, layer: wp.layer]; net: CoreRouteFlat.Net _ BoundInternalNet[wp.wire, root, bindings, structure]; act: Core.Wire _ NARROW[RefTab.Fetch[actuals, wp.wire].val]; AddONodePin[pin, wp.wire, act, structure.oNodes, net, inst, propKeys]; ENDLOOP ENDLOOP; CoreRoute.FlushLayPinCache[instance.type]; CoreRoute.FlushSchPinCache[instance.type]}; rootName: Rope.ROPE _ CoreOps.GetCellTypeName[root]; TerminalIO.PutF["Flatten %g into routing structure.\n", IO.rope[rootName]]; structure _ CreateRootStructure[root, properties, propKeys]; FlattenWithSchLocs[root, EachLeaf]}; IsPublic: PUBLIC PROC[net: CoreRouteFlat.Net] RETURNS [isPublic: BOOLEAN] ~ { FOR ins: LIST OF CoreRouteFlat.InstONode _ net.instONodes, ins.rest WHILE ins#NIL DO IF ins.first.oNode.public THEN RETURN[TRUE] ENDLOOP; RETURN[FALSE]}; TranslateRange: PUBLIC PROC[instance: Instance, pin: CoreRouteFlat.Pin] RETURNS [range: CoreRouteFlat.Range]~ { range _ SELECT pin.side FROM top, bottom => [instance.position.x + pin.range.min, instance.position.x + pin.range.max], left, right => [instance.position.y + pin.range.min, instance.position.y + pin.range.max], ENDCASE => ERROR}; PrintStructure: PUBLIC PROC[structure: Structure] ~ { TerminalIO.PutF["Core Route Flat Structure: %g\n", IO.rope[structure.name]]; FOR insts: LIST OF Instance _ structure.instances, insts.rest WHILE insts#NIL DO PrintInstance[insts.first] ENDLOOP}; <> CreateRootStructure: PROC [root: CellType, properties: Core.Properties, propKeys: Atoms] RETURNS[structure: Structure] ~ { rootName: Rope.ROPE _ CoreOps.GetCellTypeName[root]; bindings: RefTab.Ref _ CoreFlat.InitialBindingTable[root]; schObj: CD.Object _ CoreGeometry.GetObject[schDeco, root]; rootInstance: Instance _ NEW[CoreRouteFlat.InstanceRec _ [ name: rootName, schIR: CD.InterestRect[schObj], rootInstance: TRUE, props: CopyProps[properties, root.properties, propKeys]]]; structure _ NEW[CoreRouteFlat.StructureRec _[ name: rootName, instances: LIST[rootInstance], nets: SymTab.Create[], oNodes: RefTab.Create[], outerInstance: rootInstance, bindings: bindings, auxLabels: SymTab.Create[] ] ]; FOR side: DABasics.Side IN DABasics.Side DO step: INT _ 8*8; -- Just to record order of oNodes on each side index: INT _ 0; wires: Core.Wires _ CoreRoute.OrderedAtomicSchWires[root, side]; FOR wires _ wires, wires.rest WHILE wires#NIL DO pin: CoreRouteFlat.Pin _ [range: [index*step, index*step + step/2], side: side]; net: CoreRouteFlat.Net _ BoundInternalNet[wires.first, root, bindings, structure]; AddONodePin[pin, wires.first, NIL, structure.oNodes, net, rootInstance, propKeys]; index _ index + 1 ENDLOOP ENDLOOP}; AddONodePin: PROC[ pin: CoreRouteFlat.Pin, wire: Core.Wire, actual: Core.Wire, oNodes: RefTab.Ref, -- wire to oNode net: CoreRouteFlat.Net, inst: Instance, propKeys: Atoms] = { oNode: CoreRouteFlat.ONode _ NARROW[RefTab.Fetch[oNodes, wire].val]; IF oNode=NIL THEN { shortName: Rope.ROPE _ CoreOps.GetShortWireName[wire]; oNode _ NEW[CoreRouteFlat.ONodeRec _ [name: shortName, public: actual=NIL]]; [] _ RefTab.Store[oNodes, wire, oNode]; oNode.properties _ CopyProps[wire.properties, NIL, propKeys]}; FOR nns: LIST OF CoreRouteFlat.NetONode _ inst.netONodes, nns.rest WHILE nns#NIL DO IF nns.first.oNode=oNode THEN EXIT; REPEAT FINISHED => { -- first pin of this oNode for this instance inst.netONodes _ CONS[CoreRouteFlat.NetONode[net, oNode], inst.netONodes]; net.instONodes _ CONS[CoreRouteFlat.InstONode[inst, oNode], net.instONodes]; IF actual#NIL THEN net.properties _ CopyProps[actual.properties, net.properties, propKeys]; net.properties _ CopyProps[wire.properties, net.properties, propKeys]} ENDLOOP; FOR pins: LIST OF CoreRouteFlat.Pin _ oNode.pins, pins.rest WHILE pins#NIL DO IF pins.first=pin THEN EXIT; REPEAT FINISHED => {oNode.pins _ CONS[pin, oNode.pins]} ENDLOOP}; BoundInternalNet: PROC[ wire: Core.Wire, root: CellType, bindings: CoreFlat.Bindings, structure: Structure ] RETURNS[net: CoreRouteFlat.Net] = { name: Rope.ROPE _ BoundFlatWireName[wire, root, bindings]; IF (net _ NARROW[SymTab.Fetch[structure.nets, name].val])=NIL THEN { net _ NEW[CoreRouteFlat.NetRec _ [name: name]]; [] _ SymTab.Store[structure.nets, name, net]} }; BoundFlatWireName: PROC[wire: Core.Wire, root: CellType, bindings: CoreFlat.Bindings] RETURNS[Rope.ROPE] = { flatWire: CoreFlat.FlatWire _ NARROW [RefTab.Fetch[bindings, wire].val]; RETURN[CoreRoute.LabelFlatWire[root, flatWire^]]}; CopyProps: PROC[primary, secondary: Core.Properties _ NIL, propKeys: Atoms] RETURNS [destProperties: Core.Properties _ NIL] ~ { FOR keys: Atoms _ propKeys, keys.rest WHILE keys#NIL DO val: REF _ CoreProperties.GetProp[primary, keys.first]; IF val=NIL THEN val _ CoreProperties.GetProp[secondary, keys.first]; destProperties _ CoreProperties.PutProp[destProperties, keys.first, val] ENDLOOP}; FlattenWithSchLocs: PROC[ root: CellType, leafProc: LeafProc ] = { Loc: TYPE = CD.Position; PathName: PROC[flatInstance: CoreFlat.FlatCellTypeRec _ [ ]] RETURNS[name: Rope.ROPE] = { RETURN[IF flatInstance = CoreFlat.rootCellType THEN CoreOps.GetCellTypeName[root] ELSE CoreFlat.CellTypePathRope[root, flatInstance]]}; FlattenCell: CoreFlat.BoundFlatCellProc = { childLoc: REF Loc; IF instance#NIL THEN { parentPath: Rope.ROPE _ PathName[flatParent]; childPath: Rope.ROPE _ PathName[flatCell]; childTran: DABasics.Transformation _ CoreGeometry.GetTrans[schDeco, instance]; parentLoc: REF Loc _ NARROW[SymTab.Fetch[locations, parentPath].val]; childLoc _ NEW[Loc _ CDBasics.AddPoints[childTran.off, parentLoc^ ]]; IF childTran.orient#original THEN ERROR; -- Rotated instances are not allowed. IF NOT SymTab.Insert[locations, childPath, childLoc] THEN ERROR}; IF instance=NIL OR PWCore.GetLayoutAtom[cell]=NIL THEN CoreFlat.NextBoundCellType [cell, target, flatCell, instance, index, parent, flatParent, data, bindings, FlattenCell] ELSE leafProc[flatCell, instance, bindings, childLoc^]}; locations: SymTab.Ref _ SymTab.Create[]; [] _ SymTab.Store[locations, PathName[], NEW[Loc _ [0,0] ] ]; FlattenCell[root]}; PrintInstance: PROC[inst: Instance] ~ { TerminalIO.PutF[" Instance: %g\n", IO.rope[inst.name]]; TerminalIO.PutF[" Pos: [%g, %g]\n", IO.int[inst.position.x], IO.int[inst.position.y]]; TerminalIO.PutF[" SchIR: [%g, %g, %g, %g]\n", IO.int[inst.schIR.x1], IO.int[inst.schIR.y1], IO.int[inst.schIR.x2], IO.int[inst.schIR.y2]]; FOR nn: LIST OF CoreRouteFlat.NetONode _ inst.netONodes, nn.rest WHILE nn#NIL DO PrintNetONode[nn.first] ENDLOOP}; PrintNetONode: PROC[nONode: CoreRouteFlat.NetONode] ~ { TerminalIO.PutF[" NetONode: %g %g%g\n", IO.rope[nONode.net.name], IO.rope[nONode.oNode.name], IO.rope[IF nONode.oNode.public THEN " (public)" ELSE ""]]; FOR pins: LIST OF CoreRouteFlat.Pin _ nONode.oNode.pins, pins.rest WHILE pins#NIL DO PrintPin[pins.first] ENDLOOP}; PrintPin: PROC[pin: CoreRouteFlat.Pin] ~ { TerminalIO.PutF[" Pin: %6g %5g [%g, %g]\n", IO.rope[SideNames[pin.side]], IO.atom[CD.LayerKey[pin.layer]], IO.int[pin.range.min], IO.int[pin.range.max]]}; SideNames: ARRAY DABasics.Side OF Rope.ROPE _ [bottom: "Bottom", top: "Top", left: "Left", right: "Right"]; END.