CoreRouteFlatImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Don Curry December 7, 1987 11:29:29 am PST
Massoud Pedram July 8, 1988 4:31:54 pm PDT
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
Types
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;
Exported Procedures
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];
CoreRoute.FilteredCellTypeLayoutPins[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};
Auxiliary Procedures
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.