IFUPWContDrive.mesa
Copyright c 1985 by Xerox Corporation. All rights reserved.
Last Edited by Curry, January 28, 1986 4:49:41 pm PST
DIRECTORY
CD,
CDDirectory,
CDFrame,
IO,
IFUPW,
IFUPWControl,
REFBit,
PW,
PWPins,
Rope;
IFUPWContDrive: CEDAR PROGRAM
IMPORTS CDDirectory, CDFrame, IFUPW, IO, PW, PWPins, REFBit, Rope
EXPORTS IFUPWControl =
BEGIN OPEN IFUPWControl, CDF: CDFrame;
driverTilesDesign: CD.Design;
tileBuffer:   REF DrTileRec ← NIL;
DrTileRec:   TYPE = RECORD[nconn: DrTileNonConn, conn: DrTileConn];
DrTileNonConn:  TYPE = ARRAY PLAType OF ARRAY RowType OF CD.Object;
DrTileConn:   TYPE = ARRAY Dir OF REF DrTileArray;
DrTileArray:   TYPE = ARRAY DriveTileType OF CD.Object;
DriveTileType:  TYPE = {inPos, inNeg, latchA, latchB, gateP, gateN, gateA, gateB, latch, posSing, negSing, posDual, negDual};
GetDriverTiles: PROC RETURNS[tiles: REF DrTileRec] = {
tDesign: CD.Design;
IF tileBuffer#NIL THEN RETURN[tileBuffer];
log.PutRope["\n Initialize control driver tiles"];
tDesign ← driverTilesDesign← PW.OpenDesign["IFUPWControl.dale"];
IF tDesign=NIL THEN
ERROR PW.Error[MissingDesign, "TileSet design not found or empty"];
tiles ← tileBuffer ← NEW[DrTileRec];
tiles.conn[in]  ← NEW[DrTileArray];
tiles.conn[out]  ← NEW[DrTileArray];
tiles.nconn [precharged][header] ← PW.Get[design: tDesign, name: "DrHead" ];
tiles.nconn [precharged][xheader] ← PW.Get[design: tDesign, name: "DrXHead" ];
tiles.nconn [precharged][extend] ← PW.Get[design: tDesign, name: "DrExtend" ];
tiles.nconn [precharged][blank] ← PW.Get[design: tDesign, name: "DrBlank" ];
tiles.nconn [precharged][dataUp] ← tiles.nconn [precharged][blank];
tiles.nconn [precharged][dataDn] ← tiles.nconn [precharged][blank];
tiles.nconn [precharged][footer] ← PW.FlipY[tDesign, tiles.nconn [precharged][header]];
tiles.nconn [precharged][xfooter] ← PW.FlipY[tDesign, tiles.nconn [precharged][xheader]];
tiles.nconn [static][header]   ← PW.Get[design: tDesign, name: "SPlaDrHead" ];
tiles.nconn [static][xheader]  ← PW.Get[design: tDesign, name: "DrXHead" ];
tiles.nconn [static][extend]   ← PW.Get[design: tDesign, name: "DrExtend" ];
tiles.nconn [static][blank]   ← PW.Get[design: tDesign, name: "SPlaDrBlank24" ];
tiles.nconn [static][dataUp]   ← tiles.nconn [static][blank];
tiles.nconn [static][dataDn]  ← tiles.nconn [static][blank];
tiles.nconn [static][footer]   ← PW.FlipY[tDesign, tiles.nconn [static][header]];
tiles.nconn [static][xfooter]   ← PW.FlipY[tDesign, tiles.nconn [static][xheader]];
tiles.nconn [decoder][blank]  ← PW.Get[design: tDesign, name: "DPlaDrBlank6" ]; --1 use
tiles.conn [in][inPos]  ← PW.Get[design: tDesign, name: "DrInInPos" ];
tiles.conn [in][inNeg]  ← PW.Get[design: tDesign, name: "DrInInNeg" ];
tiles.conn [in][latchA]  ← PW.Get[design: tDesign, name: "DrInA" ];
tiles.conn [in][latchB]  ← PW.Get[design: tDesign, name: "DrInB" ];
tiles.conn [in][latch]  ← PW.Get[design: tDesign, name: "DrLatch" ];
tiles.conn [in][posSing]  ← PW.Get[design: tDesign, name: "DrInPosSing" ];
tiles.conn [in][negSing] ← PW.Get[design: tDesign, name: "DrInNegSing" ];
tiles.conn [in][posDual] ← PW.Get[design: tDesign, name: "DrInPosDual" ];
tiles.conn [in][negDual] ← PW.Get[design: tDesign, name: "DrInNegDual" ];
tiles.conn [out][inPos]  ← PW.Get[design: tDesign, name: "DrOutInPos" ];
tiles.conn [out][inNeg]  ← PW.Get[design: tDesign, name: "DrOutInNeg" ];
tiles.conn [out][latchA] ← PW.Get[design: tDesign, name: "DrOutLatchA" ];
tiles.conn [out][latchB]  ← PW.Get[design: tDesign, name: "DrOutLatchB" ];
tiles.conn [out][latch]  ← PW.Get[design: tDesign, name: "DrLatch" ];
tiles.conn [out][gateP]  ← PW.Get[design: tDesign, name: "DrOutPos" ];
tiles.conn [out][gateN]  ← PW.Get[design: tDesign, name: "DrOutNeg" ];
tiles.conn [out][gateA]  ← PW.Get[design: tDesign, name: "DrOutAc" ];
tiles.conn [out][gateB]  ← PW.Get[design: tDesign, name: "DrOutBc" ];
tiles.conn [out][posSing] ← PW.Get[design: tDesign, name: "DrOutPosSing" ];
tiles.conn [out][negSing] ← PW.Get[design: tDesign, name: "DrOutNegSing" ];
tiles.conn [out][posDual] ← PW.Get[design: tDesign, name: "DrOutPosDual" ];
tiles.conn [out][negDual] ← PW.Get[design: tDesign, name: "DrOutNegDual" ];
RETURN[tiles]};
RefToDriverFrame: PUBLIC PROC[
name: ROPE, xory: CDF.XorY, data, refRec: REF, unordered: BOOL, initial: DriveRec]
RETURNS[frame: Frame]= {
index: INT ← 0;
desc: REFBit.REFBitDesc ← REFBit.Desc[refRec];
frame ← CDF.NewFrame
[desc.fieldForm.size, xory, name.Cat["Core"], data, unordered];
FOR field: INT IN [0..desc.fieldForm.size) DO
frame[field] ← CDF.NewFrame[
size:  desc.fieldForm[field].bitSize,
xory:  xory,
name:  BitNameToSigName[desc.fieldForm[field].name],
unord: unordered];
FOR bit: INT IN [0..desc.fieldForm[field].bitSize) DO
rec: REF DriveRec ← NEW[DriveRec ← initial ];
frame[field][bit] ← CDF.NewFrame
[size: 0, xory: xory, name: desc.bitForm[index].name, data:NIL, unord: unordered];
rec.name  ← BitNameToSigName[desc.bitForm[index].name];
rec.nameInv ← BitNameToSigName[desc.bitForm[index].nameInv];
frame[field][bit].shell.name ← IF rec.name#NIL THEN rec.name ELSE rec.nameInv;
frame[field][bit].data   ← rec;
index ← index + 1;
ENDLOOP ENDLOOP;
frame ← IFUPW.NFS[name, y, LIST[
CDF.NewObjectFrame[DriverCell[static, xheader]],
frame,
CDF.NewObjectFrame[DriverCell[static, xfooter]]
] ] };
DrRope: PROC[rec: REF DriveRec] RETURNS[rope: ROPE] = {
dirRope: ARRAY Dir OF ROPE  = [" in", "out"];
polRope: ARRAY Polarity OF ROPE = ["pos", "neg", "unk"];
phRope: ARRAY Ph OF ROPE   = ["A ", "B ", "AB ", "BA ", "Ac ", "Bc ", "unk"];
gateRope: ARRAY DrGate OF ROPE = [" neg", "negAc", "negBc", " pos"];
dualSing: ARRAY BOOL OF ROPE  = ["sing", "dual"];
rope ← IO.PutFR["%3g %12g %12g",
IO.rope[dirRope[rec.drDir]],
IO.rope[rec.name],
IO.rope[rec.nameInv] ];
rope ← rope.Cat[IO.PutFR[" %g%g %g%g",
IO.rope[polRope [rec.in.pol]],
IO.rope[phRope [rec.in.ph]],
IO.rope[polRope [rec.ref.pol]],
IO.rope[phRope [rec.ref.ph]] ] ];
rope ← rope.Cat[IO.PutFR[" %g %g %g%g",
IO.rope[gateRope [rec.gate]],
IO.rope[dualSing [rec.dualOut]],
IO.rope[polRope [rec.out.pol]],
IO.rope[phRope [rec.out.ph]] ] ] };
ListDrivers: PROC[drives: Frame, list: IO.STREAMIO.noWhereStream] = {
ListDrive: CDF.EnumProc =
{list.PutF["Driver: %g", IO.rope[DrRope[NARROW[frame.data]]]]};
IF list=IO.noWhereStream THEN {list ← log};
CDF.EnumFrameBotOnly[drives, ListDrive]};
AccmPosAndAddDriversBasedOnShellSide: PUBLIC PROC
uses frame.shell.size.x and pos.x for count and position
[drivers: Frame, shell: REF CDF.ShellRec, side: Side] RETURNS[Frame]= {
AddPin: PROC[frame: Frame] RETURNS[new, dFrame: Frame←NIL, found: BOOL, pos: INT] = {
new ← frame;
IF frame.seqSize#0
THEN {
FOR index: INT IN [0..frame.seqSize) DO
[frame[index], dFrame, found, pos] ← AddPin[frame[index]];
IF NOT found THEN LOOP;
IncrAvePos[frame, pos];
IF dFrame=NIL
THEN RETURN[frame, NIL, found, pos]
ELSE {
new ← CDF.NewFrame
[frame.seqSize+1, frame.xory, frame.shell.name, frame.data, frame.unordered];
new.shell.size ← frame.shell.size;
FOR index: INT IN [0..frame.seqSize)
DO new[index] ← frame[index] ENDLOOP;
new[frame.seqSize] ← dFrame;
RETURN[new, NIL, TRUE, pos]};
ENDLOOP }
ELSE {
rec: REF DriveRec;
posMatch, negMatch: BOOL;
IF frame.data=NIL OR NOT ISTYPE[frame.data, REF DriveRec]
THEN RETURN[frame, NIL, FALSE, 0];
rec ← NARROW[frame.data];
posMatch ← Rope.Equal[root, rec.name,  FALSE];
negMatch ← Rope.Equal[root, rec.nameInv, FALSE];
IF NOT posMatch AND NOT negMatch THEN RETURN[frame, NIL, FALSE, 0];
IF posMatch AND negMatch THEN {
log.PutF["\n ERROR: PIN %g matches both %g and %g",
IO.rope[pin.name],
IO.rope[rec.name],
IO.rope[rec.nameInv]];
RETURN[frame, NIL, FALSE, 0]};
IF rec.name#NIL AND rec.nameInv#NIL AND not THEN {
log.PutF["\n ERROR: PIN %g implicitly matches %g",
IO.rope[pin.name],
IO.rope[IF posMatch THEN rec.name ELSE rec.nameInv]];
RETURN[frame, NIL, FALSE, 0]};
pos ← CDF.GetSidePos[pin];
IF rec.drDir=in AND rec.in.ph#unk AND rec.in.ph#ph OR
rec.drDir=out AND rec.out.ph#unk AND rec.out.ph#ph
THEN {
dFrame ← CDF.NewFrame
[0, frame.xory, frame.shell.name.Cat["-alt"], ,frame.unordered];
IncrAvePos[dFrame, pos];
dFrame.data ← rec ← NEW[DriveRec ← rec^];
IF rec.drDir=out THEN rec.out ← [ ] ELSE rec.in ← [ ]}
ELSE {dFrame ← NIL; IncrAvePos[frame, pos]};
IF rec.drDir=in
THEN {
IF posMatch#not
THEN rec.in.pol ← pos
ELSE rec.in.pol ← neg;
rec.in.ph ← ph}
ELSE {
SELECT rec.out.pol FROM
pos => IF posMatch=not  THEN rec.dualOut ← TRUE;
neg => IF posMatch#not THEN rec.dualOut ← TRUE;
ENDCASE => rec.out.pol ← IF posMatch#not THEN pos ELSE neg;
rec.out.ph ← ph};
RETURN[frame, dFrame, TRUE, pos]} };
pin:  REF CDF.PinRec;
not:  BOOL;
root:  ROPE;
ph:  Ph;
FOR pinIndex: INT IN [0..shell.pins[side].seqSize) DO
done:  BOOL;
pin ← shell.pins[side][pinIndex];
[not, root, ph] ← ParsePinName[pin.name];
[drivers, , done, ] ← AddPin[drivers];
IF NOT done THEN {
IF Rope.Equal[root, "VDD"] THEN LOOP;
IF Rope.Equal[root, "GND"] THEN LOOP;
IF Rope.Equal[root, "PhA"] THEN LOOP;
IF Rope.Equal[root, "PhB"] THEN LOOP;
log.PutF["\n Orphan pin: %g", IO.rope[pin.name]];
}
ENDLOOP;
RETURN[drivers] };
GetAvePos: PROC[frame: Frame] RETURNS[INT] = {
IF frame.shell.size.x=unk THEN RETURN[0];
RETURN[frame.shell.pos.x/frame.shell.size.x]};
IncrAvePos: PROC[frame: Frame, pos: INT] = {
IF frame.shell.size.x=unk THEN frame.shell.size.x ← 0;
IF frame.shell.pos.x=unk THEN frame.shell.pos ← [0,0];
frame.shell.size.x ← frame.shell.size.x + 1;
frame.shell.pos.x  ← frame.shell.pos.x + pos};
ListOrphanFrames: PROC[frame: Frame] = {
LOF: CDF.EnumProc =
{IF frame.shell.size.x<0 THEN log.PutF["\n Orphan frame: %g", IO.rope[frame.shell.name]]};
CDF.EnumFrameTopFirst[frame, LOF]};
ReorderFrameBasedOnAvePos: PUBLIC PROC[frame: Frame] = { -- shell.pos.x/shell.size.x
found: BOOLTRUE;
ListOrphanFrames[frame];
IF frame.unordered THEN WHILE found DO
found ← FALSE;
IF frame.seqSize>0 THEN FOR index: INT IN [0..frame.seqSize-1) DO
IF GetAvePos[frame[index]] > GetAvePos[frame[index+1]] THEN {
temp: Frame  ← frame[index];
frame[index]  ← frame[index+1];
frame[index+1] ← temp;
found    ← TRUE }; ENDLOOP ENDLOOP;
FOR index: INT IN [0..frame.seqSize)
DO ReorderFrameBasedOnAvePos[frame[index]] ENDLOOP};
BitNameToSigName: PUBLIC PROC [name: ROPE] RETURNS [ROPE] ~ {
Cap: PROC[rope: ROPE, idx: INT] RETURNS[ROPE] = {
char: CHAR ← rope.Fetch[idx+1];
IF char IN ['a..'z] THEN char ← char + LOOPHOLE['A - 'a];
RETURN[IO.PutFR["%g", IO.char[char]]]};
IF name = NIL THEN RETURN[NIL];
name ← Rope.Cat[Cap[name, -1], name.Substr[1]];
DO
index: INT ← name.Index[0, "."];
IF index+1 >= name.Length[] OR name.Fetch[index+1] IN ['0..'9] THEN RETURN[name];
name ← Rope.Cat[name.Substr[0,index], Cap[name, index], name.Substr[index+2]];
ENDLOOP };
ParsePinName: PUBLIC PROC [name: ROPE] RETURNS [not: BOOL, root: ROPE, ph: Ph] ~ {
phasesize: ARRAY Ph OF INT ← [1,1,2,2,2,2,0];
sufix: ROPE;
end: INT;
not4: BOOL ← Rope.Equal[name.Substr[0, 4], "Not.", FALSE];
not3: BOOL ← Rope.Equal[name.Substr[0, 3], "Not", FALSE];
name ← name.Substr[start: (IF not4 THEN 4 ELSE IF not3 THEN 3 ELSE 0)];
not ← not3 OR not4;
end ← name.Index[0, "."];
root ← name.Substr[0, end];
sufix ← IF end< name.Length THEN name.Substr[end] ELSE NIL;
ph ← SELECT name.Fetch[root.Length[]-1] FROM
'A => SELECT root.Fetch[root.Length[]-2] FROM 'B=> BA,   ENDCASE => A,
'B => SELECT root.Fetch[root.Length[]-2] FROM 'A=> AB,   ENDCASE => B,
'c => SELECT root.Fetch[root.Length[]-2] FROM 'A=> Ac, 'B=> Bc, ENDCASE => unk,
ENDCASE => unk;
root ← root.Substr[0, root.Length[]-phasesize[ph]];
root ← root.Cat[sufix] };
SignalName: PUBLIC PROC [not: BOOL, positive, negative: ROPE, ph: Ph]
RETURNS [name: ROPE] ~ {
PhRope: ARRAY Ph OF ROPE ← ["A", "B", "AB", "BA", "Ac", "Bc", ""];
altName, phRope: ROPE;
end: INT;
IF not
THEN {name ← negative; altName ← positive}
ELSE {name ← positive; altName ← negative};
phRope ← PhRope[ph];
IF name = NIL THEN name ← Rope.Cat["Not", altName];
end ← name.Index[0, "."];
name ← name.Substr[0, end].Cat[phRope, name.Substr[end]]};
DriverPinName: PUBLIC PROC[type: DriverPinType, driver: REF DriveRec]
RETURNS [name: ROPE] = {
RETURN[ SELECT type FROM
in => SignalName[driver.in.pol = neg, driver.name, driver.nameInv, driver.in.ph],
out0 => SignalName[driver.out.pol = neg, driver.name, driver.nameInv, driver.out.ph],
out1 => IF ~driver.dualOut THEN NIL ELSE
SignalName[   driver.out.pol # neg, driver.name, driver.nameInv, driver.out.ph]
ENDCASE => ERROR]};
DriverFill: PUBLIC PROC RETURNS[frame: Frame] = {
frame  ← CDF.NewFrame[2, x, CDF.ID["DriverFill"]];
frame[0] ← CDF.Glue[];
frame[1] ← CDF.NewObjectFrame[DriverCell[static, extend]]};
DriverExt: PUBLIC PROC[up: BOOLFALSE] RETURNS[frame: Frame] = {
frame  ← CDF.NewFrame[2, x, CDF.ID["DriverFill"]];
frame[0] ← IF up THEN CDF.Glue[t:ext, b:conn] ELSE CDF.Glue[t:conn, b:ext];
frame[1] ← CDF.NewObjectFrame[DriverCell[static, extend]]};
DriverCell: PUBLIC PROC[
plaType:  PLAType,
drRowType: RowType,
driver:  REF DriveRec ← NIL,
design:  CD.Design  ← NIL]
RETURNS[cell: CD.Object] = {
renameProc: PWPins.RenameProc ~ { -- newRope oldRope
RETURN[ SELECT TRUE FROM
Rope.Equal[oldRope, "in"]  => DriverPinName[in,  driver],
Rope.Equal[oldRope, "out0"] => DriverPinName[out0, driver],
Rope.Equal[oldRope, "out1"] => DriverPinName[out1, driver],
ENDCASE       => oldRope]};
drName:  ROPE;
found:  BOOL;
drTiles:  REF DrTileRec ← GetDriverTiles[];
decoderOut: BOOL ← plaType=decoder AND drRowType=conn AND driver.drDir=out;
IF plaType=decoder THEN plaType ← static;
IF drRowType#conn THEN RETURN[drTiles.nconn[plaType][drRowType]];
drName ← GenDriverName[driver];
IF decoderOut THEN drName ← Rope.Cat["D", drName];
[found, cell] ← CDDirectory.Fetch[design, drName];
IF ~found THEN {
list: PW.ListOb;
tiles: REF DrTileArray ← drTiles.conn[driver.drDir];
list ← CONS[tiles[IF driver.ref.pol=driver.in.pol THEN inPos ELSE inNeg ], list];
list ← CONS[tiles[IF driver.ref.ph=A    THEN latchA ELSE latchB  ], list];
list ← CONS[tiles[latch], list];
list ← IF driver.drDir=in THEN list ELSE CONS[tiles[SELECT driver.gate FROM
neg  => gateN,
negAc => gateA,
negBc  => gateB,
pos  => gateP,
ENDCASE => ERROR], list];
list ← CONS[tiles[(IF (driver.ref.pol=driver.out.pol)=(driver.gate=pos)
THEN (IF driver.dualOut THEN posDual ELSE posSing)
ELSE (IF driver.dualOut THEN negDual ELSE negSing)) ], list];
IF driver.drDir=out THEN list ← PW.Reverse[list];
cell ← PW.AbutListX[design, list];
IF decoderOut THEN cell ← PW.AbutY[design, drTiles.nconn[decoder][blank], cell];
PW.RenameObject[design, cell, drName] };
cell ← PWPins.RenamePins[design, cell, renameProc];
PW.RenameObject[design, cell, SignalName
[driver.out.pol=neg, driver.name, driver.nameInv, driver.out.ph]]};
BuildDrivers: PUBLIC PROC[frame: Frame, design: CD.Design] = {
IF frame.seqSize > 0
THEN FOR index: INT IN [0..frame.seqSize)
DO BuildDrivers[frame[index], design] ENDLOOP
ELSE {
driver: REF DriveRec ← NARROW[frame.data];
frame.data ← DriverCell[static, conn, driver, design];
frame.shell ← CDF.ShellFromObject[NARROW[frame.data]]} };
GenDriverName: PUBLIC PROC[driver: REF DriveRec] RETURNS[name: ROPE] = {
name ← "Dr";
name ← name.Cat[IF driver.drDir = in     THEN "In" ELSE "Out"];
name ← name.Cat[IF driver.ref.pol=driver.in.pol   THEN "Pos" ELSE "Neg"];
name ← name.Cat[IF driver.ref.ph=A      THEN "A" ELSE "B"];
name ← name.Cat[SELECT driver.gate FROM
neg  => "Neg",
negAc => "NAc",
negBc  => "NAc",
pos  => "",
ENDCASE => ERROR];
name ← name.Cat[
IF (driver.ref.pol=driver.out.pol)=(driver.gate=pos)  THEN "Pos" ELSE "Neg"];
name ← name.Cat[IF driver.dualOut       THEN "Dual" ELSE "Sing"]};
log: IO.STREAMCDF.GetLog[];
END.