IFUPWContSection:
CEDAR
PROGRAM
IMPORTS CD, CDCells, CDExtras, CDFrame, CDOps, CDPinObjects, CDViewer, IFUPW, IFUPWControl, IO, PW, PWRoute, REFBit, Rope, Route -- , CD, CDBasics, CDExtras
EXPORTS IFUPWControl =
BEGIN OPEN IFUPWControl;
ColumnFromPLAClusterDrives:
PUBLIC
PROC [drives: Frame, design:
CD.Design]
RETURNS[column: Frame] = {
column ← drives;
column ← MergeConnSections [column];
GenPlaSections [column, design];
GenConnSections [column, design];
};
MergeConnSections:
PROC[drives: Frame]
RETURNS[new: Frame] ~ {
testProc: CDFrame.TestMergeProc = {RETURN[frame.data=NIL]}; -- data=NIL => connect
new ← CDFrame.TestMergeNodes[drives, testProc]};
GenPlaSections:
PROC[drives: Frame, design:
CD.Design] ~ {
outs: INT ← 0;
FOR index:
INT
IN [0..drives.seqSize)
DO
desc: IFUPWControl.PLADescription;
IF drives[index].data = NIL THEN LOOP;
desc ← NARROW[drives[index].data];
outs ← MAX[outs, REFBit.Desc[desc.ttt.out].bitForm.size];
ENDLOOP;
FOR index:
INT
IN [0..drives.seqSize)
DO
IF drives[index].data = NIL THEN LOOP;
drives[index] ← CreateDrivenPLAFrame[
drFrame: drives[index],
design: design,
outWidth: outs];
ENDLOOP };
Trace: BOOL ← FALSE;
GenConnSections:
PROC[drives: Frame, design:
CD.Design] ~ {
params: PWRoute.RouterParams ←
NEW[PWRoute.RouterParamsRec ←
[trunkLayer: "metal2", branchLayer: "metal"]];
FOR index:
INT
IN [0..drives.seqSize)
DO
IF drives[index].data #
NIL
THEN LOOP
ELSE {
-- returns x sequence with drivers in 0
top, bottom, left, right, wire: CD.Object;
drFrame: Frame ← drives[index];
wireFrame: Frame ← CDFrame.NewFrame[0,x,drives[index].shell.name.Cat["-Wire"]];
top ←
IF (index+1)=drives.seqSize
THEN NIL
ELSE NARROW[drives[index+1][0].data];
bottom ←
IF index=0
THEN NIL
ELSE NARROW[drives[index-1][0].data];
left ← GenPassDummyFromDrives[drFrame, design];
BuildDrivers[drFrame, design];
right ← CDFrame.FrameToObject[drFrame, design];
wire ← PWRoute.AbutSbRoute
[design, bottom, right, top, left, vertical, params !
Route.Signal =>
{log.PutF["\n Route Signal: %g", IO.rope[explanation]]; RESUME}];
IF Trace THEN ShowAllFive[design, wire, bottom, right, top, left];
PW.RenameObject[design, wire, wireFrame.shell.name];
wireFrame.data ← wire;
drives[index] ← CDFrame.NewFrame[2, x, drFrame.shell.name.Cat["-DrWire"]];
drives[index][0] ← wireFrame;
drives[index][1] ← drFrame };
ENDLOOP };
ShowAllFive:
PUBLIC PROC [design:
CD.Design, wire, bottom, right, top, left:
CD.Object] = {
viewer: ViewerClasses.Viewer ← CDViewer.CreateViewer[design];
maxX:
INT ←
MAX[
IF top=NIL THEN 0 ELSE CD.InterestSize[top].x,
IF bottom=NIL THEN 0 ELSE CD.InterestSize[bottom].x];
maxY:
INT ←
MAX[
IF left=NIL THEN 0 ELSE CD.InterestSize[left].y,
IF right=NIL THEN 0 ELSE CD.InterestSize[right].y];
CDOps.SetInstList[design, NIL];
CDOps.AddAnObject[design, left, [-CD.InterestSize[left].x, 0]];
CDOps.AddAnObject[design, bottom, [0, -CD.InterestSize[bottom].y]];
CDOps.AddAnObject[design, top, [0, maxY]];
CDOps.AddAnObject[design, right, [maxX, 0]];
CDOps.AddAnObject[design, wire, [0, 0]];
CDViewer.ShowAndScale[viewer, CDExtras.BoundingBox[design]]};
MakeDummySwitchbox: PROC RETURNS[cell: CD.Object] = {
shell: REF CDFrame.ShellRec ← NEW[CDFrame.ShellRec ← [name: "Routing"]];
shell.size.x ← IF top#NIL
THEN CDBasics.SizeOfRect[CD.InterestRect[top]].x
ELSE CDBasics.SizeOfRect[CD.InterestRect[bottom]].x;
shell.size.y ← IF left#NIL
THEN CDBasics.SizeOfRect[CD.InterestRect[left]].y
ELSE CDBasics.SizeOfRect[CD.InterestRect[right]].y;
RETURN[CDFrame.ShellToBlock[design, shell]]};
route.data ← MakeDummySwitchbox[];
GenPassDummyFromDrives:
PROC[drives: Frame, design:
CD.Design]
RETURNS[cell: CD.Object] ~ {
pinSize: CD.Position ← [6,6];
driverHeight: INT ← 48;
outputOffset: INT ← 16;
minHeight: INT ← (drives.seqSize+1)*driverHeight;
cellPtr: CD.CellPtr;
FOR index:
INT
IN [0..drives.seqSize)
DO
rec: REF DriveRec ← NARROW[drives[index].data];
IF rec.pass THEN EXIT REPEAT FINISHED => RETURN[NIL] ENDLOOP;
cell ← CDCells.CreateEmptyCell[];
cellPtr ← NARROW[cell.specificRef];
FOR index:
INT
IN [0..drives.seqSize)
DO
rec: REF DriveRec ← NARROW[drives[index].data];
IF rec.pass
THEN {
height: INT ← index*driverHeight+driverHeight/2 -pinSize.y/2+outputOffset;
newInst:
CD.Instance ←
NEW[
CD.InstanceRep ← [
ob: CDPinObjects.CreatePinOb[pinSize],
location: [6, height] ] ];
minHeight ← MIN[minHeight, height];
CDPinObjects.SetLayer[newInst, IFUPW.cmosMet];
CDPinObjects.SetName[newInst,
DriverPinName[(IF rec.drDir=in THEN out0 ELSE in), rec]];
cellPtr.contents ← CONS[newInst, cellPtr.contents]};
ENDLOOP;
CDCells.SetInterestRect[cell, [0, 0, 12, drives.seqSize*driverHeight]];
PW.IncludeInDirectory[design, cell, "Dummy"];
CDCells.SetInterestRect[cell, [0, -minHeight, 12, drives.seqSize*driverHeight-minHeight]];
RETURN[cell] };
log: IO.STREAM ← CDFrame.GetLog[];
END.