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.
STREAM ←
IO.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: BOOL ← TRUE;
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:
BOOL ←
FALSE]
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.STREAM ← CDF.GetLog[];
END.