DIRECTORY
AlpsBool, AlpsPWGen, AlpsTile,
Buttons,
CD, CDAbuts, CDCells, CDDirectory, CDMenus, CDOps, CDOrient, CDPinObjects, CDProperties, CDRects, CDSequencer, CDX,
CMos, CMosContacts, CMosTransistors,
Commander, Convert,
PWPins,
RefTab, Rope, TerminalIO, ViewerClasses;
AlpsPWGenImpl:
CEDAR
PROGRAM
IMPORTS AlpsBool, AlpsTile, CDAbuts, CDCells, CDDirectory, CDOps, CDPinObjects, CDProperties, CDRects, CDX, CMos, CMosContacts, CMosTransistors, Convert, PWPins, RefTab, Rope
EXPORTS AlpsPWGen =
BEGIN
OPEN AlpsPWGen;
Tile: TYPE = AlpsTile.Tile;
TileArray: TYPE = AlpsTile.TileArray;
Utilities
ROPE: TYPE = Rope.ROPE;
Output: PROC [t1, t2, t3, t4, t5, t6: ROPE ← NIL] = AlpsBool.Output;
Break: PROC [] = {}; -- Useful for context.debugging
Always useful ...
Reverse:
PROC [list:
LIST
OF
CD.ObPtr]
RETURNS [newList:
LIST
OF
CD.ObPtr ←
NIL] =
{WHILE list#NIL DO newList ← CONS [list.first, newList]; list ← list.rest ENDLOOP};
Geometry generation
sizeY: INT = 48;
sizeTransN: INT = 10;
IncludeOb:
PROC [cell, subcell:
CD.ObPtr, location:
CD.Position ← [0, 0], orientation:
CD.Orientation ←
CD.combined]
RETURNS [newApp:
CD.ApplicationPtr] = {
newApp ←
CDX.IncludeOb[
design: NIL, cell: cell, ob: subcell, position: location, orientation: orientation,
cellCSystem: interrestCoords, obCSystem: interrestCoords, mode: dontPropagate
].newApp
};
IncludePin:
PROC [cell:
CD.ObPtr, layer:
CD.Layer, name:
ROPE, size, pos:
CD.Position] = {
pinApp: CD.ApplicationPtr ← IncludeOb[cell, CDPinObjects.CreatePinOb[size], pos];
CDPinObjects.SetName[pinApp, name]; CDPinObjects.SetLayer[pinApp, layer];
};
IncludeRect:
PROC [cell:
CD.ObPtr, layer:
CD.Layer, size, pos:
CD.Position, name:
ROPE ←
NIL] = {
appl: CD.ApplicationPtr ← IncludeOb[cell, CDRects.CreateRect[size, layer], pos];
IF name#NIL THEN CDProperties.PutPropOnApplication[onto: appl, prop: $SignalName, val: name];
};
IncludeContactPoly:
PROC [cell:
CD.ObPtr, pos:
CD.Position] = {
[] ← IncludeRect[cell, CMos.pol, [10, 10], pos];
[] ← IncludeOb[cell, CMosContacts.CreatePolyCon[8], [pos.x+1, pos.y+1]];
};
IncludeContactDiff:
PROC [cell:
CD.ObPtr, pos:
CD.Position] = {
[] ← IncludeRect[cell, CMos.ndif, [10, 10], pos];
[] ← IncludeOb[cell, CMosContacts.CreateDifCon[8], [pos.x+1, pos.y+1]];
};
IncludeContactMetal2:
PROC [cell:
CD.ObPtr, pos:
CD.Position] = {
[] ← IncludeOb[cell, CMosContacts.CreateMmCon[10], pos];
};
IncludeButtingContact:
PROC [cell:
CD.ObPtr, pos:
CD.Position] = {
[] ← IncludeOb[cell, CMosContacts.CreateButCon[], pos];
};
IncludeTransN:
PROC [cell:
CD.ObPtr, pos:
CD.Position] = {
[] ← IncludeOb[cell, CMosTransistors.CreateTransistor[sizeTransN, 4], pos, CDOrient.rotate90];
};
Does NOT include in directory
Reposition:
PROC [cell:
CD.ObPtr, sizeX:
INT] = {
IF NARROW[cell.specificRef, CD.CellPtr].contents=NIL THEN IncludePin[cell, CMos.met2, "JustForAvoidingEmptyCell", [4, 4], [(sizeX-4)/2, (sizeY-4)/2]];
CDCells.SetInterestRect[cell, [0, 0, sizeX, sizeY]];
[] ← CDCells.RepositionCell[cell, NIL];
};
CellFromTile:
PUBLIC
PROC [context: AlpsTile.Context, tile: Tile]
RETURNS [cell:
CD.ObPtr] = {
found: BOOL; val: RefTab.Val;
[found, val] ← RefTab.Fetch[context.computedCells, tile];
SELECT
TRUE
FROM
found => RETURN[NARROW[val]];
tile.special => {
cell ← CDDirectory.Fetch[context.design, tile.name].object;
IF cell=NIL THEN ERROR; -- cell missing!
};
tile.input => {
cell ← CDCells.CreateEmptyCell[];
IF (~(tile.high AND tile.throughTrans) AND tile.leftPin) THEN IncludeRect[cell, CMos.met, [14, 6], [0, 36]];
IF (~(tile.high AND tile.throughTrans) AND tile.rightPin) THEN IncludeRect[cell, CMos.met, [14, 6], [4 , 36]];
IncludeRect[cell, CMos.met, [18, 12], [0, 18]]; IncludePin[cell, CMos.met, "Gnd", [4, 12], [0, 18]]; IncludePin[cell, CMos.met, "Gnd", [4, 12], [14, 18]];
IF (~(tile.low AND tile.throughTrans) AND tile.leftPin) THEN IncludeRect[cell, CMos.met, [14, 6], [0, 6]];
IF (~(tile.low AND tile.throughTrans) AND tile.rightPin) THEN IncludeRect[cell, CMos.met, [14, 6], [4, 6]];
IncludePin[cell, CMos.met2, IF tile.leftSide THEN "Input" ELSE "NotInput", [8, 4], [5, sizeY-4]];
IncludePin[cell, CMos.pol, IF tile.leftSide THEN "InputPoly" ELSE "NotInputPoly", [4, 4], [7, sizeY-4]];
IncludePin[cell, CMos.met2, IF tile.leftSide THEN "Input" ELSE "NotInput", [8, 4], [5, 0]];
IncludePin[cell, CMos.pol, IF tile.leftSide THEN "InputPoly" ELSE "NotInputPoly", [4, 4], [7, 0]];
IncludeRect[cell, CMos.pol, [4, sizeY], [7, 0]];
IncludeRect[cell, CMos.met2, [8, sizeY], [5, 0]];
IF (tile.throughTrans
OR tile.gndTrans)
AND tile.high
THEN {
IncludeTransN[cell, [3, 31]];
IncludeContactDiff[cell, [IF tile.leftSide THEN -5 ELSE 13, 35]];
IF tile.throughTrans THEN IncludeContactDiff[cell, [IF tile.leftSide THEN 13 ELSE -5, 35]] ELSE IncludeRect[cell, CMos.ndif, [10, 18], [IF tile.leftSide THEN 13 ELSE -5, 27]];
};
IF (tile.throughTrans
OR tile.gndTrans)
AND tile.low
THEN {
IncludeTransN[cell, [3, -1]];
IncludeContactDiff[cell, [IF tile.leftSide THEN -5 ELSE 13, 3]];
IF tile.throughTrans THEN IncludeContactDiff[cell, [IF tile.leftSide THEN 13 ELSE -5, 3]] ELSE IncludeRect[cell, CMos.ndif, [10, 18], [IF tile.leftSide THEN 13 ELSE -5, 3]];
};
We can always put those contacts to Gnd when gndTrans
IF tile.gndTrans THEN IncludeContactDiff[cell, [IF tile.leftSide THEN 13 ELSE -5, 19]];
IF tile.contact AND tile.high THEN IncludeContactPoly[cell, [5, 35]];
IF tile.contact AND tile.low THEN IncludeContactPoly[cell, [5, 3]];
Reposition[cell, 18];
[] ← CDDirectory.Include[context.design, cell, "@AlpsInputTile"];
};
tile.route => {
sizeX: INT = 36;
cell ← CDCells.CreateEmptyCell[];
IF ~tile.noLeftMetal THEN IncludeRect[cell, CMos.met, [25, 6], [0, 36]];
IF ~tile.noRightMetal THEN IncludeRect[cell, CMos.met, [25, 6], [11, 36]];
IncludeRect[cell, CMos.met, [sizeX, 12], [0, 18]]; IncludePin[cell, CMos.met, "Gnd", [4, 12], [0, 18]]; IncludePin[cell, CMos.met, "Gnd", [4, 12], [sizeX-4 , 18]];
IF ~tile.noLeftMetal THEN IncludeRect[cell, CMos.met, [25, 6], [0, 6]];
IF ~tile.noRightMetal THEN IncludeRect[cell, CMos.met, [25, 6], [11, 6]];
IF ~tile.noUpPoly THEN {IncludeRect[cell, CMos.pol, [4, sizeY-6], [7, 6]]; IncludeRect[cell, CMos.pol, [4, sizeY-6], [25, 6]]};
IF ~tile.noDownPoly THEN {IncludeRect[cell, CMos.pol, [4, sizeY-6], [7, 0]]; IncludeRect[cell, CMos.pol, [4, sizeY-6], [25, 0]]};
The metal2 and the connection to Gnd is justy a bonus
IncludePin[cell, CMos.met2, "Gnd", [22, 4], [7, 0]];
IncludePin[cell, CMos.met2, "Gnd", [22, 4], [7, sizeY-4]];
IncludeRect[cell, CMos.met2, [22, sizeY], [7, 0]];
IncludeContactMetal2[cell, [13, 19]];
IF tile.contactPoly THEN {IncludeContactPoly[cell, [7, IF tile.spin THEN 35 ELSE 3]]; IncludeContactPoly[cell, [19, IF tile.spin THEN 3 ELSE 35]]};
Reposition[cell, sizeX];
[] ← CDDirectory.Include[context.design, cell, "@AlpsRouteTile"];
};
ENDCASE => ERROR;
[] ← RefTab.Store[context.computedCells, tile, cell];
IF cell=NIL THEN ERROR;
};
CellsFromTiles:
PUBLIC
PROC [context: AlpsTile.Context, tiles:
LIST
OF Tile]
RETURNS [cells:
LIST
OF
CD.ObPtr ←
NIL] = {
WHILE tiles#
NIL
DO
cells ← CONS [CellFromTile[context, tiles.first], cells]; tiles ← tiles.rest ENDLOOP;
cells ← Reverse[cells];
};
Columns: TYPE = [0 .. 1000]; -- ?!?!?!
TilesRows: TYPE = REF TilesRowsRec;
TilesRowsRec:
TYPE =
RECORD [
contents: SEQUENCE size: Columns OF LIST OF Tile]; -- from left to right
Row: TYPE = REF RowRec;
RowRec:
TYPE =
RECORD [
contents: SEQUENCE size: Columns OF Tile]; -- from left to right, from LeftVdd to Self
TileArrayToTilesRows:
PROC [context: AlpsTile.Context]
RETURNS [tileRows: TilesRows, emptyRow: Row, nullRouteRow: Row] = {
size, nb: Columns ← 0;
FOR i: AlpsBool.VarNb
IN [0 .. context.tileArray.lastPosNb)
DO
Output[" ", Convert.RopeFromInt[i], ": "];
FOR horTileType: AlpsTile.HorTileType
IN AlpsTile.HorTileType
DO
IF context.tileArray[i][horTileType]#NIL THEN {size ← size+1; Output["."]};
ENDLOOP;
ENDLOOP;
Output["\n", Convert.RopeFromInt[size], " useful columns.\n"];
tileRows ← NEW [TilesRowsRec[size]]; emptyRow ← NEW [RowRec[size]];
FOR i: AlpsBool.VarNb
IN [0 .. context.tileArray.lastPosNb)
DO
FOR horTileType: AlpsTile.HorTileType
IN AlpsTile.HorTileType
DO
IF context.tileArray[i][horTileType]#
NIL
THEN {
tileRows[nb] ← context.tileArray[i][horTileType];
emptyRow[nb] ← AlpsTile.
TILE[
SELECT horTileType
FROM
RightRoute => [route: TRUE, noUpPoly: TRUE, noDownPoly: TRUE, noLeftMetal: TRUE, noRightMetal: TRUE, leftPin: FALSE, rightPin: FALSE],
LeftInput => [input: TRUE, leftSide: TRUE, leftPin: FALSE, rightPin: FALSE],
RightInput => [input: TRUE, leftPin: FALSE, rightPin: FALSE],
VddGlue => [special: TRUE, name: IF nb=size-1 AND context.isLatched THEN "LatchNull" ELSE "NullVddGlue"],
GndGlue => [special: TRUE, name: "NullGndGlue"],
ENDCASE => ERROR];
nb ← nb + 1;
};
ENDLOOP;
ENDLOOP;
IF nb#size THEN ERROR;
RedundancyCheck[context, tileRows];
};
MakeCellInCaseOfError:
PROC [context: AlpsTile.Context, tileRows: TilesRows]
RETURNS [cell:
CD.ObPtr] = {
columns: LIST OF CD.ObPtr ← NIL;
FOR i: Columns
DECREASING
IN [0..tileRows.size)
DO
columns ← CONS[CDAbuts.CreateNewAbutY[CellsFromTiles[context, tileRows[i]]], columns];
ENDLOOP;
cell ← CDAbuts.CreateNewAbutX[columns];
};
RedundancyCheck:
PROC [context: AlpsTile.Context, tileRows: TilesRows] = {
Some redundancy check
size: Columns ← tileRows.size;
FOR i: Columns IN [0 .. size) DO
upDownMetal: INT ← IF tileRows[i]#NIL AND tileRows[i].first.downMetal THEN 1 ELSE 0;
FOR list: LIST OF Tile ← tileRows[i], list.rest WHILE list#NIL DO
tile: Tile ← list.first;
IF tile.upMetal THEN upDownMetal ← upDownMetal + 1;
IF tile.downMetal THEN upDownMetal ← upDownMetal - 1;
ENDLOOP;
IF upDownMetal#0 THEN {
cell: CD.ObPtr ← MakeCellInCaseOfError[context, tileRows];
CDOps.AddAnObject[context.design, cell, [0, 0]];
Output["Mismatch of pins in column ", Convert.RopeFromInt[i]]; ERROR;
};
ENDLOOP;
FOR i: Columns
IN (0 .. size)
DO
leftPins, rightPins: INT ← 0;
FOR list:
LIST
OF Tile ← tileRows[i-1], list.rest
WHILE list#
NIL
DO
tile: Tile ← list.first;
IF tile.rightPin THEN rightPins ← rightPins + 1;
ENDLOOP;
FOR list:
LIST
OF Tile ← tileRows[i], list.rest
WHILE list#
NIL
DO
tile: Tile ← list.first;
IF tile.leftPin THEN leftPins ← leftPins + 1;
ENDLOOP;
IF leftPins#rightPins
THEN {
cell: CD.ObPtr ← MakeCellInCaseOfError[context, tileRows];
CDOps.AddAnObject[context.design, cell, [0, 0]];
Output["Mismatch of pins between columns right ", Convert.RopeFromInt[i-1], " and next left\n"]; ERROR;
};
ENDLOOP;
};
TilesRowsToListOfRows:
PROC [context: AlpsTile.Context, tileRows: TilesRows, emptyRow: Row]
RETURNS [rowsOfTiles:
LIST
OF Row ←
NIL] = {
ATTENTION, rowsOfTiles is from top to bottom
posx: INT ← 0; posy: INT ← 0;
size: Columns ← emptyRow.size;
DO
fillHappened: BOOL ← FALSE; allEmpty: BOOL ← TRUE;
previousI: Columns; previousTile: Tile ← NIL;
FOR i: Columns
IN [0 .. size)
DO
FillColumn:
PROC [i: Columns, tile: Tile] = {
Output["*"];
fillHappened ← TRUE;
SELECT
TRUE
FROM
tile.special => {
name:
ROPE ←
SELECT
TRUE
FROM
Rope.Equal[tile.name, "LatchReceive"] => "LatchNull",
Rope.Equal[tile.name, "LatchSend"] => "LatchNull",
Rope.Equal[tile.name, "LatchNull"] => "LatchNull",
Rope.Equal[tile.name, "LatchSimple"] => "LatchNull",
Rope.Equal[tile.name, "AuxReceive"] => "LatchNull",
Rope.Equal[tile.name, "AuxSend"] => "LatchNull",
Rope.Equal[tile.name, "CascodeVddGlue"] => "NullVddGlue",
Rope.Equal[tile.name, "ThroughVddGlue"] => "NullVddGlue",
Rope.Equal[tile.name, "NullVddGlue"] => "NullVddGlue",
Rope.Equal[tile.name, "CascodeGndGlue"] => "NullGndGlue",
Rope.Equal[tile.name, "ThroughGndGlue"] => "NullGndGlue",
Rope.Equal[tile.name, "NullGndGlue"] => "NullGndGlue",
ENDCASE => ERROR;
tileRows[i] ← CONS [AlpsTile.TILE[[special: TRUE, name: name]], tileRows[i]];
};
tile.input => {
tileRows[i] ← CONS [AlpsTile.TILE[[input: TRUE, leftSide: tile.leftSide, leftPin: FALSE, rightPin: FALSE]], tileRows[i]];
};
tile.route => {
tileRows[i] ← CONS [AlpsTile.TILE[[route: TRUE, noUpPoly: tile.noDownPoly, noDownPoly: tile.noDownPoly, noLeftMetal: TRUE, noRightMetal: TRUE, leftPin: FALSE, rightPin: FALSE]], tileRows[i]];
};
ENDCASE => ERROR;
};
tile: Tile;
IF tileRows[i]=
NIL
THEN tileRows[i] ← LIST[emptyRow[i]]
ELSE allEmpty ← FALSE;
tile ← tileRows[i].first;
Output[" ", Convert.RopeFromInt[i]];
IF previousTile#
NIL
AND ~previousTile.rightPin
AND tile.leftPin
THEN {FillColumn[i, tile]; tile ← tileRows[i].first};
IF previousTile#
NIL
AND previousTile.rightPin
AND ~tile.leftPin
THEN FillColumn[previousI, previousTile];
previousI ← i; previousTile ← tile;
ENDLOOP;
IF allEmpty THEN EXIT;
RedundancyCheck[context, tileRows];
IF ~fillHappened
THEN {
copy bottom row
newRow: Row ← NEW [RowRec[size]];
Output["|"];
FOR i: Columns
IN [0 .. size)
DO
newRow[i] ← tileRows[i].first; tileRows[i] ← tileRows[i].rest;
ENDLOOP;
rowsOfTiles ← CONS [newRow, rowsOfTiles];
};
ENDLOOP;
};
Modifies the array of cells for adding all cells due to the insert of an expr.
TileArrayToGeometry:
PUBLIC
PROC [context: AlpsTile.Context]
RETURNS [cell:
CD.ObPtr ←
NIL] =
BEGIN
shortRouteRow: REF RouteRowBools;
RouteRowBools: TYPE = RECORD [contents: PACKED SEQUENCE size: Columns OF BOOL]; -- TRUE means a short Route
tileRows: TilesRows;
emptyRow: Row;
rowsOfTiles: LIST OF Row ← NIL; -- from top to bottom
listOfCells: LIST OF CD.ObPtr ← NIL;
posx: INT ← 0; posy: INT ← 0;
size: Columns;
top, bottom, left, right: BOOL ← FALSE;
contacts: CD.ObPtr;
distSinceLastContacts: INT ← 0;
outputNames: LIST OF ROPE ← NIL; -- a times the name of each output
FOR outs:
LIST
OF AlpsBool.OutputRef ← context.table.outputs, outs.rest
WHILE outs#
NIL
DO
name: ROPE ← outs.first.name;
outputNames ← CONS[name, CONS[name, CONS[name, CONS[name, outputNames]]]];
ENDLOOP;
context.computedCells ← RefTab.Create[]; -- for remembering computed cells
[tileRows, emptyRow] ← TileArrayToTilesRows[context];
size ← emptyRow.size;
rowsOfTiles ← TilesRowsToListOfRows[context, tileRows, emptyRow];
We find which Route columns can be contracted into 4 lambdas wide filler
shortRouteRow ← NEW[RouteRowBools[size]];
FOR i: Columns IN [0 .. size) DO shortRouteRow[i] ← TRUE ENDLOOP;
FOR rows:
LIST
OF Row ← rowsOfTiles, rows.rest
WHILE rows#
NIL
DO
FOR i: Columns
IN [0 .. size)
DO
tile: AlpsTile.Tile ← rows.first[i];
IF ~tile.route OR ~tile.noDownPoly OR ~tile.noUpPoly THEN shortRouteRow[i] ← FALSE;
ENDLOOP;
ENDLOOP;
FOR i: Columns IN [0 .. size) DO IF shortRouteRow[i] THEN Output["$"] ENDLOOP;
Generation of the contacts cell
IF rowsOfTiles#
NIL
THEN {
listOfContacts: LIST OF CD.ObPtr ← NIL;
thisRow: Row ← rowsOfTiles.first;
FOR i: Columns
DECREASING
IN [0 .. size)
DO
thisTile: AlpsTile.Tile ← thisRow[i];
tile: AlpsTile.Tile ←
SELECT
TRUE
FROM
shortRouteRow[i] => AlpsTile.TILE[[special: TRUE, name: "ContactFiller"]],
thisTile.route => AlpsTile.TILE[[special: TRUE, name: "ContactRoute"]],
thisTile.input => AlpsTile.TILE[[special: TRUE, name: "ContactInput"]],
Rope.Equal[thisTile.name, "BigCascodeVddGlue"] OR Rope.Equal[thisTile.name, "CascodeVddGlue"] OR Rope.Equal[thisTile.name, "ThroughVddGlue"] OR Rope.Equal[thisTile.name, "NullVddGlue"] => AlpsTile.TILE[[special: TRUE, name: "ContactVddGlue"]],
Rope.Equal[thisTile.name, "CascodeGndGlue"] OR Rope.Equal[thisTile.name, "ThroughGndGlue"] OR Rope.Equal[thisTile.name, "NullGndGlue"] => AlpsTile.TILE[[special: TRUE, name: "ContactGndGlue"]],
ENDCASE => AlpsTile.TILE[[special: TRUE, name: "ContactLatch"]];
listOfContacts ← CONS [CellFromTile[context, tile], listOfContacts];
ENDLOOP;
contacts ← CDAbuts.CreateNewAbutX[listOfContacts];
[] ← CDDirectory.Include[context.design, contacts, "@Contacts"];
};
Generation of the abuts in X
Output["\nGeneration of Abuts...\n"];
FOR theseRowsOfTiles:
LIST
OF Row ← rowsOfTiles, theseRowsOfTiles.rest
WHILE theseRowsOfTiles#
NIL
DO
thisRow: Row ← theseRowsOfTiles.first;
rowCells: LIST OF CD.ObPtr ← NIL;
rowCellsAbut: CD.ObPtr;
index, notIndex: INT ← context.table.size*4; -- hack because 4 pins of each name ...
top ← theseRowsOfTiles=rowsOfTiles; bottom ← theseRowsOfTiles.rest=NIL;
FOR i: Columns
DECREASING
IN [0 .. size)
DO
Rename: PWPins.RenameProc
-- [oldRope: ROPE] RETURNS [newRope: ROPE] -- = {
SELECT
TRUE
FROM
(right
OR left)
AND Rope.Equal[oldRope, "Output"] => {
newRope ← outputNames.first;
outputNames ← outputNames.rest;
};
(right
OR left)
AND Rope.Equal[oldRope, "OutputPoly"] => {
newRope ← Rope.Cat[outputNames.first, "Poly"];
outputNames ← outputNames.rest;
};
(right
OR left)
AND Rope.Equal[oldRope, "NotOutput"] => {
newRope ← Rope.Cat["Not", outputNames.first];
outputNames ← outputNames.rest;
};
(right
OR left)
AND Rope.Equal[oldRope, "NotOutputPoly"] => {
newRope ← Rope.Cat["Not", outputNames.first, "Poly"];
outputNames ← outputNames.rest;
};
(top
OR bottom)
AND Rope.Equal[oldRope, "Input"] => {
IF ~tile.input OR ~tile.leftSide THEN ERROR;
index ← index-1;
newRope ← Rope.Cat[context.table[index/4].name];
};
(top
OR bottom)
AND Rope.Equal[oldRope, "NotInput"] => {
IF ~tile.input OR tile.leftSide THEN ERROR;
notIndex ← notIndex-1;
newRope ← Rope.Cat["Not", context.table[notIndex/4].name];
};
(top
OR bottom)
AND Rope.Equal[oldRope, "InputPoly"] => {
IF ~tile.input OR ~tile.leftSide THEN ERROR;
index ← index-1;
newRope ← Rope.Cat[context.table[index/4].name, "Poly"];
};
(top
OR bottom)
AND Rope.Equal[oldRope, "NotInputPoly"] => {
IF ~tile.input OR tile.leftSide THEN ERROR;
notIndex ← notIndex-1;
newRope ← Rope.Cat["Not", context.table[notIndex/4].name, "Poly"];
};
ENDCASE => newRope ← oldRope;
};
tile: AlpsTile.Tile ←
IF shortRouteRow[i]
THEN AlpsTile.TILE[[special: TRUE, name: IF thisRow[i].noLeftMetal THEN "EmptyRouteFiller" ELSE "RouteFiller"]]
ELSE thisRow[i];
thisCell: CD.ObPtr ← CellFromTile[context, tile];
left ← i=0; right ← i=size-1;
IF left
OR right
OR top
OR bottom
THEN thisCell ← PWPins.RenamePins[context.design, thisCell, Rename];
IF ABS [index - notIndex] > 4 THEN ERROR;
rowCells ← CONS [thisCell, rowCells];
ENDLOOP;
IF distSinceLastContacts>=context.distanceBetweenContacts
THEN {
distSinceLastContacts ← 0;
listOfCells ← CONS [contacts, listOfCells];
} ELSE distSinceLastContacts ← distSinceLastContacts+1;
rowCellsAbut ← CDAbuts.CreateNewAbutX[rowCells];
[] ← CDDirectory.Include[context.design, rowCellsAbut, "@AlpsRow"];
listOfCells ← CONS [rowCellsAbut, listOfCells];
ENDLOOP;
Just in case, the AbutX won't work, we add them in the context.design
posx ← posy ← 0;
FOR list: LIST OF CD.ObPtr ← listOfCells, list.rest WHILE list#NIL DO
CDOps.AddAnObject[context.design, list.first, [posx, posy]]; posy ← posy + CD.InterestRect[list.first].y2;
ENDLOOP;
We compute the AbutY, at least, and grasp the top level pins
cell ← CDAbuts.CreateNewAbutY[listOfCells];
[] ← CDDirectory.Include[context.design, cell, "@AlpsResult"];
cell ← PWPins.RenamePins[context.design, cell];
Output["Done!\n"];
END;
This one is the only one clients have to know
TableToLayout:
PUBLIC PROC [context: AlpsTile.Context]
RETURNS [cell:
CD.ObPtr] = {
Output["\nLet's start Layout!"];
AlpsTile.TableAndPositionToTileArray[context];
Output["Generation of the TileArray finished\n"];
cell ← TileArrayToGeometry[context];
};
END.