!! POSTPRO      08/10/79
%BEGIN

%EXTERNAL %STRING(63) %FN %SPEC ITOS(%INTEGER N ,P)
%EXTERNALSTRING(127)%FNSPEC CLIPARAM
%EXTERNALINTEGERFNSPEC DEF STREAMS(%STRING(127) STREAMS,DEFAULTS)
%INTEGER RETURN CODE
%OWNSTRING(15) DEFAULTS=".TRC/%I1.WVM"

%CONSTINTEGER MAXTRACES=200
%RECORDFORMAT TRACEF(%STRING(15) NAME, %INTEGER VALUE)
%RECORD(TRACEF)%ARRAY TRACES(1:MAXTRACES)
%RECORD(TRACEF)%NAME TRACE

%CONSTINTEGER MAXSIGNALS=80
%RECORD(TRACEF)%NAME %ARRAY SIGNALS(1:MAXSIGNALS)

%CONSTINTEGER NULL=0;          !! null address
%CONSTINTEGER LINELENGTH=60;   !! length of console line
%CONSTINTEGER PAGELEN=66,   BOTTOM=2,   TOP=1

%STRING(63)   TRACENAME,   NAME
%STRING(15)%NAME T
%INTEGER TIME,   VALUE,   NTRACES,   NSIGNALS
%INTEGER WIDTH,   POSN,   COMPRESSION,   I,   CH
%INTEGER COLS PER TRACE,   LINE

%ROUTINE SKIP BLANKS
   SKIPSYMBOL %WHILE NEXTSYMBOL=' ' %OR NEXTSYMBOL=NL
%END

%ROUTINE SKIP LINE
   SKIPSYMBOL %WHILE NEXTSYMBOL#NL
   SKIPSYMBOL
%END

%ROUTINE TRUNCATE(%STRING(*)%NAME S)
!! truncate the string S to 15 characters
!! the first 5 and the last 9 characters are left
   %INTEGER I,   L
   L=LENGTH(S)-10
   %IF L>5 %START
      !! length > 15
      %FOR I=2,1,10 %CYCLE
         !! for last 10 characters
         CHARNO(S,I+5)=CHARNO(S,I+L)
      %REPEAT
      CHARNO(S,6)='?'
      CHARNO(S,0)=15
   %FINISH
%END

%ROUTINE GET STRING(%STRING(*)%NAME S)
!! read in a string (from the terminal or from a file)
!! certain characters are taken to terminate the string
!! namely blank, newline, comma
   %INTEGER L,   CH
   SKIP BLANKS
   L=0
   %CYCLE
      CH=NEXTSYMBOL
      %EXIT %IF CH=' ' %OR CH=',' %OR CH=NL
      SKIPSYMBOL
      L=L+1
      CH=CH-'a'+'A' %IF 'a'<=CH<='z'
      CHARNO(S,L)=CH
   %REPEAT
   CHARNO(S,0)=L
%END

%RECORD(TRACEF)%MAP FIND TRACE(%STRING(15) NAME)
   %RECORD(TRACEF)%NAME TRACE
   %INTEGER I
   %FOR I=1,1,NTRACES %CYCLE
      TRACE==TRACES(I)
      %RESULT==TRACE %IF TRACE_NAME=NAME
   %REPEAT
   %RESULT==RECORD(NULL)
%END

%RECORD(TRACEF)%MAP FIND SIGNAL(%STRING(15) NAME)
   %INTEGER I
   %RECORD(TRACEF)%NAME TRACE
   %FOR I=1,1,NSIGNALS %CYCLE
      TRACE==SIGNALS(I)
      %RESULT==TRACE %IF TRACE_NAME=NAME
   %REPEAT
   %RESULT==RECORD(NULL)
%END

%ROUTINE NULINE
   NEWLINE
   LINE=LINE+1
%END

%ROUTINE NEWPAGE
   NEWLINES(PAGELEN+TOP-LINE)
   LINE=TOP
%END

%ROUTINE HEADING
!! output a simulation trace heading
   %INTEGERARRAY DONE(1:NSIGNALS)
   %INTEGER I, NSPACES, NDONE
   %STRING(15)%NAME NAME

   PRINTSTRING(" Time")
   DONE(I)=0 %FOR I=1,1,NSIGNALS;   NDONE=0
   %CYCLE
      !! until all signal names have been output
      NSPACES=0
      %FOR I=1,1,NSIGNALS %CYCLE
         NSPACES=NSPACES+COLS PER TRACE
         %CONTINUE %IF NSPACES<1
         SPACES(NSPACES)
         %IF DONE(I)=1 %START
            !! already output this name
            PRINTSYMBOL('|');
            NSPACES=-1
         %FINISH %ELSE %START
            NAME==SIGNALS(I)_NAME
            PRINTSTRING(NAME)
            NSPACES=0-LENGTH(NAME)
            DONE(I)=1
            NDONE=NDONE+1
         %FINISH
      %REPEAT
      NULINE
      %EXIT %IF NDONE>=NSIGNALS
      SPACES(5)
   %REPEAT
   NULINE
