IFUPWContPLA:
CEDAR
PROGRAM
IMPORTS Basics, CD, CDFrame, CDPinObjects, IFUPW, IFUPWControl, IO, PLAOps, PW, REFBit, Rope
EXPORTS IFUPWControl =
BEGIN OPEN IFUPWControl;
MakePLA:
PUBLIC
PROC [
name: ROPE, plaType: PLAType, drIn, drInClk, plaIn, drOutClk, drOut: Ph←unk,
design: CD.Design, orCols: INT𡤀, termCols: INT𡤁,
fullWidthTerms:
BOOL←
FALSE, termsPerHeader:
INT ← 1000]
RETURNS[new: Frame] = {
fileName: ROPE ← Rope.Cat["IFUPLA", name, ".ttt"];
desc: IFUPWControl.PLADescription;
plaFm, outFm, inFm: Frame;
pla: PLAOps.PLA ← PLAOps.ReadPLAFile[fileName, log];
IF plaType = precharged AND termsPerHeader=1000 THEN termsPerHeader
outFm ← DrPLA[name, pla, plaType, plaIn, drOutClk, drOut];
desc ← NARROW[outFm.data];
plaFm ← DrivenPLA[ outFm, design, orCols, termCols, fullWidthTerms, termsPerHeader];
inFm ← RefToDriverFrame[name: name.Cat["InDrs"], xory: y, data:
NIL,
unordered:
FALSE, refRec: pla.data,
initial: [drDir: in, dualOut: TRUE, in:[pos, drIn], ref:[pos, drInClk], out:[pos, plaIn] ] ];
IF plaType # precharged THEN DeleteUnusedStaticInDrs[desc, inFm];
new ←
IFUPW.
NFS[name, x,
LIST[
CDFrame.Glue[l: ext, r: conn],
IFUPW.
NFS[name.Cat["Main"],
y,
LIST[
plaFm,
IFUPW.
NFS[name.Cat["InputsSBDr"],
x,
LIST[
CDFrame.Glue[t: conn, r: conn],
inFm ] ] ] ] ] ] };
DrPLA:
PUBLIC
PROC
[name:
ROPE, pla: PLAOps.
PLA, plaType: PLAType, plaIn, plaOut, drOut: Ph←unk]
RETURNS[new: Frame] = {
desc: REF PLADescriptionRec ← NEW[PLADescriptionRec];
inForm: REFBit.Format ← REFBit.Desc[pla.data].bitForm;
outForm: REFBit.Format ← REFBit.Desc[pla.out].bitForm;
new ← IFUPWControl.RefToDriverFrame[
name: name, xory: y, data: desc, unordered: TRUE, refRec: pla.out,
initial: [drDir: out, in: [neg, plaOut], ref: [pos, plaOut], out: [pos, drOut] ] ];
new ← new[1]; -- throw away xheader and xfooter frames
desc.ttt ← pla;
desc.name ← name;
desc.plaType ← plaType;
desc.drFrame ← new; -- can change
FOR i:
CARDINAL
DECREASING
IN [0..inForm.size)
DO
namePos: ROPE ← BitNameToSigName[inForm[i].name];
nameInv: ROPE ← BitNameToSigName[inForm[i].nameInv];
desc.plaInNames ← CONS[ SignalName[TRUE, namePos, nameInv, plaIn], desc.plaInNames];
desc.plaInNames ← CONS[ SignalName[FALSE, namePos, nameInv, plaIn], desc.plaInNames];
ENDLOOP;
FOR i:
CARDINAL
DECREASING
IN [0..outForm.size)
DO
namePos: ROPE ← BitNameToSigName[outForm[i].name];
nameInv: ROPE ← BitNameToSigName[outForm[i].nameInv];
desc.plaOutNames ←
CONS[ SignalName[FALSE, namePos, nameInv, plaOut], desc.plaOutNames];
ENDLOOP};
DrivenPLA:
PUBLIC
PROC [
drFrame: Frame, design: CD.Design,
orCols: INT𡤀, termCols: INT𡤁,
fullWidthTerms: BOOL←FALSE, termsPerHeader: INT ← 1000]
RETURNS [new: Frame] = {
desc: REF PLADescriptionRec ← NARROW[drFrame.data];
log.PutRope["\n"];
desc.design ← design;
desc.drFrame ← drFrame;
desc.nofOrCols ← MAX[orCols, desc.nofOrCols];
desc.nofTermCols ← MAX[termCols, desc.nofTermCols];
desc.termsPerHeader ← MIN[termsPerHeader, desc.termsPerHeader];
desc.fullWidthTerms ← fullWidthTerms OR desc.fullWidthTerms;
BuildSignalOrderListFromDrFrame[desc];
BuildConnTranslationArray[desc];
SELECT desc.plaType
FROM
precharged => MakePreChargedPLA[desc];
ENDCASE => MakeStaticPLASection[desc];
new ← CDFrame.NewFrame[2, x, desc.name.Cat["-PlaDr"] ];
new[0] ← CDFrame.NewObjectFrame[desc.cell];
new[1] ← desc.drFrame;
log.PutRope["\n"]};
CheckSize: PROC[obj1, obj2: CD.Object, xory: CDFrame.XorY, design: CD.Design] = {
size1: CD.Position ← CD.InterestSize[obj1];
size2: CD.Position ← CD.InterestSize[obj2];
IF (IF xory=x THEN size1.x#size2.x ELSE size1.y#size2.y) THEN {
viewer: ViewerClasses.Viewer;
log.PutRope["\n Checksize error \n"];
viewer ← CDViewer.CreateViewer[design];
CDOps.SetInstList[design, NIL];
CDOps.AddAnObject[design, obj1, [0, 0]];
CDOps.AddAnObject[design, obj2,
[(IF xory=y THEN size1.x ELSE 0), (IF xory=x THEN size1.y ELSE 0)]];
CDViewer.ShowAndScale[viewer, CDExtras.BoundingBox[design]];
ERROR} };
BuildSignalOrderListFromDrFrame:
PUBLIC
PROC[desc:
REF PLADescriptionRec] = {
proc: CDFrame.EnumProc = {
rec: REF DriveRec ← NARROW[frame.data];
name: ROPE ← BitNameToSigName[rec.name];
nameInv: ROPE ← BitNameToSigName[rec.nameInv];
desc.drSignalOrder ←
CONS[ SignalName[FALSE, name, nameInv, rec.in.ph], desc.drSignalOrder]};
CDFrame.EnumFrameBotOnly[desc.drFrame, proc];
desc.drSignalOrder ← ReverseList[desc.drSignalOrder]};
CreatePLAFromDesc: PUBLIC PROC [desc: PLADescription]
RETURNS [drives, pla: CD.Object] = {
log.PutRope["\n"];
CheckSufficientDesc[desc];
BuildConnTranslationArray[desc];
[pla, drives] ← SELECT desc.plaType FROM
static => MakeStaticPLASection[desc],
precharged => MakePreChargedPLA[desc],
ENDCASE => ERROR;
log.PutRope["\n"]};
IFUPWControlProc: PUBLIC PW.UserProc = {
drives, pla: CD.Object;
fileName: ROPE ← TerminalIO.RequestRope["PLA specification file: "];
desc: PLADescription ← ReadParameters[fileName];
CheckSufficientDesc[desc];
desc.design ← design;
[drives, pla] ← CreatePLAFromDesc[desc];
RETURN[PW.AbutX[desc.design, drives, pla]]};
See InstrDecode.plaSpec for example of a .plaSpec file.
ReadParameters: PROC [fileName: ROPE] RETURNS [desc: PLADescription] = {
symTab: SymTab.Ref ← NIL;
ref: REF;
desc ← NEW[PLADescriptionRec ← [plaSpecFile: fileName] ];
symTab ← CDExpr.ReadFile[desc.plaSpecFile]; -- Read xxx.plaSpec
ref ← CDExpr.FetchRef[symTab, "TypedTruthTableName"].val;
IF ref = NIL OR NOT ISTYPE[ref, REF ROPE] THEN ERROR;
desc.name ← NARROW[ref, REF ROPE]^;
desc.ttt ← PLAOps.ReadPLAFile[desc.name.Cat[".ttt"]];
ref ← CDExpr.FetchRef[symTab, "InputNames"].val;
IF ref # NIL THEN desc.plaInNames ← ToRopeList[NARROW[ref]];
ref ← CDExpr.FetchRef[symTab, "OutputNames"].val;
IF ref # NIL THEN desc.plaOutNames ← ToRopeList[NARROW[ref]];
ref ← CDExpr.FetchRef[symTab, "Signals"].val;
IF ref # NIL THEN desc.drSignalOrder ← ToRopeList[NARROW[ref]]};
CheckSufficientDesc: PROC [desc: PLADescription] = {
IF desc.drFrame#NIL THEN ERROR;
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};
BuildConnTranslationArray:
PROC [desc: PLADescription ] = {
index: INT ← -1;
smlOutNames: LIST OF ROPE;
log.PutRope["\n Building pla translation array"];
desc.connSeq will contain indexes relative to the big (original) PLA
desc.connSeq ← NEW[ConnSeq[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.drFrame#
NIL
THEN {
index: INT ← 0;
proc: CDFrame.EnumProc = {
desc.connSeq[index].dr ← NARROW[frame.data];
index ← index+1};
CDFrame.EnumFrameBotOnly[desc.drFrame, proc]} };
ZeroUnusedTTTOutputs:
PROC [desc: PLADescription ] = {
maskTerm: PLAOps.Term ← PLAOps.CopyTerm[desc.ttt.termList.begin];
log.PutRope["\n Zero unused TTT outputs"];
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 ] = {
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 ]} };
ToRopeList:
PROC [ refList:
LIST
OF
REF ]
RETURNS [ ropeList:
LIST
OF
ROPE ] = {
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]} };
MakePreChargedPLA:
PROC[desc: PLADescription] = {
ZeroUnusedTTTOutputs [desc];
CheckPLACompress [desc];
DefinePLARows [desc];
MakeOutDrs [desc];
MakePla [desc]};
PreChargedParams:
TYPE =
RECORD[
minConnSpace: INT ← 2, -- SPACING rows between driver rows;
insPerExtra: INT ← 10, -- SPACING cols between extra columns;
outsPerExtra: INT ← 10,
nextTerm: PLAOps.Term ← NIL, -- specific parameter
nextConn: INT ← 0, -- specific parameter
rows: REF RowsRec ← NIL ]; -- specific parameter
RowsRec: TYPE = RECORD[SEQUENCE size: CARDINAL OF REF RowRec];
RowRec:
TYPE =
RECORD[
dr: REF DriveRec,
type: RowType,
and: ColSeqRef,
or: ColSeqRef ];
ColSeqRef: TYPE = REF ColSeqRec;
ColSeqRec: TYPE = RECORD[SEQUENCE size: CARDINAL OF NormalCellType];
DefinePLARows:
PROC [desc: PLADescription] = {
pp:
REF PreChargedParams ←
NEW[PreChargedParams ← [nextTerm: desc.ttt.termList.begin]];
firstRow: BOOL ← TRUE;
index: INT ← 0;
termUp: BOOL ← TRUE;
nofOuts: INT ← MAX[ListLength[desc.plaOutNames], desc.nofOrCols];
nofIns: INT ← ListLength[desc.plaInNames];
cRowsLeft: INT ← ListLength[desc.drSignalOrder];
dRowsLeft: INT ← desc.ttt.termList.length;
hRowsLeft: INT;
dRowsLeft ← MAX[dRowsLeft, cRowsLeft*(pp.minConnSpace)];
hRowsLeft ← MAX[1, (dRowsLeft+ desc.termsPerHeader/2)/desc.termsPerHeader];
log.PutRope["\n Assign precharged pla row types"];
desc.data ← pp;
desc.nofAndCols ← nofIns/2 + (nofIns/2 -1) / pp.insPerExtra;
desc.nofOrCols ← nofOuts + (nofOuts -1) / pp.outsPerExtra;
pp.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 {pp.rows[index] ← NextRow[desc, xheader]; index←index+1};
pp.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 < pp.minConnSpace
OR
(CperD>1) AND (pp.minConnSpace>0) THEN ERROR;
RperH ← RperH - CperD - DperC;
WHILE CperD > 0
DO
pp.rows[index] ← NextRow[desc, conn];
index←index+1; cRowsLeft𡤌RowsLeft-1; CperD𡤌perD-1;
ENDLOOP;
termUp ← TRUE;
WHILE DperC > 0
DO
pp.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#pp.rows.size THEN ERROR;
pp.rows[index] ← NextRow[desc, footer]};
NextRow:
PROC [desc: PLADescription, type: RowType]
RETURNS[row:
REF RowRec] = {
pp: REF PreChargedParams ← NARROW[desc.data];
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 (pp.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 (pp.outsPerExtra+1) = 0
THEN row.or[index] ← extra
ELSE {
row.or[index] ← nc;
IF orIndex < desc.smlToBigOut.size
THEN {
IF (type=dataUp
OR type=dataDn)
AND PLAOps.GetOutQrt
[data, REFBit.Desc[desc.ttt.out].bitForm[desc.smlToBigOut[orIndex]].firstBit]=one
THEN row.or[index] ← left;
IF type=conn
AND conn.isOutput
AND conn.index=desc.smlToBigOut[orIndex]
THEN row.or[index] ← left };
orIndex←orIndex+1 } ENDLOOP};
NextDataTerm:
PROC [desc: PLADescription]
RETURNS[term: PLAOps.Term] = {
pp: REF PreChargedParams ← NARROW[desc.data];
term ← pp.nextTerm;
IF term#NIL THEN pp.nextTerm ← pp.nextTerm.next};
NextConnection:
PROC [desc: PLADescription]
RETURNS[conn: Connection] = {
pp: REF PreChargedParams ← NARROW[desc.data];
conn ← desc.connSeq[pp.nextConn];
pp.nextConn ← pp.nextConn+1};
MakeOutDrs:
PROC[desc: PLADescription] = {
pp: REF PreChargedParams ← NARROW[desc.data];
new: Frame;
last: INT ← -1-pp.minConnSpace;
cnt: INT ← 0;
list: LIST OF Frame;
FOR driverIndex:
INT
IN [0..pp.rows.size)
DO
SELECT pp.rows[driverIndex].type
FROM
header, xheader, footer => {
IF (driverIndex-last) <= pp.minConnSpace THEN ERROR;
last ← driverIndex-pp.minConnSpace};
blank, dataUp, dataDn => {
IF (driverIndex-last) <= pp.minConnSpace THEN LOOP};
conn => {
IF (driverIndex-last) <= pp.minConnSpace THEN ERROR;
last ← driverIndex}
ENDCASE => ERROR;
list ←
CONS[CDFrame.NewObjectFrame[ DriverCell
[precharged, pp.rows[driverIndex].type, pp.rows[driverIndex].dr, desc.design]], list];
cnt ← cnt+1;
ENDLOOP;
new ← CDFrame.NewFrame[cnt, y, desc.name.Cat["-OutDr"]];
FOR ii: INT IN [0..cnt) DO new[ii] ← list.first; list ← list.rest ENDLOOP;
desc.drFrame ← new};
MakePla:
PROC[desc: PLADescription] = {
tiles: REF TileVarieties ← GetPLATiles[ ];
pp: REF PreChargedParams ← NARROW[desc.data];
refPhase: Ph ← unk;
rowList: PW.ListOb ← NIL;
log.PutRope["\n Assemble precharged pla row cells"];
FOR rowIndex:
INT
IN [0..pp.rows.size)
DO
objects: PW.ListOb ← NIL;
row: REF RowRec ← pp.rows[rowIndex];
IF pp.rows[rowIndex].dr#NIL THEN refPhase ← pp.rows[rowIndex].dr.ref.ph;
objects ← CONS[tiles.glue[row.type][leftSide], objects];
FOR index:
INT
IN [0..row.and.size)
DO
objects ← CONS[tiles.and[row.type][row.and[index]], objects] ENDLOOP;
IF desc.nofOrCols#0
THEN {
objects ← CONS[tiles.glue[row.type][between], objects];
FOR index:
INT
IN [0..row.or.size)
DO
objects ← CONS[tiles.or[row.type][row.or[index]], objects] ENDLOOP;
objects ← CONS[tiles.glue[row.type][rightSide], objects] };
rowList ← CONS[PW.AbutListX[desc.design, PW.Reverse[objects]], rowList]
ENDLOOP;
desc.cell ← PW.AbutListY[desc.design, rowList];
ReNamePLAInputPins[desc]};
ReNamePLAInputPins:
PROC[desc: PLADescription] = {
pp: REF PreChargedParams ← NARROW[desc.data];
tiles: REF TileVarieties ← GetPLATiles[ ];
format: REFBit.Format ← REFBit.Desc[desc.ttt.data].bitForm;
leftSize: INT ← CD.InterestSize[tiles.glue[blank][leftSide]].x;
andWidth: INT ← CD.InterestSize[tiles.and[blank][nc]].x;
extraWidth: INT ← CD.InterestSize[tiles.and[blank][extra]].x;
renameProc:
IFUPW.PinNameProc ~ {
list: LIST OF ROPE ← desc.plaInNames;
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)/(pp.insPerExtra*andWidth+extraWidth);
index ← (pin.location.x - leftSize - extraWidth*index)/andWidth;
WHILE index#0 DO list ← list.rest.rest; index ← index-1 ENDLOOP;
name ← IF in1 THEN list.rest.first ELSE list.first};
desc.cell ← IFUPW.RenameObjAndPins[desc.design, desc.cell, desc.name, renameProc] };
plaTilesDesign: CD.Design;
tileBuffer: REF TileVarieties;
TileVarieties: TYPE = RECORD[glue: REF GlueTiles, and, or: REF NormalTiles];
GlueTiles: TYPE = ARRAY RowType OF ARRAY GlueCellType OF CD.Object;
GlueCellType: TYPE = {leftSide, between, rightSide};
NormalTiles: TYPE = ARRAY RowType OF ARRAY NormalCellType OF CD.Object;
NormalCellType: TYPE = {left, right, nc, extra};
GetPLATiles:
PROC
RETURNS[tiles:
REF TileVarieties] = {
tDesign: CD.Design;
IF tileBuffer#NIL THEN RETURN[tileBuffer];
log.PutRope["\n Initialize precharged PLA tiles"];
tDesign ← plaTilesDesign← PW.OpenDesign["IFUPWControl.dale"];
IF tDesign=
NIL
THEN
ERROR PW.Error[MissingDesign, "TileSet design not found or empty"];
tiles ← tileBuffer ← NEW[TileVarieties];
tiles.glue ← NEW[GlueTiles];
tiles.and ← NEW[NormalTiles];
tiles.or ← NEW[NormalTiles];
tiles.glue [xheader][leftSide] ← PW.Get[design: tDesign, name: "XLeftSide" ];
tiles.glue [xheader][between] ← PW.Get[design: tDesign, name: "XBetween" ];
tiles.glue [xheader][rightSide] ← PW.Get[design: tDesign, name: "XOrEx" ];
tiles.and [xheader][nc] ← PW.Get[design: tDesign, name: "XAnd" ];
tiles.and [xheader][extra] ← PW.Get[design: tDesign, name: "XAndEx" ];
tiles.or [xheader][nc] ← PW.Get[design: tDesign, name: "XOr" ];
tiles.or [xheader][extra] ← PW.Get[design: tDesign, name: "XOrEx" ];
tiles.glue [header][leftSide] ← PW.Get[design: tDesign, name: "HLeftSide" ];
tiles.glue [header][between] ← PW.Get[design: tDesign, name: "HBetween" ];
tiles.glue [header][rightSide] ← PW.Get[design: tDesign, name: "HOrEx" ];
tiles.and [header][nc] ← PW.Get[design: tDesign, name: "HAnd" ];
tiles.and [header][extra] ← PW.Get[design: tDesign, name: "HAndEx" ];
tiles.or [header][nc] ← PW.Get[design: tDesign, name: "HOr" ];
tiles.or [header][extra] ← PW.Get[design: tDesign, name: "HOrEx" ];
tiles.glue [footer][leftSide] ← PW.FlipY[tDesign, tiles.glue [header][leftSide] ];
tiles.glue [footer][between] ← PW.FlipY[tDesign, tiles.glue [header][between] ];
tiles.glue [footer][rightSide] ← PW.FlipY[tDesign, tiles.glue [header][rightSide] ];
tiles.and [footer][nc] ← PW.FlipY[tDesign, tiles.and [header][nc] ];
tiles.and [footer][extra] ← PW.FlipY[tDesign, tiles.and [header][extra] ];
tiles.or [footer][nc] ← PW.FlipY[tDesign, tiles.or [header][nc] ];
tiles.or [footer][extra] ← PW.FlipY[tDesign, tiles.or [header][extra] ];
tiles.glue [blank][leftSide] ← PW.Get[design: tDesign, name: "BLeftSide" ];
tiles.glue [blank][between] ← PW.Get[design: tDesign, name: "BBetween" ];
tiles.glue [blank][rightSide] ← PW.Get[design: tDesign, name: "BOrEx" ];
tiles.and [blank][nc] ← PW.Get[design: tDesign, name: "BAnd" ];
tiles.and [blank][extra] ← PW.Get[design: tDesign, name: "BAndEx" ];
tiles.or [blank][nc] ← PW.Get[design: tDesign, name: "BOr" ];
tiles.or [blank][extra] ← PW.Get[design: tDesign, name: "BOrEx" ];
tiles.glue [conn][leftSide] ← PW.Get[design: tDesign, name: "BLeftSide" ];
tiles.glue [conn][between] ← PW.Get[design: tDesign, name: "BBetween" ];
tiles.glue [conn][rightSide] ← PW.Get[design: tDesign, name: "CRightSide" ];
tiles.and [conn][left] ← PW.Get[design: tDesign, name: "CAndLt" ];
tiles.and [conn][right] ← PW.Get[design: tDesign, name: "CAndRt" ];
tiles.and [conn][nc] ← PW.Get[design: tDesign, name: "BAnd" ];
tiles.and [conn][extra] ← PW.Get[design: tDesign, name: "BAndEx" ];
tiles.or [conn][left] ← PW.Get[design: tDesign, name: "COr" ];
tiles.or [conn][nc] ← PW.Get[design: tDesign, name: "COrNC" ];
tiles.or [conn][extra] ← PW.Get[design: tDesign, name: "COrEx" ];
tiles.glue [dataUp][leftSide] ← PW.Get[design: tDesign, name: "DLeftSide" ];
tiles.glue [dataUp][between] ← PW.Get[design: tDesign, name: "DBetween" ];
tiles.glue [dataUp][rightSide] ← PW.Get[design: tDesign, name: "DRightSide" ];
tiles.and [dataUp][left] ← PW.Get[design: tDesign, name: "DAndLt" ];
tiles.and [dataUp][right] ← PW.Get[design: tDesign, name: "DAndRt" ];
tiles.and [dataUp][nc] ← PW.Get[design: tDesign, name: "DAnd" ];
tiles.and [dataUp][extra] ← PW.Get[design: tDesign, name: "DAndEx" ];
tiles.or [dataUp][left] ← PW.Get[design: tDesign, name: "DOr" ];
tiles.or [dataUp][nc] ← PW.Get[design: tDesign, name: "DOrNC" ];
tiles.or [dataUp][extra] ← PW.Get[design: tDesign, name: "DOrEx" ];
tiles.glue [dataDn][leftSide] ← tiles.glue [dataUp][leftSide];
tiles.glue [dataDn][between] ← tiles.glue [dataUp][between];
tiles.glue [dataDn][rightSide] ← PW.FlipY[tDesign, tiles.glue [dataUp][rightSide] ];
tiles.and [dataDn][left] ← tiles.and [dataUp][left];
tiles.and [dataDn][right] ← tiles.and [dataUp][right];
tiles.and [dataDn][nc] ← tiles.and [dataUp][nc];
tiles.and [dataDn][extra] ← tiles.and [dataUp][extra];
tiles.or [dataDn][left] ← PW.FlipY[tDesign, tiles.or [dataUp][left] ];
tiles.or [dataDn][nc] ← PW.FlipY[tDesign, tiles.or [dataUp][nc] ];
tiles.or [dataDn][extra] ← PW.FlipY[tDesign, tiles.or [dataUp][extra] ];
RETURN[tiles]};
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};
log: IO.STREAM ← CDFrame.GetLog[];
PW.Register[userProc: IFUPWControlProc, name: "IFUPWControl"];
END.