IFUCoreCtlPreCharge.mesa,
Copyright c 1986 by Xerox Corporation. All rights reserved.
Last Edited by Curry, October 23, 1986 2:53:40 pm PDT
Don Curry November 3, 1986 10:36:57 pm PST
DIRECTORY Basics, CD, CDCells, CDOrient, CDRects, CDSymbolicObjects, CMosB, Core, CoreBlock, CoreCreate, CoreFrame, CoreGeometry, CoreLibrary, CoreName, CoreOps, IFUCoreCells, IFUCoreCtl, IFUCoreDrive, IO, Lists, PLAOps, PLASim, Ports, PW, PWC, PWCTilingClass, PWPins, REFBit, Rope;
IFUCoreCtlPreCharge: CEDAR PROGRAM
IMPORTS Basics, CD, CDCells, CDRects, CDSymbolicObjects, CoreBlock, CoreCreate, CoreFrame, CoreGeometry, CoreLibrary, CoreName, CoreOps, IFUCoreCells, IFUCoreDrive, IO, Lists, PLAOps, PLASim, Ports, PW, PWC, PWCTilingClass, PWPins, REFBit, Rope
EXPORTS IFUCoreCtl =
BEGIN
ROPE:    TYPE = Core.ROPE;
CellType:   TYPE = Core.CellType;
Wire:    TYPE = Core.Wire;
Wires:    TYPE = Core.Wires;
Frame:   TYPE = CoreFrame.Frame;
Side:    TYPE = CoreFrame.Side;
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;
in:   ROPE ← CoreName.RopeNm["in"];
nin:  ROPE ← CoreName.RopeNm["nin"];
in0:  ROPE ← CoreName.RopeNm["in0"];
in1:  ROPE ← CoreName.RopeNm["in1"];
out:  ROPE ← CoreName.RopeNm["out"];
GND:  ROPE ← CoreName.RopeNm["GND"];
VDD:  ROPE ← CoreName.RopeNm["VDD"];
fire:  ROPE ← CoreName.RopeNm["Fire"];
fireV:  ROPE ← CoreName.RopeNm["FireControlV"];
nPreChg: ROPE ← CoreName.RopeNm["NotPreChg"];
dChrg: ROPE ← CoreName.RopeNm["DisChg"];
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];
NewMakePla     [desc]};
MakePla      [desc]};
DressInDrs: PROC [desc: PLADescription] = {
desc.inDrs ← CONS[ NEW[DriveRec ←
[drRowType: xfooter, fire: desc.fire, fireV: desc.fireV, nPreChg: desc.nPreChg] ],
desc.inDrs];
FOR list: Drives ← desc.inDrs, list.rest WHILE list.rest#NIL DO
REPEAT FINISHED => list.rest ← CONS [NEW[DriveRec ←
[drRowType: xheader, fire: desc.fire, fireV: desc.fireV, nPreChg: desc.nPreChg]], 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;
template: DriveRec ← [plaType: desc.plaType, drRowType: type, fire: desc.fire, fireV: desc.fireV, nPreChg: desc.nPreChg];
SELECT type FROM
header, xfooter, footer => {
IF (last-driverIndex) <= pp.minConnSpace THEN ERROR;
last ← driverIndex+pp.minConnSpace;
desc.outDrs ← CONS[NEW[DriveRec ← template], desc.outDrs]};
blank, dataUp, dataDn  => {
IF (last-driverIndex) <= pp.minConnSpace THEN LOOP;
desc.outDrs ← CONS[NEW[DriveRec ← template], desc.outDrs]};
conn       => {
IF (last-driverIndex) <= pp.minConnSpace THEN ERROR;
last ← driverIndex;
desc.outDrs ← CONS[pp.rows[driverIndex].dr, desc.outDrs]}
ENDCASE => ERROR;
ENDLOOP};
NewMakePla: PROC[desc: PLADescription] = {
name:    ROPE ← CoreName.RopeNm[desc.name.Cat["Body"]];
tiles:    REF TileVarieties  ← GetPLATiles[desc.plaType];
pp:    REF PreChargedParams ← NARROW[desc.data];
obj:    CD.Object;
cellType:   CellType;
input:    INT ← 0;
output:   INT ← 0;
tileArray:   PWCTilingClass.TileArray ← NIL;
fireWire:   Wire ← CoreCreate.Seq[desc.fire,  0];
fireVWire:  Wire ← CoreCreate.Seq[desc.fireV,  0];
nPreChgWire: Wire ← CoreCreate.Seq[desc.nPreChg, 0];
extras:    Wires ← IF desc.plaType#precharged
THEN NIL ELSE LIST [fireWire, fireVWire, nPreChgWire ];
public:   Wire ← PLASim.CreateSimplePLAPublic[desc.name, extras ];
vddWire:   Wire ← CoreOps.FindWire[public, VDD];
gndWire:   Wire ← CoreOps.FindWire[public, GND];
log.PutRope["\n Assemble precharged/hot pla row tiles"];
tileArray ← NEW[PWCTilingClass.TileArrayRec[pp.rows.size]];
FOR rr: INT IN [0..pp.rows.size) DO
TileIt: PROC
[cell: CellType, type: {in, out, none} ← none, index: INT ← 0, header: BOOL�LSE] = {
pas: LIST OF CoreCreate.PANIL;
SELECT type FROM
in  => pas ← LIST[
[in0, CoreOps.FindWire[public, in][index]],
[in1, CoreOps.FindWire[public, nin][index]] ];
out => pas ← LIST[[out, CoreOps.FindWire[public, out][index]]];
ENDCASE;
IF header THEN{
pas ← CONS[[VDD, vddWire], CONS[[GND, gndWire], pas]];
IF extras#NIL THEN pas ←
CONS[[fire,  fireWire],
CONS[[fireV,  fireVWire],
CONS[[nPreChg, nPreChgWire], pas ] ] ]};
tileArray[rr][col] ← NEW[PWCTilingClass.TileRec ← [cell, pas]];
col ← col+1};
row:  REF RowRec ← pp.rows[rr];
col:  INT ← 1 + row.and.size + 1 + row.or.size + 1;
header: BOOL ← row.type=header OR row.type=footer;
tileArray[rr] ← NEW[PWCTilingClass.TileRowRec[col]];
col ← 0;
TileIt[ tiles.glue[row.type][leftSide], none, 0];
FOR i: INT IN [0..row.and.size) DO IF rr=0 AND row.and[i]#extra
THEN {TileIt[tiles.and[row.type][row.and[i]], in, input]; input ← input+1}
ELSE {TileIt[tiles.and[row.type][row.and[i]]]}; ENDLOOP;
TileIt[ tiles.glue[row.type][between]];
FOR i: INT IN [0..row.or.size) DO
TileIt[ tiles.or[row.type][row.or[i]]] ENDLOOP;
IF row.type#conn
THEN {TileIt[tiles.glue[row.type][rightSide], none, 0, header]}
ELSE {TileIt[tiles.glue[row.type][rightSide], out, output ]; output ← output+1};
ENDLOOP;
AssignPublicNames[desc, public];
cellType    ← PWCTilingClass.CreateTiling[
public:   public,
tileArray:   tileArray,
neighborX:  PWCTilingClass.LayoutNeighborX,
neighborY:  PWCTilingClass.LayoutNeighborY,
name:    name,
props:    NIL,
cacheNeighbor: TRUE ];
obj  ← PWC.Layout[cellType]; -- cause recast
cellType ← PWC.Extract[obj];   -- get record CT
[]𡤌oreName.CellNm[cellType, name];
PLASim.SetUpRose[cellType];
CoreBlock.MarkSides[cellType, desc.capSides];
desc.outBodyCT ← CoreFrame.NewFrameCell[0, name, [first: left, cell: cellType] ]};
MakePla: PROC[desc: PLADescription] = {
name: ROPE ← CoreName.RopeNm[desc.name.Cat["Body"]];
IF (desc.outBodyCT ← CoreFrame.ReadFrameCache[name])=NIL THEN {
{
body:  CD.Object;
cellType: 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[PWC.Layout[tiles.glue[row.type][leftSide]], objects];
FOR index: INT IN [0..row.and.size) DO
objects ← CONS[PWC.Layout[tiles.and[row.type][row.and[index]]], objects] ENDLOOP;
IF desc.nofOrCols#0 THEN {
objects ← CONS[PWC.Layout[tiles.glue[row.type][between]], objects];
FOR index: INT IN [0..row.or.size) DO
objects ← CONS[PWC.Layout[tiles.or[row.type][row.or[index]]], objects] ENDLOOP;
objects ← CONS[PWC.Layout[tiles.glue[row.type][rightSide]], objects] };
rowList ← CONS[PW.SharedAbutListX[PW.Reverse[objects]], rowList]
rowList ← CONS[PW.AbutListX[PW.Reverse[objects]], rowList]
ENDLOOP;
body ← PW.AbutListY[PW.Reverse[rowList]];
cellType ← MakeSimplePLACell[body, desc];
body ← ApplyNames[body, desc];
cellType ← CoreLibrary.ObjCell[body, name, NIL, 0];
CoreBlock.MarkSides[cellType, desc.capSides];
desc.outBodyCT ← CoreFrame.NewFrameCell[0, name, [first: left, cell: cellType] ];
} };
CoreFrame.WriteFrameCache[desc.outBodyCT]} };
MakeSimplePLACell: PROC[obj: CD.Object, desc: PLADescription]
RETURNS[cellType: CellType] = {
iSize:   CD.Position ← CD.InterestSize[obj];
shell:   CD.Object  ← CDCells.CreateEmptyCell[];
minW:  INT = CMosB.lambda;
sides:   CoreBlock.Sides;
loc, size: INT;
loc2, size2: CD.Position;
wire:   Wire;
extras:   Wires ← IF desc.plaType#precharged THEN NIL ELSE LIST [
CoreCreate.Seq[fire,   0],
CoreCreate.Seq[fireV,  0],
CoreCreate.Seq[nPreChg, 0],
CoreCreate.Seq[dChrg,  0] ];
renameProc: PWPins.ChangePinProc ~ { -- oldPin: CD.Instance => newPin: CD.Instance
newPin2:  CD.Instance; -- additional copy for decorating cellType
layer:   CD.Layer ← CDSymbolicObjects.GetLayer[oldPin];
oldNm:  ROPE  ← CoreName.RopeNm[CDSymbolicObjects.GetName[oldPin]];
[sides, loc, size] ← CoreBlock.GetInstSideLocSize[obj, oldPin];
loc2 ← SELECT sides FROM
left  => [0,     loc],
right  => [iSize.x-minW, loc],
top  => [loc,    iSize.y-minW],
bottom => [loc,    0],
ENDCASE => ERROR;
size2 ← SELECT sides FROM
top, bottom => [size,  minW]
ENDCASE  => [minW, size];
newPin ← PW.IncludeInCell[shell, CDRects.CreateRect[size2, layer], loc2];
newPin2 ← NEW[CD.InstanceRep ← newPin^];
wire  ← FindPublicWire[desc, cellType.public, oldNm, loc];
CDSymbolicObjects.SetName[newPin, CoreName.WireNm[wire].n];
CoreGeometry.PutPins[
decoration: PWC.extractMode.decoration,
public: wire,
pins:  CONS[ newPin2, CoreGeometry.GetPins[PWC.extractMode.decoration, wire] ] ]};
cellType  ← PLASim.CreateSimplePLA
[desc.name, PLASim.CreateSimplePLAPublic[desc.name, extras] ];
IF desc.plaType=precharged THEN {
[]←Ports.InitPort[wire: CoreOps.FindWire[cellType.public, fire],
levelType:b, initDrive: none];
[]←Ports.InitPort[wire: CoreOps.FindWire[cellType.public, fireV],
levelType:b, initDrive: none];
[]←Ports.InitPort[wire: CoreOps.FindWire[cellType.public, nPreChg],
levelType:b, initDrive: none];
[]←Ports.InitPort[wire: CoreOps.FindWire[cellType.public, dChrg], -- present by accident
levelType:l, initDrive: none] };
AssignPublicNames[desc, cellType.public];
Make new object with renamed pins and also decorate cellType with additional copies of renamed pins
obj ← PWPins.ChangePins[obj, renameProc];
PWC.SetExtractCell[obj,   cellType];
PWC.SetLayoutObj[cellType, obj];
CoreGeometry.PutIR[PWC.extractMode.decoration, cellType, CD.InterestRect[obj]];
PW.SetInterestRect[shell, iSize];
PW.RepositionCell[shell]}; -- note: this shell is not currently used
AssignPublicNames: PROC[desc: PLADescription, public: Wire] = {
pp:  REF PreChargedParams ← NARROW[desc.data];
name:  ROPE;
oIndex: INT ← 0;
iIndex: INT ← 0;
IF desc.plaType=precharged AND desc.fire#NIL THEN
[ ] ← CoreName.WireNm[CoreOps.FindWire[public, fire], desc.fire];
IF desc.plaType=precharged AND desc.fireV#NIL THEN
[ ] ← CoreName.WireNm[CoreOps.FindWire[public, fireV], desc.fireV];
IF desc.plaType=precharged AND desc.nPreChg#NIL THEN
[ ] ← CoreName.WireNm[CoreOps.FindWire[public, nPreChg], desc.nPreChg];
FOR rIndex: INT IN [0..pp.rows.size) DO
IF pp.rows[rIndex].type # conn THEN LOOP;
IF pp.rows[rIndex].dr = NIL THEN LOOP;
name ← IFUCoreDrive.DriveName[pp.rows[rIndex].dr, nin];
[ ] ← CoreName.WireNm[CoreOps.FindWire[public, out][oIndex], name];
oIndex ← oIndex + 1 ENDLOOP;
FOR list: LIST OF ROPE ← desc.plaInNames, list.rest.rest WHILE list#NIL DO
[ ] ← CoreName.WireNm[CoreOps.FindWire[public, in ][iIndex], list.first];
[ ] ← CoreName.WireNm[CoreOps.FindWire[public, nin ][iIndex], list.rest.first];
iIndex ← iIndex + 1 ENDLOOP};
FindPublicWire: PROC[desc: PLADescription, public: Wire, oldNm: ROPE, loc: INT]
RETURNS[wire: Wire] = {
TileSize: PROC[cell: CellType] RETURNS[size: CD.Position] =
{IF cell=NIL THEN RETURN[[0, 0]]; RETURN[PWC.InterestSize[cell]]};
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;
SELECT oldNm FROM
out => {
oIndex: INT ← 0;
yPos:  INT ← 0;
FOR rIndex: INT IN [0..pp.rows.size) DO
SELECT pp.rows[rIndex].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   => Signal[];
ENDCASE;
SELECT loc FROM
< yPos   => Signal[];
< yPos + rowHt => RETURN[CoreOps.FindWire[public, out][oIndex]]
ENDCASE;
yPos  ← yPos + rowHt;
oIndex ← oIndex + 1;
ENDLOOP;
Signal[]};
in0,
in1 => {
xpos: INT ← (loc - leftSize)/(pp.insPerExtra*andWidth+extraWidth);
xpos  ← (loc - leftSize - extraWidth*xpos)/(andWidth/2);
IF ((xpos MOD 2)=0) # (oldNm=in0) THEN Signal[];
IF ((xpos MOD 2)=0)
THENRETURN[CoreOps.FindWire[public, in ][xpos/2]]
ELSERETURN[CoreOps.FindWire[public, nin ][xpos/2]] };
ENDCASE  => RETURN[CoreOps.FindWire[public, oldNm]]};
ApplyNames: PROC[oldObj: CD.Object, desc: PLADescription] RETURNS[newObj: CD.Object]= {
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[oldObj, 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"];
fireV  => CDSymbolicObjects.SetName[newPin, "FireControlV"]; -- to conn pad
nPreChg  => CDSymbolicObjects.SetName[newPin, "NotPreChg"];  -- to conn pad
ENDCASE => RETURN};
newObj ← PWPins.ChangePins[oldObj, 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 CellType;
GlueCellType: TYPE = {leftSide, between, rightSide};
NormalTiles:  TYPE = ARRAY RowType OF ARRAY NormalCellType OF CellType;
NormalCellType: TYPE = {left, right, nc, extra};
GetPLATiles: PROC[type: PLAType] RETURNS[tiles: REF TileVarieties] = {
tiles ← SELECT type FROM
hot  => GetHotPLATiles[],
ENDCASE => GetPreChargedPLATiles[]};
FlipY: PROC[orig: CellType] RETURNS[flipped: CellType] = {
name: ROPE ← CoreName.CellNm[orig].n;
IF name.Length[]=0 THEN Signal[];
flipped ← CoreFrame.RotateCellType[orig, CDOrient.mirrorY];
[] ← CoreName.CellNm[flipped, name.Cat["-FlipY"]]};
FlipY: PROC[orig: CD.Object] RETURNS[flipped: CD.Object] = {
name: ROPE ← CDDirectory.Name[orig];
IF name.Length[]=0 THEN Signal[];
flipped ← PW.FlipY[orig];
PWC.SetObjName[flipped, name.Cat["-FlipY"]]};
GetPreChargedPLATiles: PROC RETURNS[tiles: REF TileVarieties] = {
Get: PROC[name: ROPE] RETURNS[CellType] = {RETURN[CoreLibrary.Get[library, 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]  ← FlipY[ tiles.glue [header][leftSide] ];
tiles.glue [footer][between] ← FlipY[ tiles.glue [header][between] ];
tiles.glue [footer][rightSide] ← FlipY[ tiles.glue [header][rightSide] ];
tiles.and [footer][nc]   ← FlipY[ tiles.and [header][nc]   ];
tiles.and [footer][extra]  ← FlipY[ tiles.and [header][extra]  ];
tiles.or [footer][nc]   ← Get[ "HOrFooter" ]; -- isolate outs from next stage
tiles.or [footer][extra]  ← 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] ← FlipY[ tiles.glue [dataUp][between] ];
tiles.glue [dataDn][rightSide] ← 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]  ← FlipY[ tiles.or [dataUp][left]  ];
tiles.or [dataDn][nc]   ← FlipY[ tiles.or [dataUp][nc]   ];
tiles.or [dataDn][extra]  ← FlipY[ tiles.or [dataUp][extra]  ];
RETURN[tiles]};
GetHotPLATiles: PROC RETURNS[tiles: REF TileVarieties] = {
Get: PROC[name: ROPE] RETURNS[CellType] = {RETURN[CoreLibrary.Get[library, 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]  ← FlipY[ tiles.glue [header][leftSide] ];
tiles.glue [footer][between] ← FlipY[ tiles.glue [header][between] ];
tiles.glue [footer][rightSide] ← FlipY[ tiles.glue [header][rightSide] ];
tiles.and [footer][nc]   ← FlipY[ tiles.and [header][nc]   ];
tiles.or [footer][nc]   ← FlipY[ tiles.or [header][nc]   ];
tiles.or [footer][extra]  ← 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" ];  -- input connections not used
tiles.and [conn][right]  ← Get[ "CAndRt" ];  -- input connections not used
tiles.and [conn][nc]   ← Get[ "HPlaBAnd" ]; -- input connections not used
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] ← FlipY[ tiles.glue [dataUp][between] ];
tiles.glue [dataDn][rightSide] ← 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]  ← FlipY[ tiles.or [dataUp][left]  ];
tiles.or [dataDn][nc]   ← FlipY[ tiles.or [dataUp][nc]   ];
tiles.or [dataDn][extra]  ← FlipY[ tiles.or [dataUp][extra]  ];
RETURN[tiles]};
log: IO.STREAM ← CoreFrame.GetLog[];
END.