DIRECTORY
AlpsBool, AlpsHeur, AlpsTile, AlpsPWGen, CD, CDCells, CDDirectory, CDExtras, CDPinObjects, CDIO, CMos, Convert, MC, MCCtl, PW, PWCmos, PWPins, Rope;
MCCtlImpl:
CEDAR
PROGRAM
IMPORTS AlpsBool, AlpsHeur, AlpsPWGen, CD, CDCells, CDDirectory, CDExtras, CDPinObjects, CDIO, Convert, CMos, MC, PW, PWPins, Rope
EXPORTS MCCtl =
BEGIN OPEN AlpsBool, MCCtl;
ctlOutNames: PUBLIC LIST OF Rope.ROPE;
InitCtlOutNames:
PUBLIC
PROC [] = {
ctlOutNames ← NIL;
};
AddListToCtlOutNames:
PUBLIC
PROC[names:
LIST
OF Rope.
ROPE] = {
FOR l:
LIST
OF Rope.
ROPE ← names, l.rest
UNTIL l=
NIL
DO
ctlOutNames ← CONS[l.first, ctlOutNames];
ENDLOOP;
};
AddTableToCtlOutNames:
PUBLIC PROC [table: TableOfVariables] = {
FOR l:
LIST
OF OutputRef ← table.outputs, l.rest
UNTIL l=
NIL
DO
ctlOutNames ← CONS[l.first.name, ctlOutNames];
ENDLOOP;
};
CreateTable:
PUBLIC
PROC [names:
LIST
OF
ROPE]
RETURNS [table: TableOfVariables] = {
count: INT ← 1;
FOR list: LIST OF ROPE ← names, list.rest WHILE list#NIL DO count ← count+1 ENDLOOP;
table ← InitTableOfVariables[count];
count ← 1;
FOR list:
LIST
OF
ROPE ← names, list.rest
WHILE list#
NIL
DO
table[count].name ← list.first; count ← count + 1;
ENDLOOP;
};
EqualInt:
PUBLIC
PROC [table: TableOfVariables, rope:
ROPE, start, end, value:
INT]
RETURNS [Expression] = {
expr: Expression;
IF start>end THEN RETURN[true];
expr ← Find[table, MC.IndexedName[rope, end]];
RETURN [And[table,
IF (value MOD 2) = 1 THEN expr ELSE Not[expr],
EqualInt[table, rope, start, end-1, value/2]]];
};
FindInternal:
PUBLIC
PROC [table: TableOfVariables, rope:
ROPE]
RETURNS [internalIndex:
INT] = {
FOR i:
INT
IN [1..table.size)
DO
IF Rope.Equal[rope, table[i].name] THEN RETURN [i];
ENDLOOP;
ERROR;
};
Find:
PUBLIC
PROC [table: TableOfVariables, rope:
ROPE]
RETURNS [Expression] = {
RETURN [Var[FindInternal[table, rope]]];
};
DefaultDontCare:
PUBLIC
PROC []
RETURNS [Expression] = {
RETURN[false];
};
GenerateLayout:
PUBLIC
PROC [design:
CD.Design, table: TableOfVariables, distanceBetweenGlue:
INT ← 5]
RETURNS [obj:
CD.ObPtr] = {
Include tileset if necessary
BEGIN
file: ROPE ← "AlpsCells";
IF CDDirectory.Fetch[design, file].found
THEN Output["AlpsCells already present in design\n"]
ELSE
BEGIN
to: CD.Design ← design;
Check:
PROC [design:
CD.Design]
RETURNS [ok:
BOOL] =
BEGIN
ok ← design.technology=to.technology;
IF ~ok THEN Output["Technology mismatch: includee is ", design.technology.name, "\n"];
END;
from: CD.Design ← CDIO.ReadDesign[file, Check];
Output["Design AlpsCells read and included in the design"];
[] ← CDExtras.MergeIn[design: to, from: from, name: file];
END;
END;
Print info
BEGIN
input, aux, output, latch: INT;
[input, aux, output, latch] ← AlpsBool.NbOfVars[table];
Output[" Input: ", Convert.RopeFromInt[input], " Aux: ", Convert.RopeFromInt[aux], " Output: ", Rope.Cat[Convert.RopeFromInt[output], " Latch: ", Convert.RopeFromInt[latch], "\n"]];
END;
Layout at last
BEGIN
alpsTileContext: AlpsTile.Context ← NEW[AlpsTile.ContextRec ← [design: design, table: table, distanceBetweenGlue: distanceBetweenGlue, distanceBetweenContacts: 20, debug: FALSE]];
Output["\nLet's start Layout!"];
obj ← AlpsPWGen.TableToLayout[alpsTileContext];
Output["Done!"];
END;
};
InputsFromTable:
PUBLIC
PROC [table: TableOfVariables]
RETURNS [inputs:
LIST
OF
ROPE ←
NIL] = {
FOR i: INT DECREASING IN [1..table.size) DO inputs ← CONS[table[i].name, inputs] ENDLOOP;
};
Permute:
PUBLIC
PROC [table: TableOfVariables, permute: PermuteFlags ← permuteFast]
RETURNS [newTable: TableOfVariables] = {
SELECT permute
FROM
dontPermute => newTable ← table;
permuteFast => newTable ← AlpsHeur.BestPermuteInfinitely[table, AlpsHeur.ImproveAreaAndDelay];
permuteAllCases => newTable ← AlpsHeur.AllPermute[table, AlpsHeur.ImproveAreaAndDelay, 200]; -- Increase if it writes "Aborted" on the terminal and you want to try more.
ENDCASE => ERROR;
};
ListSize:
PUBLIC PROC [list:
LIST
OF
ROPE]
RETURNS [size:
INT ← 0] = {
FOR l: LIST OF ROPE ← list, l.rest UNTIL l=NIL DO size ← size+1 ENDLOOP;
};
ListCat:
PUBLIC
PROC [l1, l2:
LIST
OF
ROPE]
RETURNS[l3:
LIST
OF
ROPE] = {
l3 ← l2;
FOR l: LIST OF Rope.ROPE ← l1, l.rest UNTIL l=NIL DO l3 ← CONS[l.first, l3]; ENDLOOP;
};
MakeAlpsLatchandDrive:
PUBLIC PROC [design:
CD.Design, target:
PW.ObPtr]
RETURNS [result:
PW.ObPtr] = {
phASlice: PW.ObPtr ← PW.Get[design, "phALatchandDriveSlice"];
phBSlice: PW.ObPtr ← PW.Get[design, "phBLatchandDriveSlice"];
unLatchedDriveSlice: PW.ObPtr ← PW.Get[design, "unLatchedDriveSlice"];
targetIR: CD.Rect ← CD.InterestRect[target];
sliceIR: CD.Rect ← CD.InterestRect[phASlice];
resultIR: CD.Rect ← [0, 0, targetIR.x2-targetIR.x1, sliceIR.y2-sliceIR.y1];
attatchment: PW.ObPtr;
attatchmentIR: CD.Rect;
targetPinPosInResult: CD.Position;
attatchmentIRPosInResult: CD.Position ← [0, 0];
ProcessTargetPin: PWPins.AppEnumerator = {
[app: CD.ApplicationPtr] RETURNS [quit: BOOL ← FALSE]
side: PWPins.Side ← PWPins.GetSide[target, app].side;
name: ROPE ← CDPinObjects.GetName[app];
layer: CD.Layer ← CDPinObjects.GetLayer[app];
ProcessAttatchmentPin: PWPins.AppEnumerator = {
[app: CD.ApplicationPtr] RETURNS [quit: BOOL ← FALSE]
side: PWPins.Side ← PWPins.GetSide[attatchment, app].side;
IF side=PWPins.top THEN attatchmentIRPosInResult.x ← targetPinPosInResult.x-(app.location.x-attatchmentIR.x1);
};
NewName: PWPins.RenameProc = {newRope ← name};
targetPinPosInResult ← [app.location.x-targetIR.x1, sliceIR.y2-sliceIR.y1];
IF side=PWPins.bottom
AND (layer=CMos.met)
AND (Rope.Index[name, 0, "Not"]#0)
THEN {
SELECT
TRUE
FROM
Rope.Match["xAB", name] => attatchment ← PWPins.RenamePins[design, phASlice, NewName];
Rope.Match["xBA", name] => attatchment ← PWPins.RenamePins[design, phBSlice, NewName];
ENDCASE => attatchment ← PWPins.RenamePins[design, unLatchedDriveSlice, NewName];
attatchmentIR ← CD.InterestRect[attatchment];
[] ← PWPins.EnumerateEdgePins[phASlice, ProcessAttatchmentPin];
PW.IncludeInCell[design, result, attatchment, [attatchmentIRPosInResult.x, attatchmentIRPosInResult.y]]
};
result ← PW.CreateEmptyCell[];
CDCells.SetInterestRect[result, resultIR];
[] ← PWPins.EnumerateEdgePins[target, ProcessTargetPin];
Now put down two filler cells, one on the left of the last attatchment and one on its right. These will connect all of the horizontal bussed signals. But, of course, check for null filler cells first!
BEGIN
leftFillDist: INT ← attatchmentIRPosInResult.x;
rightFillDist: INT ← (resultIR.x2-resultIR.x1)- (attatchmentIRPosInResult.x+attatchmentIR.x2-attatchmentIR.x1);
IF leftFillDist > 0
THEN
PW.IncludeInCell[design,
result,
MC.LeftFillerCell[design, attatchment, leftFillDist],
[0, 0]];
IF rightFillDist > 0
THEN
PW.IncludeInCell[design,
result,
MC.RightFillerCell[design, attatchment, rightFillDist],
[attatchmentIRPosInResult.x+attatchmentIR.x2-attatchmentIR.x1, 0]];
END;
PW.IncludeInDirectory[design, result, "LatchResult"];
};
MakeFeedBackLatchandDrive:
PUBLIC PROC[design:
CD.Design, signals:
LIST
OF
ROPE]
RETURNS [result:
PW.ObPtr] = {
nbFedBackInputs: INT ← ListSize[signals];
phASlice: PW.ObPtr ← PW.Get[design, "FBphAlatchandDriveSlice"];
phBSlice: PW.ObPtr ← PW.Get[design, "FBphBLatchandDriveSlice"];
unLatchedDriveSlice: PW.ObPtr ← PW.Get[design, "FBunLatchedDriveSlice"];
glue: PW.ObPtr ← PW.Get[design, "FeedBackLatchToOutputLatchGlue"];
sliceIR: CD.Rect ← CD.InterestRect[phASlice]; -- all slices must have same IR
glueIR: CD.Rect ← CD.InterestRect[glue];
resultIR: CD.Rect ← [0, 0, nbFedBackInputs*(sliceIR.x2-sliceIR.x1)+glueIR.x2-glueIR.x1, sliceIR.y2-sliceIR.y1];
sliceNum: INT ← 0;
name: ROPE;
NewName: PWPins.RenameProc = {
index: INT;
newRope ← oldRope;
IF Rope.Equal[oldRope, "in"] OR Rope.Equal[oldRope, "out"] THEN newRope ← name;
IF Rope.Equal[oldRope, "Notout"] THEN newRope ← Rope.Cat["Not", name];
IF Rope.Find[name, "CyclexAB"] # -1 THEN RETURN;
IF Rope.Equal[oldRope, "out"]
AND (index ← Rope.Find[name, "xAB"])#-1
THEN newRope ← Rope.Replace[name, index, 3, "xBA"];
IF Rope.Equal[oldRope, "Notout"]
AND (index ← Rope.Find[name, "xAB"])#-1
THEN newRope ← Rope.Cat["Not", Rope.Replace[name, index, 3, "xBA"]];
IF Rope.Equal[oldRope, "out"]
AND (index ← Rope.Find[name, "xBA"])#-1
THEN newRope ← Rope.Replace[name, index, 3, "xAB"];
IF Rope.Equal[oldRope, "Notout"]
AND (index ← Rope.Find[name, "xBA"])#-1
THEN newRope ← Rope.Cat["Not", Rope.Replace[name, index, 3, "xAB"]];
};
SpecialNewName: PWPins.RenameProc = {
index: INT;
IF Rope.Equal[oldRope, "out"] THEN newRope ← name;
IF Rope.Equal[oldRope, "Notout"] THEN newRope ← Rope.Cat["Not", name];
IF Rope.Equal[oldRope, "in"]
AND (index ← Rope.Find[name, "xBA"])#-1
THEN newRope ← Rope.Replace[name, index, 3, "xAB"];
};
result ← PW.CreateEmptyCell[];
CDCells.SetInterestRect[result, resultIR];
FOR l:
LIST
OF
ROPE ← signals, l.rest
WHILE l#
NIL
DO
slice: PW.ObPtr;
name ← l.first;
SELECT
TRUE
FROM
Rope.Find[name, "CyclexAB"] # -1 => slice ← PWPins.RenamePins[design, unLatchedDriveSlice, NewName];
Rope.Find[name, "CyclexBA"] # -1 => slice ← PWPins.RenamePins[design, phBSlice, SpecialNewName];
Rope.Find[name, "xAB"] # -1 => slice ← PWPins.RenamePins[design, phBSlice, NewName];
Rope.Find[name, "xBA"] # -1 => slice ← PWPins.RenamePins[design, phASlice, NewName];
ENDCASE => slice ← PWPins.RenamePins[design, unLatchedDriveSlice, NewName];
PW.IncludeInCell[design, result, slice, [sliceNum*(sliceIR.x2-sliceIR.x1), 0]];
sliceNum ← sliceNum+1;
ENDLOOP;
PW.IncludeInCell[design, result, glue, [nbFedBackInputs*(sliceIR.x2-sliceIR.x1), 0]];
PW.IncludeInDirectory[design, result, "FeedBackLatchandDrive"];
};
MakeFeedBack:
PUBLIC PROC [design:
CD.Design, alpsTarget, latchTarget:
PW.ObPtr]
RETURNS [result:
PW.ObPtr] = {
alpsTargetIR: CD.Rect ← CD.InterestRect[alpsTarget];
latchTargetIR: CD.Rect ← CD.InterestRect[latchTarget];
resultIR: CD.Rect ← [0, 0, latchTargetIR.x2-latchTargetIR.x1, alpsTargetIR.y2-alpsTargetIR.y1];
bus: PW.ObPtr;
SelectPin:
MC.SelectPinProc
-- [pin: CD.ApplicationPtr] RETURNS [sel: BOOL] -- = {
sel ← (CDPinObjects.GetLayer[pin]=CMos.met2);
};
result ← PW.CreateEmptyCell[];
CDCells.SetInterestRect[result, resultIR];
Put down the input bus to alps
PW.IncludeInCell[design,
result,
bus ← MC.LeftFillerCell[design, alpsTarget, resultIR.x2-resultIR.x1, SelectPin],
[0, 0]];
Put down the connections from the latch to the bus
PW.IncludeInCell[design,
result,
MC.ConnectTopToBus[design, latchTarget, bus],
[0, 0]];
PW.IncludeInDirectory[design, result, "FeedBack"];
};
END.