Create:
PROC [desc: PLADescription]
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;
-- 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;
LoadTiles:
PROC[]
RETURNS[
BOOL] =
BEGIN
anyTilesNotFound: BOOL ← FALSE;
everthingIsJustFineAndDandy: BOOL ← TRUE;
GetTile:
PROC[name1, name2, name3: Rope.
ROPE ←
NIL, required:
BOOL]
RETURNS [Parquet.Tile] =
BEGIN
tile: Parquet.Tile ← NIL;
tile ← Parquet.InstantiateTile[desc.tileSet, name1];
IF name2 #
NIL
AND tile =
NIL
THEN {
tile ← Parquet.InstantiateTile[desc.tileSet, name2];
IF name3 #
NIL
AND tile =
NIL
THEN {
tile ← Parquet.InstantiateTile[desc.tileSet, name3];
};
};
IF required
AND tile =
NIL
THEN {
anyTilesNotFound ← TRUE;
TerminalIO.WriteRope[Rope.Cat["MakePLA could not find tile '", name1]];
IF name2 #
NIL
THEN {
IF name3 #
NIL
THEN
TerminalIO.WriteRope[Rope.Cat[" nor its alternates '", name2, "' and '", name3]]
ELSE
TerminalIO.WriteRope[Rope.Cat[" nor its alternate '", name2]]
};
TerminalIO.WriteRope["'.\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 anyTilesNotFound THEN everthingIsJustFineAndDandy ← FALSE;
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 {
TerminalIO.WriteRope["Set of tiles must have all of the extra horizontal tiles or none of them.\n"];
everthingIsJustFineAndDandy ← FALSE;
}
ELSE
haveHorizontalExtras ← FALSE;
};
IF
AUV =
NIL
OR
ADV =
NIL
THEN {
IF
AUV #
NIL
OR
ADV #
NIL
THEN {
TerminalIO.WriteRope["Set of tiles must have all of the extra vertical AND plane tiles or none of them.\n"];
everthingIsJustFineAndDandy ← FALSE;
}
ELSE
haveVerticalAndExtras ← FALSE;
};
IF
OUV =
NIL
OR
ODV =
NIL
THEN {
IF
OUV #
NIL
OR
ODV #
NIL
THEN {
TerminalIO.WriteRope["Set of tiles must have all of the extra vertical OR plane tiles or none of them.\n"];
everthingIsJustFineAndDandy ← FALSE;
}
ELSE
haveVerticalOrExtras ← FALSE;
};
IF haveHorizontalExtras
THEN {
IF haveVerticalAndExtras
AND
AHV =
NIL
THEN {
TerminalIO.WriteRope["Tile 'AHV' is missing.\n"];
everthingIsJustFineAndDandy ← FALSE;
};
IF haveVerticalOrExtras
AND
OHV =
NIL
THEN {
TerminalIO.WriteRope["Tile 'OHV' is missing.\n"];
everthingIsJustFineAndDandy ← FALSE;
};
};
IF Aul #
NIL
AND AUleft =
NIL
THEN {
TerminalIO.WriteRope["Tile 'Aul' exists but it connects to AUleft which is missing.\n"];
everthingIsJustFineAndDandy ← FALSE;
};
IF All #
NIL
AND (AUleft =
NIL
OR ADleft =
NIL)
THEN {
TerminalIO.WriteRope["Tile 'All' exists but it connects to AUleft or ADleft which is missing.\n"];
everthingIsJustFineAndDandy ← FALSE;
};
IF Our #
NIL
AND OUright =
NIL
THEN {
TerminalIO.WriteRope["Tile 'Our' exists but it connects to OUright which is missing.\n"];
everthingIsJustFineAndDandy ← FALSE;
};
IF Olr #
NIL
AND (OUright =
NIL
OR ODright =
NIL)
THEN {
TerminalIO.WriteRope["Tile 'Olr' exists but it connects to OUright or ODright which is missing.\n"];
everthingIsJustFineAndDandy ← FALSE;
};
RETURN[everthingIsJustFineAndDandy];
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]][desc.truthTable.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]][desc.truthTable.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;
IF desc = NIL THEN ERROR Error[NoDescription, "No description was specified!"];
IF desc.truthTable = NIL THEN ERROR Error[NoTruthTable, "No truth table was specified!"];
-- initialization
IF ~LoadTiles[]
THEN {
TerminalIO.WriteRope["MakePLA exitting due to errors while loading tiles.\n"];
RETURN[NIL];
};
numInputs ← desc.truthTable.numInputs;
numOutputs ← desc.truthTable.numOutputs;
numPTerms ← desc.truthTable.numPTerms;
[constructedPLA, startOfPreviousRow] ← Parquet.NewModule[desc.technology];
-- create the PLA row by row
{
noisy: BOOL ← ((numInputs + numOutputs) * numPTerms > 300);
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;
MakePLAProc: Parquet.ModuleGeneratorProc =
BEGIN
-- PROC[parameters: SymTab.Ref] RETURNS [Module]
FetchRope:
PROC [symTab: SymTab.Ref, name: Rope.
ROPE]
RETURNS [Rope.
ROPE] =
BEGIN
tv: AMTypes.TV;
r: Rope.ROPE;
[ , tv] ← SymTab.Fetch[symTab, name];
IF tv = NIL THEN RETURN[NIL];
r ← ExprRead.TVToRope[tv];
IF r =
NIL
THEN {
TerminalIO.WriteRope[Rope.Cat["Value for '", name, "' must be a rope.\n"]];
RETURN[NIL];
};
RETURN[r];
END;
FetchRopeList:
PROC [symTab: SymTab.Ref, name: Rope.
ROPE]
RETURNS [
LIST
OF Rope.
ROPE] =
BEGIN
tv: AMTypes.TV;
r: LIST OF Rope.ROPE;
[ , tv] ← SymTab.Fetch[symTab, name];
IF tv = NIL THEN RETURN[NIL];
r ← ExprRead.TVToListOfRope[tv];
IF r =
NIL
THEN {
TerminalIO.WriteRope[Rope.Cat["Value for '", name, "' must be a list of ropes.\n"]];
RETURN[NIL];
};
RETURN[r];
END;
FetchCard:
PROC [symTab: SymTab.Ref, name: Rope.
ROPE]
RETURNS [
REF
CARDINAL] =
BEGIN
tv: AMTypes.TV;
i: REF CARDINAL;
[ , tv] ← SymTab.Fetch[symTab, name];
IF tv = NIL THEN RETURN[NIL];
i ← ExprRead.TVToCardinal[tv];
IF i =
NIL
THEN {
TerminalIO.WriteRope[Rope.Cat["Value for '", name, "' must be a cardinal.\n"]];
RETURN[NIL];
};
RETURN[i];
END;
GetEQN:
PROC[inNames, outNames:
LIST
OF Rope.
ROPE]
RETURNS[BoolOps.TruthTable] =
BEGIN
tt: BoolOps.TruthTable;
problems: BOOL ← FALSE;
inAtoms, reverseAtoms: LIST OF ATOM ← NIL;
eqnTrees: LIST OF BoolOps.Tree ← NIL;
message: Rope.ROPE;
IF inNames =
NIL
OR outNames =
NIL
THEN {
TerminalIO.WriteRope["Both 'Inputs' and 'Outputs' must be specified.\n"];
RETURN[NIL];
};
-- read equations one at a time, converting to sum-of-products as we go
FOR outs:
LIST
OF Rope.
ROPE ← outNames, outs.rest
WHILE outs #
NIL
DO
eqn: Rope.ROPE;
t: BoolOps.Tree ← NIL;
eqn ← FetchRope[parameters, outs.first];
IF eqn =
NIL
THEN {
problems ← TRUE;
TerminalIO.WriteRope[Rope.Cat["Equation for output '", outs.first, "' is missing.\n"]];
};
FOR i:
INT
DECREASING
IN [0 .. Rope.Length[eqn])
DO
-- remove trailing semicolon
ch: CHAR ← Rope.Fetch[eqn, i];
IF ch # '
AND ch # '\t
AND ch # '\n
THEN {
IF ch = '; AND i > 0 THEN eqn ← Rope.Substr[eqn, 0, i];
EXIT;
};
ENDLOOP;
message ← NIL;
t ← BoolOps.RopeToTree[eqn ! BoolOps.Error => {message ← msg; CONTINUE}];
IF message #
NIL
THEN {
problems ← TRUE;
TerminalIO.WriteRope[Rope.Cat["Could not translate equation for output '", outs.first, "', error was: ", message, "\n"]];
}
ELSE {
message ← NIL;
t ← BoolOps.TreeToSOP[t ! BoolOps.Error => {message ← msg; CONTINUE}];
IF message #
NIL
THEN {
problems ← TRUE;
TerminalIO.WriteRope[Rope.Cat["Could not translate output '", outs.first, "' to sum-of-products form, error was: ", message, "\n"]];
}
ELSE {
eqnTrees ← CONS[t, eqnTrees];
};
};
ENDLOOP;
IF problems THEN RETURN[NIL];
FOR ins:
LIST
OF Rope.
ROPE ← inNames, ins.rest
WHILE ins #
NIL
DO
reverseAtoms ← CONS[Atom.MakeAtom[ins.first], reverseAtoms];
ENDLOOP;
FOR ins:
LIST
OF
ATOM ← reverseAtoms, ins.rest
WHILE ins #
NIL
DO
inAtoms ← CONS[ins.first, inAtoms];
ENDLOOP;
message ← NIL;
tt ← BoolOps.SOPToTT[inAtoms, eqnTrees ! BoolOps.Error => {message ← msg; CONTINUE}];
IF message #
NIL
THEN {
TerminalIO.WriteRope[Rope.Cat["Could not translate equations to truth table form, error was: ", message, "\n"]];
RETURN[NIL];
};
RETURN[tt];
END;
GetTT:
PROC[]
RETURNS[BoolOps.TruthTable] =
BEGIN
tt: BoolOps.TruthTable;
ttFile: Rope.ROPE;
ttStream: IO.STREAM;
explanation: Rope.ROPE;
ttFile ← FetchRope[parameters, "TruthTableFile"];
IF ttFile = NIL THEN RETURN[NIL];
ttStream ← FS.StreamOpen[ttFile ! FS.Error => IF error.group = user THEN {ttStream ← NIL; CONTINUE}];
IF ttStream =
NIL
THEN {
TerminalIO.WriteRope[Rope.Cat["Could not open truth table file '", ttFile, "'.\n"]];
RETURN[NIL];
};
tt ← BoolOps.StreamToTT[ttStream ! BoolOps.Error => {explanation ← msg; CONTINUE}];
IF explanation #
NIL
THEN {
TerminalIO.WriteRope[Rope.Cat["Error in reading truth table: ", explanation, "\n"]];
RETURN[NIL];
};
RETURN[tt];
END;
InteractiveInput:
PROC[]
RETURNS[PLADescription] =
BEGIN
TerminalIO.WriteRope["Sorry, no interactive input for MakePLA, use a description file.\n"];
RETURN[NIL];
END;
GetOptions:
PROC[params: SymTab.Ref]
RETURNS[PLADescription] =
BEGIN
opt: PLADescription ← NEW[PLADescriptionRec];
card: REF CARDINAL;
-- get names of inputs and outputs
opt.inputNames ← FetchRopeList[params, "Inputs"];
opt.outputNames ← FetchRopeList[params, "Outputs"];
-- get the number of extra rows and columns
card ← FetchCard[params, "Extras"];
IF card # NIL THEN opt.extraRows ← opt.extraAndColumns ← opt.extraOrColumns ← card^;
card ← FetchCard[params, "ExtraRows"];
IF card # NIL THEN opt.extraRows ← card^;
card ← FetchCard[params, "ExtraColumns"];
IF card # NIL THEN opt.extraAndColumns ← opt.extraOrColumns ← card^;
card ← FetchCard[params, "ExtraAndColumns"];
IF card # NIL THEN opt.extraAndColumns ← card^;
card ← FetchCard[params, "ExtraOrColumns"];
IF card # NIL THEN opt.extraOrColumns ← card^;
-- get a truth table
IF FetchRope[parameters, "TruthTableFile"] #
NIL
THEN
opt.truthTable ← GetTT[]
ELSE
opt.truthTable ← GetEQN[options.inputNames, options.outputNames];
RETURN[opt];
END;
DumpTruthTable:
PROC [tt: BoolOps.TruthTable] =
BEGIN
-- dump truth table to file
ttFile: Rope.ROPE ← FetchRope[parameters, "TruthTableDumpFile"];
IF ttFile #
NIL
THEN {
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 {
TerminalIO.WriteRope[Rope.Cat["Could not create truth table dump file '", ttFile, "'.\n"]];
};
BoolOps.TTToStream[tt, ttStream ! BoolOps.Error => {message ← msg; CONTINUE}];
IF message #
NIL
THEN {
TerminalIO.WriteRope[Rope.Cat["Could not dump truth table to file '", ttFile, "', error was: ", message, "\n"]];
};
};
RETURN;
END;
PLA: Parquet.Module;
options: PLADescription;
-- get parameters
IF parameters =
NIL
THEN {
options ← InteractiveInput[];
}
ELSE {
options ← GetOptions[parameters];
};
IF options = NIL THEN RETURN[NIL];
IF options.truthTable = NIL THEN RETURN[NIL];
-- load tiles
{
fileName: Rope.ROPE;
fileName ← FetchRope[parameters, "TileSet"];
IF fileName =
NIL
THEN {
TerminalIO.WriteRope["No 'TileSet' was specified in the input file.\n"];
RETURN[NIL];
};
[options.tileSet, options.technology, ] ← Parquet.ReadDesign[fileName];
IF options.tileSet =
NIL
THEN {
TerminalIO.WriteRope[Rope.Cat["Could not load tiles from file '", fileName, "'.\n"]];
RETURN[NIL];
};
};
-- create stuff
DumpTruthTable[options.truthTable];
PLA ← Create[options];
RETURN[PLA];
END;