!Program to convert Output from MINIMO
!into PAL-blower fuse-plot format
!RWT April 1985

! Input: three files
! (1) Minimo file, defining the logic functions.
! (2) Pin file, defining which signals correspond to which pins.
! (3) PAL definition file, defining the internal layout of the PAL.

! Output: one file, the fuse plot diagram.

! The format of the minimo file is assumed to be as follows:
!Any old junk up to a line containing ':' and followed by a blank line.
!Then a number of lines defining the logic functions,
!each of the form  IN* : OUT*
!An input signal name may be prefixed by \, indicating
!that the P-term is to be connected to the complemented input, or it may
!be '.', indicating that the corresponding input is unused in that term.
!An output signal, if present, must be 1 for that P-term.

! The format of the pin file is as follows:
!Any number of lines of the form  NUMBER SIGNALNAME
!a line containing a zero
!any number of lines of the form  NUMBER SIGNALNAME
!a line containing a zero.
!The first/second group defines the inputs/outputs.

! The format of the PAL definition file is:
! The number of fuse columns, the number of term rows,
! the number of inputs, the number of outputs.
! Then, for each input,
!  three numbers PIN TRUE FALSE, giving the pin number by which it is
!  referred to in the pin file, and the numbers of the fuse columns to
!  which the true and false buffered inputs are connected.
! Then, for each output,
!  a PIN number followed by a LIST of term row numbers.
!  A list consists of at least one number which may be followed by
!  either ',', indicating that more numbers follow, or by '-', indicating
!  that at least another number follows, and indicates a range of term numbers.

%include "inc:util.imp"

%begin
%string(31)minimofile,pinfile="",palfile,fuseplotfile=""
%constinteger defext=16_80000000
%integer options=defext
%integer cols,rows,inputs,outputs

%onevent 3 %start
  printstring(event_message); newline; %stop
%finish

%routine skipmostjunk
! Skip spaces, comments
%integer sym
  %cycle
    sym = nextsymbol
    %if sym='{' %start
      readsymbol(sym) %until sym='}'
    %else
      %returnif sym#' '
      skipsymbol
    %finish
  %repeat
%end

%routine skipalljunk
! Skip newlines too
  %cycle
    skipmostjunk; %exitunless nextsymbol=nl
    skipsymbol
  %repeat
%end

defineparam("Minimo file",minimofile,pammajor!pamnodefault)
defineparam("Pin file",pinfile,pammajor)
defineparam("PAL type",palfile,pammajor!pamnodefault)
defineparam("Fuseplot file",fuseplotfile,pamnewgroup!pammajor)
definebooleanparams("Defext",options,pamnewgroup)
processparameters(cliparam)
palfile = "stag:".palfile %unless palfile->(":")
palfile = palfile.".def"  %unless palfile->(".")
%if options&defext#0 %start
  pinfile = minimofile %if pinfile=""
  fuseplotfile = minimofile %if fuseplotfile=""
  minimofile = minimofile.".MIN"
  pinfile = pinfile.".PIN"
  fuseplotfile = fuseplotfile.".FUS"
%finish

! Open the PAL def file and read the array bounds we will need

openinput(1,palfile); selectinput(1)
skipalljunk; read(cols)
skipalljunk; read(rows)
skipalljunk; read(inputs)
skipalljunk; read(outputs)

! Now declare the arrays

%begin
%constinteger x=0,t=1,f=2
%constinteger unused=0,used=32767
%constinteger no=0,yes=1
%constinteger phantom='.',intact='X',blown='-'
%constinteger stx=2,etx=3
%recordformat inf(%string(31)name,%byte pin,true,false)
%recordformat outf(%string(31)name,%short pin)
%record(inf)%array intab(1:inputs)
%record(outf)%array outtab(1:outputs)
%bytearray currentexpr(1:inputs);      !X/T/F
%bytearray currentrow(0:cols-1);       !Intact/Blown
%bytearray colsused(0:cols-1);         !No/Yes
%shortarray rowsused(0:rows-1);        !unused/used/pinnumber
%bytearray fusemap(0:rows-1,0:cols-1); !phantom/intact/blown

%integer i,j,k,l
%string(31)n
%record(inf)%name in
%record(outf)%name out

%routine readname(%string(*)%name n)
! Skip spaces, read sequence of non-control/space characters,
! standardise to upper case,
! Don't proceed past newline.
%integer sym
  n = ""
  skipmostjunk
  %cycle
    sym = nextsymbol; %exitif sym<=' '
    sym = sym&95 %if 'a'<=sym<='z'
    n = n.tostring(sym); skipsymbol
  %repeat
%end

%integerfn findoutputgate(%integer pin)
%integer i=-1
  %cycle
    i = i+1; %exitif i>=rows
    %exitif rowsused(i)=pin
  %repeat
  %if i>=rows %start
    printstring("No free gates for output ".n); newline
    i = -1
  %finish
  %result = i
%end


%integerfn findinputname
%integer i
  i = inputs
  %cycle
    in == intab(i)
    %result = i %if in_name=n
    i = i-1
  %repeatuntil i=0
  printstring("Undeclared input signal ".n); newline
  %result = 0
%end

%integerfn findoutputname(%integer from)
%integer i
  i = from
  %cycle
    i = i+1; %exitif i>outputs
    out == outtab(i)
    %result = i %if out_name=n
  %repeat
  %result = 0 %unless from=0
  printstring("Undeclared output signal ".n); newline
  %result = 0
