IFUPWContALPs:
CEDAR
PROGRAM
IMPORTS Basics, CDExpr, CDPinObjects, IFUPW, IFUPWControl, IO, PLAOps, PW, REFBit, Rope, TerminalIO, ViewerIO
EXPORTS IFUPWControl =
BEGIN OPEN IFUPWControl;
CreateAlpsFromDrivers:
PUBLIC
PROC [desc: PLADescription, log:
IO.
STREAM]
RETURNS [drives, pla: CD.Object] = {
CheckSufficientDesc[desc];
BuildConnTranslationArray[desc];
ZeroUnusedTTTOutputs[desc];
CheckPLACompress[desc, log];
LoadPLATiles[desc];
DefinePLARows[desc];
drives ← AssembleDrivers[desc];
pla ← AssembleRows[desc] };
IFUPWControlProc:
PUBLIC
PW.UserProc = {
logName: Rope.ROPE;
log: IO.STREAM;
drives, pla: CD.Object;
fileName: ROPE ← TerminalIO.RequestRope["PLA specification file: "];
desc: PLADescription ← ReadParameters[fileName];
CheckSufficientDesc[desc];
desc.design ← design;
logName ← fileName.Cat[".log"];
log ← ViewerIO.CreateViewerStreams[logName, NIL, logName].out;
[drives, pla] ← CreatePLAFromDesc[desc, log];
RETURN[PW.AbutX[desc.design, drives, pla]]};
See InstrDecode.plaSpec for example of a .plaSpec file.
ReadParameters:
PROC [fileName:
ROPE]
RETURNS [desc: PLADescription] = {
ref: REF;
desc ← NEW[PLADescriptionRec ← [plaSpecFile: fileName] ];
desc.symTab ← CDExpr.ReadFile[desc.plaSpecFile]; -- Read xxx.plaSpec
ref ← CDExpr.FetchRef[desc.symTab, "TypedTruthTableFile"].val;
IF ref = NIL OR NOT ISTYPE[ref, REF ROPE] THEN ERROR;
desc.tttFile ← NARROW[ref, REF ROPE]^;
desc.ttt ← PLAOps.ReadPLAFile[desc.tttFile];
ref ← CDExpr.FetchRef[desc.symTab, "
InputNames"].val;
IF ref # NIL THEN desc.plaInNames ← ToRopeList[NARROW[ref]];
ref ← CDExpr.FetchRef[desc.symTab, "
OutputNames"].val;
IF ref # NIL THEN desc.plaOutNames ← ToRopeList[NARROW[ref]];
ref ← CDExpr.FetchRef[desc.symTab, "
Signals"].val;
IF ref # NIL THEN desc.drSignalOrder ← ToRopeList[NARROW[ref]];
Check for renaming parameters and renamed signals
ref ← CDExpr.FetchRef[desc.symTab, "
PLAParams"].val;
IF ref = NIL OR NOT ISTYPE[ref, PLAParams] THEN ERROR;
desc.plaParams ←
NARROW[ref];
IF desc.plaParams.tileFile = NIL OR NOT ISTYPE[desc.plaParams.tileFile, ROPE] THEN ERROR};
CheckSufficientDesc:
PROC [desc: PLADescription] = {
IF desc.drivers#
NIL
THEN {
drivers: REF DriveSeq ← NARROW[desc.drivers];
plaInputRecordRef: REF ← NIL;
FOR index:
INT
DECREASING
IN [0..drivers.size)
DO
driver: REF DriveRec ← NARROW[drivers[index]];
name: ROPE ← driver.name;
IF name=NIL THEN name ← Rope.Cat["Not",driver.nameInv];
SELECT driver.cellType
FROM
pla => {
IF desc.ttt = NIL THEN desc.ttt ← NARROW[driver.cellData];
IF desc.ttt=NIL THEN ERROR;
IF driver.drDir = out THEN desc.plaOutNames ← CONS[name, desc.plaOutNames];
IF desc.plaInNames=
NIL
THEN {
desc.plaInNames ← REFBit.BitNameList[ref: desc.ttt.data, both: TRUE];
FOR list:
LIST
OF
ROPE ← desc.plaInNames, list.rest
WHILE list#
NIL
DO
list.first ← BitNameToSigName[list.first] ENDLOOP}};
alps => ERROR;
conn => ERROR;
conn => {
IF desc.plaInNames=NIL THEN {
desc.plaInNames ← REFBit.BitNameList[ref: driver.refRec, both: TRUE];
FOR list: LIST OF ROPE ← desc.plaInNames, list.rest WHILE list#NIL DO
list.first ← BitNameToSigName[list.first] ENDLOOP} };
ENDCASE => ERROR;
desc.drSignalOrder ← CONS[name, desc.drSignalOrder];
ENDLOOP }
ELSE {
IF desc.ttt=NIL THEN ERROR;
IF desc.design=NIL THEN ERROR;
IF desc.plaInNames=
NIL
THEN {
desc.plaInNames ← REFBit.BitNameList[ref: desc.ttt.data, both: TRUE];
FOR list:
LIST
OF
ROPE ← desc.plaInNames, list.rest
WHILE list#
NIL
DO
list.first ← BitNameToSigName[list.first] ENDLOOP};
IF desc.plaOutNames=
NIL
THEN {
desc.plaOutNames ← REFBit.BitNameList[ref: desc.ttt.out, both: FALSE];
FOR list:
LIST
OF
ROPE ← desc.plaOutNames, list.rest
WHILE list#
NIL
DO
list.first ← BitNameToSigName[list.first] ENDLOOP};
IF desc.drSignalOrder=
NIL
THEN desc.drSignalOrder ← ListConcat[desc.plaInNames, desc.plaOutNames] };
IF desc.design=NIL THEN ERROR;
IF desc.plaParams=NIL THEN desc.plaParams ← NEW[PLAParamsRec ← [ ]];
IF desc.plaParams.tileFile=NIL THEN desc.plaParams.tileFile ← "IFUPWControl.dale";
IF desc.drivers#NIL THEN desc.plaParams.minConnSpace ← 2};
BuildConnTranslationArray:
PROC [desc: PLADescription ] = {
index: INT ← -1;
smlOutNames: LIST OF ROPE;
PW.Output["Building pla translation array\n"];
desc.connSeq will contain indexes relative to the big (original) PLA
desc.connSeq ← NEW[ConnSeqRec[ListLength[desc.drSignalOrder]]];
FOR list:
LIST
OF
ROPE ← desc.drSignalOrder, list.rest
WHILE list#
NIL
DO
pos: INT ← ListItemIndex[desc.plaInNames, list.first];
index ← index+1;
IF pos#-1
THEN {
desc.connSeq[index] ← [index: pos/2, isOutput: FALSE, isLeftSide: (pos MOD 2 = 0)];
LOOP};
pos ← ListItemIndex[desc.plaOutNames, list.first];
IF pos=-1 THEN ERROR; -- Signal name not found;
smlOutNames ← CONS[list.first, smlOutNames];
desc.connSeq[index] ← [index: pos, isOutput: TRUE, isLeftSide: FALSE];
ENDLOOP;
smlOutNames ← ReverseList[smlOutNames];
desc.smlToBigOut ← NEW[XsFormSeqRec[ListLength[smlOutNames]]];
FOR i:
CARDINAL
IN [0..desc.smlToBigOut.size)
DO
desc.smlToBigOut[i] ← ListItemIndex[desc.plaOutNames, ListIndexItem[smlOutNames, i]]
ENDLOOP;
desc.plaOutNames ← smlOutNames;
IF desc.drivers#
NIL
THEN {
drivers: REF DriveSeq ← NARROW[desc.drivers];
FOR index
IN [0..desc.connSeq.size)
DO
driver: REF DriveRec ← NARROW[drivers[index]];
IF driver=NIL THEN ERROR;
desc.connSeq[index].dr ← driver ENDLOOP} };
ZeroUnusedTTTOutputs:
PROC [desc: PLADescription ] = {
maskTerm: PLAOps.Term ← PLAOps.CopyTerm[desc.ttt.termList.begin];
PW.Output["Zero unused TTT outputs\n"];
FOR i:
CARDINAL
IN [0..maskTerm.out.wdSize)
DO maskTerm.out[i] ← PLAOps.initOutQrtWz ENDLOOP;
FOR index:
INT
IN [0..desc.smlToBigOut.size)
DO
pos: INT ← desc.smlToBigOut[index];
PLAOps.SetOutQrt[one, maskTerm, REFBit.Desc[desc.ttt.out].bitForm[pos].firstBit] ENDLOOP;
FOR term: PLAOps.Term ← desc.ttt.termList.begin, term.next
WHILE term#
NIL
DO
FOR i:
CARDINAL
IN [0..maskTerm.out.wdSize)
DO
term.out[i].d ← Basics.BITAND[term.out[i].d, maskTerm.out[i].d] ENDLOOP ENDLOOP };
CheckPLACompress:
PROC [desc: PLADescription, log:
IO.
STREAM ] = {
IF desc.doCompleteSum
THEN
[ ] ← PLAOps.ConvertTermListToCompleteSum[
list: desc.ttt.termList,
addMerges: desc.csAddMerges,
addConsensus: desc.csAddConsensus,
log: log ];
IF desc.doMinimization
THEN {
[ ] ← PLAOps.FindAMinimalCover[
list: desc.ttt.termList,
time: desc.timeOutMinutes,
log: log ]};
desc.nextTerm ← desc.ttt.termList.begin };
ToRopeList:
PROC [ refList:
LIST
OF
REF ]
RETURNS [ ropeList: RopeList ] = {
FOR l:
LIST
OF
REF ← refList, l.rest
UNTIL l =
NIL
DO
IF l.first # NIL AND NOT ISTYPE[l.first, ROPE] THEN ERROR;
ENDLOOP;
TRUSTED {ropeList ← LOOPHOLE[refList]} };
GlobalTiles: RECORD[glue: REF GlueTiles, and, or: REF NormalTiles];
LoadPLATiles:
PROC [desc: PLADescription ] = {
OPEN desc.plaParams;
tileDefDesign: CD.Design;
IF glueTiles#NIL AND andTiles#NIL AND orTiles#NIL THEN RETURN;
glueTiles ← GlobalTiles.glue;
andTiles ← GlobalTiles.and;
orTiles ← GlobalTiles.or;
IF glueTiles#NIL AND andTiles#NIL AND orTiles#NIL THEN RETURN;
PW.Output["Initialize pla tiles\n"];
tileDefDesign ← PW.OpenDesign[tileFile];
IF tileDefDesign=
NIL
THEN
ERROR PW.Error[MissingDesign, "TileSet design not found or empty"];
glueTiles ← NEW[GlueTileArray];
andTiles ← NEW[NormalTileArray];
orTiles ← NEW[NormalTileArray];
glueTiles [xheader][leftSide] ← PW.Get[design: tileDefDesign, name: "XLeftSide" ];
glueTiles [xheader][between] ← PW.Get[design: tileDefDesign, name: "XBetween" ];
glueTiles [xheader][rightSide] ← PW.Get[design: tileDefDesign, name: "XOrEx" ];
andTiles [xheader][nc] ← PW.Get[design: tileDefDesign, name: "XAnd" ];
andTiles [xheader][extra] ← PW.Get[design: tileDefDesign, name: "XAndEx" ];
orTiles [xheader][nc] ← PW.Get[design: tileDefDesign, name: "XOr" ];
orTiles [xheader][extra] ← PW.Get[design: tileDefDesign, name: "XOrEx" ];
glueTiles [header][leftSide] ← PW.Get[design: tileDefDesign, name: "HLeftSide" ];
glueTiles [header][between] ← PW.Get[design: tileDefDesign, name: "HBetween" ];
glueTiles [header][rightSide] ← PW.Get[design: tileDefDesign, name: "HOrEx" ];
andTiles [header][nc] ← PW.Get[design: tileDefDesign, name: "HAnd" ];
andTiles [header][extra] ← PW.Get[design: tileDefDesign, name: "HAndEx" ];
orTiles [header][nc] ← PW.Get[design: tileDefDesign, name: "HOr" ];
orTiles [header][extra] ← PW.Get[design: tileDefDesign, name: "HOrEx" ];
glueTiles [footer][leftSide] ← PW.FlipY[tileDefDesign, glueTiles [header][leftSide] ];
glueTiles [footer][between] ← PW.FlipY[tileDefDesign, glueTiles [header][between] ];
glueTiles [footer][rightSide] ← PW.FlipY[tileDefDesign, glueTiles [header][rightSide] ];
andTiles [footer][nc] ← PW.FlipY[tileDefDesign, andTiles [header][nc] ];
andTiles [footer][extra] ← PW.FlipY[tileDefDesign, andTiles [header][extra] ];
orTiles [footer][nc] ← PW.FlipY[tileDefDesign, orTiles [header][nc] ];
orTiles [footer][extra] ← PW.FlipY[tileDefDesign, orTiles [header][extra] ];
glueTiles [blank][leftSide] ← PW.Get[design: tileDefDesign, name: "BLeftSide" ];
glueTiles [blank][between] ← PW.Get[design: tileDefDesign, name: "BBetween" ];
glueTiles [blank][rightSide] ← PW.Get[design: tileDefDesign, name: "BRightSide" ];
andTiles [blank][nc] ← PW.Get[design: tileDefDesign, name: "BAnd" ];
andTiles [blank][extra] ← PW.Get[design: tileDefDesign, name: "BAndEx" ];
orTiles [blank][nc] ← PW.Get[design: tileDefDesign, name: "BOr" ];
orTiles [blank][extra] ← PW.Get[design: tileDefDesign, name: "BOrEx" ];
glueTiles [conn][leftSide] ← PW.Get[design: tileDefDesign, name: "CLeftSide" ];
glueTiles [conn][between] ← PW.Get[design: tileDefDesign, name: "CBetween" ];
glueTiles [conn][rightSide] ← PW.Get[design: tileDefDesign, name: "CRightSide" ];
andTiles [conn][left] ← PW.Get[design: tileDefDesign, name: "CAndLt" ];
andTiles [conn][right] ← PW.Get[design: tileDefDesign, name: "CAndRt" ];
andTiles [conn][nc] ← PW.Get[design: tileDefDesign, name: "CAndNC" ];
andTiles [conn][extra] ← PW.Get[design: tileDefDesign, name: "CAndEx" ];
orTiles [conn][left] ← PW.Get[design: tileDefDesign, name: "COr" ];
orTiles [conn][nc] ← PW.Get[design: tileDefDesign, name: "COrNC" ];
orTiles [conn][extra] ← PW.Get[design: tileDefDesign, name: "COrEx" ];
glueTiles [dataUp][leftSide] ← PW.Get[design: tileDefDesign, name: "DLeftSide" ];
glueTiles [dataUp][between] ← PW.Get[design: tileDefDesign, name: "DBetween" ];
glueTiles [dataUp][rightSide] ← PW.Get[design: tileDefDesign, name: "DRightSide" ];
andTiles [dataUp][left] ← PW.Get[design: tileDefDesign, name: "DAndLt" ];
andTiles [dataUp][right] ← PW.Get[design: tileDefDesign, name: "DAndRt" ];
andTiles [dataUp][nc] ← PW.Get[design: tileDefDesign, name: "DAndNC" ];
andTiles [dataUp][extra] ← PW.Get[design: tileDefDesign, name: "DAndEx" ];
orTiles [dataUp][left] ← PW.Get[design: tileDefDesign, name: "DOr" ];
orTiles [dataUp][nc] ← PW.Get[design: tileDefDesign, name: "DOrNC" ];
orTiles [dataUp][extra] ← PW.Get[design: tileDefDesign, name: "DOrEx" ];
glueTiles [dataDn][leftSide] ← glueTiles [dataUp][leftSide];
glueTiles [dataDn][between] ← glueTiles [dataUp][between];
glueTiles [dataDn][rightSide] ← PW.FlipY[tileDefDesign, glueTiles [dataUp][rightSide] ];
andTiles [dataDn][left] ← andTiles [dataUp][left];
andTiles [dataDn][right] ← andTiles [dataUp][right];
andTiles [dataDn][nc] ← andTiles [dataUp][nc];
andTiles [dataDn][extra] ← andTiles [dataUp][extra];
orTiles [dataDn][left] ← PW.FlipY[tileDefDesign, orTiles [dataUp][left] ];
orTiles [dataDn][nc] ← PW.FlipY[tileDefDesign, orTiles [dataUp][nc] ];
orTiles [dataDn][extra] ← PW.FlipY[tileDefDesign, orTiles [dataUp][extra] ];
GlobalTiles ← [glueTiles, andTiles, orTiles]};
DefinePLARows:
PROC [desc: PLADescription] = {
firstRow: BOOL ← TRUE;
index: INT ← 0;
termUp: BOOL ← TRUE;
nofIns: INT ← ListLength[desc.plaInNames];
nofOuts: INT ← ListLength[desc.plaOutNames];
cRowsLeft: INT ← ListLength[desc.drSignalOrder];
dRowsLeft: INT ← desc.ttt.termList.length;
hRowsLeft: INT;
dRowsLeft ← MAX[dRowsLeft, cRowsLeft*(desc.plaParams.minConnSpace)];
hRowsLeft ← (dRowsLeft+ desc.plaParams.termsPerHeader/2)/desc.plaParams.termsPerHeader;
PW.Output["Assign pla row types\n"];
desc.nofAndCols ← nofIns/2 + (nofIns/2 -1) / desc.plaParams.insPerExtra;
desc.nofOrCols ← nofOuts + (nofOuts -1) / desc.plaParams.outsPerExtra;
desc.rows ← NEW[RowsRec[cRowsLeft+dRowsLeft+2*hRowsLeft]];
WHILE hRowsLeft#0
DO
-- actually one more header is appended afterwards
RperH: INT ← (cRowsLeft+dRowsLeft+hRowsLeft + hRowsLeft/2)/hRowsLeft;
IF firstRow
THEN firstRow←FALSE
ELSE {desc.rows[index] ← NextRow[desc, xheader]; index←index+1};
desc.rows[index] ← NextRow[desc, header];
index←index+1; RperH←RperH-1; hRowsLeft←hRowsLeft-1;
WHILE RperH > 0
DO
CperD, DperC: INT;
CperD ← MAX[1, (cRowsLeft + dRowsLeft/2)/dRowsLeft];
DperC ← MAX[1, (dRowsLeft + cRowsLeft/2)/cRowsLeft];
IF DperC < desc.plaParams.minConnSpace
OR
(CperD>1) AND (desc.plaParams.minConnSpace>0) THEN ERROR;
RperH ← RperH - CperD - DperC;
WHILE CperD > 0
DO
desc.rows[index] ← NextRow[desc, conn];
index←index+1; cRowsLeft𡤌RowsLeft-1; CperD𡤌perD-1;
ENDLOOP;
termUp ← TRUE;
WHILE DperC > 0
DO
desc.rows[index] ← NextRow[desc, IF termUp THEN dataUp ELSE dataDn];
index←index+1; dRowsLeft𡤍RowsLeft-1; DperC𡤍perC-1;
termUp ← NOT termUp;
ENDLOOP;
ENDLOOP;
ENDLOOP;
IF index+1#desc.rows.size THEN ERROR;
desc.rows[index] ← NextRow[desc, footer] };
NextRow:
PROC [desc: PLADescription, type: RowType]
RETURNS[row: RowRef] = {
andIndex, orIndex, index: INT ← 0;
data: PLAOps.Term;
conn: Connection;
row ← NEW[RowRec ← [type: type]];
row.and ← NEW[ColSeqRec[desc.nofAndCols]];
IF desc.nofOrCols#0 THEN row.or ← NEW[ColSeqRec[desc.nofOrCols]];
SELECT type
FROM
header => { };
conn => {conn ← NextConnection[desc]; row.dr ← conn.dr};
dataUp, dataDn => {
data ← NextDataTerm[desc];
row.dr ← NIL;
IF data=NIL THEN type ← row.type ← blank};
ENDCASE;
FOR index
IN[0..desc.nofAndCols)
DO
IF (index+1)
MOD (desc.plaParams.insPerExtra+1) = 0
THEN row.and[index] ← extra
ELSE {
SELECT type
FROM
dataUp, dataDn =>
SELECT PLAOps.GetInQrt
[data, REFBit.Desc[desc.ttt.data].bitForm[andIndex].firstBit]
FROM
zero => row.and[index] ← left;
one => row.and[index] ← right;
ENDCASE => row.and[index] ← nc;
conn =>
IF conn.isOutput
OR conn.index#andIndex
THEN row.and[index] ← nc
ELSE
IF conn.isLeftSide
THEN row.and[index] ← left
ELSE row.and[index] ← right;
ENDCASE => row.and[index] ← nc;
andIndex𡤊ndIndex+1 } ENDLOOP;
IF desc.nofOrCols#0
THEN
FOR index
IN[0..desc.nofOrCols)
DO
IF (index+1)
MOD (desc.plaParams.outsPerExtra+1) = 0
THEN row.or[index] ← extra
ELSE {
SELECT type
FROM
dataUp, dataDn =>
SELECT PLAOps.GetOutQrt
[data, REFBit.Desc[desc.ttt.out].bitForm[desc.smlToBigOut[orIndex]].firstBit]
FROM
one => row.or[index] ← left;
ENDCASE => row.or[index] ← nc;
conn =>
IF conn.isOutput
AND conn.index=desc.smlToBigOut[orIndex]
THEN row.or[index] ← left
ELSE row.or[index] ← nc;
ENDCASE => row.or[index] ← nc;
orIndex←orIndex+1 } ENDLOOP};
NextDataTerm:
PROC [desc: PLADescription]
RETURNS[term: PLAOps.Term] = {
term ← desc.nextTerm;
IF term#NIL THEN desc.nextTerm ← desc.nextTerm.next};
NextConnection:
PROC [desc: PLADescription]
RETURNS[conn: Connection] = {
conn ← desc.connSeq[desc.nextConn];
desc.nextConn ← desc.nextConn+1};
AssembleDrivers:
PROC[desc: PLADescription]
RETURNS[drivers:
CD.Object] = {
driverList: PW.ListOb ← NIL;
FOR driverIndex:
INT
IN [0..desc.rows.size)
DO
driverList ←
CONS[DriverCell
[desc.rows[driverIndex].type, desc.rows[driverIndex].dr, desc.design], driverList];
ENDLOOP;
drivers ← PW.AbutListY[desc.design, driverList]};
AssembleRows:
PROC[desc: PLADescription]
RETURNS[pla:
CD.Object] = {
refPhase, inputPh: Ph ← unk;
rowList: PW.ListOb ← NIL;
PW.Output["Assemble pla row cells\n"];
FOR rowIndex:
INT
IN [0..desc.rows.size)
DO
objects: PW.ListOb ← NIL;
row: RowRef ← desc.rows[rowIndex];
IF desc.rows[rowIndex].dr#NIL THEN refPhase ← desc.rows[rowIndex].dr.ref.ph;
objects ← CONS[desc.plaParams.glueTiles[row.type][leftSide], objects];
FOR index:
INT
IN [0..row.and.size)
DO
objects ← CONS[desc.plaParams.andTiles[row.type][row.and[index]], objects] ENDLOOP;
IF desc.nofOrCols#0
THEN {
objects ← CONS[desc.plaParams.glueTiles[row.type][between], objects];
FOR index:
INT
IN [0..row.or.size)
DO
objects ← CONS[desc.plaParams.orTiles[row.type][row.or[index]], objects] ENDLOOP;
objects ← CONS[desc.plaParams.glueTiles[row.type][rightSide], objects] };
rowList ← CONS[PW.AbutListX[desc.design, PW.Reverse[objects]], rowList]
ENDLOOP;
pla ← PW.AbutListY[desc.design, rowList];
inputPh ← SELECT refPhase FROM A=>BA, B=>AB, ENDCASE => ERROR;
pla ← ReNamePLAInputPins[pla, inputPh, desc]};
ReNamePLAInputPins:
PROC[pla:
CD.Object, inputPh: Ph, desc: PLADescription]
RETURNS[cell: CD.Object] = {
format: REFBit.Format ← REFBit.Desc[desc.ttt.data].bitForm;
leftSize: INT ← PW.IRSize[desc.plaParams.glueTiles[blank][leftSide]].x;
andWidth: INT ← PW.IRSize[desc.plaParams.andTiles[blank][nc]].x;
extraWidth: INT ← PW.IRSize[desc.plaParams.andTiles[blank][extra]].x;
renameProc:
IFUPW.PinNameProc ~ {
PROC[pin: CD.Instance, side: Side] RETURNS[name: ROPE]
index: INT;
oldRope: Rope.ROPE ← CDPinObjects.GetName[pin];
in0: BOOL ← Rope.Equal[oldRope, "in0"];
in1: BOOL ← Rope.Equal[oldRope, "in1"];
IF NOT(in0 OR in1) THEN RETURN[oldRope];
index ← (pin.location.x - leftSize)/(desc.plaParams.insPerExtra*andWidth+extraWidth);
index ← (pin.location.x - leftSize - extraWidth*index)/andWidth;
name ← SignalName[in1, format[index].name, format[index].nameInv, inputPh]};
cell ← IFUPW.RenameObjAndPins[desc.design, pla, "PLA", renameProc] };
ReverseList:
PUBLIC
PROC [list:
LIST
OF
ROPE]
RETURNS [new:
LIST
OF
ROPE] =
{FOR list ← list, list.rest WHILE list#NIL DO new ← CONS[list.first, new] ENDLOOP};
ListLength:
PUBLIC
PROC [list:
LIST
OF
ROPE]
RETURNS[size:
INT] =
{FOR size ← 0, size+1 WHILE list#NIL DO list←list.rest ENDLOOP};
ListIndexItem:
PUBLIC
PROC [list:
LIST
OF
ROPE, index:
INT]
RETURNS[item:
ROPE] = {
FOR index ← index, index-1 WHILE index#0 AND list#NIL DO list←list.rest ENDLOOP;
RETURN[IF list=NIL THEN NIL ELSE list.first]};
ListItemIndex:
PUBLIC
PROC [list:
LIST
OF
ROPE, item:
ROPE]
RETURNS[index:
INT] = {
IF item=NIL THEN RETURN[-1];
FOR index ← 0, index+1
WHILE list#
NIL
DO
IF Rope.Equal[list.first, item, FALSE] THEN RETURN[index];
list←list.rest ENDLOOP;
RETURN[-1]};
ListConcat:
PUBLIC
PROC [list1, list2:
LIST
OF
ROPE]
RETURNS[new: LIST OF ROPE] = {
FOR i:
INT
DECREASING
IN [0..ListLength[list2])
DO
new ← CONS[ ListIndexItem[list2, i], new] ENDLOOP;
FOR i:
INT
DECREASING
IN [0..ListLength[list1])
DO
new ← CONS[ ListIndexItem[list1, i], new] ENDLOOP};
PW.Register[userProc: IFUPWControlProc, name: "IFUPWControl"];
END.