<> <> <> <> DIRECTORY Atom, CD, CDDirectory, CDExpr, CDIO, PW, PWPLABasics, BoolOps, Rope, IO, FS, SymTab, TerminalIO; PWPLABasicsImpl: CEDAR PROGRAM IMPORTS Atom, BoolOps, CDDirectory, CDExpr, CDIO, FS, IO, PW, Rope, TerminalIO EXPORTS PWPLABasics SHARES CDDirectory = BEGIN OPEN PWPLABasics; Error: PUBLIC ERROR[ec: ErrorCode, msg: ROPE] ~ CODE; <<-- Looks for name1, name2, then name3; if absent, return NIL and screams if required>> GetTile: PROC[from: CD.Design, name1, name2, name3: ROPE _ NIL, required: BOOL] RETURNS [obj: CD.Object] = BEGIN obj _ SELECT TRUE FROM IsPresent[from, name1] => PW.Get[from, name1], IsPresent[from, name2] => PW.Get[from, name2], IsPresent[from, name3] => PW.Get[from, name3], ENDCASE => NIL; IF obj = NIL AND required THEN BEGIN TerminalIO.PutF["PWPLA could not find tile '%g'", IO.rope[name1]]; IF name2 # NIL THEN TerminalIO.PutF[" nor '%g'", IO.rope[name2]]; IF name3 # NIL THEN TerminalIO.PutF[" nor '%g'", IO.rope[name3]]; TerminalIO.PutF[".\n'"]; ERROR Error[MissingTile, NIL]; END; END; IsPresent: PROC [whereTilesAre: CD.Design, name: ROPE] RETURNS [BOOL] = {RETURN [CDDirectory.Fetch[whereTilesAre, name]#NIL]}; <<>> <<-- Check if all names are non-NIL>> AllPresent: PUBLIC PROC [list: LIST OF CD.Object] RETURNS [b: BOOL _ TRUE] = {WHILE list#NIL DO b _ b AND list.first#NIL; list _ list.rest; ENDLOOP}; RequiredTile: PUBLIC PROC [from: CD.Design, name1, name2, name3: ROPE _ NIL] RETURNS [CD.Object] = {RETURN[GetTile[from, name1, name2, name3, TRUE]]}; OptionalTile: PUBLIC PROC [from: CD.Design, name1, name2, name3: ROPE _ NIL] RETURNS [CD.Object] = {RETURN[GetTile[from, name1, name2, name3, FALSE]]}; <<>> ListRefAnyToListRope: PUBLIC PROC [list: LIST OF REF] RETURNS [LIST OF ROPE] = BEGIN RETURN[IF list=NIL THEN NIL ELSE CONS[NARROW[list.first], ListRefAnyToListRope[list.rest]]]; END; ListRefAnyToListOfListRope: PUBLIC PROC [list: LIST OF REF] RETURNS [llr: LIST OF LIST OF ROPE] = BEGIN IF list=NIL THEN RETURN[NIL]; llr _ CONS[ ListRefAnyToListRope[NARROW[list.first, LIST OF REF]], ListRefAnyToListOfListRope[list.rest]]; END; Length: PUBLIC PROC [list: LIST OF ROPE] RETURNS [length: INT _ 0] = BEGIN WHILE list # NIL DO length _ length+1; list _ list.rest; ENDLOOP; END; EnsureSize: PUBLIC PROC [list: LIST OF ROPE, quantity: INT] = {IF Length[list] # quantity THEN ERROR}; <<-- Read equations one at a time, converting to sum-of-products as we go>> GetEQN: PUBLIC PROC[par: SymTab.Ref, inNames, outNames: LIST OF ROPE] RETURNS[BoolOps.TruthTable] = BEGIN tt: BoolOps.TruthTable; inAtoms, reverseAtoms: LIST OF ATOM _ NIL; eqnTrees, reversedEqnTrees: LIST OF BoolOps.Tree _ NIL; message: ROPE; allErrorMessages: ROPE _ NIL; IF inNames = NIL OR outNames = NIL THEN ERROR Error[ParameterErrors, "Both 'Inputs' and 'Outputs' must be specified."]; <<-- read equations one at a time, converting to sum-of-products as we go>> FOR outs: LIST OF ROPE _ outNames, outs.rest WHILE outs # NIL DO eqn: ROPE _ NIL; t: BoolOps.Tree _ NIL; eqn _ CDExpr.FetchRope[par, outs.first].val; IF eqn = NIL THEN { 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 allErrorMessages _ Rope.Cat[allErrorMessages, "Could not translate equation for output '", outs.first, Rope.Cat["', error was: ", message, "\n"]] ELSE { message _ NIL; t _ BoolOps.TreeToSOP[t ! BoolOps.Error => {message _ msg; CONTINUE}]; IF message # NIL THEN allErrorMessages _ Rope.Cat[allErrorMessages, "Could not translate output '", outs.first, Rope.Cat["' to sum-of-products form, error was: ", message, "\n"]] ELSE { reversedEqnTrees _ CONS[t, reversedEqnTrees]; }; }; ENDLOOP; IF ~Rope.Equal[allErrorMessages, NIL] THEN ERROR Error[ParameterErrors, allErrorMessages]; <<-- reverse our list of equations since it is backwards>> FOR trees: LIST OF BoolOps.Tree _ reversedEqnTrees, trees.rest WHILE trees # NIL DO eqnTrees _ CONS[trees.first, eqnTrees]; ENDLOOP; <<-- create a list of atoms from the input names>> FOR ins: LIST OF 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; <<-- make a truth table>> 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; FetchTT: PUBLIC PROC [par: SymTab.Ref] RETURNS [truthTable: BoolOps.TruthTable] = BEGIN <<-- get the truth table from a file>> GetTTFile: PROC[ttFile: ROPE] RETURNS[tt: BoolOps.TruthTable] = BEGIN ttStream: IO.STREAM; explanation: ROPE; IF ttFile = NIL THEN RETURN[NIL]; ttStream _ FS.StreamOpen[fileName: ttFile, wDir: CDIO.GetWorkingDirectory[] ! 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"]]; END; <<-- read the truth table directly from parameters file>> GetTT: PROC[par: SymTab.Ref] RETURNS[BoolOps.TruthTable] = BEGIN ref: REF ANY; ref _ CDExpr.FetchRef[par, "TruthTable"].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; <<-- get a truth table>> SELECT TRUE FROM CDExpr.FetchRope[par, "TruthTableFile"].found => truthTable _ GetTTFile[CDExpr.FetchRope[par, "TruthTableFile"].val]; -- Read TruthTable from a file CDExpr.FetchRef[par, "TruthTable"].found => truthTable _ GetTT[par]; -- Read TruthTable directly ENDCASE => -- should be GetEQN[inputNames, outputNames] truthTable _ NIL; END; DumpTruthTable: PUBLIC PROC [tt: BoolOps.TruthTable, ttFile: ROPE] = BEGIN <<-- dump truth table to file>> ttStream: IO.STREAM; message: ROPE _ NIL; ttStream _ FS.StreamOpen[fileName: ttFile, wDir: CDIO.GetWorkingDirectory[], accessOptions: $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; END.