Create:
PUBLIC PROC [context: Parquet.Context]
RETURNS [Parquet.Module] =
BEGIN
haveHorizontalExtras, haveVerticalOrExtras, haveVerticalAndExtras: BOOL ← TRUE;
numInputs, numOutputs, numPTerms: INT;
constructedPLA: Parquet.Module ← NIL;
startOfPreviousRow: Parquet.PlacedTile;
inputNames, outputNames: LIST OF Rope.ROPE ← NIL;
ourTruthTable: BoolOps.TruthTable;
desc: PLADescription;
-- tiles outside of the core of the PLA, and extra tiles in the core
Aul, AUleft, ADleft, All, ALtop, ARtop, ALbot, ARbot: Parquet.Tile ← NIL;
AHleft, ALH, ARH, AHV, AVtop, AUV, ADV, AVbot: Parquet.Tile ← NIL;
Btop, BU, BD, BH, Bbot: Parquet.Tile ← NIL;
OLtop, ORtop, Our, OUright, ODright, Olr, ORbot, OLbot: Parquet.Tile ← NIL;
OVtop, OUV, ODV, OHV, OVbot, OLH, ORH, OHright: Parquet.Tile ← NIL;
-- major tiles in the core of the PLA
AUL1, AUL0, AULx, AUR1, AUR0, AURx: Parquet.Tile ← NIL;
ADL1, ADL0, ADLx, ADR1, ADR0, ADRx: Parquet.Tile ← NIL;
OUL1, OUL0, OUR1, OUR0: Parquet.Tile ← NIL;
ODL1, ODL0, ODR1, ODR0: Parquet.Tile ← NIL;
-- blocks of the PLA
AndBlock: Rope.ROPE ← NIL;
OrBlock: Rope.ROPE ← NIL;
LeftBlock: Rope.ROPE ← "PLA-left";
MidBlock: Rope.ROPE ← "PLA-mid";
RightBlock: Rope.ROPE ← "PLA-right";
TopAndBlock: Rope.ROPE ← "PLA-topAnd";
BotAndBlock: Rope.ROPE ← "PLA-botAnd";
TopOrBlock: Rope.ROPE ← "PLA-topOr";
BotOrBlock: Rope.ROPE ← "PLA-botOr";
ODD: PROC[i: INT] RETURNS[BOOL] = INLINE BEGIN RETURN[(i MOD 2 # 0)] END;
EVEN:
PROC[i:
INT]
RETURNS[
BOOL] =
INLINE
BEGIN
RETURN[(i
MOD 2 = 0)]
END;
DumpTruthTable:
PROC [tt: BoolOps.TruthTable, ttFile: Rope.
ROPE] =
BEGIN
-- dump truth table to file
ttStream: IO.STREAM;
message: Rope.ROPE ← NIL;
ttStream ← FS.StreamOpen[ttFile, $create ! FS.Error => IF error.group = user THEN {ttStream ← NIL; CONTINUE}];
IF ttStream = NIL THEN ERROR Error[NoDump, Rope.Cat["Could not create truth table dump file '", ttFile, "'.\n"]];
BoolOps.TTToStream[tt, ttStream ! BoolOps.Error => {message ← msg; CONTINUE}];
IF message # NIL THEN ERROR Error[NoDump, Rope.Cat["Could not dump truth table to file '", ttFile, "', error was: ", message, "\n"]];
END;
LoadTiles:
PROC[context: Parquet.Context] =
BEGIN
anyTilesNotFound: BOOL ← FALSE;
anyErrorsMessages: Rope.ROPE ← NIL;
anyErrors: BOOL ← FALSE;
GetTile:
PROC[name1, name2, name3: Rope.
ROPE ←
NIL, required:
BOOL]
RETURNS [Parquet.Tile] =
BEGIN
tile: Parquet.Tile ← NIL;
tile ← Parquet.InstantiateTile[context, name1];
IF name2 #
NIL
AND tile =
NIL
THEN {
tile ← Parquet.InstantiateTile[context, name2];
IF name3 #
NIL
AND tile =
NIL
THEN {
tile ← Parquet.InstantiateTile[context, name3];
};
};
IF required
AND tile =
NIL
THEN {
anyErrors ← TRUE;
anyErrorsMessages ← Rope.Cat[anyErrorsMessages, "MakePLA could not find tile '", name1];
IF name2 #
NIL
THEN {
IF name3 #
NIL
THEN
anyErrorsMessages ← Rope.Cat[anyErrorsMessages, " nor its alternates '", name2, "' and '", name3]
ELSE
anyErrorsMessages ← Rope.Cat[" nor its alternate '", name2];
};
anyErrorsMessages ← Rope.Cat[anyErrorsMessages, "'.\n"]
};
RETURN[tile];
END;
RequiredTile:
PROC[name1, name2, name3: Rope.
ROPE ←
NIL]
RETURNS [Parquet.Tile] =
BEGIN
RETURN[GetTile[name1, name2, name3, TRUE]];
END;
OptionalTile:
PROC[name1, name2, name3: Rope.
ROPE ←
NIL]
RETURNS [Parquet.Tile] =
BEGIN
RETURN[GetTile[name1, name2, name3, FALSE]];
END;
-- left side of AND plane
Aul ← OptionalTile["Aul"];
AUleft ← OptionalTile["AUleft", "Aleft"];
ADleft ← OptionalTile["ADleft", "Aleft"];
AHleft ← OptionalTile["AHleft"];
All ← OptionalTile["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"];
-- now take care of dependencies between tiles
IF
ALH =
NIL
OR
ARH =
NIL
OR
BH =
NIL
OR
OLH =
NIL
OR
ORH =
NIL
THEN {
IF
ALH #
NIL
OR
ARH #
NIL
OR
BH #
NIL
OR
OLH #
NIL
OR
ORH #
NIL
THEN {
anyErrorsMessages ← Rope.Cat[anyErrorsMessages, "Set of tiles must have all of the extra horizontal tiles or none of them.\n"];
anyErrors ← TRUE;
}
ELSE
haveHorizontalExtras ← FALSE;
};
IF
AUV =
NIL
OR
ADV =
NIL
THEN {
IF
AUV #
NIL
OR
ADV #
NIL
THEN {
anyErrorsMessages ← Rope.Cat[anyErrorsMessages, "Set of tiles must have all of the extra vertical AND plane tiles or none of them.\n"];
anyErrors ← TRUE;
}
ELSE
haveVerticalAndExtras ← FALSE;
};
IF
OUV =
NIL
OR
ODV =
NIL
THEN {
IF
OUV #
NIL
OR
ODV #
NIL
THEN {
anyErrorsMessages ← Rope.Cat[anyErrorsMessages, "Set of tiles must have all of the extra vertical OR plane tiles or none of them.\n"];
anyErrors ← TRUE;
}
ELSE
haveVerticalOrExtras ← FALSE;
};
IF haveHorizontalExtras
THEN {
IF haveVerticalAndExtras
AND
AHV =
NIL
THEN {
anyErrorsMessages ← Rope.Cat[anyErrorsMessages, "Tile 'AHV' is missing.\n"];
anyErrors ← TRUE;
};
IF haveVerticalOrExtras
AND
OHV =
NIL
THEN {
anyErrorsMessages ← Rope.Cat[anyErrorsMessages, "Tile 'OHV' is missing.\n"];
anyErrors ← TRUE;
};
};
IF Aul #
NIL
AND AUleft =
NIL
THEN {
anyErrorsMessages ← Rope.Cat[anyErrorsMessages, "Tile 'Aul' exists but it connects to AUleft which is missing.\n"];
anyErrors ← TRUE;
};
IF All #
NIL
AND (AUleft =
NIL
OR ADleft =
NIL)
THEN {
anyErrorsMessages ← Rope.Cat[anyErrorsMessages, "Tile 'All' exists but it connects to AUleft or ADleft which is missing.\n"];
anyErrors ← TRUE;
};
IF Our #
NIL
AND OUright =
NIL
THEN {
anyErrorsMessages ← Rope.Cat[anyErrorsMessages, "Tile 'Our' exists but it connects to OUright which is missing.\n"];
anyErrors ← TRUE;
};
IF Olr #
NIL
AND (OUright =
NIL
OR ODright =
NIL)
THEN {
anyErrorsMessages ← Rope.Cat[anyErrorsMessages, "Tile 'Olr' exists but it connects to OUright or ODright which is missing.\n"];
anyErrors ← TRUE;
};
IF anyErrors THEN ERROR Error[TileSet, anyErrorsMessages];
END;
rowTabInitialized: BOOL ← FALSE;
rowTab:
ARRAY
BOOL
--and plane--
OF
ARRAY
BOOL
--upper row--
OF
ARRAY
BOOL
-- left col--
OF
ARRAY BoolOps.TruthBit --bit-- OF Parquet.Tile;
OptAdjTile:
PROC [oldTile: Parquet.PlacedTile, newTile: Parquet.Tile, dir: Parquet.Direction, orient: Parquet.Orientation, newBlock: Rope.
ROPE]
RETURNS[Parquet.PlacedTile] =
INLINE
BEGIN
pt: Parquet.PlacedTile;
oldBlock: Rope.ROPE;
IF newTile = NIL THEN RETURN[NIL];
oldBlock ← Parquet.GetCurrentBlock[constructedPLA];
Parquet.SwitchBlock[constructedPLA, newBlock];
pt ← Parquet.AdjacentTile[oldTile, newTile, dir, orient];
Parquet.SwitchBlock[constructedPLA, oldBlock];
RETURN[pt];
END;
PlaceExtra:
PROC[startBelow: Parquet.PlacedTile]
RETURNS[Parquet.PlacedTile] =
BEGIN
prevTile, startRow: Parquet.PlacedTile;
tilesSinceExtra: INT;
tile: Parquet.Tile;
-- AND plane
Parquet.SwitchBlock[constructedPLA, AndBlock];
tilesSinceExtra ← 0;
FOR i:
INT
IN [0 .. numInputs)
DO
IF tilesSinceExtra+1 >= desc.extraAndColumns
AND haveVerticalAndExtras
AND
EVEN[i]
THEN {
-- do extra vertical columns in AND plane
prevTile ← Parquet.AdjacentTile[prevTile, AHV, $rightOf, Parquet.IdentityOrient]
};
IF i = 0
THEN {
-- do first tile in core of row, and tiles to its left
startRow ← prevTile ← Parquet.AdjacentTile[startBelow, ALH, $below, Parquet.IdentityOrient];
[] ← OptAdjTile[prevTile, AHleft, $leftOf, Parquet.IdentityOrient, LeftBlock]
}
ELSE {
-- do other tiles in core of AND plane, and tiles above and below
IF EVEN[i] THEN tile ← ALH ELSE tile ← ARH;
prevTile ← Parquet.AdjacentTile[prevTile, tile, $rightOf, Parquet.IdentityOrient];
};
tilesSinceExtra ← tilesSinceExtra + 1;
ENDLOOP;
-- Between planes
Parquet.SwitchBlock[constructedPLA, MidBlock];
prevTile ← Parquet.AdjacentTile[prevTile, BH, $rightOf, Parquet.IdentityOrient];
-- OR plane
Parquet.SwitchBlock[constructedPLA, OrBlock];
tilesSinceExtra ← 0;
FOR i:
INT
IN [0 .. numOutputs)
DO
IF tilesSinceExtra+1 >= desc.extraOrColumns
AND haveVerticalOrExtras
AND
EVEN[i]
THEN {
-- do extra vertical columns in OR plane
prevTile ← Parquet.AdjacentTile[prevTile, OHV, $rightOf, Parquet.IdentityOrient]
};
IF EVEN[i] THEN tile ← OLH ELSE tile ← ORH;
prevTile ← Parquet.AdjacentTile[prevTile, tile, $rightOf, Parquet.IdentityOrient];
IF i = numOutputs - 1
THEN {
t: Parquet.PlacedTile;
-- do tiles to the right of the last core tile
t ← OptAdjTile[prevTile, OHright, $rightOf, Parquet.IdentityOrient, RightBlock];
};
tilesSinceExtra ← tilesSinceExtra + 1;
ENDLOOP;
-- we're done with the row, return the start of it
RETURN[startRow];
END;
PlaceRow:
PROC[startBelow: Parquet.PlacedTile, rowNum:
INT]
RETURNS[Parquet.PlacedTile] =
BEGIN
topRow: BOOL ← (rowNum = 0);
botRow: BOOL ← (rowNum = numPTerms - 1);
prevTile, startRow: Parquet.PlacedTile;
tilesSinceExtra: INT;
tile: Parquet.Tile;
IF ~rowTabInitialized
THEN {
-- 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;
rowTabInitialized ← TRUE;
};
-- AND plane
Parquet.SwitchBlock[constructedPLA, AndBlock];
tilesSinceExtra ← 0;
FOR i:
INT
IN [0 .. numInputs)
DO
tile ← rowTab[TRUE][EVEN[rowNum]][EVEN[i]][ourTruthTable.pterms[rowNum].bits[i]];
IF tilesSinceExtra+1 >= desc.extraAndColumns
AND haveVerticalAndExtras
AND
EVEN[i]
THEN {
-- do extra vertical columns in AND plane
IF
EVEN[rowNum]
THEN
prevTile ← Parquet.AdjacentTile[prevTile, AUV, $rightOf, Parquet.IdentityOrient]
ELSE
prevTile ← Parquet.AdjacentTile[prevTile, ADV, $rightOf, Parquet.IdentityOrient];
-- upper tile
IF rowNum = 0 THEN [] ← OptAdjTile[prevTile, AVtop, $above, Parquet.IdentityOrient, TopAndBlock];
-- lower tile
IF rowNum = numPTerms - 1 THEN [] ← OptAdjTile[prevTile, AVbot, $below, Parquet.IdentityOrient, BotAndBlock];
};
IF i = 0
THEN {
t: Parquet.PlacedTile;
-- do first tile in core of row, and tiles to its left
startRow ← prevTile ← Parquet.AdjacentTile[startBelow, tile, $below, Parquet.IdentityOrient];
IF
EVEN[rowNum]
THEN
t ← OptAdjTile[prevTile, AUleft, $leftOf, Parquet.IdentityOrient, LeftBlock]
ELSE
t ← OptAdjTile[prevTile, ADleft, $leftOf, Parquet.IdentityOrient, LeftBlock];
-- upper left tile
IF rowNum = 0 THEN [] ← OptAdjTile[t, Aul, $above, Parquet.IdentityOrient, LeftBlock];
-- lower left tile
IF rowNum = numPTerms - 1 THEN [] ← OptAdjTile[t, All, $below, Parquet.IdentityOrient, LeftBlock];
}
ELSE {
-- do other tiles in core of AND plane, and tiles above and below
prevTile ← Parquet.AdjacentTile[prevTile, tile, $rightOf, Parquet.IdentityOrient];
};
IF rowNum = 0
THEN {
-- tiles above
IF
EVEN[i]
THEN
[] ← OptAdjTile[prevTile, ALtop, $above, Parquet.IdentityOrient, TopAndBlock]
ELSE
[] ← OptAdjTile[prevTile, ARtop, $above, Parquet.IdentityOrient, TopAndBlock];
};
IF rowNum = numPTerms - 1
THEN {
-- tiles below
IF
EVEN[i]
THEN
[] ← OptAdjTile[prevTile, ALbot, $below, Parquet.IdentityOrient, BotAndBlock]
ELSE
[] ← OptAdjTile[prevTile, ARbot, $below, Parquet.IdentityOrient, BotAndBlock];
};
tilesSinceExtra ← tilesSinceExtra + 1;
ENDLOOP;
-- Between planes
Parquet.SwitchBlock[constructedPLA, MidBlock];
IF
EVEN[rowNum]
THEN
prevTile ← Parquet.AdjacentTile[prevTile, BU, $rightOf, Parquet.IdentityOrient]
ELSE
prevTile ← Parquet.AdjacentTile[prevTile, BD, $rightOf, Parquet.IdentityOrient];
-- tile above
IF rowNum = 0 THEN [] ← OptAdjTile[prevTile, Btop, $above, Parquet.IdentityOrient, MidBlock];
-- tile below
IF rowNum = numPTerms - 1 THEN [] ← OptAdjTile[prevTile, Bbot, $below, Parquet.IdentityOrient, MidBlock];
-- OR plane
Parquet.SwitchBlock[constructedPLA, OrBlock];
tilesSinceExtra ← 0;
FOR i:
INT
IN [0 .. numOutputs)
DO
tile ← rowTab[FALSE][EVEN[rowNum]][EVEN[i]][ourTruthTable.pterms[rowNum].bits[i + numInputs]];
IF tilesSinceExtra+1 >= desc.extraOrColumns
AND haveVerticalOrExtras
AND
EVEN[i]
THEN {
-- do extra vertical columns in OR plane
IF
EVEN[rowNum]
THEN
prevTile ← Parquet.AdjacentTile[prevTile, OUV, $rightOf, Parquet.IdentityOrient]
ELSE
prevTile ← Parquet.AdjacentTile[prevTile, ODV, $rightOf, Parquet.IdentityOrient];
-- upper tile
IF rowNum = 0 THEN [] ← OptAdjTile[prevTile, OVtop, $above, Parquet.IdentityOrient, TopOrBlock];
-- lower tile
IF rowNum = numPTerms - 1 THEN [] ← OptAdjTile[prevTile, OVbot, $below, Parquet.IdentityOrient, BotOrBlock];
};
prevTile ← Parquet.AdjacentTile[prevTile, tile, $rightOf, Parquet.IdentityOrient];
IF i = numOutputs - 1
THEN {
t: Parquet.PlacedTile;
-- do tiles to the right of the last core tile
IF
EVEN[rowNum]
THEN
t ← OptAdjTile[prevTile, OUright, $rightOf, Parquet.IdentityOrient, RightBlock]
ELSE
t ← OptAdjTile[prevTile, ODright, $rightOf, Parquet.IdentityOrient, RightBlock];
-- upper left tile
IF rowNum = 0 THEN [] ← OptAdjTile[t, Our, $above, Parquet.IdentityOrient, RightBlock];
-- lower left tile
IF rowNum = numPTerms - 1 THEN [] ← OptAdjTile[t, Olr, $below, Parquet.IdentityOrient, RightBlock];
};
IF rowNum = 0
THEN {
-- tiles above
IF
EVEN[i]
THEN
[] ← OptAdjTile[prevTile, OLtop, $above, Parquet.IdentityOrient, TopOrBlock]
ELSE
[] ← OptAdjTile[prevTile, ORtop, $above, Parquet.IdentityOrient, TopOrBlock];
};
IF rowNum = numPTerms - 1
THEN {
-- tiles below
IF
EVEN[i]
THEN
[] ← OptAdjTile[prevTile, OLbot, $below, Parquet.IdentityOrient, BotOrBlock]
ELSE
[] ← OptAdjTile[prevTile, ORbot, $below, Parquet.IdentityOrient, BotOrBlock];
};
tilesSinceExtra ← tilesSinceExtra + 1;
ENDLOOP;
-- we're done with the row, return the start of it
RETURN[startRow];
END;
-- start of main body of module generator --
IF context = NIL THEN ERROR Error[NoDescription, "No description was specified!"];
-- store parameters for tiles
{
ourParams: SymTab.Ref ← SymTab.Create[];
ExprRead.StoreInt[ourParams, "numInputs", numInputs];
ExprRead.StoreInt[ourParams, "numOutputs", numOutputs];
ExprRead.StoreInt[ourParams, "numProductTerms", numPTerms];
Parquet.CombineParameters[context, ourParams];
};
-- check & create input
desc ← ReadParameters[context];
IF desc.truthTable = NIL THEN ERROR Error[NoTruthTable, "No truth table was specified!"];
-- optimize
IF desc.optimize
THEN
ourTruthTable ← BoolOps.TTOptimize[desc.truthTable]
ELSE
ourTruthTable ← desc.truthTable;
IF desc.dumpFile # NIL THEN DumpTruthTable[ourTruthTable, desc.dumpFile];
-- initialization
LoadTiles[context];
numInputs ← ourTruthTable.numInputs;
numOutputs ← ourTruthTable.numOutputs;
numPTerms ← ourTruthTable.numPTerms;
[constructedPLA, startOfPreviousRow] ← Parquet.NewModule[context];
-- create the PLA row by row, inserting extra ground rows as needed
{
noisy: BOOL ← (numPTerms > desc.printRows);
rowsSinceExtra: INT ← 0;
rowsSinceBlock: INT ← -1;
blocksSinceChunk: INT ← -1;
blockNumber: INT ← 1;
chunkNumber: INT ← 1;
rowsPerBlock: INT ← MAX[1, maxCellSize / MAX[numInputs, numOutputs, 1]];
blocksPerChunk: INT ← -1;
AndChunk, OrChunk: Rope.ROPE ← NIL;
IF numPTerms / rowsPerBlock > 5
THEN
blocksPerChunk ← MAX[1, maxChunkSize / rowsPerBlock];
IF noisy THEN TerminalIO.WriteRope["Rows (product terms) placed: "];
FOR row:
INT
IN [0 .. numPTerms)
DO
IF (blocksSinceChunk > blocksPerChunk
OR blocksSinceChunk < 0)
AND blocksPerChunk > 0
THEN {
AndChunk ← Rope.Concat["PLA-andBlock", Convert.RopeFromInt[chunkNumber, 10, FALSE]];
OrChunk ← Rope.Concat["PLA-orBlock", Convert.RopeFromInt[chunkNumber, 10, FALSE]];
chunkNumber ← chunkNumber + 1;
blocksSinceChunk ← 0;
};
IF rowsSinceBlock > rowsPerBlock
OR rowsSinceBlock < 0
THEN {
AndBlock ← Rope.Concat["PLA-and", Convert.RopeFromInt[blockNumber, 10, FALSE]];
OrBlock ← Rope.Concat["PLA-or", Convert.RopeFromInt[blockNumber, 10, FALSE]];
IF ~Parquet.NestBlock[constructedPLA, AndBlock, AndChunk] THEN ERROR;
IF ~Parquet.NestBlock[constructedPLA, OrBlock, OrChunk] THEN ERROR;
blockNumber ← blockNumber + 1;
blocksSinceChunk ← blocksSinceChunk + 1;
rowsSinceBlock ← 0;
};
IF rowsSinceExtra+1 >= desc.extraRows
AND haveHorizontalExtras
AND
EVEN[row]
THEN {
startOfPreviousRow ← PlaceExtra[startBelow: startOfPreviousRow];
rowsSinceExtra ← 0;
};
startOfPreviousRow ← PlaceRow[startBelow: startOfPreviousRow, rowNum: row];
IF noisy THEN TerminalIO.WriteInt[row + 1];
rowsSinceExtra ← rowsSinceExtra + 1;
rowsSinceBlock ← rowsSinceBlock + 1;
ENDLOOP;
IF noisy THEN TerminalIO.WriteRope[" . . . that's all.\n"];
};
-- we're done!
RETURN[constructedPLA];
END;