CCImpl.mesa
Don Curry August 15, 1987 5:26:35 pm PDT
DIRECTORY
CC, CD, CDDirectory, CDIO, CDRects, CDRoutingObjects, CDSimpleRules, CDViewer, CMosB, Core, CoreClasses, CoreCreate, CoreDirectory, CoreGeometry, CoreOps, IO, PLAOps, PWCore, TilingClass, REFBit, RefTab, Rope, RopeList, Sisyph, TerminalIO, ViewerOps, WireIconExtras;
CCImpl: CEDAR PROGRAM
IMPORTS CD, CDDirectory, CDIO, CDRects, CDRoutingObjects, CDSimpleRules, CDViewer, CMosB, CoreClasses, CoreCreate, CoreDirectory, CoreGeometry, CoreOps, IO, PLAOps, PWCore, TilingClass, REFBit, RefTab, Rope, RopeList, Sisyph, TerminalIO, ViewerOps, WireIconExtras
EXPORTS CC =
BEGIN
Types, constants and globals
ROPE:    TYPE = Rope.ROPE;
ROPES:   TYPE = LIST OF Rope.ROPE;
CellType:   TYPE = Core.CellType;
Wire:    TYPE = Core.Wire;
Wires:    TYPE = Core.Wires;
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};
RowType:  TYPE = {header, footer, conn, dataUp, dataDn, blank};
DriverTiles:  TYPE = REF DriverTileArry;
DriverTileArry: TYPE = ARRAY DriverTileType OF CellType;
DriverTileType: TYPE = {left, in, between, extra, out2, out1, rightHalf};
vddNm:   ROPE ← "Vdd";
gndNm:   ROPE ← "Gnd";
inNm:    ROPE ← "in";
in0Nm:   ROPE ← "in0";
in1Nm:   ROPE ← "in1";
outNm:   ROPE ← "out";
out0Nm:   ROPE ← "out0";
out1Nm:   ROPE ← "out1";
logicInNm:  ROPE ← "logicIn";
logicOutNm:  ROPE ← "logicOut";
rowsPerDr:  INT ← 3; -- not easily changed
outsPerExtra:  INT ← 10; -- can be changed
rowsPerExtra: INT ← 10; -- can be changed
layRules:   ATOM     ← $cmosB;
TileBuffer:  REF TileVarieties ← NIL;
DriverBuffer: DriverTiles   ← NIL;
RoutingCells: RefTab.Ref   ← RefTab.Create[];
Signal:   SIGNAL    = CODE;
Exported Procedures
ExpToPlaCell: PUBLIC PROC[expr: REF, type: ATOM ← NIL] RETURNS[cell: CellType] = {
pla:   PLAOps.PLA ← PLAOps.ExpressionToPLA[expr];
IF type=NIL THEN type ← $buffered;
SELECT type FROM
$basic   => cell ← PLABodyBasic[pla];
$bufferedBot => cell ← PLABuffered[pla];
$latchedBot => cell ← XXX[pla];
$basicRt  => cell ← PLABodyBasic[pla, TRUE];
$clockedRt => cell ← XXX[pla];
$latchedRt => cell ← XXX[pla];
ENDCASE  => ERROR};
PLABuffered: PROC[pla: PLAOps.PLA] RETURNS[cell: CellType] = {
logic:   CellType ← PLABodyBasic[pla];
bufs:   CellType ← BufferedPLADrivers[pla];
vdd:   Wire  ← CoreOps.CreateWires[0,        vddNm];
gnd:   Wire  ← CoreOps.CreateWires[0,        gndNm];
logicIn:  Wire  ← WireIconExtras.RefWire[pla.data, logicInNm,  TRUE];
logicOut:  Wire  ← WireIconExtras.RefWire[pla.out,  logicOutNm,  FALSE];
in:    Wire  ← WireIconExtras.RefWire[pla.data, inNm,    FALSE];
out:   Wire  ← WireIconExtras.RefWire[pla.out,  outNm,   FALSE];
logicI:   CoreCreate.CellInstance ← CoreCreate.Instance[logic,
[inNm,   logicIn],
[outNm,   logicOut],
[vddNm,   vdd],
[gndNm,   gnd] ];
bufsI:   CoreCreate.CellInstance ← CoreCreate.Instance[bufs,
[inNm,   in],
[outNm,   out],
[logicInNm,  logicIn],
[logicOutNm, logicOut],
[vddNm,   vdd],
[gndNm,   gnd] ];
StripSubWireNames[logicIn];
StripSubWireNames[logicOut];
AddSubWireNamePrefix[to: out, prefix: "Nxt"];
cell ← CoreCreate.Cell[
public:  CoreCreate.WireList[LIST[in, out, vdd, gnd]],
onlyInternal: CoreCreate.WireList[LIST[logicIn, logicOut]],
instances:  LIST[bufsI, logicI],
name:   pla.name ];
PWCore.SetAbutY[cell];
RETURN[cell]};
PLAInSB: PUBLIC PROC[cx: CC.Context, tttFile: ROPE] RETURNS[cell: CellType] = {
pla:  PLAOps.PLA ← PLAOps.ReadPLAFile
[tttFile.Cat[".ttt"], TerminalIO.TOS[], TRUE];
rec: CoreClasses.RecordCellType ← NEW[CoreClasses.RecordCellTypeRec[0]];
in:   Wire ← WireIconExtras.RefWire[pla.data, "in",  TRUE];
out:  Wire ← WireIconExtras.RefWire[pla.out,  "out",  FALSE];
public: Wire ← CoreOps.CreateWire[LIST[in]];
internal: Wire ← CoreOps.CreateWire[LIST[in]];
flatIn:  Wire ← CoreOps.CreateWire[Flatten[in]];
flatInOrd: Wire ← CoreOps.CreateWire[Flatten[ReorderWire[in, GetSideNames[cx, right]]]];
insAtTop:  BOOL ← GetSideNames[cx, top]  #NIL;
insAtBot:  BOOL ← GetSideNames[cx, bottom] #NIL AND ~insAtTop;
ins:   NAT ← flatIn.size/2;
nofOrCols: NAT ← NofOrCols[MAX[CoreOps.WireBits[out], GetMinOuts[cx]]];
leftSize:  INT ← 44 * CMosB.lambda;
betweenSize: INT ← 16 * CMosB.lambda;
rightSize:  INT ← 16 * CMosB.lambda;
blankSize: INT ← 8 * CMosB.lambda;
biasX:   INT ← 48 * CMosB.lambda;
biasY:   INT ← 12 * CMosB.lambda;
colAnd:  INT ← 16 * CMosB.lambda;
colOr:   INT ← 8 * CMosB.lambda;
halfColSize: INT ← 8 * CMosB.lambda;
rowSize:  INT ← 24 * CMosB.lambda;
halfRowSize: INT ← 16 * CMosB.lambda;
obj:   CD.Object;
contObj:  CD.Object ← CDSimpleRules.Contact[layRules, CMosB.met, CMosB.met2];
contW:  INT ← CD.InterestSize[contObj].x;
metW:   INT ← CDSimpleRules.MinWidth[layRules, CMosB.met];
met2W:  INT ← CDSimpleRules.MinWidth[layRules, CMosB.met2];
iSizeX:  NAT ← leftSize +ins*colAnd +betweenSize +nofOrCols*colOr +rightSize;
iSizeY:  NAT ← blankSize + ins*rowSize + blankSize;
nodes:   LIST OF CDRoutingObjects.Node;
cell ← CoreClasses.CreateRecordCell[public, internal, NIL, tttFile.Cat["InSB"]];
FOR indexX: INT IN [0..ins) DO
FOR polarity: INT IN [0..2) DO
node:  CDRoutingObjects.Node;
pub:  Wire   ← flatIn[2*indexX + polarity];
name:  ROPE ← CoreOps.GetFullWireName[public, pub];
indexY: INT   ← WireIndex[flatInOrd, pub]/2;
refX:  INT   ← biasX + indexX * colAnd + polarity * halfColSize;
refY:  INT   ← biasY + indexY * rowSize + polarity * halfRowSize;
verYSize: INTSELECT TRUE FROM
insAtTop AND insAtBot => iSizeY,
insAtTop      => iSizeY-refY,
insAtBot      => refY,
ENDCASE      => ERROR;
horSize: CD.Position ← [iSizeX-refX,  metW];
verSize: CD.Position ← [met2W, verYSize];
horPos: CD.Position ← [refX,    refY-metW/2];
verPos: CD.Position ← [refX-met2W/2, (IF insAtBot THEN 0 ELSE refY)];
contPos: CD.Position ← [refX-contW/2, refY-contW/2];
horObj: CD.Object ← CDRects.CreateRect[horSize, CMosB.met];
verObj: CD.Object ← CDRects.CreateRect[verSize, CMosB.met2];
pos: LIST OF CDRoutingObjects.PlacedObject ← NIL;
pins: LIST OF CoreGeometry.Instance ← NIL;
IF name=NIL THEN ERROR;
pos ← CONS[[ horObj, horPos], pos]; --pins ← CONS[[horObj, [horPos]], pins];
pos ← CONS[[ verObj, verPos], pos]; --pins ← CONS[[verObj, [verPos]], pins];
pos ← CONS[[ contObj,  contPos], pos];
CoreGeometry.AddPins[PWCore.extractMode.decoration, pub, pins];
node ← CDRoutingObjects.CreateNode
[pos, LIST[[$SignalName, name], [$InstanceName, name]]];
nodes ← CONS[node, nodes];
ENDLOOP;
ENDLOOP;
obj ← CDRoutingObjects.CreateRoutingObject[nodes, [x1: 0, y1: 0, x2: iSizeX, y2: iSizeY]];
PWCore.SetLayout[cell, $Value, $PWCoreValue, obj]};
PWCore.PutObject[PWCore.extractMode.decoration, cell, obj]};
PLAOutDrHeader: PUBLIC PROC[tttFile: ROPE] RETURNS[cell: CellType] = {
pla:  PLAOps.PLA ← PLAOps.ReadPLAFile[tttFile.Cat[".ttt"], TerminalIO.TOS[], TRUE];
out:  Wire  ← WireIconExtras.RefWire[pla.out,  "out",  FALSE];
outSize: INT  ← CoreOps.WireBits[out];
minSize: NAT  ← (rowsPerDr-1)*outSize;
outFill: INT  ← MAX[pla.termList.length, minSize] - minSize;
header: CellType ← Get["CC.DrHeader.sch", TRUE];
blank:  CellType ← Get["CC.DrBlank.sch", TRUE];
name:  ROPE  ← "DrHeader";
insts:  CoreCreate.CellInstances ← LIST[CoreCreate.Instance[header]];
[]←PWCore.Layout[header];
[]←PWCore.Layout[blank];
IF outFill=0 THEN RETURN[header];
name ← IO.PutFR["%gWith%gBlanks", IO.rope[name], IO.int[outFill]];
FOR i: INT IN [1..outFill] DO insts ← CONS[CoreCreate.Instance[blank], insts]; ENDLOOP;
cell ← CoreCreate.Cell[
public:  CoreOps.CopyWire[header.public],
instances:  insts,
name:   name];
PWCore.SetAbutY[cell]};
PLABody: PUBLIC PROC[cx: CC.Context, tttFile: ROPE] RETURNS[cell: CellType] = {
pla:   PLAOps.PLA ← PLAOps.ReadPLAFile[tttFile, TerminalIO.TOS[], TRUE];
minOuts:  INT ← GetMinOuts[cx];
rightNames: ROPES ← GetSideNames[cx, right];
cell ← PLABodyBasic[pla, rightNames#NIL, rightNames, minOuts]};
Domestic Procedures
PLABodyBasic: PROC
[pla: PLAOps.PLA, horOuts: BOOLFALSE, rtNms: ROPESNIL, minOuts: INT𡤀]
RETURNS[cell: CellType] = {
The type of PLA is implied by where the ouputs are specified in the icon.
output names   on right  => output connections positioned every 3 rows
`out' or output names on bottom => output connections at bottom
`in' or input names may be on top or bottom or both.
vdd:   Wire  ← CoreOps.CreateWires[0,      vddNm];
gnd:   Wire  ← CoreOps.CreateWires[0,      gndNm];
in:    Wire  ← WireIconExtras.RefWire[pla.data, "in",  TRUE];
out:   Wire  ← WireIconExtras.RefWire[pla.out,  "out",  FALSE];
flatIn:   Wire  ← CoreOps.CreateWire[Flatten[in]];
flatOut:  Wire  ← CoreOps.CreateWire[Flatten[out]];
flatOutOrd: Wire  ← CoreOps.CreateWire[Flatten[ReorderWire[out, rtNms]]];
public:  Wire  ← NIL;
nofRows:  NAT  ← 2 + (IF horOuts
THEN flatOut.size+MAX[flatOut.size*(rowsPerDr-1), pla.termList.length]
ELSE pla.termList.length);
nofOrCols: NAT  ← NofOrCols[MAX[flatOut.size, minOuts] ];
nofAndCols: NAT  ← flatIn.size/2;
row:   INT  ← 0;
up:   BOOL  ← FALSE;
cRow:   INT  ← 0;
fillLt:   INT  ← 0;
ta:    TilingClass.TileArray ← NEW[TilingClass.TileArrayRec[nofRows]];
terms:   LIST OF PLAOps.Term ← NIL;
data:   PLAOps.Term   ← NIL;
GetRow: PROC[type: RowType] RETURNS[rowRef: TilingClass.TileRow ] = {
AndBit: PROC[index: INT] RETURNS[NormalCellType] = {
RETURN[SELECT type FROM
dataUp, dataDn => SELECT PLAOps.GetInQrt
[data, REFBit.Desc[pla.data].bitForm[index].firstBit] FROM
zero => left, one => right, ENDCASE => nc,
ENDCASE  => nc]};
OrBit: PROC[index: INT] RETURNS[NormalCellType] = {
IF (index+1) MOD (outsPerExtra+1) = 0 THEN RETURN[extra];
index ← index - index/(outsPerExtra+1);
IF index >= flatOut.size THEN RETURN[nc];
SELECT type FROM
conn    => IF flatOutOrd[cRow]=flatOut[index] THEN RETURN[left];
dataUp, dataDn => IF PLAOps.GetOutQrt
[data, REFBit.Desc[pla.out].bitForm[index].firstBit]=one
THEN RETURN[left];
ENDCASE;
RETURN[nc]};
TileIt: PROC[
cell:  CellType,
pubType: {in, out, none} ← none,
index:  INT ← 0,
header: BOOLFALSE ] = {
pas: LIST OF CoreCreate.PANIL;
SELECT pubType FROM
in  => pas ← LIST[[in0Nm, flatIn[2*index+0]], [in1Nm, flatIn[2*index+1]] ];
out => pas ← LIST[[outNm, flatOut[index]]];
ENDCASE;
IF header THEN pas ← CONS[[vddNm, vdd], CONS[[gndNm, gnd], pas]];
rowRef[col] ← NEW[TilingClass.TileRec ← [cell, pas, IsRoutingCell[cell]]];
col ← col+1};
col:  INT ← 0;
tiles:  REF TileVarieties ← GetPLATiles[];
MainLine GetRow Code
rowRef ← NEW[TilingClass.TileRowRec[1 + nofAndCols + 1 + nofOrCols + 1]];
SELECT type FROM
conn    => {
up    ← FALSE};
dataUp, dataDn => {
IF terms = NIL THEN data ← NIL ELSE {data ← terms.first; terms ← terms.rest};
type ← IF data=NIL THEN blank ELSE IF (up←~up) THEN dataUp ELSE dataDn};
ENDCASE;
TileIt[ tiles.glue[type][leftSide], none, 0];
FOR i: INT IN [0..nofAndCols) DO IF row=0 AND AndBit[i]#extra
THEN {TileIt[tiles.and[type][AndBit[i]], in, i]}
ELSE {TileIt[tiles.and[type][AndBit[i]]]}; ENDLOOP;
TileIt[ tiles.glue[type][between]];
FOR i: INT IN [0..nofOrCols) DO
outI: INT ← i-i/(outsPerExtra+1);
IF row=0 AND OrBit[i]#extra AND outI < flatOut.size
THEN {TileIt[ tiles.or[type][OrBit[i]], out, outI]}
ELSE {TileIt[ tiles.or[type][OrBit[i]]]} ENDLOOP;
IF type#conn
THEN {TileIt[tiles.glue[type][rightSide], none, 0, (type=header OR type=footer)]}
ELSE {TileIt[tiles.glue[type][rightSide] ]} };
MainLine PLAOut Code
IF horOuts
THEN terms ← GetHorOutsTermList[pla, flatOut, flatOutOrd]
ELSE {
size: INT ← pla.termList.length + (pla.termList.length-1)/rowsPerExtra;
term: PLAOps.Term ← pla.termList.end;
FOR index: INT DECREASING IN[0..size) DO
IF (index+1) MOD (outsPerExtra+1) # 0
THEN {terms ← CONS[PLAOps.CopyTerm[term], terms]; term ← term.last}
ELSE {terms ← CONS[NIL,       terms]}
ENDLOOP };
FOR row IN [0..ta.size) DO SELECT TRUE FROM
row=0     => {ta[row]← GetRow[footer]; fillLt ← rowsPerDr-1};
row+1=nofRows  => {ta[row]← GetRow[header]};
fillLt#0    => {ta[row]← GetRow[dataUp]; fillLt ← fillLt -1};
cRow=flatOut.size => {ta[row]← GetRow[dataUp]};
~horOuts    => {ta[row]← GetRow[dataUp]}; --fillLt not used unless horOuts
ENDCASE    => {ta[row]← GetRow[conn]; fillLt←rowsPerDr-1; cRow𡤌Row+1};
ENDLOOP;
This should not be quaified by horOuts.
Its just too painful to change the dozen or so icons in IFUSch just yet.
IF ~horOuts THEN AddSubWireNamePrefix[to: out, prefix: "Nxt"];
cell ← TilingClass.CreateTiling[
public:   CoreOps.CreateWire[LIST[in, out, vdd, gnd]],
tileArray:   ta,
neighborX:  TilingClass.LayoutNeighborX,
neighborY:  TilingClass.LayoutNeighborY,
name:    pla.name,
props:    NIL ]};
BufferedPLADrivers: PROC[pla: PLAOps.PLA] RETURNS[cell: CellType]={
vdd:   Wire  ← CoreOps.CreateWires[0,        vddNm];
gnd:   Wire  ← CoreOps.CreateWires[0,        gndNm];
lIn:   Wire  ← WireIconExtras.RefWire[pla.data, logicInNm,  TRUE];
lOut:   Wire  ← WireIconExtras.RefWire[pla.out,  logicOutNm,  FALSE];
dIn:   Wire  ← WireIconExtras.RefWire[pla.data, inNm,    FALSE];
dOut:   Wire  ← WireIconExtras.RefWire[pla.out,  outNm,   FALSE];
flatLIn:  Wire  ← CoreOps.CreateWire[Flatten[lIn]];
flatLOut:  Wire  ← CoreOps.CreateWire[Flatten[lOut]];
flatDIn:  Wire  ← CoreOps.CreateWire[Flatten[dIn]];
flatDOut:  Wire  ← CoreOps.CreateWire[Flatten[dOut]];
nofOrCols: NAT  ← NofOrCols[flatDOut.size];
nofOrColExs: NAT  ← nofOrCols/(outsPerExtra+1);
nofOrColOut: NAT  ← nofOrCols - nofOrColExs;
nofAndCols: NAT  ← flatDIn.size;
drivers:  DriverTiles ← GetPLADriverTiles[];
ta:    TilingClass.TileArray ← NEW[TilingClass.TileArrayRec[1]];
orIndex:  INT ← 0;
extras:   INT ← 0;
col:   INT ← 0;
TileIt: PROC[
cell:  CellType,
pubType: {in, out2, out1, filler} ← filler,
index:  INT ← 0] = {
pas:  LIST OF CoreCreate.PALIST[[vddNm, vdd], [gndNm, gnd]];
SELECT pubType FROM
in  => pas ←
CONS[[inNm,  flatDIn[index]],
CONS[[out0Nm, flatLIn[2*index+0]],
CONS[[out1Nm, flatLIn[2*index+1]], pas]]];
out1  => pas ←
CONS[[in0Nm, flatLOut[index]],
CONS[[out0Nm, flatDOut[index]], pas]];
out2  => pas ←
CONS[[in0Nm, flatLOut[index]],
CONS[[out0Nm, flatDOut[index]],
CONS[[in1Nm, flatLOut[index+1]],
CONS[[out1Nm, flatDOut[index+1]], pas]]]];
ENDCASE;
ta[0][col] ← NEW[TilingClass.TileRec ← [cell, pas, IsRoutingCell[cell]]];
col ← col+1};
ta[0] ← NEW[TilingClass.TileRowRec
[1 + nofAndCols + 1 + nofOrColExs + nofOrColOut/2 + 2]];
TileIt[ drivers[left], filler];
FOR i: INT IN [0..nofAndCols) DO TileIt[drivers[in], in, i] ENDLOOP;
TileIt[ drivers[between], filler];
WHILE orIndex < nofOrCols DO
IF ((orIndex+1) MOD (outsPerExtra+1)) = 0
THEN {TileIt[ drivers[extra], filler]; orIndex ← orIndex+1; extras ← extras+1; LOOP}
ELSE {IF orIndex+1=nofOrCols
THEN {TileIt[ drivers[out1], out1, orIndex-extras]; orIndex ← orIndex+1}
ELSE {TileIt[ drivers[out2], out2, orIndex-extras]; orIndex ← orIndex+2}};
ENDLOOP;
TileIt[ drivers[rightHalf], filler];
IF ((nofOrCols-extras) MOD 2)=0
THEN TileIt[ drivers[rightHalf], filler];
StripSubWireNames[lIn]; -- to prevent confusion with driver in subWire names
StripSubWireNames[lOut]; -- to prevent confusion with driver out subWire names
MainLine Code
cell ← TilingClass.CreateTiling[
public:   CoreOps.CreateWire[LIST[dIn, dOut, lIn, lOut, vdd, gnd]],
tileArray:   ta,
neighborX:  TilingClass.LayoutNeighborX,
neighborY:  TilingClass.LayoutNeighborY,
name:    pla.name,
props:    NIL ]};
GetMinOuts: PROC[cx: Sisyph.Context] RETURNS[nofOrCols: INT] = {
RETURN[IF (cx=NIL OR NOT Sisyph.FetchInt[cx, "CCPLAOuts"].found)
THEN 0 ELSE Sisyph.FetchInt[cx, "CCPLAOuts"].value]};
NofOrCols: PROC[nofOuts: INT] RETURNS[nofOrCols: INT] =
{RETURN[nofOuts+(nofOuts-1)/outsPerExtra]};
StripSubWireNames: PROC[w: Wire] = {
IF w.size=0 THEN RETURN;
FOR i: INT IN [0..w.size) DO
[]𡤌oreOps.SetShortWireName[w[i], NIL]; StripSubWireNames[w[i]]; ENDLOOP};
AddSubWireNamePrefix: PROC[to: Wire, prefix: ROPE] = {
FOR i: INT IN [0..to.size) DO
name: ROPE ← CoreOps.GetShortWireName[to[i]];
IF name.Length[]=0 OR to[i].size>0 THEN ERROR;
[]𡤌oreOps.SetShortWireName[to[i], Rope.Cat[prefix, name]] ENDLOOP;};
AddSubWireNamePrefixIfClash: PROC[to, ck: Wire, prefix: ROPE] = {
FOR i: INT IN [0..to.size) DO
CkClash: PROC [w: Wire] =
{clash ← clash OR CoreOps.GetShortWireName[w].Equal[name]};
clash: BOOLFALSE;
name: ROPE ← CoreOps.GetShortWireName[to[i]];
IF name.Length[] > 0 THEN [] ← CoreOps.VisitRootAtomics[ck, CkClash];
IF clash THEN []𡤌oreOps.SetShortWireName[to[i], Rope.Cat[prefix, name]];
IF to[i].size>0 THEN AddSubWireNamePrefixIfClash[to[i], ck, prefix]; ENDLOOP};
GetHorOutsTermList: PROC[pla: PLAOps.PLA, flatOut, flatOutOrd: Wire]
RETURNS[terms: LIST OF PLAOps.Term ← NIL] = {
Assumes 3 rows per driver
SeqTermLists:  TYPE = REF SeqTermListsRec;
SeqTermListsRec: TYPE = RECORD[SEQUENCE size: CARDINAL OF LIST OF PLAOps.Term];
TwoTermRecs:  TYPE = RECORD[t1, t2: PLAOps.TermRec];
MoveFromTermsToOuts: PROC[idx: INT] = {
terms ← CONS[NIL, terms];
IF terms=NIL THEN RETURN;
FOR list: LIST OF PLAOps.Term ← terms, list.rest WHILE list.rest#NIL DO
term: PLAOps.Term ← list.rest.first;
IF PLAOps.GetOutQrt[term, idx]#one THEN
{list.rest ← list.rest.rest; terms ← terms.rest; outs[idx] ← CONS[term, outs[idx]]; RETURN};
ENDLOOP;
FOR list: LIST OF PLAOps.Term ← terms, list.rest WHILE list.rest#NIL DO
term: PLAOps.Term ← list.rest.first;
FOR i: INT IN [0..outs.size) DO
IF PLAOps.GetOutQrt[term, i]#one THEN
FOR sub: LIST OF PLAOps.Term ← outs[i], sub.rest WHILE sub#NIL DO
IF PLAOps.GetOutQrt[sub.first, idx]#one THEN {
[term^, sub.first^] ← TwoTermRecs[sub.first^, term^];
list.rest ← list.rest.rest; terms ← terms.rest;
outs[idx] ← CONS[term, outs[idx]]; RETURN}
ENDLOOP;
ENDLOOP;
REPEAT FINISHED => ERROR ENDLOOP};
outForm:  PLAOps.Format ← REFBit.Desc[pla.out].bitForm;
end:   PLAOps.Term;
outs:   SeqTermLists ← NEW[SeqTermListsRec[pla.termList.outBits]];
FOR output: INT IN [pla.termList.length..flatOutOrd.size*2) DO
terms ← CONS[PLAOps.NewTerm[pla.termList.inBits, pla.termList.outBits], terms] ENDLOOP;
FOR term: PLAOps.Term ← pla.termList.end, term.last WHILE term#NIL DO
terms ← CONS[PLAOps.CopyTerm[term], terms] ENDLOOP;
FOR output: INT IN [0..flatOutOrd.size) DO outs[output] ← NIL ENDLOOP;
FOR output: INT IN [0..flatOutOrd.size) DO
FOR index: INT IN [0..flatOut.size) DO
IF flatOutOrd[output] # flatOut[index] THEN LOOP;
MoveFromTermsToOuts[ outForm[index].firstBit ];
MoveFromTermsToOuts[ outForm[index].firstBit ];
EXIT REPEAT FINISHED => ERROR ENDLOOP;
ENDLOOP;
MoveOutsBackToTerms
FOR output: INT DECREASING IN [0..flatOutOrd.size) DO
FOR index: INT IN [0..flatOut.size) DO
IF flatOutOrd[output] # flatOut[index] THEN LOOP;
FOR sub: LIST OF PLAOps.Term ← outs[outForm[index].firstBit], sub.rest
WHILE sub#NIL DO terms ← CONS[sub.first, terms] ENDLOOP;
outs[outForm[index].firstBit] ← NIL; ENDLOOP ENDLOOP;
terms ← ReverseTerms[terms];  -- make last first
UNTIL end#NIL DO end ← terms.first; terms ← terms.rest ENDLOOP; -- remove end term
terms ← ReverseTerms[terms];  -- make first first
terms ← CONS[end, terms]; -- add end term to beginning
FOR list: LIST OF PLAOps.Term ← terms, list.rest WHILE list#NIL DO
FOR i: CARDINAL IN [0..list.first.out.wdSize) DO
IF list.first.out[i].d#0 THEN EXIT;
REPEAT FINISHED => list.first ← NIL ENDLOOP ENDLOOP};
ReverseTerms: PROC[terms: LIST OF PLAOps.Term] RETURNS[new: LIST OF PLAOps.Term] =
{FOR terms ← terms, terms.rest WHILE terms#NIL DO new←CONS[terms.first, new] ENDLOOP};
WireIndex: PROC[big, little: Wire] RETURNS[index: INT ← -1] = {
FOR index: INT IN [0..big.size) DO
IF big[index]=little THEN RETURN[index] ENDLOOP;
RETURN[-1]};
ReorderWire: PROC[wire: Wire, names: ROPES, extras: BOOLFALSE] RETURNS[Wire] = {
wires: Wires ← NIL;
nms: ROPESCONS[NIL, names];
IF names=NIL THEN RETURN[wire];
IF extras THEN FOR nms ← nms, nms.rest WHILE nms.rest#NIL DO
index: INT ← CoreOps.GetWireIndex[wire, nms.rest.first];
IF index=-1 THEN nms.rest ← nms.rest.rest
REPEAT FINISHED => names ← nms.rest ENDLOOP;
FOR names ← names, names.rest WHILE names#NIL DO
index: INT ← CoreOps.GetWireIndex[wire, names.first];
IF index=-1 THEN {
TerminalIO.PutF
["The icon wire name \"%g\" is not an element of the PLA interface.\n",
IO.rope[names.first]];
ERROR};
wires ← CONS[wire[index], wires] ENDLOOP;
RETURN[ CoreOps.CreateWire[ CoreOps.Reverse[wires]]]};
Flatten: PROC[wire: Wire] RETURNS[wires: Wires ← NIL] = {
temp: Wires;
IF wire.size=0 THEN RETURN[LIST[wire]];
FOR ii: INT IN [0..wire.size) DO
FOR temp ← Flatten[wire[ii]], temp.rest WHILE temp#NIL DO
wires ← CONS[temp.first, wires] ENDLOOP ENDLOOP;
temp ← wires; wires ← NIL;
FOR temp ← temp, temp.rest WHILE temp#NIL DO wires ← CONS[temp.first, wires] ENDLOOP};
GetSideNames: PROC[cx: CC.Context, side: CoreGeometry.Side]
RETURNS[names: ROPES] = {
obj: CD.Object   ← Sisyph.GetCDObj[cx];
cell: CellType ← Sisyph.ES[CDDirectory.Name[obj, Sisyph.GetDesign[cx]], cx];
eachSortedPin: CoreGeometry.EachSortedPinProc =
{names ← CONS[CoreOps.GetShortWireName[wire], names]};
[]𡤌oreGeometry.EnumerateSortedSides
[Sisyph.mode.decoration, cell, side, eachSortedPin];
names ← RopeList.Reverse[names]};
Tiles
RegisterRoutingCell: PROC[cell: CellType] = {[]←RefTab.Store[RoutingCells, cell, cell]};
IsRoutingCell: PROC[cell: CellType] RETURNS[isRoutingCell: BOOL] =
{RETURN[RefTab.Fetch[RoutingCells, cell].found]};
See also DPImpl.GetSchCT - same except for RoutingCell registration
Get: PROC [cx: CC.Context, name: ROPE, routingOnly: BOOL] RETURNS [cellType: CellType] ~ {
design:   CD.Design ← Sisyph.GetDesign[cx];
importeeName: IO.ROPE  ← name.Substr[0, name.Index[0, "."]];
IF design.name.Equal[importeeName]
THEN name ← name.Substr[name.Index[0, "."]+1]
ELSEIF CDDirectory.Fetch[design, name]=NIL THEN {
rootName: IO.ROPE ← name.Substr[name.Index[0, "."]+1];
ob: CD.Object ←
CDImports.CreateImportFromCache[design, rootName, importeeName, TRUE];
IF NOT CDDirectory.Include[design, ob, name, FALSE] THEN ERROR};
cellType ← Sisyph.ExtractSchematicByName[name: name, cx: cx];
IF (NARROW[cellType.data, CoreClasses.RecordCellType].size=0)#routingOnly THEN Signal[];
IF routingOnly THEN RegisterRoutingCell[cellType]};
Get: PROC [name: ROPE, routingOnly: BOOL] RETURNS [cellType: CellType] ~ {
cellType ← GetCellType[name];
IF (NARROW[cellType.data, CoreClasses.RecordCellType].size=0)#routingOnly THEN Signal[];
IF routingOnly THEN RegisterRoutingCell[cellType]};
GetCellType: PROC [name: ROPE] RETURNS [cellType: CellType] ~ {
library: CoreDirectory.Library ← CoreDirectory.FetchLibrary["CMOSB"];
cellType ← CoreDirectory.Fetch[library, name];
IF cellType=NIL THEN {
designName: IO.ROPE  ← name.Substr[0, name.Find["."]];
cellName:  IO.ROPE  ← name.Substr[name.Index[0, "."]+1];
design:  CD.Design ← CDViewer.FindDesign[designName];
cx:    CC.Context;
IF design=NIL THEN {
design ← CDIO.ReadDesign[designName];
IF design=NIL THEN ERROR;
ViewerOps.CloseViewer[CDViewer.CreateViewer[design, FALSE]]}; -- caches the design
cx ← Sisyph.Create[design];
cellType ← Sisyph.ExtractSchematicByName[name: cellName, cx: cx];
[]𡤌oreDirectory.Insert[library, name, cellType]}};
FlipY: PROC[orig: CellType] RETURNS[ct: CellType] = {
flipName: ROPE      ← Rope.Cat["FlipY", CoreOps.GetCellTypeName[orig]];
library: CoreDirectory.Library ← CoreDirectory.FetchLibrary["CMOSB"];
ct          ← CoreDirectory.Fetch[library, flipName];
IF ct = NIL THEN {
ct ← PWCore.RotateCellType[orig, $FlipY];
[]𡤌oreDirectory.Insert[library, flipName, ct];
IF IsRoutingCell[orig] THEN RegisterRoutingCell[ct]}};
GetPLATiles: PROC RETURNS[tiles: REF TileVarieties] = {
IF TileBuffer # NIL THEN RETURN[TileBuffer];
TerminalIO.PutRope["Initialize PLA tiles\n"];
tiles  ← TileBuffer ← NEW[TileVarieties];
tiles.glue ← NEW[GlueTiles];
tiles.and ← NEW[NormalTiles];
tiles.or ← NEW[NormalTiles];
tiles.glue [header][leftSide] ← Get["CC.HPlaHLeftSide.sch",  TRUE];
tiles.glue [header][between] ← Get["CC.HPlaHBetween.sch",  TRUE];
tiles.glue [header][rightSide] ← Get["CC.HPlaHRightSide.sch", TRUE];
tiles.and [header][nc]   ← Get["CC.HPlaHAnd.sch",   TRUE];
tiles.or [header][nc]   ← Get["CC.HPlaHOr.sch",   FALSE];
tiles.or [header][extra]  ← Get["CC.HPlaHOrEx.sch",   TRUE];
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[ Get["CC.BPlaHOr.sch", FALSE]];
tiles.or [footer][extra]  ← FlipY[ tiles.or [header][extra]  ];
tiles.glue [blank][leftSide]  ← Get["CC.HPlaBLeftSide.sch",  TRUE];
tiles.glue [blank][between] ← Get["CC.HPlaBBetween.sch",  TRUE];
tiles.glue [blank][rightSide] ← Get["CC.HPlaBRightSide.sch", TRUE];
tiles.and [blank][nc]   ← Get["CC.HPlaBAnd.sch",   TRUE];
tiles.or [blank][nc]   ← Get["CC.BOr.sch",     TRUE];
tiles.or [blank][extra]  ← Get["CC.HPlaBOrEx.sch",   TRUE];
tiles.glue [conn][leftSide]  ← Get["CC.HPlaBLeftSide.sch",  TRUE];
tiles.glue [conn][between]  ← Get["CC.HPlaBBetween.sch",  TRUE];
tiles.glue [conn][rightSide] ← Get["CC.HPlaCRightSide.sch", TRUE];
tiles.and [conn][nc]   ← Get["CC.HPlaBAnd.sch",   TRUE];
tiles.or [conn][left]   ← Get["CC.COr.sch",     TRUE];
tiles.or [conn][nc]   ← Get["CC.COrNC.sch",    TRUE];
tiles.or [conn][extra]   ← Get["CC.HPlaCOrEx.sch",   TRUE];
tiles.glue [dataUp][leftSide] ← Get["CC.HPlaDLeftSide.sch",  FALSE];
tiles.glue [dataUp][between] ← Get["CC.HPlaDBetween.sch",  TRUE];
tiles.glue [dataUp][rightSide] ← Get["CC.HPlaDRightSide.sch", TRUE];
tiles.and [dataUp][left]  ← Get["CC.DAndLt.sch",   FALSE];
tiles.and [dataUp][right]  ← Get["CC.DAndRt.sch",   FALSE];
tiles.and [dataUp][nc]   ← Get["CC.DAnd.sch",    TRUE];
tiles.or [dataUp][left]  ← Get["CC.DOr.sch",     FALSE];
tiles.or [dataUp][nc]   ← Get["CC.DOrNC.sch",    TRUE];
tiles.or [dataUp][extra]  ← Get["CC.HPlaDOrEx.sch",   TRUE];
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]};
GetPLADriverTiles: PROC RETURNS[drivers: DriverTiles] = {
IF DriverBuffer # NIL THEN RETURN[DriverBuffer];
TerminalIO.PutRope["Initialize PLA Buffer tiles\n"];
drivers ← DriverBuffer ← NEW[DriverTileArry];
drivers[left]   ← Get["CC.BPlaDrLeftSide.sch",  TRUE];
drivers[in]   ← Get["CC.BPlaDrDualIn.sch",   FALSE];
drivers[between] ← Get["CC.BPlaDrBetween.sch",  TRUE];
drivers[extra]  ← Get["CC.BPlaDrOrEx.sch",   TRUE];
drivers[out2]   ← Get["CC.BPlaDrDualOutInv.sch", FALSE];
drivers[out1]   ← Get["CC.BPlaDrSingOutInv.sch", FALSE];
drivers[rightHalf] ← Get["CC.BPlaDrRightSideHalf.sch", TRUE]};
END.