Layout: PWCore.LayoutProc ~ {
data: CoreClasses.RecordCellType ← NARROW[cellType.data];
spec: DP.DPSpec ← NewCellTypeSpec[cellType];
interleave: BOOL ← CoreProperties.GetCellTypeProp[cellType, $DataPathInterleave]#NIL;
refPolyBits:
REF
INT ←
NARROW
[CoreProperties.GetCellTypeProp[cellType, $ChanPolyBits]];
schIR: CD.Rect ← [x1: LAST[INT], x2: FIRST[INT], y1: LAST[INT], y2: FIRST[INT]];
xIntervals: DP.Intervals ← NIL;
yIntervals: DP.Intervals ← NIL;
yIntervalsCh: DP.Intervals ← NIL;
colBuss: NAT ← spec.buses*spec.schBusW;
count: NAT ← 0;
nofRows: NAT ← 0;
nofCols: NAT ← 0;
row: NAT ← 0;
col: NAT ← 0;
dp: DP.Form ← NIL;
loc: CD.Position;
size: CD.Position;
spec.n ← GetSize[data[0].type];
spec.cols ← 0;
spec.interleave ← interleave;
spec.chPolyBits ← IF refPolyBits#NIL THEN refPolyBits^ ELSE 0;
Build Interval Lists
TerminalIO.PutF["Layout %g\n", IO.rope[CoreOps.GetCellTypeName[cellType]]];
FOR child:
NAT
IN [0..data.size)
DO
width: INT ← spec.schDWidth+colBuss;
exposedBusses: INT;
[loc, size] ← LocSize[data.instances[child]];
exposedBusses ← (width-size.x+slop)/spec.schBusW; -- icons must be correct width
xIntervals ← InsertInterval[[loc.x-exposedBusses*spec.schBusW, width], xIntervals];
yIntervals ← InsertInterval[[loc.y, size.y], yIntervals];
ENDLOOP;
yIntervalsCh ← FindChIntervals[spec, cellType, yIntervals];
Examine Interval Lists
FOR list:
DP.Intervals ← yIntervals, list.rest
WHILE list#
NIL
DO
nofRows ← nofRows+1;
schIR.y1 ← MIN[schIR.y1, list.first.loc]; schIR.y2 ← MAX[schIR.y2, list.first.loc + list.first.size];
IF list.rest#
NIL
AND list.first.loc + list.first.size > list.rest.first.loc
THEN Signal[
IO.PutFR["Rows %g and %g Overlap\n", IO.int[nofRows], IO.int[nofRows+1]]] ENDLOOP;
FOR list:
DP.Intervals ← yIntervalsCh, list.rest
WHILE list#
NIL
DO
nofRows ← nofRows+1;
schIR.y1 ← MIN[schIR.y1, list.first.loc]; schIR.y2 ← MAX[schIR.y2, list.first.loc + list.first.size];
IF list.rest#NIL AND list.first.loc + list.first.size > list.rest.first.loc THEN Signal[] ENDLOOP;
FOR list:
DP.Intervals ← xIntervals, list.rest
WHILE list#
NIL
DO
nofCols ← nofCols+1;
schIR.x1 ← MIN[schIR.x1, list.first.loc]; schIR.x2 ← MAX[schIR.x2, list.first.loc + list.first.size];
IF list.rest#NIL AND list.first.loc + list.first.size > list.rest.first.loc THEN Signal[] ENDLOOP;
Build dp: DataPath, row - column array
dp ← NEW[DP.RowSeqRec[nofRows]];
dp.schIR ← schIR;
dp.cell ← cellType;
dp.spec ← spec;
dp.wpo ← RefTab.Create[];
IF dp.spec.cols#0 AND dp.spec.cols#nofCols THEN Signal[];
dp.spec.cols ← nofCols;
FOR row
IN [0..dp.size)
DO
sb: BOOL ← yIntervals=NIL OR yIntervalsCh#NIL AND yIntervalsCh.first.loc<yIntervals.first.loc;
dp[row] ← NEW[DP.ColSeqRec[nofCols]];
dp[row].schIR ← dp.schIR;
IF sb
THEN {
dp[row].ch ← RefTab.Create[];
dp[row].schIR.y1 ← yIntervalsCh.first.loc;
dp[row].schIR.y2 ← yIntervalsCh.first.loc + yIntervalsCh.first.size;
yIntervalsCh ← yIntervalsCh.rest}
ELSE {
dp[row].schIR.y1 ← yIntervals.first.loc;
dp[row].schIR.y2 ← yIntervals.first.loc + yIntervals.first.size;
yIntervals ← yIntervals.rest};
col ← 0;
FOR xlist:
DP.Intervals ← xIntervals, xlist.rest
WHILE xlist#
NIL
DO
dp[row][col].schIR.x1 ← xlist.first.loc;
dp[row][col].schIR.x2 ← xlist.first.loc + xlist.first.size;
dp[row][col].schIR.y1 ← dp[row].schIR.y1;
dp[row][col].schIR.y2 ← dp[row].schIR.y2;
IF ~sb THEN dp[row][col].wpo ← RefTab.Create[];
col ← col+1 ENDLOOP;
ENDLOOP;
Find section instances
FOR child:
NAT
IN [0..data.size)
DO
[loc, size] ← LocSize[data.instances[child]];
FOR row
DECREASING
IN [0..dp.size)
DO
IF dp[row].schIR.y1 <= loc.y THEN EXIT REPEAT FINISHED => Signal[] ENDLOOP;
FOR col
DECREASING
IN [0..dp[row].size)
DO
IF dp[row][col].schIR.x1 <= loc.x THEN EXIT REPEAT FINISHED => Signal[] ENDLOOP;
IF dp[row][col].schInst#NIL THEN Signal[];
dp[row][col].schInst ← data.instances[child];
IF (SchHalfBus[spec, loc.x - dp[row][col].schIR.x1] MOD 2) # 0 THEN Signal[];
dp[row][col].devBOff ← SchHalfBus[spec, loc.x - dp[row][col].schIR.x1]/2;
ENDLOOP;
ShowDP[dp];
Make Device Layouts
FOR row
IN [0..dp.size)
DO
IF dp[row].ch=
NIL
THEN
FOR col
IN [0..dp[row].size)
DO
IF dp[row][col].schInst=NIL THEN LOOP;
dp[row][col].devCells ← GetDeviceCellTypes[dp[row][col].schInst];
dp[row].layY.size ← CDBasics.SizeOfRect[PWCore.InterestRect[dp[row][col].devCells[0]]].y
ENDLOOP ENDLOOP;
Make Channel Layouts
AddExplicitRoutingChannel[dp];
AddImplicitRoutingChannel[dp];
FOR row IN [0..dp.size) DO IF dp[row].ch#NIL THEN DP.BuildChan[dp, row] ENDLOOP;
Set Layout IR
FOR row
IN [1..dp.size)
DO
dp[row].layY.loc ← dp[row-1].layY.loc+dp[row-1].layY.size ENDLOOP;
dp.layIR ← [
x1: 0, x2: BitWidth[dp.spec]*dp.spec.cols*dp.spec.n,
y1: 0, y2: dp[dp.size-1].layY.loc+dp[dp.size-1].layY.size ];
Make Device Wiring Layouts then Complete Layout
AddExplicitRoutingSwitchBox[dp];
AddImplicitRoutingSwitchBox[dp];
AddExplicitDecorations[dp];
AddImplicitDecorations[dp];
obj ← dp.obj ← AssembleObject[dp];
TerminalIO.PutF["\nLayout %g\n", IO.rope[CoreOps.GetCellTypeName[dp.cell]]];
TerminalIO.PutF[" %g transistors\n", IO.int[CountTransistors[dp.cell]]];
ShowDP[dp];
TerminalIO.PutF["Layout Size (CMosB.lambda) x: %g y: %g xy: %g\n",
IO.int[CD.InterestSize[obj].x/CMosB.lambda],
IO.int[CD.InterestSize[obj].y/CMosB.lambda],
IO.int[(CD.InterestSize[obj].x/CMosB.lambda)*(CD.InterestSize[obj].y/CMosB.lambda)] ]};