IFUCoreCtlStatic:
CEDAR
PROGRAM
IMPORTS CCDUtils, CD, CDSymbolicObjects, CoreBlock, CoreFrame, CoreName, PLAOps, PW, PWCore, IFUCoreCells, IFUCoreDrive, IO, PWPins, REFBit, Rope
EXPORTS IFUCoreCtl =
BEGIN
ROPE: TYPE = Core.ROPE;
PLADescription: TYPE = IFUCoreCtl.PLADescription;
RowType: TYPE = IFUCoreDrive.RowType;
Drive: TYPE = IFUCoreDrive.Drive;
Drives: TYPE = IFUCoreDrive.Drives;
DriveRec: TYPE = IFUCoreDrive.DriveRec;
Signal: SIGNAL = CODE;
MakeStaticPLA:
PUBLIC
PROC[desc: PLADescription] = {
log.PutF["\n Make Static PLA %g", IO.rope[desc.name]];
GetOuts [desc];
GetBins [desc];
MakePla [desc];
DressInDrs [desc];
DressOutDrs [desc]};
SDesc: TYPE = RECORD[bins: REF Bins, outs: REF Outs];
Use: TYPE = RECORD[cols, wt: INT, seq: SEQUENCE size: CARDINAL OF BOOL];
SSInt: TYPE = RECORD[ seq: SEQUENCE size: CARDINAL OF REF SInt];
SInt: TYPE = RECORD[ seq: SEQUENCE size: CARDINAL OF INT];
Bins: TYPE = RECORD[ seq: SEQUENCE size: CARDINAL OF REF Use];
Outs: TYPE = RECORD[ttt: PLAOps.PLA, seq: SEQUENCE size: CARDINAL OF REF OUse];
OUse: TYPE = RECORD[lv: INT, seq: SEQUENCE size: CARDINAL OF REF TermUse];
TermUse: TYPE = RECORD[term: PLAOps.Term, bin: INT, use: REF Use];
NewUse:
PROC[size:
INT]
RETURNS [use:
REF Use] = {use ←
NEW[Use[size]];
use.cols ← 0; use.wt ← 0; FOR bit: INT IN [0..size) DO use[bit] ← FALSE ENDLOOP};
NewSInt:
PROC[size:
INT, init:
INT ← 0]
RETURNS [seq:
REF SInt] =
{seq ← NEW[SInt[size]]; FOR ii: INT IN [0..size) DO seq[ii] ← init ENDLOOP};
NewSSInt:
PROC[size0, size1:
INT]
RETURNS [seq:
REF SSInt] = {
seq ← NEW[SSInt[size0]];
FOR ii: INT IN [0..size0) DO seq[ii] ← NewSInt[size1] ENDLOOP};
NewBins:
PROC[size0, size1:
INT]
RETURNS [seq:
REF Bins] = {
seq ← NEW[Bins[size0]];
FOR ii: INT IN [0..size0) DO seq[ii] ← NewUse[size1] ENDLOOP};
GetOuts:
PROC[desc: PLADescription]= {
sd: REF SDesc ← NEW[SDesc];
TListSeq: TYPE = RECORD[SEQUENCE size: CARDINAL OF PLAOps.TermList];
nofBins: INT ← desc.nofTermCols;
nofTerms: INT ← 0;
iFormat: REFBit.Format ← REFBit.Desc[desc.ttt.data].bitForm;
oFormat: REFBit.Format ← REFBit.Desc[desc.ttt.out].bitForm;
tListSeq: REF TListSeq ← NEW[TListSeq[oFormat.size] ];
sd.outs ← NEW[Outs[oFormat.size] ];
sd.outs.ttt ← desc.ttt;
desc.data ← sd;
IF desc.plaType=decoder THEN desc.nofOrCols ← 0;
FOR out:
INT
IN [0..desc.smlToBigOut.size)
DO
bigOut: INT ← desc.smlToBigOut[out];
tListSeq[out] ← PLAOps.CopyTermListForField[desc.ttt.termList, oFormat[bigOut].firstBit, 1];
[ ] ← PLAOps.ConvertTermListToCompleteSum[tListSeq[out], TRUE, TRUE, log];
[ ] ← PLAOps.FindAMinimalCover[tListSeq[out], 10, log];
nofTerms ← MAX[nofTerms, tListSeq[out].length];
ENDLOOP;
IF desc.plaType=decoder THEN desc.nofTermCols ← nofBins ← nofTerms;
FOR out:
INT
IN [0..desc.smlToBigOut.size)
DO
term: PLAOps.Term;
level: INT;
level ←
IF desc.plaType=decoder
THEN 0 ELSE (tListSeq[out].length+nofBins-2)/nofBins;
nofTerms ← IF level=0 THEN nofBins ELSE level*nofBins+1;
sd.outs[out] ← NEW[OUse[nofTerms]];
sd.outs[out].lv ← level; -- = number of rows to be ORed with top row
term ← tListSeq[out].begin;
FOR termIdx:
INT
IN [0..nofTerms)
DO
use: REF Use ← NEW[Use[iFormat.size]];
sd.outs[out][termIdx] ← NEW[TermUse ← [term, -1, use]];
use.wt ← 0;
FOR bit:
INT
IN [0..use.size)
DO
use[bit] ← desc.fullWidthTerms
OR
(term#NIL AND PLAOps.GetInQrt[term, iFormat[bit].firstBit]#dontcare);
IF use[bit] THEN use.wt ← use.wt + 1;
ENDLOOP;
IF term#NIL THEN term ← term.next;
ENDLOOP;
ENDLOOP };
GetBins:
PROC[desc: PLADescription]={
sd: REF SDesc ← NARROW[desc.data];
useSize: INT ← sd.outs[0][0].use.size;
nofBins: INT ← desc.nofTermCols;
sd.bins ← NewBins[nofBins, useSize];
FOR out:
INT
IN [0..sd.outs.size)
DO
nofTerms: INT ← sd.outs[out].size;
minTBins: REF SInt ← NewSInt[nofTerms];
curTBins: REF SInt ← NewSInt[nofTerms, -1];
minTotalWt: INT ← useSize*nofTerms+1;
Enum:
PROC[left, wt:
INT, termBins:
REF SInt] = {
tempUse: REF Use;
bin: INT ← (nofTerms-left) MOD nofBins;
IF wt >= minTotalWt THEN RETURN;
IF left=0
THEN {
FOR tt: INT IN [0..nofTerms) DO minTBins[tt] ← termBins[tt]; ENDLOOP;
minTotalWt ← wt; RETURN};
tempUse ← NewUse[useSize];
FOR sel:
INT
DECREASING
IN [0..left)
DO
cnt, term: INT ← 0;
cnt ← sel;
FOR term ← 0, term+1
DO
IF termBins[term]>=0 THEN LOOP; IF cnt=0 THEN EXIT; cnt ← cnt-1 ENDLOOP;
UseOr[sd.bins[bin], sd.bins[bin], tempUse];
UseOr[sd.outs[out][term].use, sd.bins[bin], sd.bins[bin]];
termBins[term] ← bin;
Enum[left-1, wt + sd.bins[bin].wt - tempUse.wt, termBins];
UseOr[tempUse, tempUse, sd.bins[bin]];
termBins[term] ← -1;
ENDLOOP};
IF desc.fullWidthTerms
THEN {
FOR term:
INT
IN [0..nofTerms)
DO sd.outs[out][term].bin ← term MOD nofBins ENDLOOP;
LOOP};
Enum[nofTerms, 0, curTBins];
FOR term:
INT
IN [0..nofTerms)
DO
UseOr[sd.outs[out][term].use, sd.bins[minTBins[term]], sd.bins[minTBins[term]]];
sd.outs[out][term].bin ← minTBins[term] ENDLOOP;
ENDLOOP;
FOR out:
INT
IN [0..sd.outs.size)
DO
-- sd.bins[bin].cols used to determine OR columns/bin
FOR bin:
INT
IN [0..nofBins)
DO
binCnt: INT ← 0;
IF desc.fullWidthTerms
THEN {
FOR bit: INT IN [0..useSize) DO sd.bins[bin][bit] ← TRUE ENDLOOP;
sd.bins[bin].wt ← useSize};
FOR level:
INT
IN [1..sd.outs[out].lv]
DO
IF GetTerm[sd.outs, out, level, bin]#NIL THEN binCnt ← binCnt + 1 ENDLOOP;
sd.bins[bin].cols ← MAX[sd.bins[bin].cols, binCnt, desc.nofOrCols] ENDLOOP;
ENDLOOP};
MakePla:
PROC[desc: PLADescription] = {
name: ROPE ← CoreName.RopeNm[desc.name.Cat["Body"]];
IF (desc.outBodyCT ← CoreFrame.ReadFrameCache[name])=
NIL
THEN {
sd: REF SDesc ← NARROW[desc.data];
cellType: Core.CellType;
rowType: RowType ← header;
out: INT ← 0;
tileRows: REF StaticTiles ← GetStaticPLATiles[];
useSize: INT ← sd.bins[0].size;
index: INT ← 0;
iForm: REFBit.Format ← REFBit.Desc[sd.outs.ttt.data].bitForm;
tiles: REF StaticTileRow;
levelRng: INT;
nofOrTerms: REF SInt;
v: Variety ← IF desc.plaType=static THEN s ELSE d;
seg, row, sec: CD.Object ← NIL;
segList, rowList, secList, colList: PW.ListOb ← NIL;
DO
rowType ←
IF out = sd.outs.size
THEN header
ELSE IF rowType=header THEN footer
ELSE IF rowType=footer THEN conn
ELSE IF (out MOD desc.termsPerHeader) = 0 THEN header ELSE conn;
levelRng ← IF rowType = conn THEN sd.outs[out].lv ELSE 0; -- OR sub rows
tiles ← tileRows[rowType];
nofOrTerms ← NewSInt[sd.bins.size];
IF rowType = conn
THEN
FOR tt:
INT
IN [0..sd.outs[out].size)
DO
IF sd.outs[out][tt].term=NIL THEN LOOP;
nofOrTerms[sd.outs[out][tt].bin]←MIN[sd.outs[out].lv,nofOrTerms[sd.outs[out][tt].bin]+1];
ENDLOOP;
FOR level:
INT
IN [0..levelRng]
DO
rowList ← CONS[tiles[v][leftSide], NIL];
FOR bin:
INT
IN [0..sd.bins.size)
DO
term: PLAOps.Term;
first: BOOL ← bin=0 OR level#0 OR desc.plaType=decoder;
term ← IF rowType = conn THEN GetTerm[sd.outs, out, level, bin] ELSE NIL;
IF nofOrTerms[bin] > sd.bins[bin].cols THEN ERROR;
FOR index
IN[0..useSize)
DO
IF NOT sd.bins[bin][index] THEN LOOP;
IF term=
NIL
THEN segList ←
CONS[
IF ~first
THEN tiles[v][andPass]
ELSE
IF levelRng=0
AND desc.plaType#decoder
THEN tiles[v][andTrue] -- for term at right
ELSE tiles[v][andFalse] -- for decoder OR gate
, segList ]
ELSE
segList ←
CONS[
SELECT PLAOps.GetInQrt[term, iForm[index].firstBit]
FROM
zero => IF first THEN tiles[v][andIfNot] ELSE tiles[v][andNot],
one => IF first THEN tiles[v][andIf] ELSE tiles[v][and],
ENDCASE => IF first THEN tiles[v][andTrue] ELSE tiles[v][andPass], segList];
first ← FALSE;
ENDLOOP;
FOR index ← 0, index+1
WHILE index < nofOrTerms[bin]
DO
segList ←
CONS[ tiles[v][
SELECT index+1
FROM
< level => orBlank,
= level => orConn,
> level => IF level=0 THEN or ELSE orPass,
ENDCASE => ERROR], segList]; ENDLOOP;
THROUGH [nofOrTerms[bin]..sd.bins[bin].cols)
DO segList ← CONS[ tiles[v][orBlank] , segList] ENDLOOP;
segList ←
CONS[ tiles[v][
IF level#0
THEN innerRt
ELSE
IF bin+1 < sd.bins.size
THEN innerPass
ELSE outerRt ], segList];
seg ← PW.AbutListX[PW.Reverse[segList]];
seg ← PW.SharedAbutListX[PW.Reverse[segList]];
segList ← NIL;
rowList ← CONS[ seg, rowList];
ENDLOOP;
row ← PW.AbutListX[PW.Reverse[rowList]];
row ← PW.SharedAbutListX[PW.Reverse[rowList]];
rowList ← NIL;
secList ← CONS[ row, secList];
ENDLOOP;
sec ← PW.AbutListY[PW.Reverse[secList]];
sec ← PW.SharedAbutListY[PW.Reverse[secList]];
secList ← NIL;
colList ← CONS[ sec, colList];
IF rowType=conn THEN out ← out+1 ELSE IF out = sd.outs.size THEN EXIT;
ENDLOOP;
desc.body ← PW.AbutListY[PW.Reverse[colList]];
desc.body ← PW.SharedAbutListY[PW.Reverse[colList]];
ApplyNames[desc];
cellType ← PWCore.FromLayoutWithoutPublic[desc.body];
CoreBlock.MarkSides[cellType, desc.capSides];
[ ] ← CoreName.CellNm[cellType, name];
desc.outBodyCT ← CoreFrame.NewFrameCell[0, name, [first: left, cell: cellType] ];
CoreFrame.WriteFrameCache[desc.outBodyCT]};
desc.body ← CCDUtils.Layout[desc.outBodyCT]};
in0: ROPE ← CoreName.RopeNm["in0"];
in1: ROPE ← CoreName.RopeNm["in1"];
out0: ROPE ← CoreName.RopeNm["out0"];
out1: ROPE ← CoreName.RopeNm["out1"];
VDD: ROPE ← CoreName.RopeNm["VDD"];
GND: ROPE ← CoreName.RopeNm["GND"];
ApplyNames:
PROC[desc: PLADescription] = {
sd: REF SDesc ← NARROW[desc.data];
SSRope: TYPE = RECORD[SEQUENCE size: CARDINAL OF REF SRope];
SRope: TYPE = RECORD[SEQUENCE size: CARDINAL OF ROPE];
tiles: REF StaticTiles ← GetStaticPLATiles[];
drTiles: REF IFUCoreDrive.DrTileRec ← IFUCoreDrive.GetDriverTiles[];
inName: REF SSRope ← NEW[SSRope[sd.bins.size]];
inNameInv: REF SSRope ← NEW[SSRope[sd.bins.size]];
v: Variety ← IF desc.plaType=static THEN s ELSE d;
leftSize: INT ← CD.InterestSize[tiles[header ][v][leftSide]].x;
andWidth: INT ← CD.InterestSize[tiles[header ][v][and]].x;
orWidth: INT ← CD.InterestSize[tiles[header ][v][or]].x;
innerSize: INT ← CD.InterestSize[tiles[header ][v][innerRt]].x;
headHt: INT ← CD.InterestSize[tiles[header ][v][outerRt]].y;
rowHt: INT ← CD.InterestSize[tiles[conn ][v][outerRt]].y;
renameProc: PWPins.
ChangePinProc ~ {
old: ROPE ← CoreName.RopeNm[CDSymbolicObjects.GetName[oldPin]];
side: CoreBlock.Sides;
loc: INT;
newPin ← oldPin;
[side, loc] ← CoreBlock.GetInstSideLoc[desc.body, newPin];
SELECT old
FROM
GND => RETURN;
VDD => RETURN;
out1 => RETURN[NIL];
out0 =>
{
name: ROPE;
yPos: INT ← headHt;
FOR out:
INT
IN [0..sd.outs.size)
DO
IF out IN [1..sd.outs.size-1) AND (out MOD desc.termsPerHeader)=0 THEN yPos ← yPos + 2*headHt;
IF loc
IN (yPos..(yPos + rowHt))
THEN {
name ← IFUCoreDrive.DriveName[desc.connSeq[out].dr, in];
CDSymbolicObjects.SetName[newPin, name];
RETURN};
yPos ← yPos + (sd.outs[out].lv +1)*rowHt;
ENDLOOP;
Signal[]};
in0,
in1 =>
{
xpos: INT ← leftSize;
FOR bin:
INT
IN [0..sd.bins.size)
DO
index: INT ← (loc-xpos)/andWidth;
IF index < inName[bin].size
THEN {
IF old=in0
THEN CDSymbolicObjects.SetName[newPin, inName [bin][index]]
ELSE CDSymbolicObjects.SetName[newPin, inNameInv [bin][index]];
RETURN};
xpos ← xpos + inName[bin].size*andWidth + sd.bins[bin].cols*orWidth + innerSize;
REPEAT FINISHED => Signal[] ENDLOOP };
ENDCASE => RETURN};
FOR bin:
INT
IN [0..sd.bins.size)
DO
list: LIST OF ROPE ← desc.plaInNames;
in: INT ← 0;
inName[bin] ← NEW[SRope[sd.bins[bin].wt]];
inNameInv[bin] ← NEW[SRope[sd.bins[bin].wt]];
FOR bit:
INT
IN [0..sd.bins[bin].size)
DO
IF sd.bins[bin][bit]
THEN {
inName [bin][in] ← list.first;
inNameInv [bin][in] ← list.rest.first;
in ← in+1};
list ← list.rest.rest;
ENDLOOP;
ENDLOOP;
desc.body ← PWPins.ChangePins[desc.body, renameProc]};
DressInDrs:
PROC [desc: PLADescription] = {
sd: REF SDesc ← NARROW[desc.data];
DeleteUnusedStaticInDrs [desc];
desc.inDrs ← CONS[ NEW[DriveRec ← [drRowType: xfooter]], desc.inDrs];
FOR list: Drives ← desc.inDrs, list.rest
WHILE list.rest#
NIL DO
REPEAT
FINISHED => list.rest ← CONS [NEW[DriveRec ← [drRowType: xheader]], NIL] ENDLOOP};
DressOutDrs:
PROC [desc: PLADescription] = {
sd: REF SDesc ← NARROW[desc.data];
desc.outDrs ← CONS[ NEW[DriveRec ← [drRowType: footer]], NIL];
FOR out:
INT
IN [0..sd.outs.size)
DO
IF out
IN [1..sd.outs.size-1)
AND (out
MOD desc.termsPerHeader)=0
THEN {
desc.outDrs ← CONS[ NEW[DriveRec ← [drRowType: header]], desc.outDrs];
desc.outDrs ← CONS[ NEW[DriveRec ← [drRowType: footer]], desc.outDrs] };
FOR term:
INT
IN [0..sd.outs[out].lv]
DO
desc.outDrs ← CONS[ NEW[DriveRec ← desc.connSeq[out].dr^], desc.outDrs];
desc.outDrs.first.drRowType ← IF term=0 THEN conn ELSE blank
ENDLOOP;
ENDLOOP;
desc.outDrs ← CONS[ NEW[DriveRec ← [drRowType: header]], desc.outDrs];
desc.outDrs ← IFUCoreDrive.ReverseDrives[desc.outDrs]};
DeleteUnusedStaticInDrs:
PUBLIC
PROC [desc: PLADescription] = {
sd: REF SDesc ← NARROW[desc.data];
index: INT ← 0;
useSize: INT ← sd.bins[0].size;
tempUse: REF Use ← NewUse[useSize];
drs: Drives ← NIL;
delIns: Drives ← NIL;
FOR bin: INT IN [0..sd.bins.size) DO UseOr[sd.bins[bin], tempUse, tempUse] ENDLOOP;
IF tempUse.wt=useSize THEN RETURN;
FOR temp: Drives ← desc.inDrs, temp.rest
WHILE temp#
NIL
DO
IF tempUse[index] THEN drs ← CONS[temp.first, drs];
index ← index +1 ENDLOOP;
desc.inDrs ← IFUCoreDrive.ReverseDrives[drs]};
UseOr:
PROC[useArg0, useArg1, useOr:
REF Use] = {
IF useArg0.size#useArg1.size OR useArg1.size#useOr.size THEN ERROR;
useOr.wt ← 0;
FOR bit:
INT
IN [0..useArg0.size)
DO
useOr[bit] ← useArg0[bit] OR useArg1[bit];
IF useOr[bit] THEN useOr.wt ← useOr.wt + 1;
ENDLOOP };
GetTerm:
PROC[outs:
REF Outs, out, level, bin:
INT]
RETURNS[term: PLAOps.Term] = {
found: INT ← 0;
FOR tt:
INT
IN [0..outs[out].size)
DO
IF outs[out][tt].bin#bin THEN LOOP;
found ← found+1;
term ← outs[out][tt].term;
IF found = level THEN RETURN[term];
ENDLOOP;
IF found=0 THEN ERROR; -- Just checking, term can be NIL but bin must be represented
IF level#0 THEN ERROR; -- level 0 => last term
IF outs[out].lv#0 AND bin#0 THEN RETURN[NIL];
RETURN[term]}; -- last term for level 0 when outs[out].lv=0 OR bin=0
staticTiles: REF StaticTiles;
StaticTiles: TYPE = ARRAY RowType OF REF StaticTileRow;
StaticTileRow: TYPE = ARRAY Variety OF StaticTileVar;
StaticTileVar: TYPE = ARRAY StaticTileType OF CD.Object;
Variety: TYPE = {s, d}; -- static or decode
StaticTileType : TYPE = {leftSide, andTrue, andFalse, andIf, andIfNot, and, andNot, andPass, or, orNot, orPass, orBlank, orConn, innerPass, innerRt, outerRt};
GetStaticPLATiles:
PROC
RETURNS [tiles:
REF StaticTiles ] = {
Get:
PROC[name:
ROPE]
RETURNS[
CD.Object] =
{RETURN[PW.Get[design: library.design, name: name ]]};
library: CoreLibrary.Library ← IFUCoreCells.library;
IF staticTiles#NIL THEN RETURN[staticTiles];
log.PutRope["\n Initialize static pla tiles"];
tiles ← NEW[StaticTiles];
FOR row: RowType
IN RowType
DO
tiles[row] ←NEW[StaticTileRow] ENDLOOP;
tiles [header][s][leftSide] ← Get[ "SPlaHLeftSide" ];
tiles [header][s][andTrue] ←
tiles [header][s][andFalse] ←
tiles [header][s][andIf] ←
tiles [header][s][andIfNot] ←
tiles [header][s][and] ←
tiles [header][s][andNot] ←
tiles [header][s][andPass] ← Get[ "SPlaHAnd" ];
tiles [header][s][or] ←
tiles [header][s][orNot] ←
tiles [header][s][orPass] ←
tiles [header][s][orBlank] ←
tiles [header][s][orConn] ← Get[ "SPlaHOr" ];
tiles [header][s][innerPass] ←
tiles [header][s][innerRt] ←
tiles [header][s][outerRt] ← Get[ "SPlaHOuterRt" ];
tiles [footer][s][leftSide] ← PW.FlipY[ tiles [header][s][leftSide]];
tiles [footer][s][andTrue] ←
tiles [footer][s][andFalse] ←
tiles [footer][s][andIf] ←
tiles [footer][s][andIfNot] ←
tiles [footer][s][and] ←
tiles [footer][s][andNot] ←
tiles [footer][s][andPass] ← PW.FlipY[ tiles [header][s][andPass]];
tiles [footer][s][or] ←
tiles [footer][s][orNot] ←
tiles [footer][s][orPass] ←
tiles [footer][s][orBlank] ←
tiles [footer][s][orConn] ← PW.FlipY[ tiles [header][s][orConn]];
tiles [footer][s][innerPass] ←
tiles [footer][s][innerRt] ←
tiles [footer][s][outerRt] ← PW.FlipY[ tiles [header][s][outerRt]];
tiles [conn][s][leftSide] ← Get[ "SPlaLeftSide" ];
tiles [conn][s][andTrue] ← Get[ "SPlaAndTrue" ];
tiles [conn][s][andFalse] ← Get[ "SPlaAndFalse" ];
tiles [conn][s][andIf] ← Get[ "SPlaAndIf" ];
tiles [conn][s][andIfNot] ← Get[ "SPlaAndIfNot" ];
tiles [conn][s][and] ← Get[ "SPlaAnd" ];
tiles [conn][s][andNot] ← Get[ "SPlaAndNot" ];
tiles [conn][s][andPass] ← Get[ "SPlaAndPass" ];
tiles [conn][s][or] ← Get[ "SPlaOr" ];
tiles [conn][s][orNot] ← Get[ "SPlaOrNot" ];
tiles [conn][s][orPass] ← Get[ "SPlaOrPass" ];
tiles [conn][s][orBlank] ← Get[ "SPlaOrBlank" ];
tiles [conn][s][orConn] ← Get[ "SPlaOrConn" ];
tiles [conn][s][innerPass] ← Get[ "SPlaInnerPass" ];
tiles [conn][s][innerRt] ← Get[ "SPlaInnerRt" ];
tiles [conn][s][outerRt] ← Get[ "SPlaOuterRt" ];
FOR type: StaticTileType
IN StaticTileType
DO
tiles[header] [d][type] ← tiles[header] [s][type];
tiles[footer] [d][type] ← tiles[footer] [s][type] ENDLOOP;
tiles [header][d][innerPass] ←
tiles [header][d][innerRt] ←
tiles [header][d][outerRt] ← Get[ "DPlaHRt" ];
tiles [footer][d][innerPass] ←
tiles [footer][d][innerRt] ←
tiles [footer][d][outerRt] ← PW.FlipY[ tiles [header][d][outerRt]];
tiles [conn][d][leftSide] ← Get[ "DPlaLeftSide" ];
tiles [conn][d][andTrue] ← Get[ "DPlaAndTrue" ];
tiles [conn][d][andFalse] ← Get[ "DPlaAndFalse" ];
tiles [conn][d][andIf] ← Get[ "DPlaAndIf" ];
tiles [conn][d][andIfNot] ← Get[ "DPlaAndIfNot" ];
tiles [conn][d][and] ← Get[ "DPlaAnd" ];
tiles [conn][d][andNot] ← Get[ "DPlaAndNot" ];
tiles [conn][d][andPass] ← Get[ "DPlaAndPass" ];
tiles [conn][d][or] ←
tiles [conn][d][orNot] ←
tiles [conn][d][orPass] ←
tiles [conn][d][orBlank] ←
tiles [conn][d][orConn] ← tiles[conn][s][or];
tiles [conn][d][innerPass] ←
tiles [conn][d][innerRt] ←
tiles [conn][d][outerRt] ← Get[ "DPlaRt" ];
};
log: IO.STREAM ← CoreFrame.GetLog[];
END.