%end

%integerfn findinputpin(%integer p)
%integer i
  i = inputs
  %cycle
    in == intab(i)
    %result = i %if in_pin=p
    i = i-1
  %repeatuntil i=0
  printstring("Unknown input pin "); write(p,0); newline
  %result = 0
%end

%integerfn findoutputpin(%integer p)
%integer i
  i = outputs
  %cycle
    out == outtab(i)
    %result = i %if out_pin=p
    i = i-1
  %repeatuntil i=0
  printstring("Unknown output pin "); write(p,0); newline
  %result = 0
%end

! Initialise everything

  colsused(i) = no %for i = 0,1,cols-1
  rowsused(i) = unused %for i = 0,1,rows-1
  %for i = 0,1,rows-1 %cycle
    fusemap(i,j) = phantom %for j = 0,1,cols-1
  %repeat

! Read the input definitions

  %for i = 1,1,inputs %cycle
    in == intab(i)
    in_name = ""
    skipalljunk; read(in_pin)
    skipalljunk; read(in_true); colsused(in_true) = yes
    skipalljunk; read(in_false); colsused(in_false) = yes
  %repeat

! Read the output definitions

  %for i = 1,1,outputs %cycle
    out == outtab(i)
    out_name = ""
    skipalljunk; read(out_pin); skipalljunk
    %cycle
      read(j); skipmostjunk;     !(first) term-row number
      %if nextsymbol='-' %start; !range
        skipsymbol; skipalljunk
        read(k); skipmostjunk;   !last term number
      %finishelse k = j
      %cycle
        rowsused(j) = out_pin
        fusemap(j,l) = intact %for l = 0,1,cols-1
        %exitif j=k
        %if k>j %then j = j+1 %else j = j-1
      %repeat
      %exitunless nextsymbol=','; !more to follow
      skipsymbol; skipalljunk
    %repeat
  %repeat
  closeinput

! Now read the pin file

  openinput(1,pinfile); selectinput(1)
  %cycle
    skipalljunk; read(i)
    %exitif i=0
    skipalljunk; readname(n)
    i = findinputpin(i)
    in_name = n %unless i=0
  %repeat
  %cycle
    skipalljunk; read(i)
    %exitif i=0
    i = findoutputpin(i)
    skipalljunk; readname(n)
    out_name = n %unless i=0
    %if n="1" %start
      i = findoutputgate(out_pin)
      %unless i<0 %start
        rowsused(i) = used
        fusemap(i,j) = blown %for j = 0,1,cols-1
      %finish
    %finish
  %repeat
  closeinput

! Now process the main minimo file, first skip junk

  openinput(1,minimofile); selectinput(1)
  %cycle
    skipalljunk %and readsymbol(i) %until i=':'
    readsymbol(i) %until i=nl
    %exitif nextsymbol=nl
  %repeat
  skipsymbol %while nextsymbol=nl

  %cycle; !for each line of data
    currentexpr(i) = x %for i = 1,1,inputs
    %cycle; !build the product term
      readname(n)
      %exitif n=":"
      %if n="" %start
        printstring("I can't understand this damn minimo format")
        newline; %stop
      %finish
      %unless n="." %start
        j = charno(n,1);      !True or Complement?
        n = substring(n,2,length(n)) %if j='\'
        i = findinputname
        %unless i=0 %start
          %if j='\' %start
            currentexpr(i) = f
          %else
            currentexpr(i) = t
          %finish
        %finish
      %finish
    %repeat
! At this point, for each i, currentexpr(i) is:
! T iff M occurred
! F iff \M occurred
! X otherwise
! where M is the name corresponding to input number i.
! Now translate into row format.
    currentrow(i) = intact %for i = 0,1,cols-1
    %for i = 1,1,inputs %cycle
      in == intab(i)
      currentrow(in_true) = blown %if currentexpr(i)&t=0
      currentrow(in_false) = blown %if currentexpr(i)&f=0
    %repeat
! At this point, at least one fuse of each currentrow(?) pair
! corresponding to any one input signal is blown.
! Now process the part of the line after the ":", transferring the
! row expression just built to each row involving a specified output.
    %cycle
      readname(n)
      %exitif n=""
      %unless n="." %or n="?" %start
        k = 0
        %cycle
          k = findoutputname(k)
          %exitif k<=0
          i = findoutputgate(out_pin)
          %unless i<0 %start
            rowsused(i) = used
            fusemap(i,j) = currentrow(j) %for j = 0,1,cols-1
          %finish
        %repeat
      %finish
    %repeat
    skipsymbol; !the newline
  %repeatuntil nextsymbol=nl
  closeinput

! Finally produce the output

  openoutput(1,fuseplotfile) %and selectoutput(1) %unless fuseplotfile=""
  printsymbol(stx) %and newline %unless fuseplotfile=""
  %for i = 0,1,rows-1 %cycle
    %if rowsused(i)=used %or rowsused(i)=unused %start; !Force phantoms too
      printsymbol(i//10+'0'); printsymbol(rem(i,10)+'0'); space
      %for j = 0,1,cols-1 %cycle
        space %if j&3=0
        printsymbol(fusemap(i,j)) {%if colsused(j)=yes
      %repeat
      newline
    %finish
  %repeat
  printsymbol(etx) %and newline %unless fuseplotfile=""

%end
%endofprogram
