DIRECTORY Atom, BasicTime, CD, CDDirectory, CDExpr, CDExtras, Convert, PW, PWBasics, PWPLABasics, BoolOps, AMTypes, Rope, IO, FS, SymTab; PWPLABasicsImpl: CEDAR PROGRAM IMPORTS Atom, BasicTime, BoolOps, CDDirectory, CDExpr, Convert, FS, PWBasics, Rope EXPORTS PWPLABasics SHARES CDDirectory = BEGIN OPEN PWPLABasics; Error: PUBLIC ERROR[ec: ErrorCode, msg: ROPE] ~ CODE; GetTile: PROC[from, to: CD.Design, tilesPrefix: ROPE, tilesFetched: REF LIST OF ROPE, name1, name2, name3: PW.ObjName _ NIL, required: BOOL] RETURNS [newName: PW.ObjName] = BEGIN tile, oldTile: CD.ObPtr; done, found: BOOL; name: PW.ObjName _ SELECT TRUE FROM IsPresent[from, name1] => name1, IsPresent[from, name2] => name2, IsPresent[from, name3] => name3, ENDCASE => NIL; IF name = NIL AND required THEN BEGIN PWBasics.Output["PWPLA could not find tile '", name1, "'"]; IF name2 # NIL THEN PWBasics.Output[" nor '", name2, "'"]; IF name3 # NIL THEN PWBasics.Output[" nor '", name3, "'"]; PWBasics.Output[".\n'"]; ERROR Error[MissingTile, NIL]; END; IF name = NIL AND ~required THEN RETURN[NIL]; newName _ Rope.Cat[tilesPrefix, name]; IF ~AlreadyFetched[tilesFetched, name] THEN BEGIN tilesFetched^ _ CONS[name, tilesFetched^]; [found, oldTile] _ CDDirectory.Fetch[to, newName]; -- if an old version of the tile is already in the design it gets renamed IF found THEN BEGIN bogusName: ROPE _ Rope.Cat[newName, " renamed on ", Convert.RopeFromTime[BasicTime.Now[]]]; done _ CDDirectory.Rename[to, oldTile, bogusName]; IF ~done THEN ERROR; END; tile _ CDDirectory.Another[CDDirectory.Fetch[from, name].object, from, to]; done _ CDDirectory.Rename[to, tile, newName]; IF ~done THEN ERROR; END; END; IsPresent: PROC [whereTilesAre: CD.Design, name: ROPE] RETURNS [BOOL] = {RETURN[CDDirectory.Fetch[whereTilesAre, name].found]}; AllPresent: PUBLIC PROC [list: LIST OF PW.ObjName] RETURNS [b: BOOL _ TRUE] = {WHILE list#NIL DO b _ b AND list.first#NIL; list _ list.rest; ENDLOOP}; RequiredTile: PUBLIC PROC[from, to: CD.Design, tilesPrefix: ROPE, tilesFetched: REF LIST OF ROPE, name1, name2, name3: PW.ObjName _ NIL] RETURNS [PW.ObjName] = {RETURN[GetTile[from, to, tilesPrefix, tilesFetched, name1, name2, name3, TRUE]]}; OptionalTile: PUBLIC PROC[from, to: CD.Design, tilesPrefix: ROPE, tilesFetched: REF LIST OF ROPE, name1, name2, name3: ROPE _ NIL] RETURNS [PW.ObjName] = {RETURN[GetTile[from, to, tilesPrefix, tilesFetched, name1, name2, name3, FALSE]]}; AlreadyFetched: PROC[tilesFetched: REF LIST OF ROPE, name: ROPE] RETURNS [BOOL] = BEGIN list: LIST OF ROPE _ tilesFetched^; WHILE list#NIL DO IF name=list.first THEN RETURN[TRUE]; list _ list.rest; ENDLOOP; RETURN[FALSE]; END; 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; ReverseList: PUBLIC PROC [list: LIST OF PW.ObjName] RETURNS [newList: LIST OF PW.ObjName] = BEGIN newList _ NIL; WHILE list#NIL DO newList _ CONS[list.first, newList]; list _ list.rest; ENDLOOP; 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; LengthListOfList: PUBLIC PROC [list: LIST OF LIST OF ROPE] RETURNS [length: INT _ 0] = BEGIN WHILE list # NIL DO length _ length+Length[list.first]; list _ list.rest; ENDLOOP; END; EnsureSize: PUBLIC PROC [list: LIST OF ROPE, quantity: INT] = {IF Length[list] # quantity THEN ERROR}; 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."]; 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, "', 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, "' 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]; FOR trees: LIST OF BoolOps.Tree _ reversedEqnTrees, trees.rest WHILE trees # NIL DO eqnTrees _ CONS[trees.first, eqnTrees]; ENDLOOP; 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; 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 GetTTFile: PROC[ttFile: ROPE] RETURNS[tt: BoolOps.TruthTable] = BEGIN ttStream: IO.STREAM; explanation: ROPE; 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"]]; END; 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; 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 ttStream: IO.STREAM; message: 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; END. pFile: PWPLABasicsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Created by: Monier, March 14, 1985 9:54:02 pm PST -- Low level stuff for PLA and CP generation. -- Looks for name1, name2, then name3; if absent, return NIL and screams if required -- add the prefix to the cell name to form "tileset.tilename" -- check if this tile is already in the design -- we need a good gensym -- *** make a copy of the cell and include it: copy should be recursive *** -- rename the cell: there should be no conflict now -- If the name has changed, something is really wrong -- Check if all names are non-NIL -- Check if a tile is present -- Read equations one at a time, converting to sum-of-products as we go -- 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 the truth table from a file -- read the truth table directly from parameters file -- get a truth table PWBasics.Output[". . . not tonight dearling, I have a headache !"]; -- dump truth table to file Κ ’˜– "Cedar" stylešœ™Jšœ Οmœ1™žœ˜Išžœ žœž˜Jšœ‡˜‡—šžœ˜Jšœ žœ˜Jšœ;žœ˜Fšžœ žœž˜Jšœ’˜’—šžœ˜Jšœžœ˜-J˜—J˜—Jšžœ˜ —Jšžœžœžœžœ*˜ZJ™6š žœžœžœ-žœ žœž˜SJšœ žœ˜'Jšžœ˜—J™.š žœžœžœžœžœžœž˜