<> <> <> <> <<-- Make a PLA. Borrows more than heavily from Bob Mayo's MakePLA.>> <> <<>> DIRECTORY CD, CDIO, CDSymbolicObjects, CDExpr, PW, PWPLA, PWPLABasics, BoolOps, TerminalIO, Rope, IO, SymTab; PWPLAImpl: CEDAR PROGRAM IMPORTS BoolOps, CDExpr, CDIO, CDSymbolicObjects, IO, PW, PWPLABasics, Rope, TerminalIO EXPORTS PWPLA = BEGIN OPEN PWPLA; 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; <<>> <<-- Cell assembly procedures>> <<>> 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; CreatePLAFromFile: PUBLIC PROC [fileName: ROPE] RETURNS [pla: CD.Object] = BEGIN desc: PLADescription _ ReadParameters[fileName]; allTiles: AllTiles _ LoadTiles[desc]; pla _ CreatePLA[desc, allTiles]; END; CreatePLA: PUBLIC PROC [desc: PLADescription, allTiles: AllTiles] RETURNS [pla: CD.Object] = BEGIN <<-- Gas on>> IF desc.optimize THEN BEGIN old, new: INT _ desc.truthTable.numPTerms; desc.truthTable _ BoolOps.TTOptimize[desc.truthTable]; new _ desc.truthTable.numPTerms; IF old>new THEN PW.WriteF["The optimizer reduced the number of products terms from %g to %g\n", IO.int[old], IO.int[new]] ELSE PW.WriteF["The optimizer did not help. \n"]; END; IF desc.dumpFile#NIL THEN PWPLABasics.DumpTruthTable[desc.truthTable, desc.dumpFile]; <<-- Mixture rich>> desc.haveHorizontalExtras _ desc.extraRows <= desc.truthTable.numPTerms; desc.haveVerticalAndExtras _ desc.extraAndColumns <= desc.truthTable.numInputs; desc.haveVerticalOrExtras _ desc.extraOrColumns <= desc.truthTable.numOutputs; <<-- Carb heat off>> pla _ AssembleRows[desc, allTiles]; END; MakePLAProc: PW.UserProc = BEGIN <<-- Instrument set and trimmed>> fileName: ROPE _ TerminalIO.RequestRope["File describing the PLA: "]; <<-- Take-off !!!>> RETURN [CreatePLAFromFile[fileName]]; END; <<-- register this generator with PW>> PW.Register[MakePLAProc, "Make PLA"]; END.