MCCtlImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Created by: Sindhu, June 20, 1985 7:03:43 pm PDT
Last Edited by: Sindhu, July 14, 1985 10:46:31 pm PDT
Last Edited by: Serlet, July 6, 1985 2:10:26 pm PDT
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 ROPENIL] = {
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: BOOLFALSE]
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: BOOLFALSE]
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.