DIRECTORY MakePLA, Commander USING [CommandProc, Register], Parquet, ExprRead, BoolOps, TerminalIO, AMTypes, Rope, IO, FS, SymTab, Atom, Convert; MakePLAImpl: CEDAR PROGRAM IMPORTS Commander, Parquet, ExprRead, BoolOps, TerminalIO, Rope, FS, SymTab, Atom, Convert EXPORTS MakePLA = BEGIN OPEN MakePLA; maxCellSize: INT ~ 500; -- We will try to keep the second level core cells below this size. maxChunkSize: INT ~ 50; -- We will try to keep the first level core cells below this size. Error: PUBLIC ERROR[ec: ErrorCode, msg: Rope.ROPE] ~ CODE; PLADescription: TYPE = REF PLADescriptionRec; PLADescriptionRec: TYPE = RECORD [ context: Parquet.Context _ NIL, inputNames, outputNames: LIST OF Rope.ROPE _ NIL, -- every input and output MUST be named, ReadParameters and ReadTileSetOnly guarentee this truthTable: BoolOps.TruthTable _ NIL, extraRows, extraAndColumns, extraOrColumns: CARDINAL _ CARDINAL.LAST-100, -- SPACING (in number of minterms) between extra ground rows and columns optimize: BOOL _ TRUE, printRows: CARDINAL _ 25, -- If the PLA has more than this many rows, then list them out on the screen as we assemble them. dumpFile: Rope.ROPE _ NIL -- if non-NIL then truth table (after optimization, if any) will be dumped to this file. ]; 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; 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; 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; 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 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; Aul _ OptionalTile["Aul"]; AUleft _ OptionalTile["AUleft", "Aleft"]; ADleft _ OptionalTile["ADleft", "Aleft"]; AHleft _ OptionalTile["AHleft"]; All _ OptionalTile["All"]; ALbot _ OptionalTile["ALbot", "Abot"]; ARbot _ OptionalTile["ARbot", "Abot"]; AVbot _ OptionalTile["AVbot"]; ALtop _ OptionalTile["ALtop", "Atop"]; ARtop _ OptionalTile["ARtop", "Atop"]; AVtop _ OptionalTile["AVtop"]; 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"]; Btop _ OptionalTile["Btop"]; BU _ RequiredTile["BU", "B"]; BD _ RequiredTile["BD", "B"]; BH _ OptionalTile["BH"]; Bbot _ OptionalTile["Bbot"]; OLtop _ OptionalTile["OLtop", "Otop"]; ORtop _ OptionalTile["ORtop", "Otop"]; OVtop _ OptionalTile["OVtop"]; OLbot _ OptionalTile["OLbot", "Obot"]; ORbot _ OptionalTile["ORbot", "Obot"]; OVbot _ OptionalTile["OVbot"]; Olr _ OptionalTile["Olr"]; Our _ OptionalTile["Our"]; OUright _ OptionalTile["OUright", "Oright"]; ODright _ OptionalTile["ODright", "Oright"]; OHright _ OptionalTile["OHright"]; 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"]; 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; Parquet.SwitchBlock[constructedPLA, AndBlock]; tilesSinceExtra _ 0; FOR i: INT IN [0 .. numInputs) DO IF tilesSinceExtra+1 >= desc.extraAndColumns AND haveVerticalAndExtras AND EVEN[i] THEN { prevTile _ Parquet.AdjacentTile[prevTile, AHV, $rightOf, Parquet.IdentityOrient] }; IF i = 0 THEN { startRow _ prevTile _ Parquet.AdjacentTile[startBelow, ALH, $below, Parquet.IdentityOrient]; [] _ OptAdjTile[prevTile, AHleft, $leftOf, Parquet.IdentityOrient, LeftBlock] } ELSE { IF EVEN[i] THEN tile _ ALH ELSE tile _ ARH; prevTile _ Parquet.AdjacentTile[prevTile, tile, $rightOf, Parquet.IdentityOrient]; }; tilesSinceExtra _ tilesSinceExtra + 1; ENDLOOP; Parquet.SwitchBlock[constructedPLA, MidBlock]; prevTile _ Parquet.AdjacentTile[prevTile, BH, $rightOf, Parquet.IdentityOrient]; Parquet.SwitchBlock[constructedPLA, OrBlock]; tilesSinceExtra _ 0; FOR i: INT IN [0 .. numOutputs) DO IF tilesSinceExtra+1 >= desc.extraOrColumns AND haveVerticalOrExtras AND EVEN[i] THEN { 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; t _ OptAdjTile[prevTile, OHright, $rightOf, Parquet.IdentityOrient, RightBlock]; }; tilesSinceExtra _ tilesSinceExtra + 1; ENDLOOP; 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 { 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; 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; 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; 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; }; 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 { IF EVEN[rowNum] THEN prevTile _ Parquet.AdjacentTile[prevTile, AUV, $rightOf, Parquet.IdentityOrient] ELSE prevTile _ Parquet.AdjacentTile[prevTile, ADV, $rightOf, Parquet.IdentityOrient]; IF rowNum = 0 THEN [] _ OptAdjTile[prevTile, AVtop, $above, Parquet.IdentityOrient, TopAndBlock]; IF rowNum = numPTerms - 1 THEN [] _ OptAdjTile[prevTile, AVbot, $below, Parquet.IdentityOrient, BotAndBlock]; }; IF i = 0 THEN { t: Parquet.PlacedTile; 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]; IF rowNum = 0 THEN [] _ OptAdjTile[t, Aul, $above, Parquet.IdentityOrient, LeftBlock]; IF rowNum = numPTerms - 1 THEN [] _ OptAdjTile[t, All, $below, Parquet.IdentityOrient, LeftBlock]; } ELSE { prevTile _ Parquet.AdjacentTile[prevTile, tile, $rightOf, Parquet.IdentityOrient]; }; IF rowNum = 0 THEN { IF EVEN[i] THEN [] _ OptAdjTile[prevTile, ALtop, $above, Parquet.IdentityOrient, TopAndBlock] ELSE [] _ OptAdjTile[prevTile, ARtop, $above, Parquet.IdentityOrient, TopAndBlock]; }; IF rowNum = numPTerms - 1 THEN { IF EVEN[i] THEN [] _ OptAdjTile[prevTile, ALbot, $below, Parquet.IdentityOrient, BotAndBlock] ELSE [] _ OptAdjTile[prevTile, ARbot, $below, Parquet.IdentityOrient, BotAndBlock]; }; tilesSinceExtra _ tilesSinceExtra + 1; ENDLOOP; 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]; IF rowNum = 0 THEN [] _ OptAdjTile[prevTile, Btop, $above, Parquet.IdentityOrient, MidBlock]; IF rowNum = numPTerms - 1 THEN [] _ OptAdjTile[prevTile, Bbot, $below, Parquet.IdentityOrient, MidBlock]; 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 { IF EVEN[rowNum] THEN prevTile _ Parquet.AdjacentTile[prevTile, OUV, $rightOf, Parquet.IdentityOrient] ELSE prevTile _ Parquet.AdjacentTile[prevTile, ODV, $rightOf, Parquet.IdentityOrient]; IF rowNum = 0 THEN [] _ OptAdjTile[prevTile, OVtop, $above, Parquet.IdentityOrient, TopOrBlock]; 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; IF EVEN[rowNum] THEN t _ OptAdjTile[prevTile, OUright, $rightOf, Parquet.IdentityOrient, RightBlock] ELSE t _ OptAdjTile[prevTile, ODright, $rightOf, Parquet.IdentityOrient, RightBlock]; IF rowNum = 0 THEN [] _ OptAdjTile[t, Our, $above, Parquet.IdentityOrient, RightBlock]; IF rowNum = numPTerms - 1 THEN [] _ OptAdjTile[t, Olr, $below, Parquet.IdentityOrient, RightBlock]; }; IF rowNum = 0 THEN { IF EVEN[i] THEN [] _ OptAdjTile[prevTile, OLtop, $above, Parquet.IdentityOrient, TopOrBlock] ELSE [] _ OptAdjTile[prevTile, ORtop, $above, Parquet.IdentityOrient, TopOrBlock]; }; IF rowNum = numPTerms - 1 THEN { IF EVEN[i] THEN [] _ OptAdjTile[prevTile, OLbot, $below, Parquet.IdentityOrient, BotOrBlock] ELSE [] _ OptAdjTile[prevTile, ORbot, $below, Parquet.IdentityOrient, BotOrBlock]; }; tilesSinceExtra _ tilesSinceExtra + 1; ENDLOOP; RETURN[startRow]; END; IF context = NIL THEN ERROR Error[NoDescription, "No description was specified!"]; { ourParams: SymTab.Ref _ SymTab.Create[]; ExprRead.StoreInt[ourParams, "numInputs", numInputs]; ExprRead.StoreInt[ourParams, "numOutputs", numOutputs]; ExprRead.StoreInt[ourParams, "numProductTerms", numPTerms]; Parquet.CombineParameters[context, ourParams]; }; desc _ ReadParameters[context]; IF desc.truthTable = NIL THEN ERROR Error[NoTruthTable, "No truth table was specified!"]; IF desc.optimize THEN ourTruthTable _ BoolOps.TTOptimize[desc.truthTable] ELSE ourTruthTable _ desc.truthTable; IF desc.dumpFile # NIL THEN DumpTruthTable[ourTruthTable, desc.dumpFile]; LoadTiles[context]; numInputs _ ourTruthTable.numInputs; numOutputs _ ourTruthTable.numOutputs; numPTerms _ ourTruthTable.numPTerms; [constructedPLA, startOfPreviousRow] _ Parquet.NewModule[context]; { 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"]; }; RETURN[constructedPLA]; END; FetchTT: PUBLIC PROC [context: Parquet.Context] RETURNS [inputNames, outputNames: LIST OF Rope.ROPE, truthTable: BoolOps.TruthTable] = BEGIN 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, reversedEqnTrees: LIST OF BoolOps.Tree _ NIL; message: Rope.ROPE; allErrorMessages: Rope.ROPE _ NIL; IF inNames = NIL OR outNames = NIL THEN ERROR Error[ParameterErrors, "Both 'Inputs' and 'Outputs' must be specified."]; FOR outs: LIST OF Rope.ROPE _ outNames, outs.rest WHILE outs # NIL DO eqn: Rope.ROPE _ NIL; t: BoolOps.Tree _ NIL; eqn _ ExprRead.FetchRope[context.parameters, outs.first, TRUE].val; IF eqn = NIL THEN { problems _ TRUE; allErrorMessages _ Rope.Cat[allErrorMessages, "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; allErrorMessages _ Rope.Cat[allErrorMessages, "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; allErrorMessages _ Rope.Cat[allErrorMessages, "Could not translate output '", outs.first, "' to sum-of-products form, error was: ", message, "\n"]; } ELSE { reversedEqnTrees _ CONS[t, reversedEqnTrees]; }; }; ENDLOOP; IF problems THEN ERROR Error[ParameterErrors, allErrorMessages]; FOR trees: LIST OF BoolOps.Tree _ reversedEqnTrees, trees.rest WHILE trees # NIL DO eqnTrees _ CONS[trees.first, eqnTrees]; ENDLOOP; 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 ERROR Error[ParameterErrors, Rope.Cat["Could not translate equations to truth table form, error was: ", message, "\n"]]; RETURN[tt]; END; GetTTFile: PROC[] RETURNS[BoolOps.TruthTable] = BEGIN tt: BoolOps.TruthTable; ttFile: Rope.ROPE; ttStream: IO.STREAM; explanation: Rope.ROPE; ttFile _ ExprRead.FetchRope[context.parameters, "TruthTableFile", TRUE].val; IF ttFile = NIL THEN RETURN[NIL]; ttStream _ FS.StreamOpen[ttFile ! FS.Error => IF error.group = user THEN {ttStream _ NIL; CONTINUE}]; IF ttStream = NIL THEN ERROR Error[ParameterErrors, Rope.Cat["Could not open truth table file '", ttFile, "'.\n"]]; tt _ BoolOps.StreamToTT[ttStream ! BoolOps.Error => {explanation _ msg; CONTINUE}]; IF explanation # NIL THEN ERROR Error[ParameterErrors, Rope.Cat["Error in reading truth table: ", explanation, "\n"]]; RETURN[tt]; END; GetTT: PROC[] RETURNS[BoolOps.TruthTable] = BEGIN ref: REF ANY; ref _ ExprRead.FetchRefAny[context.parameters, "TruthTable", TRUE].val; IF ref = NIL THEN RETURN[NIL]; IF ~ISTYPE[ref, BoolOps.TruthTable] THEN ERROR Error[ParameterErrors, Rope.Cat["TruthTable option is not of type BoolOps.TruthTable!"]]; RETURN[NARROW[ref]]; END; EnsureSize: PROC [list: LIST OF Rope.ROPE, quantity: INT, defaultName: Rope.ROPE] RETURNS [LIST OF Rope.ROPE] = BEGIN forward, backward: LIST OF Rope.ROPE _ NIL; FOR i: INT IN [1..quantity] DO IF list # NIL THEN { backward _ CONS[list.first, backward]; list _ list.rest; } ELSE { backward _ CONS[Rope.Concat[defaultName, Convert.RopeFromInt[from: i, showRadix: FALSE]], backward]; }; ENDLOOP; FOR i: INT IN [1..quantity] DO forward _ CONS[backward.first, forward]; backward _ backward.rest; ENDLOOP; RETURN[forward]; END; inputNames _ ExprRead.FetchListOfRope[context.parameters, "Inputs", TRUE].val; outputNames _ ExprRead.FetchListOfRope[context.parameters, "Outputs", TRUE].val; SELECT TRUE FROM ExprRead.FetchRope[context.parameters, "TruthTableFile", TRUE].found => truthTable _ GetTTFile[]; ExprRead.FetchRefAny[context.parameters, "TruthTable", TRUE].found => truthTable _ GetTT[]; TRUE => truthTable _ GetEQN[inputNames, outputNames]; ENDCASE; inputNames _ EnsureSize[inputNames, truthTable.numInputs, "input"]; outputNames _ EnsureSize[outputNames, truthTable.numOutputs, "output"]; END; ReadParameters: PROC [context: Parquet.Context] RETURNS [options: PLADescription] = BEGIN GetOptions: PROC[context: Parquet.Context] RETURNS[PLADescription] = BEGIN opt: PLADescription _ NEW[PLADescriptionRec]; bool: BOOL; card: CARDINAL; found: BOOL; [opt.inputNames, opt.outputNames, opt.truthTable] _ FetchTT[context]; [found, bool] _ ExprRead.FetchBool[context.parameters, "Optimize", TRUE]; IF found THEN opt.optimize _ bool; [found, card] _ ExprRead.FetchCardinal[context.parameters, "Extras", TRUE]; IF found THEN opt.extraRows _ opt.extraAndColumns _ opt.extraOrColumns _ card; [found, card] _ ExprRead.FetchCardinal[context.parameters, "ExtraRows", TRUE]; IF found THEN opt.extraRows _ card; [found, card] _ ExprRead.FetchCardinal[context.parameters, "ExtraColumns", TRUE]; IF found THEN opt.extraAndColumns _ opt.extraOrColumns _ card; [found, card] _ ExprRead.FetchCardinal[context.parameters, "ExtraAndColumns", TRUE]; IF found THEN opt.extraAndColumns _ card; [found, card] _ ExprRead.FetchCardinal[context.parameters, "ExtraOrColumns", TRUE]; IF found THEN opt.extraOrColumns _ card; [found, card] _ ExprRead.FetchCardinal[context.parameters, "PrintRows", TRUE]; IF found THEN opt.printRows _ card; opt.dumpFile _ ExprRead.FetchRope[context.parameters, "TruthTableDumpFile", TRUE].val; RETURN[opt]; END; options _ GetOptions[context]; IF options = NIL THEN ERROR; IF options.truthTable = NIL THEN ERROR; options.context _ context; RETURN[options]; END; MakePLAProc: Parquet.ModuleGeneratorProc = BEGIN m: Parquet.Module; errMsg: Rope.ROPE _ NIL; m _ Create[context ! Error => {errMsg _ msg; CONTINUE}]; IF errMsg # NIL THEN { TerminalIO.WriteRope[errMsg]; RETURN[NIL]; }; RETURN[m]; END; NoOp: Commander.CommandProc = BEGIN END; [] _ Parquet.RegisterGenerator["MakePLA", MakePLAProc]; Commander.Register[key: "MakePLA", proc: NoOp, doc: "Does nothing"]; END. ΨFile: MakePLAImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Created by: Bob July 30, 1984 11:36:59 am PDT PDT Last Edited by: Mayo, August 31, 1984 1:17:46 am PDT Make a PLA. This module is documented in MakePLATileDoc.sil and in the user's manual. General plan: Read our input table and create a description record. Use that record to build a PLA. The PLA is built by producing rows from top to bottom, inserting extra rows as needed. Each row is built left to right, and may have extra columns added as needed. -- tiles outside of the core of the PLA, and extra tiles in the core -- major tiles in the core of the PLA -- blocks of the PLA -- dump truth table to file -- left side of AND plane -- top and bottom of AND plane -- core of AND plane -- area between planes -- top and bottom of OR plane -- right side of OR plane -- core of the OR plane -- now take care of dependencies between tiles -- AND plane -- do extra vertical columns in AND plane -- do first tile in core of row, and tiles to its left -- do other tiles in core of AND plane, and tiles above and below -- Between planes -- OR plane -- do extra vertical columns in OR plane -- do tiles to the right of the last core tile -- we're done with the row, return the start of it -- up (U) rows of AND plane -- down (D) rows of AND plane -- up (U) rows of OR plane -- down (D) rows of OR plane -- AND plane -- do extra vertical columns in AND plane -- upper tile -- lower tile -- do first tile in core of row, and tiles to its left -- upper left tile -- lower left tile -- do other tiles in core of AND plane, and tiles above and below -- tiles above -- tiles below -- Between planes -- tile above -- tile below -- OR plane -- do extra vertical columns in OR plane -- upper tile -- lower tile -- do tiles to the right of the last core tile -- upper left tile -- lower left tile -- tiles above -- tiles below -- we're done with the row, return the start of it -- start of main body of module generator -- -- store parameters for tiles -- check & create input -- optimize -- initialization -- create the PLA row by row, inserting extra ground rows as needed -- we're done! -- get the truth table from a description -- read equations one at a time, converting to sum-of-products as we go -- reverse our list of equations since it is backwards -- create a list of atoms from the input names -- make a truth table -- get names of inputs and outputs -- get a truth table -- get equations and names -- optimize? -- get the number of extra rows and columns -- print rows -- dump file -- get parameters -- PROC[context: Context] RETURNS [Module] -- register this generator with Parquet -- register a command so that we won't get ".load file failed to register command" Κ·˜– "Cedar" stylešœ™Jšœ Οmœ1™žœ˜Išžœ žœžœ˜Jšœ žœ˜Jšœˆ˜ˆJ˜—šžœ˜Jšœ žœ˜Jšœ;žœ˜Fšžœ žœžœ˜Jšœ žœ˜Jšœ“˜“J˜—šžœ˜Jšœžœ˜-J˜—J˜—Jšžœ˜ —Jšžœ žœžœ*˜@J™6š žœžœžœ-žœ žœž˜SJšœ žœ˜'Jšžœ˜—J™.š žœžœžœžœžœžœž˜AJšœžœ)˜JšœNžœ˜TJšžœžœ˜)JšœMžœ˜SJšžœžœ˜(J™ JšœHžœ˜NJšžœžœ˜#J™ JšœLžœ˜VJšžœ˜ Jšžœ˜—J™J™Jšœ˜Jšžœ žœžœžœ˜Jšžœžœžœžœ˜'Jšœ˜Jšžœ ˜Jšžœ˜J˜—šŸ œ žœ˜2Jšžœžœ ™*J˜Jšœ žœžœ˜Jšœ-žœ˜8šžœ žœžœ˜Jšœ˜Jšžœžœ˜ J˜—Jšžœ˜ Jšžœ˜—J˜J˜šŸœžœ˜'Jšžœ˜J˜—J™'Jšœ8˜8JšœR™RJšœD˜DJšžœ˜——…—a ‰›