ReadParameters:
PROC [fileName:
ROPE]
RETURNS [desc: PLADescription] =
-- read the options from a file and build a PLADescription
BEGIN
bool, found: BOOL;
int: INT;
symTab: SymTab.Ref;
ref: REF;
desc ← NEW[PLADescriptionRec];
symTab ← CDExpr.ReadFile[fileName, CDIO.GetWorkingDirectory[]]; -- turn a xxx.mg file into a symtab
desc.tileSet ← CDExpr.FetchRope[symTab, "TileSet"].val;
IF desc.tileSet = NIL THEN ERROR PWPLABasics.Error[TileSet, "TileSet not specified"];
[found, bool] ← CDExpr.FetchBool[symTab, "Optimize"];
IF found THEN desc.optimize ← bool;
[found, int] ← CDExpr.FetchInt[symTab, "Extras"];
IF found THEN desc.extraRows ← desc.extraAndColumns ← desc.extraOrColumns ← int;
[found, int] ← CDExpr.FetchInt[symTab, "ExtraRows"];
IF found THEN desc.extraRows ← int;
[found, int] ← CDExpr.FetchInt[symTab, "ExtraColumns"];
IF found THEN desc.extraAndColumns ← desc.extraOrColumns ← int;
[found, int] ← CDExpr.FetchInt[symTab, "ExtraAndColumns"];
IF found THEN desc.extraAndColumns ← int;
[found, int] ← CDExpr.FetchInt[symTab, "ExtraOrColumns"];
IF found THEN desc.extraOrColumns ← int;
[found, int] ← CDExpr.FetchInt[symTab, "PrintRows"];
IF found THEN desc.printRows ← int;
desc.dumpFile ← CDExpr.FetchRope[symTab, "TruthTableDumpFile"].val;
-- Input and Output names
ref ← CDExpr.FetchRef[symTab, "Inputs"].val;
IF ref#NIL THEN desc.inputNames ← PWPLABasics.ListRefAnyToListRope[NARROW[ref, REF LIST OF REF]^];
ref ← CDExpr.FetchRef[symTab, "Outputs"].val;
IF ref#NIL THEN desc.outputNames ← PWPLABasics.ListRefAnyToListRope[NARROW[ref, REF LIST OF REF]^] ;
-- Truth Table: One must provide either the truth table, or the equations
desc.truthTable ← PWPLABasics.FetchTT[symTab];
IF desc.truthTable #
NIL
THEN
BEGIN
PWPLABasics.EnsureSize[desc.inputNames, desc.truthTable.numInputs];
PWPLABasics.EnsureSize[desc.outputNames, desc.truthTable.numOutputs];
END
ELSE desc.truthTable ← PWPLABasics.GetEQN[symTab, desc.inputNames, desc.outputNames];
IF desc.truthTable = NIL THEN ERROR;
IF desc = NIL THEN ERROR;
END;
LoadTiles:
PUBLIC
PROC[desc: PLADescription]
RETURNS [allTiles: AllTiles]=
BEGIN
whereTilesAre: CD.Design ← CDIO.ReadDesign[from: desc.tileSet, wDir: CDIO.GetWorkingDirectory[]];
-- for now, just checking the technologies
OptionalTile:
PROC [name1, name2, name3:
ROPE ←
NIL]
RETURNS [
CD.Object] =
{RETURN [PWPLABasics.OptionalTile[whereTilesAre, name1, name2, name3]]};
RequiredTile:
PROC [name1, name2, name3:
ROPE ←
NIL]
RETURNS [
CD.Object] =
{RETURN [PWPLABasics.RequiredTile[whereTilesAre, name1, name2, name3]]};
RopeList: TYPE = LIST OF ROPE;
IF whereTilesAre=NIL THEN ERROR PWPLABasics.Error[TileSet, "TileSet not found or empty"];
allTiles ← NEW[AllTilesRec ← [rowTab: NEW[ProgTileRec]]];
BEGIN OPEN allTiles;
-- left side of AND plane
Aul ← RequiredTile["Aul"];
AUleft ← OptionalTile["AUleft", "Aleft"];
ADleft ← OptionalTile["ADleft", "Aleft"];
AHleft ← OptionalTile["AHleft"];
All ← RequiredTile["All"];
-- top and bottom of AND plane
ALbot ← OptionalTile["ALbot", "Abot"];
ARbot ← OptionalTile["ARbot", "Abot"];
AVbot ← OptionalTile["AVbot"];
ALtop ← OptionalTile["ALtop", "Atop"];
ARtop ← OptionalTile["ARtop", "Atop"];
AVtop ← OptionalTile["AVtop"];
-- core of AND plane
AUL0 ← RequiredTile["AUL0", "AL0", "A0"];
ADL0 ← RequiredTile["ADL0", "AL0", "A0"];
AUR0 ← RequiredTile["AUR0", "AR0", "A0"];
ADR0 ← RequiredTile["ADR0", "AR0", "A0"];
AUL1 ← RequiredTile["AUL1", "AL1", "A1"];
ADL1 ← RequiredTile["ADL1", "AL1", "A1"];
AUR1 ← RequiredTile["AUR1", "AR1", "A1"];
ADR1 ← RequiredTile["ADR1", "AR1", "A1"];
AULx ← RequiredTile["AUL-", "AL-", "A-"];
ADLx ← RequiredTile["ADL-", "AL-", "A-"];
AURx ← RequiredTile["AUR-", "AR-", "A-"];
ADRx ← RequiredTile["ADR-", "AR-", "A-"];
ALH ← OptionalTile["ALH", "AH"];
ARH ← OptionalTile["ARH", "AH"];
AUV ← OptionalTile["AUV", "AV"];
ADV ← OptionalTile["ADV", "AV"];
AHV ← OptionalTile["AHV"];
-- area between planes
Btop ← OptionalTile["Btop"];
BU ← RequiredTile["BU", "B"];
BD ← RequiredTile["BD", "B"];
BH ← OptionalTile["BH"];
Bbot ← OptionalTile["Bbot"];
-- top and bottom of OR plane
OLtop ← OptionalTile["OLtop", "Otop"];
ORtop ← OptionalTile["ORtop", "Otop"];
OVtop ← OptionalTile["OVtop"];
OLbot ← OptionalTile["OLbot", "Obot"];
ORbot ← OptionalTile["ORbot", "Obot"];
OVbot ← OptionalTile["OVbot"];
-- right side of OR plane
Olr ← OptionalTile["Olr"];
Our ← OptionalTile["Our"];
OUright ← OptionalTile["OUright", "Oright"];
ODright ← OptionalTile["ODright", "Oright"];
OHright ← OptionalTile["OHright"];
-- core of the OR plane
OUL0 ← RequiredTile["OUL0", "OU0"];
OUR0 ← RequiredTile["OUR0", "OU0"];
ODL0 ← RequiredTile["ODL0", "OD0"];
ODR0 ← RequiredTile["ODR0", "OD0"];
OUL1 ← RequiredTile["OUL1", "OU1"];
OUR1 ← RequiredTile["OUR1", "OU1"];
ODL1 ← RequiredTile["ODL1", "OD1"];
ODR1 ← RequiredTile["ODR1", "OD1"];
OLH ← OptionalTile["OLH", "OH"];
ORH ← OptionalTile["ORH", "OH"];
OUV ← OptionalTile["OUV", "OV"];
ODV ← OptionalTile["ODV", "OV"];
OHV ← OptionalTile["OHV"];
-- up (U) rows of AND plane
rowTab[TRUE][TRUE][TRUE][$One] ← AUL1;
rowTab[TRUE][TRUE][TRUE][$Zero] ← AUL0;
rowTab[TRUE][TRUE][TRUE][$NC] ← AULx;
rowTab[TRUE][TRUE][FALSE][$One] ← AUR1;
rowTab[TRUE][TRUE][FALSE][$Zero] ← AUR0;
rowTab[TRUE][TRUE][FALSE][$NC] ← AURx;
-- down (D) rows of AND plane
rowTab[TRUE][FALSE][TRUE][$One] ← ADL1;
rowTab[TRUE][FALSE][TRUE][$Zero] ← ADL0;
rowTab[TRUE][FALSE][TRUE][$NC] ← ADLx;
rowTab[TRUE][FALSE][FALSE][$One] ← ADR1;
rowTab[TRUE][FALSE][FALSE][$Zero] ← ADR0;
rowTab[TRUE][FALSE][FALSE][$NC] ← ADRx;
-- up (U) rows of OR plane
rowTab[FALSE][TRUE][TRUE][$One] ← OUL1;
rowTab[FALSE][TRUE][TRUE][$Zero] ← OUL0;
rowTab[FALSE][TRUE][TRUE][$NC] ← OUL0;
rowTab[FALSE][TRUE][FALSE][$One] ← OUR1;
rowTab[FALSE][TRUE][FALSE][$Zero] ← OUR0;
rowTab[FALSE][TRUE][FALSE][$NC] ← OUR0;
-- down (D) rows of OR plane
rowTab[FALSE][FALSE][TRUE][$One] ← ODL1;
rowTab[FALSE][FALSE][TRUE][$Zero] ← ODL0;
rowTab[FALSE][FALSE][TRUE][$NC] ← ODL0;
rowTab[FALSE][FALSE][FALSE][$One] ← ODR1;
rowTab[FALSE][FALSE][FALSE][$Zero] ← ODR0;
rowTab[FALSE][FALSE][FALSE][$NC] ← ODR0;
-- extra horizontal tiles
IF desc.haveHorizontalExtras
AND ~PWPLABasics.AllPresent[
LIST[
ALH,
ARH,
BH,
OLH,
ORH]]
THEN
{PW.WriteF["Some of the extra horizontal tiles are missing.\n"];
desc.haveHorizontalExtras ← FALSE};
-- extra vertical AND plane tiles
IF desc.haveVerticalAndExtras
AND ~PWPLABasics.AllPresent[
LIST[
AUV,
ADV]]
THEN
{PW.WriteF["Some of the extra vertical AND plane tiles are missing.\n"];
desc.haveVerticalAndExtras ← FALSE};
-- extra vertical OR plane tiles
IF desc.haveVerticalOrExtras
AND ~PWPLABasics.AllPresent[
LIST[
OUV,
ODV]]
THEN
{PW.WriteF["Some of the extra vertical OR plane tiles are missing.\n"];
desc.haveVerticalOrExtras ← FALSE};
-- intersections between extras
IF desc.haveHorizontalExtras
AND desc.haveVerticalAndExtras
AND
AHV =
NIL
THEN PW.WriteF["Tile 'AHV' is missing.\n"];
IF desc.haveHorizontalExtras
AND desc.haveVerticalOrExtras
AND
OHV =
NIL
THEN PW.WriteF["Tile 'OHV' is missing.\n"];
END; -- of the OPEN
END;
AssembleRows:
PROC[desc: PLADescription, allTiles: AllTiles]
RETURNS[pla:
CD.Object] =
BEGIN
RenamePin:
PROC[ob:
CD.Object, old, new:
ROPE]
RETURNS [newOb:
CD.Object] =
BEGIN
Rename: CDSymbolicObjects.InstEnumerator = {
IF Rope.Equal[CDSymbolicObjects.GetName[inst], old]
THEN CDSymbolicObjects.SetName[inst, new]};
newOb ← PW.Copy[ob]; -- just a copy
[] ← CDSymbolicObjects.EnumerateSymbolicObs[newOb, Rename];
END;
SpecialRow:
PROC[left, andVert, andLeft, andRight, between, orVert, orLeft, orRight, right:
CD.Object, namePins:
BOOL ←
FALSE]
RETURNS [row:
CD.Object] =
BEGIN
names: LIST OF ROPE;
cell, newCell: CD.Object;
tilesSinceExtra: INT;
colList: LIST OF CD.Object;
-- left column
colList ← CONS[left, NIL];
-- AND plane
tilesSinceExtra ← 0;
names ← desc.inputNames;
FOR i:
INT
IN [0 .. desc.truthTable.numInputs)
DO
IF tilesSinceExtra+1 >= desc.extraAndColumns
AND desc.haveVerticalAndExtras
AND
PW.
EVEN[i]
THEN
{colList ← CONS[andVert, colList]; -- extra column in AND plane
tilesSinceExtra ← 0};
cell ← IF PW.EVEN[i] THEN andLeft ELSE andRight;
IF namePins
THEN {
newCell ← RenamePin[cell, "In", names.first];
names ← names.rest}
ELSE newCell ← cell;
colList ← CONS[newCell, colList]; -- normal column
tilesSinceExtra ← tilesSinceExtra + 1;
ENDLOOP;
-- Between planes
colList ← CONS[between, colList];
-- OR plane
tilesSinceExtra ← 0;
names ← desc.outputNames;
FOR i:
INT
IN [0 .. desc.truthTable.numOutputs)
DO
IF tilesSinceExtra+1 >= desc.extraOrColumns
AND desc.haveVerticalOrExtras
AND
PW.
EVEN[i]
THEN
{colList ← CONS[orVert, colList]; -- extra column in OR plane
tilesSinceExtra ← 0};
cell ← IF PW.EVEN[i] THEN orLeft ELSE orRight;
IF namePins
THEN {
newCell ← RenamePin[cell, "Out", names.first];
names ← names.rest}
ELSE newCell ← cell;
colList ← CONS[newCell, colList]; -- normal
tilesSinceExtra ← tilesSinceExtra + 1;
ENDLOOP;
-- right column
colList ← CONS[right, colList];
row ← PW.AbutListX[PW.Reverse[colList]];
END;
NormalRow:
PROC[rowNum:
INT, left, andVert, between, orVert, right:
CD.Object, rowTab: ProgTile]
RETURNS[row:
CD.Object] =
BEGIN
colList: LIST OF CD.Object;
tilesSinceExtra: INT;
-- left column
colList ← CONS[left, NIL];
-- AND plane
tilesSinceExtra ← 0;
FOR i:
INT
IN [0 .. desc.truthTable.numInputs)
DO
IF tilesSinceExtra+1 >= desc.extraAndColumns
AND desc.haveVerticalAndExtras
AND
PW.
EVEN[i]
THEN
{colList ← CONS[andVert, colList]; -- extra column in AND plane
tilesSinceExtra ← 0};
colList ←
CONS[
-- normal cell
rowTab[TRUE][PW.EVEN[rowNum]][PW.EVEN[i]][desc.truthTable.pterms[rowNum].bits[i]],
colList];
tilesSinceExtra ← tilesSinceExtra + 1;
ENDLOOP;
-- Between planes
colList ← CONS[between, colList];
-- OR plane
tilesSinceExtra ← 0;
FOR i:
INT
IN [0 .. desc.truthTable.numOutputs)
DO
IF tilesSinceExtra+1 >= desc.extraOrColumns
AND desc.haveVerticalOrExtras
AND
PW.
EVEN[i]
THEN
{colList ← CONS[orVert, colList]; -- extra column in OR plane
tilesSinceExtra ← 0};
colList ←
CONS[
-- normal cell
rowTab[FALSE][PW.EVEN[rowNum]][PW.EVEN[i]][desc.truthTable.pterms[rowNum].bits[i + desc.truthTable.numInputs]],
colList];
tilesSinceExtra ← tilesSinceExtra + 1;
ENDLOOP;
-- right column
colList ← CONS[right, colList];
row ← PW.AbutListX[PW.Reverse[colList]];
END;
noisy: BOOL;
rowList: LIST OF CD.Object;
rowsSinceExtra: INT ← 0;
-- create the PLA row by row, inserting extra ground rows as needed
noisy ← (desc.truthTable.numPTerms > desc.printRows);
IF noisy THEN PW.WriteF["Rows (product terms) placed: "];
-- Start with the top row
BEGIN OPEN allTiles;
rowList ← LIST [SpecialRow[Aul, AVtop, ALtop, ARtop, Btop, OVtop, OLtop, ORtop, Our, TRUE]];
-- Now the rows, from top to bottom
FOR rowIndex:
INT
IN [0 .. desc.truthTable.numPTerms)
DO
-- if conditions are right, we add an extra ground row
IF rowsSinceExtra+1 >= desc.extraRows
AND desc.haveHorizontalExtras
AND
PW.
EVEN[rowIndex]
THEN
BEGIN
rowList ←
CONS[
SpecialRow[AHleft, AHV, ALH, ARH, BH, OHV, OLH, ORH, OHright],
rowList];
rowsSinceExtra ← 0;
END;
-- now we add the normal row at the bottom
rowList ←
CONS[
IF
PW.
EVEN[rowIndex]
THEN
NormalRow[rowIndex, AUleft, AUV, BU, OUV, OUright, rowTab]
ELSE NormalRow[rowIndex, ADleft, ADV, BD, ODV, ODright, rowTab],
rowList];
IF noisy THEN PW.WriteF["%g", IO.int[rowIndex + 1]];
rowsSinceExtra ← rowsSinceExtra + 1;
ENDLOOP;
-- Finally the bottom row
rowList ←
CONS[
SpecialRow[All, AVbot, ALbot, ARbot, Bbot, OVbot, OLbot, ORbot, Olr],
rowList];
END; -- OPEN allTiles
-- Assemble the cells
pla ← PW.AbutListY[rowList];
IF noisy THEN PW.WriteF[" . . . that's all.\n"];
END;