IFUPWContGlue:
CEDAR
PROGRAM
IMPORTS CD, CDCells, CDDirectory, CDExtras, CDFrame, CDOps, CDOrient, CDPinObjects, CDProperties, CMosB, IFUPW, IFUPWControl, IO, PW, PWPins, PWRoute, REFBit, Rope, Route, CDSimpleRules
EXPORTS IFUPWControl =
BEGIN
Ph: TYPE = IFUPWControl.Ph;
Frame: TYPE = IFUPWControl.Frame;
ROPE: TYPE = IFUPWControl.ROPE;
DriveRec: TYPE = IFUPWControl.DriveRec;
Side: TYPE = IFUPWControl.Side;
Status: TYPE = {rejustify, progress, delayed, complete1, complete2};
StatusRope:
ARRAY Status
OF
IO.
ROPE
= ["rejustify", "progress", "delayed", "complete1", "complete2"];
chanObjDesign: CD.Design ← CDOps.CreateDesign[IFUPW.cmos];
InstantiateDrivers:
PROC[root: Frame, design:
CD.Design] = {
MakeDrivers: CDFrame.EnumProc = {
driver: REF DriveRec;
IF frame.data=NIL OR NOT ISTYPE[frame.data, REF DriveRec] THEN RETURN;
driver ← NARROW[frame.data];
frame.data ← IFUPWControl.DriverCell[static, conn, NARROW[frame.data], design];
frame.shell ← CDFrame.ShellFromObject[NARROW[frame.data]]};
CDFrame.EnumFrameBotOnly[root, MakeDrivers]};
CheckExpandedFrame:
PROC[root: Frame] = {
CheckFrameProc: CDFrame.EnumProc = {
IF frame.shell.name=NIL OR frame.shell.name.Length[]=0 THEN Signal[];
IF frame.seqSize=0
THEN {
IF frame.data =
NIL
THEN Signal[]
ELSE
WITH frame.data
SELECT
FROM
cell: CD.Object => {};
glue: REF CDFrame.GlueSpec => {};
ENDCASE => Signal[];
IF frame.shell.size.x<1 OR frame.shell.size.y<1 THEN Signal[]} };
CDFrame.EnumFrameTopFirst[root, CheckFrameProc]};
Instantiate:
PROC[frame: Frame, design:
CD.Design]
RETURNS[new: Frame, status: Status] = {
IF frame.data#NIL AND ISTYPE[frame.data, CD.Object] THEN RETURN[frame, complete2];
IF frame.data#NIL AND frame.seqSize#0 THEN {Signal[]; frame.data ← NIL};
IF frame.seqSize=0
THEN {
IF frame.data = NIL THEN {Signal[]; RETURN[frame, complete2]};
[new, status] ← InstantiateGlue[frame, design];
IF status=complete2 THEN ERROR;
RETURN[new, status]};
status ← complete2;
new ← frame;
FOR kid:
INT
IN [0..new.seqSize)
WHILE status#rejustify
DO
stat: Status;
[new[kid], stat] ← Instantiate[new[kid], design];
status ← MIN[status, stat];
ENDLOOP;
IF status=complete2
THEN {
log.PutF["\n Completed Instantiation of: %g", IO.rope[new.shell.name]];
IF design.technology#CMosB.cmosB THEN ERROR;
new.data ← TempFrameToObject[new, design];
RETURN[new, progress]};
};
TempFrameToObject:
PUBLIC
PROC[frame: Frame, design:
CD.Design, detailed:
BOOL ←
TRUE]
RETURNS[cell: CD.Object] = {
IF frame.data#NIL THEN Signal[];
IF frame.seqSize=0
THEN Signal[]
ELSE {
list: PW.ListOb;
FOR i:
INT
DECREASING
IN [0..frame.seqSize)
DO
IF frame.seq[i].data=NIL OR NOT ISTYPE[frame.seq[i].data, CD.Object] THEN Signal[];
list ← CONS[ NARROW[frame.seq[i].data], list] ENDLOOP;
IF frame.xory=x
THEN cell ← PW.AbutListX[design, list]
ELSE cell ← PW.AbutListY[design, list];
PW.RenameObject[design, cell, frame.shell.name]} };
InstantiateGlue:
PROC[frame: Frame, design:
CD.Design]
RETURNS[new: Frame, status: Status] = {
glue: REF CDFrame.GlueSpec ← NARROW[frame.data];
status ← complete1;
FOR side: Side
IN Side
DO
neighbor: Frame;
SELECT glue.type[side]
FROM
chan => {IF glue.obj[side]=NIL THEN Signal[]; LOOP};
sum => LOOP;
diff => LOOP;
cap => LOOP;
ext => {
IF glue.obj[side]#NIL THEN LOOP;
IF glue.obj[CDFrame.OppSide[side]]#
NIL
THEN {
IF glue.class=xlt THEN LOOP;
glue.obj[side] ←
IF side=left
OR side=right
THEN PW.FlipX[design, glue.obj[CDFrame.OppSide[side]]]
ELSE PW.FlipY[design, glue.obj[CDFrame.OppSide[side]]];
status ← MIN[status, progress]}
ELSE {
log.PutF["\n Glue %g %g side waiting on %g side.",
IO.rope[frame.shell.name],
IO.rope[CDFrame.SideRope[side]],
IO.rope[CDFrame.SideRope[CDFrame.OppSide[side]]]];
status ← MIN[status, delayed]};
LOOP};
conn, pwr => {
found: BOOL;
IF glue.obj[side]#NIL THEN LOOP;
[neighbor, found] ← CDFrame.Neighbor[frame, side];
IF ~found
THEN {status ← MIN[status, delayed]; Signal[]} -- Drop To printout
ELSE {
IF neighbor.data#
NIL
THEN
WITH neighbor.data
SELECT
FROM
--
ELSE Drop
cell:
CD.Object => {
glue.obj[side] ← NARROW[neighbor.data];
status ← MIN[status, progress];
LOOP};
neighborGlue:
REF CDFrame.GlueSpec => {
IF neighborGlue.type[CDFrame.OppSide[side]]=ext
AND neighborGlue.obj[side]#
NIL
AND neighborGlue.class#xlt
AND neighborGlue.class#pwr
THEN {
glue.obj[side] ← neighborGlue.obj[side];
status ← MIN[status, progress];
LOOP} };
ELSE Drop To printout
ENDCASE => {Signal[]; LOOP} };
log.PutF["\n Glue %g can not yet%guse %g as %g %g.",
IO.rope[frame.shell.name],
IO.rope[IF found THEN " " ELSE " (never?) "],
IO.rope[IF neighbor=NIL THEN "???" ELSE neighbor.shell.name],
IO.rope[CDFrame.SideRope[side]],
IO.rope[IF glue.type[side]=conn THEN "conn" ELSE "pwr"]];
status ← MIN[status, delayed]; LOOP};
ENDCASE => ERROR ENDLOOP;
IF status < complete1 THEN RETURN[frame, status];
[new, status] ← GlueIt[frame, design]};
GlueIt:
PROC[frame: Frame, design:
CD.Design]
RETURNS[new: Frame, status: Status] = {
msg: IO.ROPE;
initSize: CD.Position ← [frame.shell.size.x, frame.shell.size.y];
cell: CD.Object;
glue: REF CDFrame.GlueSpec ← NARROW[frame.data];
variable: BOOL ← MAX[frame.shell.size.xfree, frame.shell.size.yfree]#fixed;
pwrSide: Side;
new ← frame;
IF variable AND glue.class IN [fill..xlt] THEN RETURN[new, complete1];
IF glue.class=chan AND ((new.father.xory=y) = (glue.tDir=vertical)) THEN Signal[];
SELECT glue.class
FROM
fill => cell ← CDFrame.BlankCell[design, initSize];
ext, xlt => {
OPEN glue;
cell ←
SELECT
TRUE
FROM
type[top] = ext => FillerCell [design, glue, top, initSize.y],
type[bottom] = ext => FillerCell [design, glue, bottom, initSize.y],
type[left] = ext => FillerCell [design, glue, left, initSize.x],
type[right] = ext => FillerCell [design, glue, right, initSize.x],
ENDCASE => ERROR};
chan, pwr, sb => {
ENABLE {
Route.Signal => {log.PutF["\n Route Signal: %g", IO.rope[explanation]]; RESUME};
Route.Error => {log.PutF["\n Route ERROR: %g",
IO.rope[explanation]];
cell ← CDFrame.BlankCell[design, initSize]; CONTINUE}};
pwrCell: CD.Object ← NIL;
routeType: PWRoute.RouteType ← IF glue.class=sb THEN switchBox ELSE channel;
sizeSpec: REF CD.Rect ← NEW[CD.Rect ← [0, 0, CDFrame.minSize.x, CDFrame.minSize.y]];
IF glue.class=pwr
THEN {
OPEN glue;
width: INT;
SELECT
TRUE
FROM
type[bottom] = pwr => {pwrSide ← bottom; width ← sizeSpec.y2};
type[top] = pwr => {pwrSide ← top; width ← sizeSpec.y2};
type[left] = pwr => {pwrSide ← left; width ← sizeSpec.x2};
type[right] = pwr => {pwrSide ← right; width ← sizeSpec.x2};
ENDCASE => ERROR;
pwrCell ← MergePwr [design, glue, pwrSide, width]};
IF
NOT variable
THEN {
sizeSpec.x2 ← initSize.x; sizeSpec.y2 ← initSize.y;
IF pwrCell#
NIL
THEN
IF glue.tDir=horizontal
THEN sizeSpec.y2 ← MAX[0, sizeSpec.y2 - CD.InterestSize[pwrCell].y]
ELSE sizeSpec.x2 ← MAX[0, sizeSpec.x2 - CD.InterestSize[pwrCell].x] };
IF glue.class=pwr THEN glue.obj[pwrSide] ← pwrCell;
MakeChanDummys[design, glue];
IF glue.class#pwr THEN CheckGlue[design, glue];
IF glue.tDir=horizontal
THEN cell ← PWRoute.
MakeChannel[design,
glue.obj[bottom],
glue.obj[top],
glue.obj[left],
glue.obj[right], sizeSpec, glue.params, glue.tDir=vertical, routeType]
ELSE cell ← PWRoute.
MakeChannel[design,
glue.obj[left],
glue.obj[right],
glue.obj[bottom],
glue.obj[top], sizeSpec, glue.params, glue.tDir=vertical, routeType];
IF glue.class=pwr
THEN cell ←
SELECT pwrSide
FROM
bottom => PW.AbutY[design, pwrCell, cell],
top => PW.AbutY[design, cell, pwrCell],
left => PW.AbutX[design, pwrCell, cell],
right => PW.AbutX[design, cell, pwrCell], ENDCASE => ERROR;
};
ENDCASE => Signal[];
IF
CellBad[cell]
THEN {
temp: CD.Object;
log.PutF["\n ERROR: Substituting Blank cell for: %g", IO.rope[new.shell.name]];
temp ← CDFrame.BlankCell[design, initSize];
Signal[];
cell ← temp};
PW.RenameObject[design, cell, new.shell.name];
new.data ← cell;
new.shell.size ← CDFrame.FixedSize[CD.InterestSize[cell]];
msg ←
IO.PutFR["\n Routed %g %g Frame: %g",
IO.rope[IF variable THEN "variable" ELSE "fixed"],
IO.rope[(
SELECT glue.class
FROM
fill => "fill",
ext => "extend",
xlt => "translate",
chan => "channel",
pwr => "power",
sb => "switchbox",
ENDCASE => " *B*A*D* ")],
IO.rope[new.shell.name] ];
log.PutRope[msg]; PW.Output[msg]; PW.Output["\n"];
IF variable
AND (glue.class=chan
OR glue.class=pwr)
THEN {
IF glue.tDir=vertical
THEN {IF new.shell.size.y # initSize.y THEN Signal[]}
ELSE {IF new.shell.size.x # initSize.x THEN Signal[]};
new ← AddExtention[
frame: new,
xory: (IF glue.tDir=vertical THEN x ELSE y),
glueFirst: glue.type[left]=conn OR glue.type[bottom]=conn ];
RETURN[new, rejustify]}
ELSE {
IF initSize # [new.shell.size.x, new.shell.size.y] THEN Signal[];
RETURN[new, progress] } };
GetPinsLayer:
PROC[pins:
REF CDFrame.PinSeq]
RETURNS[same: BOOL, layer: CD.Layer] = {
IF pins = NIL OR pins.seqSize=0 THEN RETURN[TRUE, CD.combined];
layer ← pins[0].layer;
FOR pin:
INT
IN [1..pins.seqSize)
DO
IF pins[pin].layer#layer THEN RETURN[FALSE, CD.combined] ENDLOOP;
RETURN[TRUE, layer]};
CellBad:
PROC[cell:
CD.Object]
RETURNS[bad:
BOOL] = {
bad ← cell=NIL OR cell.specificRef=NIL;
IF
NOT bad
THEN
WITH cell.specificRef
SELECT
FROM
cellPtr: CD.CellPtr => bad ← cellPtr.contents=NIL;
list: LIST OF CD.Object => bad ← list=NIL; -- redundant
ENDCASE => bad ← TRUE;
RETURN[bad OR CD.InterestSize[cell].x<1 OR CD.InterestSize[cell].y<1]};
AddExtention:
PROC[frame: Frame, xory: CDFrame.XorY, glueFirst:
BOOL]
RETURNS[new: Frame] = {
glue: Frame ← CDFrame.Glue[
b: (IF xory#y THEN cap ELSE IF glueFirst THEN ext ELSE conn ),
t: (IF xory#y THEN cap ELSE IF glueFirst THEN conn ELSE ext ),
l: (IF xory#x THEN cap ELSE IF glueFirst THEN ext ELSE conn ),
r: (IF xory#x THEN cap ELSE IF glueFirst THEN conn ELSE ext ) ];
frame.shell.pos ← [0,0];
new ← CDFrame.NewFrame[2, xory, frame.shell.name.Cat["Ext"]];
new.father ← frame.father;
new[1] ← IF glueFirst THEN frame ELSE glue;
new[0] ← IF glueFirst THEN glue ELSE frame;
new[0].father ← new[1].father ← new};
NameSize: TYPE = RECORD[name: IO.ROPE, size: INT];
SideObject:
PROC[design:
CD.Design, side: Side, layer:
CD.Layer, list:
LIST
OF NameSize]
RETURNS[cell: CD.Object] = {
dim: INT ← 4*IFUPW.lambda;
pos: CD.Position ← [0, 0];
size: CD.Position ← [0, 0];
cell ← CDCells.CreateEmptyCell[];
FOR list ← list, list.rest
WHILE list#
NIL
DO
pinApl: CD.Instance;
size ←
SELECT side
FROM
top, bottom => [list.first.size, dim]
ENDCASE => [dim, list.first.size];
pinApl ← PW.IncludeInCell[cell, CDPinObjects.CreatePinOb[size], pos];
CDPinObjects.SetName[pinApl, list.first.name];
CDPinObjects.SetLayer[pinApl, layer];
SELECT side
FROM
top, bottom => pos.x ← pos.x + dim + list.first.size;
ENDCASE => pos.y ← pos.y + dim + list.first.size;
ENDLOOP;
CDCells.SetInterestRect[cell,
SELECT side
FROM
left => [-dim, -dim, +dim, pos.y ],
bottom => [-dim, -dim, pos.x, +dim ],
right => [0, -dim, 2*dim, pos.y ],
top => [-dim, 0, pos.x, 2*dim ],
ENDCASE => ERROR ];
PW.IncludeInDirectory[design, cell, "SideObject"]};
ChanObj:
PUBLIC
PROC [
layer: CD.Layer,
side: Side,
ref: REF ← NIL,
ph: Ph ← unk,
dim: INT ← 0,
design:
CD.Design ←
NIL ]
RETURNS [cell: CD.Object] ~ {
pos: CD.Position ← [0, 0];
form: REFBit.Format ← REFBit.Desc[ref].bitForm;
list: LIST OF NameSize;
IF design=NIL THEN design ← chanObjDesign;
dim ← MAX[dim, 4*IFUPW.lambda];
FOR i:
CARDINAL
DECREASING
IN [0..form.size)
DO
name: ROPE ← IFUPWControl.BitNameToSigName[form[i].name];
nameInv: ROPE ← IFUPWControl.BitNameToSigName[form[i].nameInv];
list ← CONS[ NameSize[IFUPWControl.SignalName[FALSE, name, nameInv, ph], dim], list];
ENDLOOP;
cell ← SideObject[design, side, layer, list]};
MakeChanDummys:
PROC[design:
CD.Design, glue:
REF CDFrame.GlueSpec] = {
AddIfUnique:
PROC[item: NameSize, tlist:
LIST
OF NameSize]
RETURNS[new: LIST OF NameSize, done: BOOL] = {
IF tlist=NIL THEN RETURN[CONS[item, NIL], TRUE];
new ← tlist;
FOR tlist ← tlist, tlist.rest
WHILE tlist#
NIL
DO
IF Rope.Equal[tlist.first.name, item.name]
THEN
{tlist.first.size ← MAX[tlist.first.size, item.size] ; RETURN[new, FALSE]};
ENDLOOP;
RETURN[CONS[item, new], TRUE] };
sum, diff: LIST OF NameSize;
unique: BOOL;
FOR side: Side
IN Side
DO IF glue.type[side]=sum OR glue.type[side]=diff THEN EXIT;
REPEAT FINISHED => RETURN ENDLOOP;
FOR side: Side
IN Side
DO
list: LIST OF NameSize ← NIL;
proc: PWPins.InstanceEnumerator = {
IF PWPins.GetSide[glue.obj[side], inst]=CDFrame.OppSide[side]
THEN {
iSize: CD.Position ← CDOrient.OrientedSize[inst.ob.size, inst.orientation];
nameSize: NameSize ← [
name: CDPinObjects.GetName[inst],
size: SELECT side FROM top, bottom => iSize.x, ENDCASE => iSize.y];
[list, ] ← AddIfUnique[nameSize, list] } };
IF glue.type[side]#conn AND glue.type[side]#chan AND glue.type[side]#pwr THEN LOOP;
[ ] ← PWPins.EnumerateEdgePins[glue.obj[side], proc];
FOR list ← list, list.rest
WHILE list#
NIL
DO
[sum, unique] ← AddIfUnique[list.first, sum];
IF unique
THEN diff ← CONS[list.first, diff]
ELSE
IF diff#
NIL
THEN {
IF Rope.Equal[diff.first.name, list.first.name]
THEN diff ← diff.rest
ELSE
FOR tdiff:
LIST
OF NameSize ← diff, tdiff.rest
WHILE tdiff.rest#
NIL
DO
IF ~Rope.Equal[tdiff.rest.first.name, list.first.name] THEN LOOP;
tdiff.rest ← tdiff.rest.rest; EXIT ENDLOOP};
ENDLOOP;
ENDLOOP;
FOR side: Side
IN Side
DO
layer:
CD.Layer ← CDSimpleRules.GetLayer[design.technology.key,
IF (side=top
OR side=bottom) = (glue.tDir=vertical)
THEN glue.params.trunkLayer ELSE glue.params.branchLayer];
IF glue.type[side]=sum THEN glue.obj[side] ← SideObject[design, side, layer, sum];
IF glue.type[side]=diff THEN glue.obj[side] ← SideObject[design, side, layer, diff];
ENDLOOP};
FillerCell:
PROC [design:
CD.Design, glue:
REF CDFrame.GlueSpec, objSide: Side, width:
INT]
RETURNS [cell: CD.Object] = {
template: CD.Object ← glue.obj[CDFrame.OppSide[objSide]];
templateSize: CD.Position ← CD.InterestSize[template];
resultSize: CD.Position;
deslayer: CD.Layer ← GlueSideLayer[design, glue, objSide];
deslayerRope:
IO.
ROPE ←
SELECT deslayer
FROM
IFUPW.cmosMet => "metal",
IFUPW.cmosMet2 => "metal2",
IFUPW.cmosPoly => "poly", ENDCASE => ERROR;
IF glue.class=xlt
THEN cell ← IFUPWControl.XferPins[design, template, objSide, deslayerRope, width]
ELSE cell ← IFUPWControl.XferPins[design, template, objSide, NIL, width];
resultSize ← CD.InterestSize[cell];
IF (
SELECT objSide
FROM
left, right => resultSize.x#width OR resultSize.y#templateSize.y,
top, bottom => resultSize.y#width OR resultSize.x#templateSize.x,
ENDCASE => ERROR) THEN Signal[]};
MergePwr:
PROC [design:
CD.Design, glue:
REF CDFrame.GlueSpec, objSide: Side, width:
INT]
RETURNS [cell: CD.Object] = {
pinObj: CD.Object ← glue.obj[objSide];
pinSide: Side ← CDFrame.OppSide[objSide];
vgObj: CD.Object ← glue.obj[CDFrame.OppSide[objSide]];
size1: CD.Position ← CD.InterestSize[pinObj];
size2: CD.Position ← CD.InterestSize[vgObj];
size3: CD.Position;
deslayer: CD.Layer ← GlueSideLayer[design, glue, objSide];
deslayerRope:
IO.
ROPE ←
SELECT deslayer
FROM
IFUPW.cmosMet => "metal",
IFUPW.cmosMet2 => "metal2",
IFUPW.cmosPoly => "poly", ENDCASE => ERROR;
cell ← IFUPWControl.MergePwrPins[design, vgObj, pinObj, pinSide, deslayerRope, width];
size3 ← CD.InterestSize[cell];
IF (
SELECT objSide
FROM
left, right => size3.y#size1.y OR size3.y#size2.y OR size3.x < width,
top, bottom => size3.x#size1.x OR size3.x#size2.x OR size3.y < width,
ENDCASE => ERROR) THEN Signal[]};
GlueSideLayer:
PROC[design:
CD.Design, glue:
REF CDFrame.GlueSpec, side: Side]
RETURNS[layer: CD.Layer] = {
tLayer:
BOOL ←
SELECT side
FROM
left, right => glue.tDir=horizontal,
top, bottom => glue.tDir=vertical,
ENDCASE => ERROR;
RETURN[CDSimpleRules.GetLayer[design.technology.key,
IF tLayer THEN glue.params.trunkLayer ELSE glue.params.branchLayer]]};
CheckGlue:
PROC[design:
CD.Design, glue:
REF CDFrame.GlueSpec] = {
technology: CD.Technology ← design.technology;
shell: REF CDFrame.ShellRec ← NEW[CDFrame.ShellRec];
shells: ARRAY Side OF REF CDFrame.ShellRec;
FOR side: Side
IN Side
DO
IF glue.obj[side]#
NIL
THEN shells[side] ← CDFrame.ShellFromObject[glue.obj[side]]
ELSE shells[side] ← NEW[CDFrame.ShellRec]; ENDLOOP;
shell.size.x ← MAX[shells[top].size.x, shells[bottom].size.x];
shell.size.y ← MAX[shells[left].size.y, shells[right].size.y];
FOR side: Side
IN Side
DO
shell.pins[side] ← shells[side].pins[CDFrame.OppSide[side]] ENDLOOP;
FOR side: Side
IN Side
DO
IF glue.type[side]#cap
THEN {
layer: CD.Layer;
ok: BOOL;
IF (shell.pins[side]=
NIL
OR shell.pins[side].seqSize=0)
THEN {
log.PutF["\n ERROR: No %g side pins.", IO.rope[CDFrame.SideRope[side]]];
Signal[];
LOOP};
[ok, layer] ← GetPinsLayer[shell.pins[side]];
IF
NOT ok
OR layer # GlueSideLayer[design, glue, side]
THEN {
log.PutF["\n ERROR: %g side pin layer mismatch.", IO.rope[CDFrame.SideRope[side]]];
Signal[];
}};
ENDLOOP;
FOR tside: Side
IN Side
DO
tpins: REF CDFrame.PinSeq ← shell.pins[tside];
IF tpins=NIL THEN LOOP;
FOR tpin:
INT
IN [0..tpins.seqSize)
DO
found: BOOL ← FALSE;
FOR side: Side
IN Side
WHILE
NOT found
DO
pins: REF CDFrame.PinSeq ← shell.pins[side];
IF side=tside THEN LOOP;
IF pins=NIL THEN LOOP;
FOR pin:
INT
IN [0..pins.seqSize)
WHILE
NOT found
DO
IF Rope.Equal[pins[pin].name,tpins[tpin].name] THEN found ← TRUE;
ENDLOOP;
ENDLOOP;
IF
NOT found
THEN log.PutF["\n Unique %g side pin: %g",
IO.rope[CDFrame.SideRope[tside]], IO.rope[tpins[tpin].name]];
ENDLOOP;
ENDLOOP};
IFUPW.Show5Objects[glue.obj[bottom], glue.obj[right], glue.obj[top], glue.obj[left], NIL]
IncludeRecursiveInDesign: PUBLIC PROC [design: CD.Design] = {
ExpandAll: CDDirectory.EnumerateObjectsProc = {
new: CD.Object ← CDDirectory.Expand[me, NIL, NIL];
IF new#NIL THEN {
me^ ← new^;
ExpandAll[me, NIL];
RETURN };
CDDirectory.EnumerateChildObjects[me, ExpandAll]};
DeleteOwner: CDDirectory.EnumerateObjectsProc = {
CDProperties.PutPropOnObject[me, $Owner, NIL];
CDDirectory.EnumerateChildObjects[me, DeleteOwner]};
SetOwner: CDDirectory.EnumerateObjectsProc = {
IF CDProperties.GetPropFromObject[me, $Owner]#NIL THEN RETURN;
[] ← CDDirectory.Include[design, me];
CDDirectory.EnumerateChildObjects[me, SetOwner]};
FOR list: LIST OF CD.Instance ← CDOps.InstList[design], list.rest WHILE list#NIL DO
CDDirectory.EnumerateChildObjects[list.first.ob, ExpandAll]; ENDLOOP;
FOR list: LIST OF CD.Instance ← CDOps.InstList[design], list.rest WHILE list#NIL DO
CDDirectory.EnumerateChildObjects[list.first.ob, DeleteOwner]; ENDLOOP;
FOR list: LIST OF CD.Instance ← CDOps.InstList[design], list.rest WHILE list#NIL DO
CDDirectory.EnumerateChildObjects[list.first.ob, SetOwner]; ENDLOOP};
IncludeRecursiveInDesign: PUBLIC PROC [design: CD.Design, ob: CD.Object] = {
ExpandAll: CDDirectory.EnumerateObjectsProc = {
new: CD.Object ← CDDirectory.Expand[me, NIL, NIL];
IF new#NIL THEN {me^ ← new^; ExpandAll[me, NIL]; RETURN };
CDDirectory.EnumerateChildObjects[me, ExpandAll]};
DeleteOwner: CDDirectory.EnumerateObjectsProc = {
CDProperties.PutPropOnObject[me, $Owner, NIL];
CDDirectory.EnumerateChildObjects[me, DeleteOwner]};
SetOwner: CDDirectory.EnumerateObjectsProc = {
IF CDProperties.GetPropFromObject[me, $Owner]#NIL THEN RETURN;
[] ← CDDirectory.Include[design, me];
CDDirectory.EnumerateChildObjects[me, SetOwner]};
FOR list: LIST OF CD.Instance ← CDOps.InstList[design], list.rest WHILE list#NIL DO
ExpandAll[list.first.ob, NIL]; ENDLOOP;
FOR list: LIST OF CD.Instance ← CDOps.InstList[design], list.rest WHILE list#NIL DO
DeleteOwner[list.first.ob, NIL]; ENDLOOP;
FOR list: LIST OF CD.Instance ← CDOps.InstList[design], list.rest WHILE list#NIL DO
SetOwner[list.first.ob, NIL]; ENDLOOP};
IncludeRecursiveInDesign
--pfui--:
PUBLIC
PROC [design:
CD.Design] = {
--this procedure violates some ChipNDale requirements
--objects are illegaly removed from library designs
--don't use any of the library designs afterwards, even indirectly
myKey: REF INT ← NEW[INT];
myVal: REF INT ← NEW[INT];
DoIt: CDDirectory.EnumerateObjectsProc = {
--uses globals design and myKey
IF me.class.inDirectory
AND CDProperties.GetPropFromObject[me, myKey]#x
THEN {
CDProperties.PutProp[me, myKey, x];
WHILE ~CDCells.IsCell[me]
DO
new: CD.Object ← CDDirectory.Expand[me, NIL, NIL];
IF new=NIL THEN EXIT ELSE me^ ← new^ ENDLOOP; --real dirty--
CDProperties.PutProp[me, $OwnerDesign, NIL]; --real dirty--
[] ← CDDirectory.Include[design, me];
CDDirectory.EnumerateChildObjects[me, DoIt, x]} };
FOR list:
LIST
OF
CD.Instance ← CDOps.InstList[design], list.rest
WHILE list#
NIL
DO
DoIt[list.first.ob, myVal]; ENDLOOP;
At this point, we should attach the holding company (holds all the cached library cells) to the design as a property and flush the caches of all the generator modules.
CDExtras.RemoveProperties[design, myKey] };
BuildFrame:
PUBLIC CDFrame.SpecificFrameProc = {
PROC[frame: Frame, name: IO.ROPE, design: CD.Design ← NIL]
RETURNS [new: Frame, done: BOOL];
status: Status ← rejustify;
IF name=NIL THEN name ← frame.shell.name;
done ← FALSE;
new ← frame;
IF new.shell=
NIL
OR
NOT Rope.Equal[new.shell.name, name]
THEN {
FOR index:
INT
IN [0..new.seqSize)
WHILE
NOT done
DO
[new[index], done] ← BuildFrame[new[index], name, design] ENDLOOP;
RETURN[new, done]};
log.PutF["\n\n Building Frame: %g", IO.rope[name]];
new ← CDFrame.ExpandFrame [new, design];
InstantiateDrivers [new, design];
CDFrame.ReOrient [new, design];
CDFrame.TellKidsAboutDad [new];
CheckExpandedFrame [new];
FOR pass:
INT ← 1, pass+1
WHILE status<complete2
DO
log.PutF["\n\n Pass %g\n", IO.int[pass]]; log.Flush[];
IF status=rejustify
THEN {
log.PutRope[" Rejustify\n"]; log.Flush[];
CDFrame.GetSize [new];
CDFrame.PutSize [new];
CDFrame.PutPos [new, [0,0]];
IF pass<2 THEN {log.PutRope["\n\n"]; CDFrame.LogFrame[new]; log.Flush[]};
};
log.PutRope["\n"];
[new, status] ← Instantiate[new, design];
log.PutF["\n Status: %g", IO.rope[StatusRope[status]]];
SELECT status
FROM
rejustify => {LOOP};
progress => {LOOP};
delayed => {IF NOT CDFrame.FixOneSize[new] THEN Signal[]};
complete1 => {IF NOT CDFrame.FixOneSize[new] THEN Signal[]};
complete2 => {EXIT};
ENDCASE => {ERROR};
ENDLOOP;
log.PutRope["\n\n"]; CDFrame.LogFrame[new]; log.Flush[];
CDFrame.GetPins[new];
RETURN[new, TRUE]};
Signal: SIGNAL = CODE;
log: IO.STREAM ← CDFrame.GetLog[];
END.