IFUCoreCtlPreCharge.mesa,
Copyright c 1986 by Xerox Corporation. All rights reserved.
Last Edited by Curry, July 18, 1986 10:44:02 am PDT
DIRECTORY Basics, CCDUtils, CD, CDSymbolicObjects, Core, CoreBlock, CoreFrame, CoreLibrary, CoreName, IFUCoreCells, IFUCoreCtl, IFUCoreDrive, IO, Lists, PLAOps, PW, PWCore, PWPins, REFBit, Rope;
IFUCoreCtlPreCharge: CEDAR PROGRAM
IMPORTS Basics, CCDUtils, CD, CDSymbolicObjects, CoreBlock, CoreFrame, CoreName, IFUCoreCells, IFUCoreDrive, IO, Lists, PLAOps, PW, PWCore, PWPins, REFBit, Rope
EXPORTS IFUCoreCtl =
BEGIN
ROPE:    TYPE = Core.ROPE;
CellType:   TYPE = Core.CellType;
Wire:    TYPE = Core.Wire;
Frame:   TYPE = CoreFrame.Frame;
PLADescription: TYPE = IFUCoreCtl.PLADescription;
Connection:  TYPE = IFUCoreCtl.Connection;
PLAType:  TYPE = IFUCoreDrive.PLAType;
Drive:    TYPE = IFUCoreDrive.Drive;
Drives:   TYPE = IFUCoreDrive.Drives;
DriveRec:   TYPE = IFUCoreDrive.DriveRec;
RowType:  TYPE = IFUCoreDrive.RowType;
Dir:    TYPE = IFUCoreDrive.Dir;
DrGate:   TYPE = IFUCoreDrive.DrGate;
Ph:    TYPE = IFUCoreDrive.Ph;
Polarity:   TYPE = IFUCoreDrive.Polarity;
Signal: SIGNAL = CODE;
MakeHotPLA,
MakePreChargedPLA: PUBLIC PROC[desc: PLADescription] = {
log.PutF["\n Make PreCharged/Hot PLA %g", IO.rope[desc.name]];
ZeroUnusedTTTOutputs [desc];
DefinePLARows    [desc];
DressInDrs     [desc];
MakeOutDrs     [desc];
MakePla      [desc]};
DressInDrs: PROC [desc: PLADescription] = {
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};
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 };
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,
nextConn: desc.connSeq.size-1,
insPerExtra: IF desc.plaType = hot THEN 10000 ELSE 10]]; --extra AND column undefined
firstRow:  BOOLTRUE;
index:   INT ← 0;
termUp:  BOOLTRUE;
nofOuts:  INTMAX[Lists.ListLength[desc.plaOutNames], desc.nofOrCols];
nofIns:  INT ← Lists.ListLength[desc.plaInNames];
cRowsLeft: INT ← Lists.ListLength[desc.plaOutNames];
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/hot 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]];
index ← pp.rows.size-1; -- start at the top
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, xfooter]; 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#0 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
ELSEIF 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];
last: INT ← pp.rows.size+pp.minConnSpace;
FOR driverIndex: INT DECREASING IN [0..pp.rows.size) DO
type: RowType ← pp.rows[driverIndex].type;
SELECT type FROM
header, xfooter, footer => {
IF (last-driverIndex) <= pp.minConnSpace THEN ERROR;
last ← driverIndex+pp.minConnSpace;
desc.outDrs ←
CONS[NEW[DriveRec ← [plaType: desc.plaType, drRowType: type]], desc.outDrs]};
blank, dataUp, dataDn  => {
IF (last-driverIndex) <= pp.minConnSpace THEN LOOP;
desc.outDrs ←
CONS[NEW[DriveRec ← [plaType: desc.plaType, drRowType: type]], desc.outDrs]};
conn       => {
IF (last-driverIndex) <= pp.minConnSpace THEN ERROR;
last ← driverIndex;
desc.outDrs ← CONS[pp.rows[driverIndex].dr, desc.outDrs]}
ENDCASE => ERROR;
ENDLOOP};
MakePla: PROC[desc: PLADescription] = {
name: ROPE ← CoreName.RopeNm[desc.name.Cat["Body"]];
IF (desc.outBodyCT ← CoreFrame.ReadFrameCache[name])=NIL THEN {
cellType: Core.CellType;
tiles:  REF TileVarieties ← GetPLATiles[desc.plaType];
pp:  REF PreChargedParams ← NARROW[desc.data];
refPhase: Ph ← unk;
rowList: PW.ListOb ← NIL;
log.PutRope["\n Assemble precharged/hot 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.SharedAbutListX[PW.Reverse[objects]], rowList]
rowList ← CONS[PW.AbutListX[PW.Reverse[objects]], rowList]
ENDLOOP;
desc.body ← PW.SharedAbutListY[PW.Reverse[rowList]];
desc.body ← PW.AbutListY[PW.Reverse[rowList]];
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"];
out:   ROPE ← CoreName.RopeNm["out"];
fire:   ROPE ← CoreName.RopeNm["Fire"];
fireControlV: ROPE ← CoreName.RopeNm["FireControlV"];
notPreChg: ROPE ← CoreName.RopeNm["NotPreChg"];
VDD:   ROPE ← CoreName.RopeNm["VDD"];
GND:   ROPE ← CoreName.RopeNm["GND"];
ApplyNames: PROC[desc: PLADescription] = {
TileSize: PROC[obj: CD.Object] RETURNS[size: CD.Position] =
{IF obj=NIL THEN RETURN[[0, 0]]; RETURN[CD.InterestSize[obj]]};
pp:   REF PreChargedParams ← NARROW[desc.data];
tiles:   REF TileVarieties ← GetPLATiles[desc.plaType];
leftSize:  INT ← TileSize[tiles.glue [blank] [leftSide]].x;
andWidth: INT ← TileSize[tiles.and  [blank] [nc]].x;
extraWidth: INT ← TileSize[tiles.and  [blank] [extra]].x;
headHt:  INT ← TileSize[tiles.glue [header] [rightSide]].y;
xfootHt:  INT ← TileSize[tiles.glue [xfooter] [rightSide]].y;
rowHt:  INT ← TileSize[tiles.glue [blank] [rightSide]].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;
out => {
name: ROPE;
yPos: INT;
FOR oIndex: INT IN [0..pp.rows.size) DO
SELECT pp.rows[oIndex].type FROM
header, footer => {yPos ← yPos + headHt; LOOP};
xfooter   => {yPos ← yPos + xfootHt; LOOP};
dataUp, dataDn  => {yPos ← yPos + rowHt;  LOOP};
blank    => {yPos ← yPos + rowHt;  LOOP};
conn    => {IF loc < yPos THEN Signal[]};
ENDCASE   => Signal[];
yPos ← yPos + rowHt;
IF loc > yPos THEN LOOP;
name ← IFUCoreDrive.DriveName[pp.rows[oIndex].dr, nin];
CDSymbolicObjects.SetName[newPin, name]; RETURN ENDLOOP;
Signal[]};
in0,
in1 => {
name: ROPE;
list: LIST OF ROPE ← desc.plaInNames;
xpos: INT;
xpos ← (loc - leftSize)/(pp.insPerExtra*andWidth+extraWidth);
xpos ← (loc - leftSize - extraWidth*xpos)/(andWidth/2);
WHILE xpos>1 DO
IF list=NIL THEN RETURN;
list ← list.rest.rest; xpos ← xpos-2 ENDLOOP;
name ← IF xpos=0 THEN list.first ELSE list.rest.first;
IF (xpos=0)#(old=in0) THEN Signal[];
CDSymbolicObjects.SetName[newPin, name];
RETURN};
fire   => CDSymbolicObjects.SetName[newPin, "PhB"];
fireControlV => CDSymbolicObjects.SetName[newPin, "FireControlV"]; -- to conn pad
notPreChg => CDSymbolicObjects.SetName[newPin, "NotPreChg"];  -- to conn pad
ENDCASE => RETURN};
desc.body ← PWPins.ChangePins[desc.body, renameProc]};
tileBuffer:  REF TileVarieties;
hotTileBuffer: 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[type: PLAType] RETURNS[tiles: REF TileVarieties] = {
tiles ← SELECT type FROM
hot  => GetHotPLATiles[],
ENDCASE => GetPreChargedPLATiles[]};
GetPreChargedPLATiles: PROC RETURNS[tiles: REF TileVarieties] = {
Get: PROC[name: ROPE] RETURNS[CD.Object] =
{RETURN[PW.Get[design: library.design, name: name ]]};
library: CoreLibrary.Library ← IFUCoreCells.library;
IF tileBuffer # NIL THEN RETURN[tileBuffer];
log.PutRope["\n Initialize precharged PLA tiles"];
tiles  ← tileBuffer ← NEW[TileVarieties];
tiles.glue ← NEW[GlueTiles];
tiles.and ← NEW[NormalTiles];
tiles.or ← NEW[NormalTiles];
tiles.glue [xfooter][leftSide] ← Get[ "XLeftSide" ];
tiles.glue [xfooter][between] ← Get[ "XBetween" ];
tiles.glue [xfooter][rightSide] ← Get[ "XOrEx" ];
tiles.and [xfooter][nc]   ← Get[ "XAnd" ];
tiles.and [xfooter][extra]  ← Get[ "XAndEx" ];
tiles.or [xfooter][nc]   ← Get[ "XOr" ];
tiles.or [xfooter][extra]  ← Get[ "XOrEx" ];
tiles.glue [header][leftSide] ← Get[ "HLeftSide" ];
tiles.glue [header][between] ← Get[ "HBetween" ];
tiles.glue [header][rightSide] ← Get[ "HRightSide" ];
tiles.and [header][nc]   ← Get[ "HAnd" ];
tiles.and [header][extra]  ← Get[ "HAndEx" ];
tiles.or [header][nc]   ← Get[ "HOr" ];
tiles.or [header][extra]  ← Get[ "HOrEx" ];
tiles.glue [footer][leftSide]  ← PW.FlipY[ tiles.glue [header][leftSide] ];
tiles.glue [footer][between] ← PW.FlipY[ tiles.glue [header][between] ];
tiles.glue [footer][rightSide] ← PW.FlipY[ tiles.glue [header][rightSide] ];
tiles.and [footer][nc]   ← PW.FlipY[ tiles.and [header][nc]   ];
tiles.and [footer][extra]  ← PW.FlipY[ tiles.and [header][extra]  ];
tiles.or [footer][nc]   ← PW.FlipY[ tiles.or [header][nc]   ];
tiles.or [footer][extra]  ← PW.FlipY[ tiles.or [header][extra]  ];
tiles.glue [blank][leftSide]  ← Get[ "BLeftSide" ];
tiles.glue [blank][between] ← Get[ "BBetween" ];
tiles.glue [blank][rightSide] ← Get[ "BOrEx" ];
tiles.and [blank][nc]   ← Get[ "BAnd" ];
tiles.and [blank][extra]  ← Get[ "BAndEx" ];
tiles.or [blank][nc]   ← Get[ "BOr" ];
tiles.or [blank][extra]  ← Get[ "BOrEx" ];
tiles.glue [conn][leftSide]  ← Get[ "BLeftSide" ];
tiles.glue [conn][between]  ← Get[ "BBetween" ];
tiles.glue [conn][rightSide] ← Get[ "CRightSide" ];
tiles.and [conn][left]   ← Get[ "CAndLt" ];
tiles.and [conn][right]  ← Get[ "CAndRt" ];
tiles.and [conn][nc]   ← Get[ "BAnd" ];
tiles.and [conn][extra]   ← Get[ "BAndEx" ];
tiles.or [conn][left]   ← Get[ "COr" ];
tiles.or [conn][nc]   ← Get[ "COrNC" ];
tiles.or [conn][extra]   ← Get[ "COrEx" ];
tiles.glue [dataUp][leftSide] ← Get[ "DLeftSide" ];
tiles.glue [dataUp][between] ← Get[ "DBetween" ];
tiles.glue [dataUp][rightSide] ← Get[ "DRightSide" ];
tiles.and [dataUp][left]  ← Get[ "DAndLt" ];
tiles.and [dataUp][right]  ← Get[ "DAndRt" ];
tiles.and [dataUp][nc]   ← Get[ "DAnd" ];
tiles.and [dataUp][extra]  ← Get[ "DAndEx" ];
tiles.or [dataUp][left]  ← Get[ "DOr" ];
tiles.or [dataUp][nc]   ← Get[ "DOrNC" ];
tiles.or [dataUp][extra]  ← Get[ "DOrEx" ];
tiles.glue [dataDn][leftSide] ←    tiles.glue [dataUp][leftSide];
tiles.glue [dataDn][between] ← PW.FlipY[ tiles.glue [dataUp][between] ];
tiles.glue [dataDn][rightSide] ← PW.FlipY[ 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[ tiles.or [dataUp][left]  ];
tiles.or [dataDn][nc]   ← PW.FlipY[ tiles.or [dataUp][nc]   ];
tiles.or [dataDn][extra]  ← PW.FlipY[ tiles.or [dataUp][extra]  ];
RETURN[tiles]};
GetHotPLATiles: PROC RETURNS[tiles: REF TileVarieties] = {
Get: PROC[name: ROPE] RETURNS[CD.Object] =
{RETURN[PW.Get[design: library.design, name: name ]]};
library: CoreLibrary.Library ← IFUCoreCells.library;
IF hotTileBuffer # NIL THEN RETURN[hotTileBuffer];
log.PutRope["\n Initialize hot PLA tiles"];
tiles  ← hotTileBuffer ← NEW[TileVarieties];
tiles.glue ← NEW[GlueTiles];
tiles.and ← NEW[NormalTiles];
tiles.or ← NEW[NormalTiles];
tiles.glue [header][leftSide] ← Get[ "HPlaHLeftSide" ];
tiles.glue [header][between] ← Get[ "HPlaHBetween" ];
tiles.glue [header][rightSide] ← Get[ "HPlaHRightSide" ];
tiles.and [header][nc]   ← Get[ "HPlaHAnd" ];
tiles.or [header][nc]   ← Get[ "HPlaHOr" ];
tiles.or [header][extra]  ← Get[ "HPlaHOrEx" ];
tiles.glue [footer][leftSide]  ← PW.FlipY[ tiles.glue [header][leftSide] ];
tiles.glue [footer][between] ← PW.FlipY[ tiles.glue [header][between] ];
tiles.glue [footer][rightSide] ← PW.FlipY[ tiles.glue [header][rightSide] ];
tiles.and [footer][nc]   ← PW.FlipY[ tiles.and [header][nc]   ];
tiles.or [footer][nc]   ← PW.FlipY[ tiles.or [header][nc]   ];
tiles.or [footer][extra]  ← PW.FlipY[ tiles.or [header][extra]  ];
tiles.glue [blank][leftSide]  ← Get[ "HPlaBLeftSide" ];
tiles.glue [blank][between] ← Get[ "HPlaBBetween" ];
tiles.glue [blank][rightSide] ← Get[ "HPlaBRightSide" ];
tiles.and [blank][nc]   ← Get[ "HPlaBAnd" ];
tiles.or [blank][nc]   ← Get[ "BOr" ];
tiles.or [blank][extra]  ← Get[ "HPlaBOrEx" ];
tiles.glue [conn][leftSide]  ← Get[ "HPlaBLeftSide" ];
tiles.glue [conn][between]  ← Get[ "HPlaBBetween" ];
tiles.glue [conn][rightSide] ← Get[ "HPlaCRightSide" ];
tiles.and [conn][left]   ← Get[ "CAndLt" ];
tiles.and [conn][right]  ← Get[ "CAndRt" ];
tiles.and [conn][nc]   ← Get[ "BAnd" ];
tiles.or [conn][left]   ← Get[ "COr" ];
tiles.or [conn][nc]   ← Get[ "COrNC" ];
tiles.or [conn][extra]   ← Get[ "HPlaCOrEx" ];
tiles.glue [dataUp][leftSide] ← Get[ "HPlaDLeftSide" ];
tiles.glue [dataUp][between] ← Get[ "HPlaDBetween" ];
tiles.glue [dataUp][rightSide] ← Get[ "HPlaDRightSide" ];
tiles.and [dataUp][left]  ← Get[ "DAndLt" ];
tiles.and [dataUp][right]  ← Get[ "DAndRt" ];
tiles.and [dataUp][nc]   ← Get[ "DAnd" ];
tiles.or [dataUp][left]  ← Get[ "DOr" ];
tiles.or [dataUp][nc]   ← Get[ "DOrNC" ];
tiles.or [dataUp][extra]  ← Get[ "HPlaDOrEx" ];
tiles.glue [dataDn][leftSide] ←    tiles.glue [dataUp][leftSide];
tiles.glue [dataDn][between] ← PW.FlipY[ tiles.glue [dataUp][between] ];
tiles.glue [dataDn][rightSide] ← PW.FlipY[ 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[ tiles.or [dataUp][left]  ];
tiles.or [dataDn][nc]   ← PW.FlipY[ tiles.or [dataUp][nc]   ];
tiles.or [dataDn][extra]  ← PW.FlipY[ tiles.or [dataUp][extra]  ];
RETURN[tiles]};
log: IO.STREAM ← CoreFrame.GetLog[];
END.