%END

%ROUTINE PRINT LINE
!! print a line of the simulation trace
   %INTEGER I, VALUE, NSPACES, F, TRACEWIDTH, CH

   TRACEWIDTH=COLS PER TRACE-1
   TRACEWIDTH=4 %IF TRACEWIDTH>4
   NSPACES=0
   %FOR I=1,1,NSIGNALS %CYCLE
      NSPACES=NSPACES+COLS PER TRACE
      SPACES(NSPACES)
      VALUE=SIGNALS(I)_VALUE
      %IF VALUE=0 %START
         PRINTSYMBOL('0')
         NSPACES=-1
      %FINISH %ELSE %START
         %IF VALUE=1 %THEN CH='X' %ELSE CH=' '
         PRINTSYMBOL(CH) %FOR F=1,1,TRACEWIDTH-1
         %IF VALUE=1 %THEN PRINTSYMBOL('X') %ELSE PRINTSYMBOL('1')
         NSPACES=0-TRACEWIDTH
      %FINISH
   %REPEAT
   NULINE
%END

%ROUTINE PRINT TO(%INTEGER WHEN)
!! print the simulation trace up to just before the time WHEN
   %OWNINTEGER TIME=0
   %INTEGER T

%ROUTINE PRINT TIME(%INTEGER T)
   !! print out the time
   %IF (COMPRESSION=0 %AND REM(T,5)=0) %OR %C
       (COMPRESSION#0 %AND T=TIME) %START
      WRITE(T,4)
   %FINISH %ELSE SPACES(5)
%END

   %RETURN %IF WHEN<=TIME
   NEWPAGE %AND HEADING %UNLESS LINE<PAGELEN-BOTTOM
   PRINT TIME(TIME);   PRINT LINE
   %IF COMPRESSION>0 %START
      !! could be the compressed form
      %IF WHEN-TIME>COMPRESSION %START
         NEWPAGE %AND HEADING %UNLESS LINE<=PAGELEN-BOTTOM-2
         PRINTSTRING(" ++++");   PRINT LINE
         ->OUT
      %FINISH
   %FINISH
   %FOR T=TIME+1,1,WHEN-1 %CYCLE
      NEWPAGE %AND HEADING %UNLESS LINE<PAGELEN-BOTTOM
      PRINT TIME(T);   PRINT LINE
   %REPEAT
OUT:
   TIME=WHEN
%END

!!************************************************
!! mainline code for POSTPROcessor               *
!!************************************************

%ON %EVENT 3,9 %START
   SELECTOUTPUT(0)
   PRINTSTRING("* Unexpected end of file")
   NEWLINE
   %STOP
%FINISH

RETURN CODE=DEF STREAMS(CLIPARAM,DEFAULTS)
->DONE %UNLESS RETURN CODE=1

!! first copy any 'comments' to the heading page
SELECTINPUT(1);   SELECTOUTPUT(1)
%IF NEXTSYMBOL='$' %START
   SKIPSYMBOL
   %CYCLE
      READSYMBOL(CH)
      %EXIT %IF CH='$' %AND NEXTSYMBOL=NL
      PRINTSYMBOL(CH)
   %REPEAT
   SKIPSYMBOL
%FINISH

!!...first read the list of signal names at time 0...
SELECTOUTPUT(0)
NTRACES=0
%CYCLE
   SKIP BLANKS
   SKIP LINE %WHILE NEXTSYMBOL='$'
   GET STRING(TRACENAME)
   TRUNCATE(TRACENAME)
   %IF TRACENAME="*" %START
      !! premature end of trace
      PRINTSTRING("*Trace is empty - processing abandonned")
      NEWLINE
      %STOP
   %FINISH
   READ(VALUE);   READ(TIME)
   %EXIT %IF TIME>0
   %IF NTRACES>=MAXTRACES %START
      PRINTSTRING("*Too many signal names (re-compile program)")
      NEWLINE
      %STOP
   %FINISH
   NTRACES=NTRACES+1
   TRACE==TRACES(NTRACES)
   TRACE_NAME=TRACENAME;   TRACE_VALUE=VALUE
%REPEAT

!!...prompt for output control parameters.............
SELECTINPUT(0)
%CYCLE
   PROMPT("Width of page= ")
   SKIP BLANKS
   %UNLESS '0'<=NEXTSYMBOL<='9' %START
      !! help information
      PRINTSTRING("* Give the width of the page (in character columns)
* on which the signal traces are to appear.
")
   %FINISH %ELSE %START
      READ(WIDTH)
      %EXIT %IF 10<=WIDTH<=132
   %FINISH
   PRINTSTRING("* Width must be in range 10 to 132.
")
   SKIP LINE
%REPEAT
SKIP LINE

!!...prompt for signal names to be traced........
NSIGNALS=0
%CYCLE
   PROMPT("Signal  names  ")
   GET STRING(NAME)
   TRUNCATE(NAME)
   NAME="?" %IF NAME=""
   %IF NAME="?" %START
      POSN=0
      %FOR I=1,1,NTRACES %CYCLE
         T==TRACES(I)_NAME
         NEWLINE %AND POSN=0 %IF POSN+LENGTH(T)>LINELENGTH
         SPACE;   PRINTSTRING(T)
         POSN=POSN+LENGTH(T)+1
      %REPEAT
      PRINTSTRING("
* Use an asterisk (*) to terminate the list of names.
")
   %FINISH %ELSE %IF NAME="*" %START
      %EXIT
   %FINISH %ELSE %START
      TRACE==FIND TRACE(NAME)
      %IF TRACE==RECORD(NULL) %START
         !! NAME not found
         PRINTSTRING("* ".NAME." is not a signal name")
         NEWLINE
      %FINISH %ELSE %START
         %IF NSIGNALS>=MAXSIGNALS %START
            PRINTSTRING("* Only ".ITOS(MAXSIGNALS,0)." signals can be traced")
            NEWLINE
         %FINISH %ELSE %START
            NSIGNALS=NSIGNALS+1
            SIGNALS(NSIGNALS)==TRACE
         %FINISH
      %FINISH
   %FINISH
   SKIPSYMBOL
%REPEAT

!!...work out whether trace will fit or not...
COLS PER TRACE=(WIDTH-6)//(NSIGNALS+1)
%IF COLS PER TRACE<2 %START
   PRINTSTRING("*Width of page is too small for no. of signals")
   NEWLINE
   NSIGNALS=(WIDTH-6)//2
   %IF NSIGNALS<2 %START
      PRINTSTRING("*Trace abandonned");   NEWLINE
      %STOP
   %FINISH %ELSE %START
      PRINTSTRING("*Only the first ".ITOS(NSIGNALS,0)." signals will be traced")
      NEWLINE
   %FINISH
%FINISH

!!...prompt for compression factor.........
%CYCLE
   SKIP LINE
   PROMPT("Compr'n factor=")
   SKIP BLANKS
   READ(COMPRESSION) %AND %EXIT %IF '0'<=NEXTSYMBOL<='9'
   PRINTSTRING("* If a compression factor of 'n' > 0 is specified, 
* then all time periods of length 'n' or more in which
* no events occur are removed from the signal trace.
* A value of 0 specifies no compression.
")
%REPEAT
SKIP LINE

!!...and finally generate the signal traces.........
SELECTINPUT(1);   SELECTOUTPUT(1)
LINE=PAGELEN
%CYCLE
   TRACE==FIND SIGNAL(TRACENAME)
   %IF %NOT TRACE==RECORD(NULL) %START
      PRINT TO (TIME)
      TRACE_VALUE=VALUE
   %FINISH
   !! output any 'comments' (identified by '$')
   %CYCLE
      SKIP BLANKS;   !! get rid of NL etc
      %EXIT %UNLESS NEXTSYMBOL='$'
      SKIPSYMBOL;   !! skip the marker
      !! and copy the comment to the output stream
      %CYCLE
         CH=NEXTSYMBOL
         %EXIT %IF CH=NL
         PRINTSYMBOL(CH)
         SKIPSYMBOL
      %REPEAT
      NULINE
   %REPEAT
   GET STRING(TRACENAME)
   TRUNCATE(TRACENAME)
   %EXIT %IF TRACENAME="*";      !! end of trace
   READ(VALUE);   READ(TIME)
%REPEAT
PRINT TO(TIME+1)

DONE:
%ENDOFPROGRAM
