koreth@ssyx.ucsc.edu (Steven Grimm) (01/19/89)
Submitted-by: sun.com!skywest!BRENES (Erasmo Brenes) Posting-number: Volume 1, Issue 94 Archive-name: passm/part01 [Documentation is the first part of the sharfile, so page down a bit to read it. This program probably isn't for everyone. Binaries will appear in the binaries group. -sg] #!/bin/sh # shar: Shell Archiver (v1.22) # # This is part 1 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # # Run the following text with /bin/sh to create: # passm.doc # PASSM.PAS # if test -r s2_seq_.tmp then echo "Must unpack archives in sequence!" next=`cat s2_seq_.tmp`; echo "Please unpack part $next next" exit 1; fi sed 's/^X//' << 'SHAR_EOF' > passm.doc && X X X X X X X X _I_n_t_r_o_d_u_c_t_i_o_n X X Passm, a PAL Assembler, allows the user to write boolean X equations describing the outputs of a PAL and generates a JEDEC fuse X file. This assembler supports most 20 and 24 pin PALs. Currently, the X list of parts supported are: X X X 20 Pin PALs 24 Pin PALs X ------------ ----------- X 10L8, 10H8 12L10 X 12L6, 12H6 14L8 X 14L4, 14H4 16L6 X 16L2, 16H2 18L4 X 16L8 20L2 X 16R4 20L10 X 16R6 20L8 X 16R8 20R4 X 20R6 X 20R8 X 22V10 X X X The sources for PASSM are included so that customizing for additional X parts can be done. The program has been writen in Pascal and conforms X with ISO Pascal, except for two areas. One, it uses the 'otherwise' X descriptor for the CASE statements, and two, it uses packed arrays. X X The following is a description of PASSM syntax. X X _1. _L_a_n_g_u_a_g_e _D_e_s_c_r_i_p_t_i_o_n X X Before describing the syntax for PASSM, let us go thru the X notation used in describing the language. When showing a PASSM key- X word, it will be enclosed using angle brackets, > and < . The ASCII X string enclosed within these bracket must always appear in such form X (ie. use the indicated case, as well as spaces, etc.). When a given X portion, or section, is optional, it will be enclosed with { and }. X With this in mind, let us start. X X A PASSM source file consists of three main sections, all X enclosed within a module description. These three sections are: one, X the device specification (ie. what type of PAL), two, a pin list (ie. X symbolic names to be attached to a particular pin), and three, the X equations section (ie. a boolean description of a given output). All X comments in PASSM start with a double quote >"< and are assumed to end X with the end of line terminator (ie. carriage return). Also, valid X PASSM delimiters are tabs or space characters. X X Every source file MUST have a 'module' declaration. This X module declaration informs PASSM that it must start assembling a par- X ticular PAL description. A module declaration consists of the follow- X ing: X X X X X X X X X X X Passm Manual X X X >module< module_name{;} {optional_sections} X device_type_declaration X pin_list_section X boolean_equations X >end< X X X The module_name is an identifier, no more than 15 characters, which X must start with a letter. The set of valid characters for an identif- X ier is : a..z, A..Z, underscore '_', and the minus sign '-'. Notice X that the semicolon ending the module name is optional. X X The next element within a module is the optional_section. This X section is being reserved for future features, such as flags indicat- X ing what type of reduction to do with the boolean equations, include X files, etc. At the present time, no optional features are enabled. X X The next section is the device_type_declaration. This section X informs PASSM as to what type of device is being targeted, ie. a 16r4, X etc. This section syntax is as follows: X X X device_name >device< >'<part_type>';< X X X The device_name, an identifier, is the symbolic name with which the X user may refer to the PAL. The part_type is the actual device being X programmed. The following is the list of available devices: X X X 20 Pin Pals 24 Pin Pals X ----------- ----------- X p10l8, p10h8 p12l10 X p12l6, p12h6 p14l8 X p14l4, p14h4 p16l6 X p16l2, p16h2 p18l4 X p16l8 p20l2 X p16r4 p20l10 X p16r6 p20l8 X p16r8 p20r4 X p20r6 X p20r8 X p22v10 X X X Notice that the part_type must appear as shown above. X X The next section in a module description is the pin list. This X section provides a symbolic reference between the signal names used in X the equations, and the device physical pins. The syntax followed is: X X X signal_name {, signal_name} >pin< pin_numbers >;< X X X Page 2 X X X X X X X SHAR_EOF chmod 0600 passm.doc || echo "restore of passm.doc fails" sed 's/^X//' << 'SHAR_EOF' > PASSM.PAS && X{***************************************************************************} X{* This program is a general purpose PAL assembler. You may copy and use *} X{* it for personal purposes. No commercial use of this program is allowed *} X{* without the consent of the author. *} X{* THIS IS THE Atari ST Version *} X{* (c) Copyright 1987,1988 by Erasmo Brenes. *} X{***************************************************************************} Xprogram passm (input,output,source,simfile); X const X linewidth = 40; X blank = ' '; semicol = ';'; comment = '"'; X maxterms = 19; maxinputs = 22; X maxpins = 24; npals = 23; X maxcols = 44; maxouts = 10; X X type X symbol =( ident, int, num, eql, quotes, semicolon, apostrophe, X leftbrkt, rightbrkt, device, pin, equations,module,flag, X lftparen,rgtparen,title,node,stype,macro,andoperator, X oroperator,invert,colon,ends,enable,preset,clear); X palsymb = ( p10l8,p12l6,p14l4,p16l2,p16l8,p16rx,p12l10,p14l8,p16l6, X p18l4,p20l2,p20l10,p20l8,p20rx,p22vx); X tkens = packed array [1..15] of char; X kind = (reg, nonreg, bidir, tristate); X palsize = (input18, input22); X logic = (high, low); X trans1typ = X record X transfer : array[1..maxpins] of integer X end; X outtype = X record X outnumb : integer; X outname : tkens; X outkind : kind; X size : palsize; X form : logic; X matrix : array [1..maxterms,1..maxcols] of char X end; X entrytype = X record X name : tkens; X pinn : integer X end; X string2 = packed array [1..4] of char; X filnam = packed array [1..80] of char; X ptermtyp = array [1..maxcols] of char; X X var X source,simfile : text; X token : tkens; X palknds : array [1..npals] of char; X pals : array [1..npals] of tkens; X symtable: array [1..maxpins] of entrytype; X outtable: array [1..11] of outtype; X palkind : palsymb; X fusetoinp,fusetopin : array [palsymb] of trans1typ; X paltyp : array [1..npals] of palsymb; X filspc : string[80]; X sym : symbol; X reserved : array [1..13] of tkens; X pdevice : tkens; X wsym : array [1..13] of symbol; X ptype,ch,tab : char; X nexout,outindex : integer; X nexin : integer; X value,i,j,pointer,iterm,totalterms : integer; X Abort,empty,pal16,found : boolean; X ar, sp : ptermtyp; X X procedure bgetchar (var ch:char); X begin X empty := false; X if eof(source) X then begin X empty := true; X ch := blank X end X else begin X if eoln(source) X then begin X readln (source); X ch := blank X end X else X if eof(source) X then begin X empty := true; X ch := blank X end X else begin X read (source,ch); X if ch = comment X then begin X repeat X readln (source); X if eof(source) X then begin X empty := true; ch := blank X end X else read (source,ch) X until (ch <> comment) or (eof(source)) X end X end X end X end; {bgetchar} X X procedure numbr; X{this routine always leaves with ch containing the next character!} X var X j : integer; X begin X sym := int; X value := 0; j:= 0; X repeat X value := 10*value + (ord(ch) - ord('0')); X bgetchar (ch); j:= j + 1 X until not(ch in ['0'..'9']) X end; {numbr} X X procedure gettoken; X var X i,j,k : integer; X begin X i:= 0; X while ((ch=blank)or(ch=tab))and(not empty) do bgetchar(ch); X if (ch in ['A'..'Z'])or(ch in['a'..'z'])or(ch = '-') X then begin X repeat X i:= i + 1; X token [i]:= ch; bgetchar(ch) X until not((ch in ['A'..'Z'])or(ch in['a'..'z'])or(ch in ['0'..'9']) X or (ch='_')) or empty or (i = 15); X if not empty X then begin X if (i < 15) then repeat X i:= i + 1; token[i]:= blank X until (i=15); X k := 0; X for j:=1 to 13 do X if token = reserved[j] X then k := j; X if k = 0 X then sym := ident X else sym := wsym [k] X end X end X else begin X if (ch in ['0'..'9']) X then numbr X else case ch of X '^': begin X sym := num; X bgetchar (ch) X end; X '=': begin X sym := eql; X bgetchar (ch) X end; X ';': begin X sym := semicolon; X bgetchar (ch) X end; X '''': begin X sym := apostrophe; X bgetchar (ch) X end; X '`': begin X sym := apostrophe; X bgetchar (ch) X end; X '"': begin X sym := quotes; X bgetchar (ch) X end; X '[': begin X sym := leftbrkt; X bgetchar (ch) X end; X ']': begin X sym := rightbrkt; X bgetchar (ch) X end; X '(': begin X sym := lftparen; X bgetchar (ch) X end; X ')': begin X sym := rgtparen; X bgetchar (ch) X end; X '!': begin X sym := invert; X bgetchar (ch) X end; X '&': begin X sym := andoperator; X bgetchar (ch) X end; X '#': begin X sym := oroperator; X bgetchar (ch) X end; X ':': begin X sym := colon; X bgetchar (ch) X end; X otherwise: X begin X bgetchar (ch); X gettoken { get next token } X end X end X end X end; {gettoken} X X procedure semimodule; X begin X gettoken; X while sym = semicolon X do gettoken; X end; X X procedure search ( kind : integer); X var X i,j : integer; X begin X case kind of X 1: begin X pointer := 0; X for i:=1 to npals do X if token = pals[i] X then pointer := i X end; X 2: begin X j := pointer; X pointer := 0; X for i:=1 to 24 do X with symtable[i] do X if pinn = j X then pointer := i X end; X 3: begin { search a signal name for its corresponding pin } X pointer := 0; found := false; X for i:= 1 to maxpins do X with symtable[i] do X if token = name X then begin X pointer := pinn; found := true X end X end; X otherwise: X writeln ('!!! software error in search procedure') X end X end; {search} X X procedure start; X var X first : integer; X begin X while not(sym = equations) and (not Abort) and not(eof(source))do X begin X first := nexin + 1; X if sym = ident X then begin X nexin := nexin + 1; X symtable[nexin].name := token; X gettoken; X while sym = ident do X begin { get list of identifiers } X nexin := nexin + 1; X symtable[nexin].name := token; X gettoken X end; X case sym of X device: begin X nexin := first - 1; {ignore all previous identifiers} X gettoken; X if sym = apostrophe X then begin X gettoken; X search (1); X if pointer = 0 X then begin X writeln ('** not a valid part ',token); X Abort := true X end X else begin X pdevice := token; X ptype := palknds[pointer]; X palkind := paltyp [pointer]; X gettoken; X if sym = apostrophe X then gettoken; X if sym = semicolon X then gettoken X else Abort := true {screw the idiot***} X end X end X end; X pin: begin X gettoken; { it must be a pin number } X while not(sym = int) do gettoken; X repeat X symtable[first].pinn := value; X first := first + 1; X gettoken X until first > nexin; X if sym = semicolon X then gettoken X else Abort := true {screw the idiot ***} X end; X otherwise: X begin X nexin := first - 1; X while not (sym = semicolon) X do gettoken; X gettoken X end X end X end X end X end; {start} X X procedure titlemodule; X begin X gettoken; X if sym = apostrophe X then begin X repeat X gettoken X until sym = apostrophe; X gettoken; X if sym = semicolon X then begin X semimodule; X start X end X else start X end X else begin X writeln ('** illegal construct for the title section'); X Abort := true X end X end; {titlemodule} X X procedure flagmodule; X begin X gettoken; X if sym = apostrophe X then begin X repeat X gettoken X until sym = apostrophe; X gettoken; X case sym of X title : titlemodule; X semicolon: begin X semimodule; X if sym = title X then titlemodule X else start X end; X otherwise: X start X end X end X else begin X writeln ('** illegal construct for the flag section'); X Abort := true X end X end; {flagmodule} X X procedure arguments; X begin X gettoken; X case sym of X ident : begin X gettoken; X while not(sym = rgtparen) X do gettoken; X gettoken; X case sym of X flag : flagmodule; X title: titlemodule; X semicolon: begin X semimodule; X if sym = flag X then flagmodule X else if sym = title X then titlemodule X else start X end; X otherwise: X begin X writeln ('** illegal path after module arguments'); X Abort := true X end X end X end; X rgtparen: begin X gettoken; X case sym of X flag : flagmodule; X title: titlemodule; X semicolon: begin X semimodule; X if sym = flag X then flagmodule X else if sym = title X then titlemodule X else start X end; X otherwise: X start X end X end; X otherwise: X begin X writeln ('** missing right parenthesis in dummy argument list'); X Abort := true X end X end X end; {arguments} X X procedure getnames; X begin X gettoken; X while not((sym = module))and (not empty) X do gettoken; X gettoken; X if sym = ident X then begin X gettoken; X case sym of X lftparen : arguments; X flag: flagmodule; X title: titlemodule; X semicolon: begin X semimodule; X case sym of X flag : flagmodule; X title: titlemodule; X otherwise: X start X end X end; X otherwise: X start X end X end X else begin X Abort := true; X writeln ('** missing module name') X end X end; {getnames} X X procedure error (errnmbr : integer); X begin X case errnmbr of X 1 : begin X writeln ('Signal name undefined: ',token) X end; X 2 : begin X writeln ('error in andoperator!') X end; X 3 : begin X writeln ('Expecting a signal name'); X writeln ('Undetermined token ',token) X end; X 4 : begin X writeln ('Expecting a "=" operator'); X writeln ('Got instead ',token) X end; X 5 : begin X writeln ('Expecting either a ":" or "=" operator'); X writeln ('Instead it got ',token) X end; X 6 : begin X writeln ('Expecting a boolean equation'); X writeln ('Unexpected token ',token) X end; X 7 : begin X writeln ('Exceeded total or-terms'); X writeln ('Output =',outtable[nexout].outname); X end; X 8 : begin X writeln (token,' not a valid input or feedback factor') X end; X 9 : begin X writeln ('Expecting ";" at end of equation') X end; X 10 : begin X writeln ('This device is not capable of this function') X end; X 11 : begin X writeln ('This device is not capable of true-form output ',token) X end; X 12 : begin X writeln ('Not a valid output pin for ',token); X end; X otherwise: X writeln ('software error in error routine') X end X end; {error} X X procedure andterm; X begin X gettoken; X case sym of X ident : X begin X search (3); {find pin number attached to this signal name} X if not found X then begin error(1); gettoken end X else begin X j := fusetoinp[palkind].transfer[pointer]; {get fuse number} X if j < 0 X then error (8) {not a valid input or feedback factor} X else outtable[outindex].matrix[iterm,j]:= '1'; X gettoken; X if sym = andoperator then andterm {call back recursively} X end X end; X invert : X begin X gettoken; {get signal name} X if sym = ident X then X begin X search (3); {find pin number attached to this signal name} X if not found X then begin error(1); gettoken end X else begin X j := fusetoinp[palkind].transfer[pointer]; {get fuse number} X if j < 0 X then error (8) {not a valid input or feedback factor} X else begin X j := j + 1; {increment fuse number} X outtable[outindex].matrix[iterm,j]:= '1' X end; X gettoken; X if sym = andoperator then andterm {call back recursively} X end X end X else error (3) {expecting an identifier, i.e. signal name} X end; X otherwise: error (2) X end X end; {andterm} X X procedure nodeterm (var pterm : ptermtyp); X begin X gettoken; X case sym of X ident : X begin X search (3); {find pin number attached to this signal name} X if not found X then begin error(1); gettoken end X else begin X j := fusetoinp[palkind].transfer[pointer]; {get fuse number} X if j < 0 X then error (8) {not a valid input or feedback factor} X else pterm[j]:= '1'; X gettoken; X if sym = andoperator then nodeterm(pterm) {call back recursively} X end X end; X invert : X begin X gettoken; {get signal name} X if sym = ident X then X begin X search (3); {find pin number attached to this signal name} X if not found X then begin error(1); gettoken end X else begin X j := fusetoinp[palkind].transfer[pointer]; {get fuse number} X if j < 0 X then error (8) {not a valid input or feedback factor} X else begin X j := j + 1; {increment fuse number} X pterm[j]:= '1' X end; X gettoken; X if sym = andoperator then nodeterm(pterm) X end X end X else error (3) {expecting an identifier, i.e. signal name} X end; X otherwise: error (2) X end X end; {nodeterm} X X procedure setiterm; X begin X case palkind of X p22vx, p16l8, X p20l10,p20l8 : iterm := 2; { all outputs have OE term } X p16rx: X case pointer of X 19,12 : if (ptype = '5')or(ptype='6') X then iterm := 2 else iterm := 1; X 18,13 : if (ptype = '6') then iterm :=2 else iterm := 1; X otherwise: iterm := 1 X end; X p20rx: X case pointer of X 22,15 : if (ptype = 'B')or(ptype='C') X then iterm := 2 else iterm := 1; X 21,16 : if (ptype = 'C') then iterm :=2 else iterm := 1; X otherwise: iterm := 1 X end; X otherwise: iterm := 1 X end X end; {setiterm} X X procedure getterms; X begin X case palkind of X p10l8,p12l10: X totalterms := 2; X p14l4,p20l10: X totalterms := 4; X p12l6: X if (pointer = 18) or (pointer = 13) X then totalterms := 4 X else totalterms := 2; X p14l8: X if (pointer = 22) or (pointer = 15) X then totalterms := 4 X else totalterms := 2; X p16l6: X if (pointer = 19) or (pointer = 18) X then totalterms := 2 X else totalterms := 4; X p18l4: X if (pointer = 19) or (pointer = 18) X then totalterms := 4 X else totalterms := 6; X p22vx: X case pointer of X 23,14 : totalterms := 9; X 22,15 : totalterms := 11; X 21,16 : totalterms := 13; X 20,17 : totalterms := 15; X 19,18 : totalterms := 17; X otherwise: writeln ('Software error in procedure getterms!') X end; X otherwise: X totalterms := 8 X end X end; {getterms} X X procedure map (typ : char); X var i,j : integer; X begin {map} X case typ of X '0' : {initialize a new output} X begin X {first find out if output already has been defined, that is if X output has an enable previously defined } X found := false; Xwriteln ('output : ',token,' nexout=',nexout); X for i:=1 to nexout do X with outtable[i] do X if outname = token X then begin X found := true; outindex := i X end; X getterms; {find out how many or-terms this output has } X setiterm; {find out where to start orterms } X if not found X then begin X nexout := nexout + 1; X outtable[nexout].outnumb := pointer; {store output pin number} X outtable[nexout].outname := token; {store output name } X for i:=1 to maxterms do X for j:=1 to maxcols do X outtable[nexout].matrix[i,j]:= '0'; X outtable[nexout].outkind := nonreg; {default} X if iterm > 1 then outtable[nexout].matrix[1,1]:= 'H'; X case ptype of X '2' : outtable[nexout].form := high; X otherwise: outtable[nexout].form := low X end; X outindex := nexout X end X end X end X end; {map} X X procedure orterms; X begin X andterm; X if sym = oroperator X then begin X iterm := iterm + 1; X if iterm > totalterms X then error (7) X else orterms X end X else begin {mark termination of equation} X iterm := iterm + 1; X outtable[outindex].matrix[iterm,1]:= 'X' X end X end; {orterms} X X procedure getmatrix; X begin {getmatrix} X case sym of X enable : X begin X gettoken; X if sym = ident X then begin X search (3); {find out pin number} X if not found X then error (1) X else begin X map ('0'); {create an output description database} X if iterm > 1 then X begin X outtable[nexout].matrix[1,1]:= '0'; {clear possible H} X gettoken; {get equal sign} X if sym = eql X then begin X iterm := 1; X andterm; X if sym = semicolon X then begin X gettoken; {find out next step} X if sym <> ends then getmatrix X end X else error (9) {missing semicolon} X end X else error (4) X end X else error (10) { Output has no OE term } X end X end X else error (3) {expecting a signal name} X end; X clear: X begin X {find out if this is a Pal 22v10} X if ptype <> 'D' X then error (10) X else begin X gettoken; { read dummy pseudo pin name } X gettoken; { get equal sign } X if (sym = eql) X then begin X ar[1]:= '0'; {erase default} X nodeterm (ar); X if sym = semicolon X then begin X gettoken; {find out next step} X if sym <> ends then getmatrix X end X else error (9) X end X else error (4) X end X end; X preset: X begin X {find out if this is a Pal 22v10} X if ptype <> 'D' X then error (10) X else begin X gettoken; { read dummy pseudo pin name } X gettoken; { get equal sign } X if (sym = eql) X then begin X sp[1]:= '0'; {erase default} X nodeterm (sp); X if sym = semicolon X then begin X gettoken; {find out next step} X if sym <> ends then getmatrix X end X else error (9) X end X else error (4) X end X end; X ident : {a min-term equation} X begin X if (ptype = 'D') or (ptype = '2') X then begin X search (3); X if not found X then error (1) X else begin X map ('0'); {initialize new entry in the output table} X outtable[nexout].form := high; {set output pol } X gettoken; { get equal sign } X case sym of X colon : {it is a registered output } X begin X gettoken; {get equal sign} X if (sym = eql) X then X begin X outtable[outindex].outkind := reg; X orterms; X if sym = semicolon X then begin X gettoken; {find out next step} X if sym <> ends then getmatrix X end X else error (9) X end X else error (4) X end; X eql : {it is a non_registered output } X begin X outtable[outindex].outkind := nonreg; X orterms; X if sym = semicolon X then begin X gettoken; {find out next step} X if sym <> ends then getmatrix X end X else error (9) X end; X otherwise: error (5) X end X end X end X else error (11) {this device is not capable of true form output} X end; X invert: {a max-term equation} X begin X gettoken; {get signal name} X if sym = ident X then begin X search (3); {obtain pin number from table} X if (not found) X then error (1) X else begin X map ('0'); {initialize new entry in the output table} X gettoken; { get equal sign } X case sym of X colon : {it is a registered output } X begin X gettoken; {get equal sign} X if (sym = eql) X then X begin X outtable[outindex].outkind := reg; X orterms; X if sym = semicolon X then begin X gettoken; {find out next step} X if sym <> ends then getmatrix X end X else error (9) X end X else error (4) X end; X eql : {it is a non_registered output } X begin X outtable[outindex].outkind := nonreg; X orterms; X if sym = semicolon X then begin SHAR_EOF echo "End of part 1, continue with part 2" echo "2" > s2_seq_.tmp exit 0