CoreRouteMosaic.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Created by Don Curry February 23, 1988 2:20:43 pm PST
Don Curry August 18, 1988 5:34:51 pm PDT
DIRECTORY
Basics, CD, CDBasics, CDCells, CDSimpleRules, CedarProcess, CMosB, Core, CoreClasses, CoreGeometry, CoreOps, CoreProperties, CoreRoute, DABasics, IntHashTable, IO, PWCore, RefTab, Rope, Route, Sisyph, SymTab, TerminalIO;
CoreRouteMosaic:
CEDAR
PROGRAM
IMPORTS Basics, CD, CDBasics, CDCells, CDSimpleRules, CedarProcess, CMosB, CoreGeometry, CoreOps, CoreProperties, CoreRoute, DABasics, IntHashTable, IO, PWCore, RefTab, Rope, Route, Sisyph, SymTab, TerminalIO
= BEGIN
Types and constants
MosaicForm: TYPE = REF MosaicFormRec;
MosaicFormRec:
TYPE =
RECORD[
data: CoreClasses.RecordCellType,
cellType: CellType,
horizLayer: CD.Layer,
vertLayer: CD.Layer,
ignoreNWell: REF,
seq: SEQUENCE size: NAT OF MosaicRow];
MosaicRow: TYPE = REF MosaicRowRec;
MosaicRowRec: TYPE = RECORD[SEQUENCE size: NAT OF MosaicCell];
MosaicCell: TYPE = RECORD[schPos, layPos: CD.Position, ctInst: INT, sBox: CD.Object];
PPDist: TYPE = RECORD[schP1, schP2, layDist: INT];
LocSchLay: TYPE = RECORD[sch, lay: INT];
RowCol: TYPE = RECORD[row, col: INT];
WirePin: TYPE = CoreRoute.WirePin;
WirePins: TYPE = CoreRoute.WirePins;
WirePinAry: TYPE = ARRAY Side OF WirePins;
Side: TYPE = CoreGeometry.Side;
CellType: TYPE = Core.CellType;
Wire: TYPE = Core.Wire;
Wires: TYPE = Core.Wires;
NetInfo: TYPE = REF NetInfoRec;
NetInfoRec:
TYPE =
RECORD [
trunkSize: INT ← 0,
pins: LIST OF PinInfo ← NIL];
PinInfo:
TYPE =
RECORD [
side: Side,
min: CD.Number ← 0,
max: CD.Number ← 0,
layer: CD.Layer];
technologyKey: ATOM ← $cmosB;
wireWidthProp: ATOM ← $w;
mosaicLayoutProp: ATOM ← $Mosaic;
mosaicFormProp: ATOM ← $MosaicForm;
lambda: INT ← CDSimpleRules.GetTechnology[technologyKey].lambda;
Signal: SIGNAL[msg: IO.ROPE] = CODE;
Mosaic Attribute, Layout and Decorate Procs
MosaicAttributes: PWCore.AttributesProc = {
frm: MosaicForm ← CreateMosaicForm[cellType];
ShowMosaicForm[frm];
CheckInterfaces[frm];
BuildSBoxs[frm]};
MosaicLayout: PWCore.LayoutProc = {
frm: MosaicForm ← NARROW[CoreProperties.GetCellTypeProp[cellType, mosaicFormProp]];
iList: CD.InstanceList;
ctInsts: CoreClasses.CellInstances;
maxLay: CD.Position ← frm[frm.size-1][frm[0].size-1].layPos;
FOR row:
INT
DECREASING
IN [0..frm.size-1)
DO
FOR col:
INT
DECREASING
IN [0..frm[row].size-1)
DO
IF OriginRowColOf[frm, row, col] # [row, col] THEN LOOP;
IF IsSBox[frm, row, col]
THEN {
inst: CD.Instance ← NewInstance[frm[row][col].sBox, frm[row][col].layPos];
iList ← CONS[inst, iList]}
ELSE {
ctInst: CoreClasses.CellInstance ← frm.data[frm[row][col].ctInst];
inst: CD.Instance ← NewInstance[PWCore.Layout[ctInst.type], frm[row][col].layPos];
ctInsts ← CONS[ctInst, ctInsts];
iList ← CONS[inst, iList]} ENDLOOP ENDLOOP;
FOR i: NAT IN [0..frm.data.size) DO frm.data[i] ← ctInsts.first; ctInsts ← ctInsts.rest ENDLOOP;
obj ← CDCells.CreateCell[il: iList, ir: [0, 0, maxLay.x, maxLay.y]];
CDCells.ToSequenceMode[obj]};
NewInstance:
PROC[obj:
CD.Object, irLoc:
CD.Position]
RETURNS[inst:
CD.Instance] = {
CD.Instance given where you want the corner of the interest rect.
base: CD.Position ← CDBasics.BaseOfRect[CD.InterestRect[obj]];
pos: CD.Position ← CDBasics.SubPoints[irLoc, base];
inst ← NEW[CD.InstanceRep ← [obj, [pos]] ]};
MosaicDecorate: PWCore.DecorateProc = {
WireToLabels:
PROC [wire: Wire]
RETURNS [labels:
LIST
OF Route.Label ←
NIL] =
{RETURN[LIST[CoreRoute.LabelInternal[form.data.internal, wire]]]};
form: MosaicForm ← NARROW[CoreProperties.GetCellTypeProp[cellType, mosaicFormProp]];
CoreRoute.DecorateRoutedArea[
cellType: cellType,
obj: obj,
wireToLabels: WireToLabels];
form.cellType ← NIL;
form.data ← NIL;
CoreProperties.PutCellTypeProp[cellType, mosaicFormProp, NIL]};
Primary Procs
CreateMosaicForm:
PROC[cellType: CellType]
RETURNS[frm: MosaicForm] = {
RoundedIR:
PROC[index:
INT]
RETURNS[ir:
CD.Rect] = {
ir ← CoreRoute.SchMappedIR[data[index]];
ir.x1 ← (ir.x1/lambda)*lambda; ir.x2 ← (ir.x2/lambda)*lambda;
ir.y1 ← (ir.y1/lambda)*lambda; ir.y2 ← (ir.y2/lambda)*lambda};
data: CoreClasses.RecordCellType ← NARROW [cellType.data];
xs: LIST OF PPDist;
ys: LIST OF PPDist;
locsX: LIST OF LocSchLay;
locsY: LIST OF LocSchLay;
FOR i:
NAT
IN [0..data.size)
DO
ir: CD.Rect ← RoundedIR[i];
laySize: CD.Position;
laySize ← CD.InterestSize[PWCore.Layout[data[i].type]];
xs ← CONS[[ir.x1, ir.x2, laySize.x], xs];
ys ← CONS[[ir.y1, ir.y2, laySize.y], ys] ENDLOOP;
locsX ← ConsolidatePPDs[xs];
locsY ← ConsolidatePPDs[ys];
frm ← NEW[MosaicFormRec[SizeLocSchLayList[locsY]]];
CoreProperties.PutCellTypeProp[cellType, mosaicFormProp, frm];
frm.cellType ← cellType;
frm.data ← data;
[frm.vertLayer, frm.horizLayer] ← CoreRoute.GetCellTypePropLayer[cellType, $VerticalMetal];
frm.ignoreNWell ← CoreProperties.GetCellTypeProp[cellType, $IgnoreNWell];
FOR row:
INT
IN [0..frm.size)
DO
xlist: LIST OF LocSchLay ← locsX;
frm[row] ← NEW[MosaicRowRec[SizeLocSchLayList[locsX]]];
FOR col:
INT
IN [0..frm[row].size)
DO
frm[row][col].schPos ← [xlist.first.sch, locsY.first.sch];
frm[row][col].layPos ← [xlist.first.lay, locsY.first.lay];
frm[row][col].ctInst ← -1;
xlist ← xlist.rest ENDLOOP;
locsY ← locsY.rest ENDLOOP;
FOR i:
NAT
IN [0..data.size)
DO
ir: CD.Rect ← RoundedIR[i];
ir.x2 ← ir.x2 - lambda; -- 2* lambda/2
ir.y2 ← ir.y2 - lambda; -- 2* lambda/2
FOR row:
INT
IN [0..frm.size-1)
DO
FOR col:
INT
IN [0..frm[row].size-1)
DO
IF ~CDBasics.InsidePos[frm[row][col].schPos, ir]
THEN
LOOP;
IF frm[row][col].ctInst#-1 THEN ERROR;
frm[row][col].ctInst ← i ENDLOOP ENDLOOP ENDLOOP};
ConsolidatePPDs:
PROC[list:
LIST
OF PPDist]
RETURNS[locs:
LIST
OF LocSchLay] = {
GetNode:
PROC[schLoc:
INT]
RETURNS[node:
REF Node] = {
node ← NARROW[IntHashTable.Fetch[nodeTab, schLoc].value];
IF node=
NIL
THEN {node ← NEW[Node←[]]; []←IntHashTable.Store[nodeTab, schLoc, node]}};
SetLayLoc:
PROC[schLoc, layLoc:
INT] = {
node: REF Node ← GetNode[schLoc];
IF node.layLoc#-1 THEN {IF node.layLoc=layLoc THEN RETURN ELSE ERROR};
node.layLoc ← layLoc;
locs ← CONS[[schLoc, layLoc], locs];
FOR lst:
LIST
OF LocSchLay ← locs, lst.rest
WHILE lst#
NIL
AND lst.rest#
NIL
DO
TwoLocSchLays: TYPE = RECORD[l1,l2: LocSchLay];
IF lst.first.sch <= lst.rest.first.sch
THEN
{IF lst.first.sch = lst.rest.first.sch OR lst.first.lay >= lst.rest.first.lay THEN ERROR; EXIT};
[lst.first, lst.rest.first] ← TwoLocSchLays[lst.rest.first, lst.first] ENDLOOP;
FOR links:
LIST
OF Link ← node.links, links.rest
WHILE links#
NIL
DO
SetLayLoc[links.first.schLoc, layLoc + links.first.layDist] ENDLOOP};
Node: TYPE = RECORD[layLoc: INT ← -1, links: LIST OF Link ← NIL];
Link: TYPE = RECORD[schLoc, layDist: INT ← -1];
nodeTab: IntHashTable.Table ← IntHashTable.Create[];
min: INT ← LAST[INT];
FOR list ← list, list.rest
WHILE list#
NIL
DO
nodeUp: REF Node ← GetNode[list.first.schP1];
nodeDn: REF Node ← GetNode[list.first.schP2];
nodeUp.links ← CONS[[schLoc: list.first.schP2, layDist: +list.first.layDist], nodeUp.links];
nodeDn.links ← CONS[[schLoc: list.first.schP1, layDist: -list.first.layDist], nodeDn.links];
min ← MIN[min, list.first.schP1] ENDLOOP;
SetLayLoc[min, 0]};
CheckInterfaces:
PROC[frm: MosaicForm] = {
IF CoreProperties.GetCellTypeProp[frm.cellType, $TrustMe]#NIL THEN RETURN;
FOR row:
INT
IN [0..frm.size-2)
DO
FOR col:
INT
IN [0..frm[row].size-2)
DO
IF frm[row][col].ctInst # frm[row][col+1].ctInst
AND
frm[row][col].ctInst # -1 AND
frm[row][col+1].ctInst # -1
THEN {
l1: WirePins ← GetLayoutPins[frm, row, col+1, left];
l2: WirePins ← GetLayoutPins[frm, row, col, right];
IF NOT EqualWirePins[l1, l2] THEN ERROR};
IF frm[row][col].ctInst # frm[row+1][col].ctInst
AND
frm[row][col].ctInst # -1 AND
frm[row+1][col].ctInst # -1
THEN {
l1: WirePins ← GetLayoutPins[frm, row+1, col, bottom];
l2: WirePins ← GetLayoutPins[frm, row, col, top];
IF NOT EqualWirePins[l1, l2] THEN ERROR};
ENDLOOP ENDLOOP};
BuildSBoxs:
PROC[frm: MosaicForm] = {
name: IO.ROPE ← CoreOps.GetCellTypeName[frm.cellType];
globals: Core.Wires ← CoreRoute.GlobalWires[frm.cellType];
FOR row:
INT
IN [0..frm.size-1)
DO
FOR col:
INT
IN [0..frm[row].size-1)
DO
IF OriginRowColOf[frm, row, col] # [row, col] THEN LOOP;
IF IsSBox[frm, row, col]
THEN {
lim: RowCol ← LimitRowColOf[frm, row, col];
laySize:
CD.Position ←
CDBasics.SubPoints[frm[lim.row][lim.col].layPos, frm[row][col].layPos];
pinAry: WirePinAry ← GetSBBrotherPins[frm, row, col, lim.row, lim.col];
wireAry: ARRAY Side OF Wires ← GetSBParentWires[frm, row, col, lim.row, lim.col];
TerminalIO.PutF["SBox at (%g, %g)\n", IO.int[col], IO.int[row]];
FOR side: Side
IN Side
DO
IF pinAry[side] # NIL THEN LOOP;
pinAry[side] ← CoreRoute.FilterPins[
pinAry[ DABasics.OtherSide[side]], wireAry[side], globals];
pinAry[side] ← AddMissingPins [frm, side, laySize, pinAry, wireAry[side] ]
ENDLOOP;
frm[row][col].sBox ← MakeSwitchBox[
name: IO.PutFR["%gSBox%gx%g", IO.rope[name],IO.int[col],IO.int[row]],
routingRect: [0, 0, laySize.x, laySize.y],
horizLayer: frm.horizLayer,
vertLayer: frm.vertLayer,
root: frm.data.internal,
pinAry: pinAry,
fastRoute: CoreProperties.GetCellTypeProp[frm.cellType, $FastRoute]#NIL ]};
ENDLOOP ENDLOOP;
FOR i:
NAT
IN [0..frm.data.size)
DO
CoreRoute.FlushLayPinCache[frm.data[i].type];
CoreRoute.FlushSchPinCache[frm.data[i].type] ENDLOOP;
CoreRoute.FlushSchPinCache[frm.cellType]};
AddMissingPins:
PROC
[frm: MosaicForm, side: Side, laySize:
CD.Position, pinAry: WirePinAry, wires: Core.Wires]
RETURNS[new: WirePins ← NIL] = {
range: INT ← (IF side=left OR side=right THEN laySize.y ELSE laySize.x);
layer: CD.Layer ← (IF side=left OR side=right THEN frm.horizLayer ELSE frm.vertLayer);
pins: WirePins ← pinAry[side];
FOR wires ← wires, wires.rest
WHILE wires#
NIL
DO
size: INT ← 3*lambda;
space: INT ← 4*lambda;
spaceEnd: INT ← 8*lambda;
done: BOOL ← FALSE;
inMins, inMaxs: BOOL ← FALSE;
FOR test: WirePins ← pins, test.rest
WHILE test#
NIL
DO
IF test.first.wire=wires.first THEN GOTO Loop REPEAT Loop => LOOP ENDLOOP;
FOR test: WirePins ← pinAry[MinSide[side]], test.rest
WHILE test#
NIL
DO
IF test.first.wire=wires.first
THEN
{inMins ← TRUE; size ← MAX[size, test.first.max - test.first.min]} ENDLOOP;
FOR test: WirePins ← pinAry[MaxSide[side]], test.rest
WHILE test#
NIL
DO
IF test.first.wire=wires.first
THEN
{inMaxs ← TRUE; size ← MAX[size, test.first.max - test.first.min]} ENDLOOP;
IF NOT (inMins OR inMaxs) THEN ERROR;
IF size=4*lambda AND layer=CMosB.met THEN size ← 3*lambda;
IF size=3*lambda AND layer=CMosB.met2 THEN size ← 4*lambda;
IF inMins
THEN {
IF (pins=
NIL)
AND (spaceEnd+size+spaceEnd <= range)
OR
(pins#
NIL)
AND (spaceEnd+size+space <= pins.first.min)
THEN {
pins ← CONS[[wires.first, spaceEnd, spaceEnd+size, layer], pins];
done ← TRUE};
IF
NOT done
THEN
FOR test: WirePins ← pins, test.rest
WHILE test#
NIL
DO
IF (test.rest=
NIL)
AND (test.first.max + space+size+spaceEnd <= range)
OR
(test.rest#
NIL)
AND (test.first.max + space+size+space<=test.rest.first.min)
THEN{
pos: INT ← test.first.max+space;
test.rest ← CONS[[wires.first, pos, pos+size, layer], test.rest];
done ← TRUE; EXIT} ENDLOOP}
ELSE {
pins ← CoreRoute.ReverseWirePins[pins];
IF (pins=
NIL)
AND ( spaceEnd+size+spaceEnd <= range)
OR
(pins#
NIL)
AND (pins.first.max + space+size+spaceEnd <= range)
THEN {
pins ← CONS[[wires.first, range-size-spaceEnd, range-spaceEnd, layer], pins];
done ← TRUE};
IF
NOT done
THEN
FOR test: WirePins ← pins, test.rest
WHILE test#
NIL
DO
IF (test.rest=
NIL)
AND ( space+size+spaceEnd <= test.first.min)
OR
(test.rest#NIL) AND (test.rest.first.max+space+size+space <= test.first.min) THEN {
pos: INT ← test.first.min- space-size;
test.rest ← CONS[[wires.first, pos, pos+size, layer], test.rest];
done ← TRUE; EXIT} ENDLOOP;
pins ← CoreRoute.ReverseWirePins[pins]};
IF
NOT done
THEN {
TerminalIO.PutF["\n*** A switchbox in the Mosaic layout: %g does not have enough space in which to put all of the %g side wires. Proceeding returns an incomplete route.\n",
IO.rope[CoreOps.GetCellTypeName[frm.cellType]], IO.rope[SideNm[side]]];
Signal["Insufficient space on switchbox side. See Terminal Viewer."]; EXIT};
ENDLOOP;
RETURN[pins]};
Secondary Procs
EqualWirePins:
PROC[w1, w2: WirePins]
RETURNS[equal:
BOOL ←
TRUE] = {
DO
IF w1=NIL OR w2=NIL THEN RETURN[w1=w2];
IF w1.first#w2.first THEN RETURN[FALSE];
w1←w1.rest;
w2←w2.rest ENDLOOP};
GetLayoutPins:
PROC[frm: MosaicForm, row, col:
INT, side: Side, filtered:
BOOL←
FALSE]
RETURNS[wirePins: WirePins ← NIL] = {
layer: CD.Layer ← IF LeftRight[side] THEN frm.horizLayer ELSE frm.vertLayer;
IF row
IN [0..frm.size-1)
AND col
IN [0..frm[0].size-1)
THEN {
origin: RowCol ← OriginRowColOf[frm, row, col];
inst: CoreClasses.CellInstance ← frm.data[frm[row][col].ctInst];
temp: WirePins ←
IF filtered
THEN CoreRoute.FilteredInstanceLayoutPins[inst, side]
ELSE CoreRoute.LayPins[inst.type, side];
bias:
INT ←
IF LeftRight[side]
THEN frm[row][col].layPos.y - frm[origin.row][origin.col].layPos.y
ELSE frm[row][col].layPos.x - frm[origin.row][origin.col].layPos.x;
max:
INT ←
IF LeftRight[side]
THEN frm[row+1][col].layPos.y - frm[row][col].layPos.y
ELSE frm[row][col+1].layPos.x - frm[row][col].layPos.x;
bindings: RefTab.Ref ← CoreOps.CreateBindingTable[inst.type.public, inst.actual];
FOR temp ← temp, temp.rest
WHILE temp#
NIL
DO
p: WirePin ← [temp.first.wire, temp.first.min-bias, temp.first.max-bias, temp.first.layer];
IF frm.ignoreNWell#NIL AND p.layer=CMosB.nwell THEN LOOP;
IF filtered
THEN {
IF layer=
CD.commentLayer
THEN {
IF p.layer#CMosB.met AND p.layer#CMosB.met2 THEN LOOP;
IF LeftRight[side] = (p.layer = CMosB.met2)
THEN {frm.horizLayer ← CMosB.met2; frm.vertLayer ← CMosB.met}
ELSE {frm.horizLayer ← CMosB.met; frm.vertLayer ← CMosB.met2};
layer ← IF LeftRight[side] THEN frm.horizLayer ELSE frm.vertLayer};
IF p.layer#layer THEN LOOP}
ELSE IF (p.wire ← NARROW[RefTab.Fetch[bindings, p.wire].val]) = NIL THEN ERROR;
IF p.max <=0 THEN LOOP;
IF p.min >=max THEN EXIT;
wirePins ← CONS[p, wirePins] ENDLOOP;
wirePins ← CoreRoute.ReverseWirePins[wirePins]}};
GetSBBrotherPins:
PROC[frm: MosaicForm, row1, col1, row2, col2:
INT]
RETURNS[pinAry: WirePinAry ← ALL[NIL]] = {
FOR row:
INT
IN [row1..row2)
DO
bias: INT ← frm[row][col1].layPos.y - frm[row1][col1].layPos.y;
temp: WirePins ← GetLayoutPins[frm, row, col1-1, right, TRUE];
FOR temp ← temp, temp.rest
WHILE temp#
NIL
DO
p: WirePin ← temp.first;
pinAry[left] ← CONS[[p.wire,p.min+bias,p.max+bias,p.layer],pinAry[left]] ENDLOOP;
temp ← GetLayoutPins[frm, row, col2, left, TRUE];
FOR temp ← temp, temp.rest
WHILE temp#
NIL
DO
p: WirePin ← temp.first;
pinAry[right] ← CONS[[p.wire,p.min+bias,p.max+bias,p.layer],pinAry[right]] ENDLOOP;
ENDLOOP;
FOR col:
INT
IN [col1..col2)
DO
bias: INT ← frm[row1][col].layPos.x - frm[row1][col1].layPos.x;
temp: WirePins ← GetLayoutPins[frm, row1-1, col, top, TRUE];
FOR temp ← temp, temp.rest
WHILE temp#
NIL
DO
p: WirePin ← temp.first;
pinAry[bottom]←CONS[[p.wire,p.min+bias,p.max+bias,p.layer],pinAry[bottom]] ENDLOOP;
temp ← GetLayoutPins[frm, row2, col, bottom, TRUE];
FOR temp ← temp, temp.rest
WHILE temp#
NIL
DO
p: WirePin ← temp.first;
pinAry[top] ← CONS[[p.wire,p.min+bias,p.max+bias,p.layer],pinAry[top]] ENDLOOP;
ENDLOOP;
FOR side: Side
IN Side
DO
pinAry[side] ← CoreRoute.ReverseWirePins[pinAry[side]] ENDLOOP};
GetSBParentWires:
PROC[frm: MosaicForm, row1, col1, row2, col2:
INT]
RETURNS[wireAry: ARRAY Side OF Wires ← ALL[NIL]] = {
ir: CD.Rect ← CDBasics.ToRect[frm[row1][col1].schPos, frm[row2][col2].schPos];
pir: CD.Rect ← CD.InterestRect[CoreGeometry.GetObject[Sisyph.mode.decoration, frm.cellType]];
ir ← CDBasics.MoveRect[ir, CDBasics.NegOffset[CDBasics.BaseOfRect[pir]]];
IF row1=0
THEN
wireAry[bottom] ← CoreRoute.OrderedAtomicSchWires[frm.cellType, bottom, ir.x1, ir.x2];
IF col1=0
THEN
wireAry[left] ← CoreRoute.OrderedAtomicSchWires[frm.cellType, left, ir.y1, ir.y2];
IF row2=frm.size-1
THEN
wireAry[top] ← CoreRoute.OrderedAtomicSchWires[frm.cellType, top, ir.x1, ir.x2];
IF col2=frm[0].size-1
THEN
wireAry[right] ← CoreRoute.OrderedAtomicSchWires[frm.cellType, right, ir.y1, ir.y2]};
IsSBox:
PROC[frm: MosaicForm, row, col:
INT]
RETURNS[
BOOL] =
{RETURN[
(row < (frm.size-1)) AND (col < (frm[row].size-1)) AND (frm[row][col].ctInst = -1)]};
LeftRight:
PROC[side: Side]
RETURNS[
BOOL] =
{RETURN[side=left OR side=right]};
LimitRowColOf:
PROC[frm: MosaicForm, row, col:
INT]
RETURNS[rowCol: RowCol] = {
rowI: INT ← row;
colI: INT ← col;
FOR row ← row+1, row+1
WHILE row<frm.size-1 AND frm[row-1][colI].ctInst = frm[row][colI].ctInst DO ENDLOOP;
FOR col ← col+1, col+1
WHILE col<frm[row].size-1 AND frm[rowI][col-1].ctInst=frm[rowI][col].ctInst DO ENDLOOP;
RETURN[[row, col]]};
MaxSide:
PROC[side: Side]
RETURNS[Side] =
{RETURN[DABasics.OtherSide[MinSide[side]]]};
MinSide:
PROC[side: Side]
RETURNS[Side] =
{RETURN[IF LeftRight[side] THEN bottom ELSE left]};
OriginRowColOf:
PROC[frm: MosaicForm, row, col:
INT]
RETURNS[rowCol: RowCol] = {
FOR row ← row, row-1
WHILE row#0
AND frm[row-1][col].ctInst = frm[row][col].ctInst
DO ENDLOOP;
FOR col ← col, col-1
WHILE col#0
AND frm[row][col-1].ctInst = frm[row][col].ctInst
DO ENDLOOP;
RETURN[[row, col]]};
ShowMosaicForm:
PROC[frm: MosaicForm] = {
TerminalIO.PutF["Mosaic Layout:"];
TerminalIO.PutF["\n Sch "];
FOR col:
INT
IN [0..frm[0].size-1)
DO
TerminalIO.PutF["%8g", IO.int[frm[0][col].schPos.x]] ENDLOOP;
TerminalIO.PutF["\n Lay "];
FOR col:
INT
IN [0..frm[0].size-1)
DO
TerminalIO.PutF["%8g", IO.int[frm[0][col].layPos.x]] ENDLOOP;
FOR row:
INT
DECREASING
IN [0..frm.size-1)
DO
TerminalIO.PutF["\n%8g\n%8g",
IO.int[frm[row][0].schPos.y], IO.int[frm[row][0].layPos.y]];
FOR col:
INT
IN [0..frm[row].size-1)
DO
IF frm[row][col].ctInst#-1
THEN TerminalIO.PutF["%8g", IO.int[frm[row][col].ctInst]]
ELSE TerminalIO.PutRope[" x"] ENDLOOP ENDLOOP;
TerminalIO.PutRope["\n"]};
ShowPins:
PROC[pins: WirePins, root: Wire ←
NIL] = {
index: INT ← 0;
FOR pins ← pins, pins.rest
WHILE pins#
NIL
DO
TerminalIO.PutF["%2g: %-20g min:%5g max:%5g %g\n",
IO.int[index],
IO.rope[WireName[pins.first.wire, root]],
IO.int[pins.first.min],
IO.int[pins.first.max],
IO.atom[CD.LayerKey[pins.first.layer]]];
index ← index +1;
ENDLOOP};
ShowWires:
PROC[wires: Wires, root: Wire ←
NIL] = {
index: INT ← 0;
FOR wires ← wires, wires.rest
WHILE wires#
NIL
DO
TerminalIO.PutF["%2g: %-20g\n", IO.int[index], IO.rope[WireName[wires.first, root]] ]
ENDLOOP};
SideNm:
ARRAY Side
OF
IO.
ROPE ←
[bottom: "Bottom", top: "Top", left: "Left", right: "Right"];
SizeIntList:
PROC[list:
LIST
OF
INT]
RETURNS[size:
INT ← 0] =
{FOR list ← list, list.rest WHILE list#NIL DO size ← size+1 ENDLOOP};
SizeLocSchLayList:
PROC[list:
LIST
OF LocSchLay]
RETURNS[size:
INT ← 0] =
{FOR list ← list, list.rest WHILE list#NIL DO size ← size+1 ENDLOOP};
SortIntList:
PROC[intList:
LIST
OF
INT] = {
TwoInts: TYPE = RECORD[i0, i1: INT];
DO
done: BOOL ← TRUE;
list: LIST OF INT ← intList;
FOR list ← list, list.rest
WHILE list#
NIL
AND list.rest#
NIL
DO
SELECT Basics.CompareInt[list.first, list.rest.first]
FROM
equal => {done←FALSE; list.rest ← list.rest.rest};
greater => {done←FALSE; [list.first, list.rest.first] ← TwoInts[list.rest.first, list.first]};
ENDCASE ENDLOOP;
IF done THEN EXIT ENDLOOP};
WireName:
PROC[wire, root: Wire ←
NIL]
RETURNS[rope:
IO.
ROPE] = {
RETURN[(
IF root#
NIL
THEN CoreRoute.LabelInternal[root, wire]
ELSE CoreOps.GetShortWireName[wire])]};
SBox generator
MakeSwitchBox:
PROC[
name: IO.ROPE,
routingRect: CD.Rect,
horizLayer: CD.Layer,
vertLayer: CD.Layer,
root: Wire,-- for consistant labels
pinAry: WirePinAry,
fastRoute:
BOOL ←
FALSE]
RETURNS[switchBox: CD.Object] = {
priority: CedarProcess.Priority ← CedarProcess.GetPriority[];
rulesParameters: Route.DesignRulesParameters = Route.DefaultDesignRulesParameters[
technologyHint: technologyKey,
horizLayer: horizLayer,
vertLayer: vertLayer,
trunkDirection: horizontal];
intermediateResult: Route.IntermediateResult;
nets: SymTab.Ref ← SymTab.Create[]; -- Label -> NetInfo
FOR side: Side
IN Side
DO
FOR pins: WirePins ← pinAry[side], pins.rest
WHILE pins#
NIL
DO
netInfo: NetInfo ← FetchNetInfo[nets, root, pins.first.wire];
netInfo.pins ← CONS [[side, pins.first.min, pins.first.max, pins.first.layer], netInfo.pins];
IF pins.first.wire.size#0 THEN ERROR ENDLOOP ENDLOOP;
CedarProcess.CheckAbort[];
CedarProcess.SetPriority[background];
DO
ENABLE Route.Signal => {
TerminalIO.PutF["*** Route switchBox %g preliminary warning:\n %g\n",
IO.rope[name], IO.rope[explanation]];
IF explanation.Find["Multiple channel exits"]#-1
AND
rulesParameters.trunkDirection=horizontal
THEN {
TerminalIO.PutRope[" Will try again using vertical trunk.\n"];
rulesParameters.trunkDirection ← vertical; LOOP}
ELSE RESUME};
intermediateResult ← Route.SwitchBoxRoute[
name: name,
enumerateNets: EnumerateSwitchBoxNets,
routingRect: routingRect,
rulesParameters: rulesParameters,
rules: Route.DefaultDesignRules[rulesParameters],
enumerateObstructions: NIL,
signalSinglePinNets: FALSE,
signalCoincidentPins: FALSE,
okToDiddleLLPins: FALSE,
okToDiddleURPins: FALSE,
optimization: IF fastRoute THEN noIncompletes ELSE full,
switchBoxData: nets ];
EXIT ENDLOOP;
CedarProcess.CheckAbort[];
IF intermediateResult=NIL THEN ERROR;
switchBox ← Route.SwitchBoxRetrieve[intermediateResult ! Route.Signal => {
TerminalIO.PutF["*** Route switchBox %g final warning:\n %g\n",
IO.rope[name], IO.rope[explanation]];
RESUME} ].object;
IF switchBox=NIL THEN ERROR;
CedarProcess.SetPriority[priority]};
FetchNetInfo:
PROC[nets: SymTab.Ref, root, wire: Wire]
RETURNS[netInfo: NetInfo] = {
label: Route.Label = CoreRoute.LabelInternal[root, wire];
rw: REF INT = NARROW [CoreProperties.GetWireProp[wire, wireWidthProp]];
netInfo ← NARROW [SymTab.Fetch[nets, label].val];
IF netInfo#NIL THEN RETURN;
netInfo ← NEW [NetInfoRec ← [trunkSize: IF rw=NIL THEN 0 ELSE rw^*lambda]];
[] ← SymTab.Store[nets, label, netInfo]};
EnumerateSwitchBoxNets: Route.EnumerateSwitchBoxNetsProc = {
nets: SymTab.Ref = NARROW [switchBoxData];
EachNet: SymTab.EachPairAction = {
label: Route.Label = key;
netInfo: NetInfo = NARROW[val];
eachNet[
name: label,
enumeratePins: EnumerateSwitchBoxPins,
trunkSize: netInfo.trunkSize,
switchBoxData: NIL,
netData: netInfo]};
[] ← SymTab.Pairs[nets, EachNet]};
EnumerateSwitchBoxPins: Route.EnumerateSwitchBoxPinsProc = {
netInfo: NetInfo = NARROW [netData];
FOR pins:
LIST
OF PinInfo ← netInfo.pins, pins.rest
WHILE pins#
NIL
DO
pin: PinInfo = pins.first;
eachPin[
side: pin.side,
min: pin.min,
max: pin.max,
layer: pin.layer] ENDLOOP };