CoreRouteFlatImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Don Curry December 2, 1987 12:14:28 pm PST
DIRECTORY
Atom, CD, CDBasics, Core, CoreClasses, CoreFlat, CoreGeometry, CoreOps, CoreProperties, CoreRoute, CoreRouteFlat, DABasics, GC, IO, PWCore, RefTab, Rope, Route, Sisyph, SymTab, TerminalIO;
CoreRouteFlatImpl: CEDAR PROGRAM
IMPORTS Atom, CD, CDBasics, CoreFlat, CoreGeometry, CoreOps, CoreProperties, CoreRoute, CoreRouteFlat, GC, IO, PWCore, RefTab, Rope, Sisyph, SymTab, TerminalIO
EXPORTS CoreRouteFlat =
BEGIN
Types
Structure: TYPE = CoreRouteFlat.Structure;
Instance: TYPE = CoreRouteFlat.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
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],
cdObject: PWCore.Layout[instance.type],
props:  CopyProps[instance.properties, instance.type.properties, propKeys]]];
nodes:  RefTab.Ref ← RefTab.Create[];
actuals: RefTab.Ref ← CoreOps.CreateBindingTable[instance.type.public, instance.actual];
structure.instances ← CONS[inst, structure.instances];
FOR side: DABasics.Side IN DABasics.Side DO
instPins: CoreRoute.WirePins ←
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];
AddNodePin[pin, wp.wire, act, nodes, 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.InstNode ← net.instNodes, ins.rest WHILE ins#NIL DO
IF ins.first.node.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];
nodes:   RefTab.Ref ← RefTab.Create[];
rootInstance: Instance ← NEW[CoreRouteFlat.InstanceRec ← [
name:    rootName,
rootInstance:  TRUE,
props:    CopyProps[properties, root.properties, propKeys]]];
structure  ← NEW[CoreRouteFlat.StructureRec ←[
name:    rootName,
instances:   LIST[rootInstance],
nets:    SymTab.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 nodes 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];
AddNodePin[pin, wires.first, NIL, nodes, net, rootInstance, propKeys];
index ← index + 1 ENDLOOP ENDLOOP};
AddNodePin:    PROC[
pin:   CoreRouteFlat.Pin,
wire:   Core.Wire,
actual:  Core.Wire,
nodes:   RefTab.Ref, -- wire to node
net:   CoreRouteFlat.Net,
inst:   Instance,
propKeys: Atoms] = {
node: CoreRouteFlat.Node ← NARROW[RefTab.Fetch[nodes, wire].val];
IF node=NIL THEN {
shortName:  Rope.ROPE ← CoreOps.GetShortWireName[wire];
node    ← NEW[CoreRouteFlat.NodeRec ← [name: shortName, public: actual=NIL]];
[]     ← RefTab.Store[nodes, wire, node];
net.instNodes  ← LIST[CoreRouteFlat.InstNode[inst, node]];
inst.netNodes  ← LIST[CoreRouteFlat.NetNode[net, node]];
net.properties ← CopyProps[wire.properties, net.properties, propKeys];
net.properties ← CopyProps[actual.properties, net.properties, propKeys];
node.properties ← CopyProps[wire.properties, NIL,    propKeys]};
node.pins ← CONS[pin, node.pins ]};
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 AND cell.class.recast#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.NetNode ← inst.netNodes, nn.rest WHILE nn#NIL DO
PrintNetNode[nn.first] ENDLOOP};
PrintNetNode:    PROC[nNode: CoreRouteFlat.NetNode] ~ {
TerminalIO.PutF[" NetNode: %g %g%g\n",
IO.rope[nNode.net.name],
IO.rope[nNode.node.name],
IO.rope[IF nNode.node.public THEN " (public)" ELSE ""]];
FOR pins: LIST OF CoreRouteFlat.Pin ← nNode.node.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"];
Attributes, Layout and Decorate ($Hybrid, $GC)
Attributes:  PWCore.AttributesProc = {
layAtom:  ATOM ← PWCore.GetLayoutAtom[cellType];
hLayer:  Rope.ROPE ← "metal";
vLayer:  Rope.ROPE ← "metal2";
rules:   GC.DesignRules;
structure:  Structure;
prop:   REF ← CoreProperties.GetCellTypeProp[cellType, $VerticalLayer];
IF prop#NIL THEN {
name: IO.ROPEWITH prop SELECT FROM
atom: ATOM  => Atom.GetPName[atom],
rope: IO.ROPE => rope,
ENDCASE   => ERROR;
IF name.Find["2"]=-1 THEN {hLayer ← "metal2"; vLayer ← "metal"}};
rules ← SELECT layAtom FROM
HybridAtom  => GC.CreateDesignRules[$cmosB, $Hybrid, hLayer, vLayer],
GlobalAtom  => GC.CreateDesignRules[$cmosB, $cmosB, hLayer, vLayer],
ENDCASE    => ERROR;
structure  ← CoreRouteFlat.FlattenToLayout[cellType, LIST[$w]];
CoreProperties.PutCellTypeProp[cellType, $GCRules, rules];
CoreProperties.PutCellTypeProp[cellType, $GCStruc, structure]};
Layout:   PWCore.LayoutProc = {
name:  Rope.ROPE ← CoreOps.GetCellTypeName[cellType];
result:  GC.Result;
context: GC.Context;
rules:  GC.DesignRules ← NARROW[CoreProperties.GetCellTypeProp[cellType, $GCRules]];
struc:  Structure ← NARROW[CoreProperties.GetCellTypeProp[cellType, $GCStruc]];
GC.InitialPlace[struc];
context  ← GC.CreateContext[name, struc, rules];
GC.DoInitialGlobalRoute[context];
result   ← GC.DoDetailRoute[context];
RETURN[result.object]};
Decorate:   PWCore.DecorateProc = {
CompareFlatInstances: PUBLIC CoreRoute.CompareFlatCTProc = {
FOR insts: LIST OF Instance ← struc.instances, insts.rest WHILE insts#NIL DO
IF CoreFlat.FlatCellTypeEqualRec[insts.first.flatCell^, flatCT1] THEN RETURN[TRUE];
IF CoreFlat.FlatCellTypeEqualRec[insts.first.flatCell^, flatCT2] THEN RETURN[FALSE];
ENDLOOP; ERROR};
WireToLabels: PROC[wire: Core.Wire] RETURNS [labels: LIST OF Route.Label ← NIL] = {
flatWire:  CoreFlat.FlatWire = NARROW[RefTab.Fetch[struc.bindings, wire].val];
label:   Route.Label   = CoreRoute.LabelFlatWire[cellType, flatWire^];
auxLabels: LIST OF Rope.ROPE = NARROW[SymTab.Fetch[struc.auxLabels, label].val];
labels ← CONS [label, auxLabels]};
struc: Structure ← NARROW[CoreProperties.GetCellTypeProp[cellType, $GCStruc]];
CoreRoute.DecorateRoutedArea[
cellType:   cellType,
obj:    obj,
wireToLabels: WireToLabels,
compareCT:  CompareFlatInstances]};
HybridAtom: ATOM ← PWCore.RegisterLayoutAtom[$Hybrid, Layout, Decorate, Attributes];
GlobalAtom: ATOM ← PWCore.RegisterLayoutAtom[$GC,  Layout, Decorate, Attributes];
END.