(SimMOS Utilities of November 5, 1980  4:00 PM
).print

(simmos)(simmosdict /begin).cvx .def

(simmosdict).where
  (.pop).cvx
  ((simmosdict)256 .dict .def).cvx
.ifelse

simmosdict .begin

(begin)
(jamrun simmosrun .eq .not
   ((SimMOS.bcd) .loadbcd
    (simmosrun)jamrun .def
   ).cvx
 .if
 (SimMOS)/print
).cvx .def

(simmosrun)0 .def

(simstep)
(carry out one solution of the circuit
)
(simsolve .pop
).cvx /def

(arraysim)
(<array of input string names><array of output string names> arraysim
for each input value:
  sets up values of each input, calls clock1, collects outputs, calls clock2.
See also resumearraysim
)
((arraysimOut) .exch .def (arraysimIn) .exch .def
 arraysimIn .length 1 .sub (arraysimInL) .exch .def
 arraysimOut .length 1 .sub (arraysimOutL) .exch .def
 (arraysimSi)0 .def
 resumearraysim
).cvx /def

(resumearraysim)
(Resume arraysim after interruption
 no parameters
)
(arraysimIn 0 .aget .load .length 1 .sub (arraysimSL) .exch .def
 arraysimcheckinputs
 arraysimsetupoutputs
 arraysimrun
).cvx /def

(arraysimcheckinputs)
(1 1 arraysimInL
 ( arraysimIn .exch .aget .dup .load .length 1 .sub arraysimSL .eq
     (.pop).cvx
     (.print ( has different length from ).print arraysimIn 0 .aget /print
      .stop
     ).cvx
   .ifelse
 ).cvx .for
).cvx .def

(arraysimsetupoutputs)
(0 1 arraysimOutL
 ( arraysimOut .exch .aget
   .dup arraysimcheckoutputok
   .not
   ( .dup arraysimSL 1 .add .string .def).cvx
   .if
   .load arraysimsetblanks
 ).cvx .for
).cvx .def

(arraysimcheckoutputok)
(  .where
   ( .pop .dup .load .type (.stringtype) .eq
     ( .dup .load .length 1 .sub arraysimSL .eq).cvx
     ( .false).cvx
     .ifelse
   ).cvx
   ( .false).cvx
   .ifelse
).cvx .def

(arraysimsetblanks)
(  arraysimSi 1 arraysimSL
   ( ( ).putstring
   ).cvx .for
   .pop
).cvx .def

(arraysimrun)
(arraysimsetinterrupt
 arraysimSi 1 arraysimSL
 ( (arraysimSi) .exch .def
   0 1 arraysimInL
   ( arraysimIn .exch .aget .dup .load
     arraysimSi 1 .substring .load .exec
   ).cvx .for
   clock1
   0 1 arraysimOutL
   ( arraysimOut .exch .aget .dup .load
     .exch getnodevalue arraysimSi .exch .putstring .pop
   ).cvx .for
   clock2
   arraysimcheckinterrupt
 ).cvx .for
 arraysimunsetinterrupt
).cvx .def

(arraysimsetinterrupt)
((arraysimsaveinterrupt)(.interrupt).load .def
 (arraysiminterruptflag).false .def
 (.interrupt)((arraysiminterruptflag).true .def).cvx .def
).cvx .def

(arraysimcheckinterrupt)
(arraysiminterruptflag
   ((arraysim interrupted after step ).print
    arraysimSi =
    (arraysimSi)arraysimSi 1 .add .def
    arraysimunsetinterrupt
    .stop
   ).cvx
 .if
).cvx .def

(arraysimunsetinterrupt)
((.interrupt)(arraysimsaveinterrupt).load .def
).cvx .def

(arraysimSi)0 .def
(0)(lo).cvx .def
(1)(hi).cvx .def

(arraynames)
(<array of output string names> arraynames
prints names of signals in the array
)
((arraysimOut) .exch .def
 0 1 arraysimOut .length 1 .sub
 ( arraysimOut .exch .aget /lp .print .print /rp .print
 ).cvx .for
 ()/print
).cvx /def

(arrayvalues)
(<array of output string names> arrayvalues
prints values of signals in the array
)
((arraysimOut) .exch .def
 0 1 arraysimOut .length 1 .sub
 ( arraysimOut .exch .aget .dup .print ( = ).print getnodevalue /print
 ).cvx .for
).cvx /def

(arraystrings)
(<array of output string names> printarray
prints stored strings of signals in the array
)
((arraysimOut) .exch .def
 (arraysimOutSL) arraysimOut 0 .aget .load .length .def
 0 64 arraysimOutSL 1 .sub
 ( ()/print
   .dup arraysimOutSL .exch .sub 64 2 .copy .lt (.pop).cvx (.exch .pop).cvx .ifelse 
   0 1 arraysimOut .length 1 .sub
   ( arraysimOut .exch .aget .dup .load
     4 .copy .pop .pop .substring .print
    ( = ).print /print
   ).cvx .for
   .pop .pop
 ).cvx .for
).cvx /def



(logchanges)
(<outstream> logchanges
switches on log of commands that change the stored circuit for subsequent redoing
)
((logstream).exch .def
 /cr logprint
 logging .not
   (
    (simreset1)(simreset).load .def
    (simreset)
    ((simreset) logprint /cr logprint simreset1
    ).cvx .def

    (etrans1)(etrans).load .def
    (etrans)
    (3 logrollprint 3 logrollprint 3 logrollprint (etrans) logprint
     /cr logprint etrans1
    ).cvx .def

    (dtrans1)(dtrans).load .def
    (dtrans)
    (3 logrollprint 3 logrollprint 3 logrollprint (dtrans) logprint
     /cr logprint dtrans1
    ).cvx .def

    (redefinetrans1)(redefinetrans).load .def
    (redefinetrans)
    (6 logrollprint 6 logrollprint 6 logrollprint
     6 logrollprint 6 logrollprint 6 logrollprint (redefinetrans) logprint
     /cr logprint redefinetrans1
    ).cvx .def

    (logging).true .def
   ).cvx
 .if
).cvx /def

(unlogchanges)
(unlogchanges
switches off log of commands that change the stored circuit for subsequent redoing
)
(logging
  ((simreset)(simreset1).load .def
   (etrans)(etrans1).load .def
   (dtrans)(dtrans1).load .def
   (redefinetrans)(redefinetrans1).load .def
   (logging).false .def
  ).cvx
 .if
).cvx /def

(logging).false .def
(logrollprint)(-1 .roll /lp logprint .dup logprint /rp logprint).cvx .def
(logprint)(logstream .exch .writebytes).cvx .def



(getbit)
((nodename) getbit
 get value of node as integer 0,-1,0 for lo,hi,x
)
(getnodevalue (1).eq -1 0 .ifelse
).cvx /def

(putbit)
((nodename)value putbit
 set value of node to lo,hi for value=0,#0
)
(0 .eq (lo).load (hi).load .ifelse
).cvx /def

(getword)
(wordspecifier getword
 get a word made up of the values of the nodes given in wordspecifier
 wordspecifier is an array of node names, e.g. [ (bit3)(bit2)(bit1)(bit0) ]
 The node values are right justified in the word
)
((gwarray).exch .def
 (gwbit)15 .def
 0
 gwarray .length 1 .sub -1 0
 ( gwarray .exch .aget getbit
   gwmaskarray gwbit .aget .bitand
   .bitor
   (gwbit) gwbit 1 .sub .def
 ).cvx .for
).cvx /def

(putword)
(wordspecifier word putword
 put a word made up of the values of the nodes given in wordspecifier
 wordspecifier is an array of node names, e.g. [ (bit3)(bit2)(bit1)(bit0) ]
 The node values are right justified in the word
)
((pwword).exch .def
 (pwarray).exch .def
 (pwbit)15 .def
 pwarray .length 1 .sub -1 0
 ( pwarray .exch .aget
   gwmaskarray pwbit .aget pwword .bitand
   putbit
   (pwbit) pwbit 1 .sub .def
 ).cvx .for
).cvx /def

(gwmaskarray) [ -32768 16384 8192 4096 2048 1024 512 256 128 64 32 16 8 4 2 1 ] .def

(listtrans)(3 .copy listetrans listdtrans).cvx .def


(clock1)
(simstep
) .cvx .def

(clock2)
() .cvx .def

(pullup)
((node)pullup
)
(.dup (VDD) dtrans
).cvx /def

(inverter)
((input)(output)inverter
)
(.dup pullup
 (GND) .exch etrans
) .cvx /def

(nand)
((input1)(input2)(output)nand
)
(.dup pullup gensym .dup 4 1 .roll .exch etrans (GND) .exch etrans
) .cvx /def

(nor)
((input1)(input2)(output)nor
)
(.dup pullup .dup 3 1 .roll (GND) .exch etrans (GND) .exch etrans
) .cvx /def

(gensym)
(makes a unique name
)
(6 .string genindex .exch .cvis
 (genindex)genindex 1 .add .def)
.cvx /def
(genindex)0 .def

(gennames)
(Generate node names e.g.
 (in out int) gennames
 would generate 3 JaM variables - in, out, and int, with the string values
 (in#),(out#), and (int#), respectively, where # is the result of a single call
 to gensym
)
(gensym .exch (2 .copy .exch /concat .def).cvx /tokall .pop
).cvx /def

(nodedict) 256 .dict .def
(namedict) 256 .dict .def

(namenode)
(<JaMname><SimMOSname> namenode
 make name by which node will subsequently be known
)
(2 .copy nodedict 3 1 .roll .put
 namedict 3 1 .roll .put
).cvx /def

(node)
(<JaMname> node => <SimMOSname>
)
(nodedict .exch 2 .copy .known
   (.get).load
   (.exch .pop).cvx
 .ifelse
).cvx /def

(name)
(<SimMOSname> name => <JaMname>
)
(namedict .exch 2 .copy .known
   (.get).load
   (.exch .pop).cvx
 .ifelse
).cvx /def

(VDD)(VDD).def
(GND)(GND).def

(dummysimmos) 50 .dict .def
dummysimmos .begin

 (simreset)
 ((simreset) /print).cvx .def

 (circuitreset)
 ((circuitreset) /print).cvx .def

 (etrans)
 ((etrans) : 3 -1 .roll : .exch : : ()/print).cvx .def

 (dtrans)
 ((dtrans) : 3 -1 .roll : .exch : : ()/print).cvx .def

 (hi)
 ((hi) : /print).cvx .def

 (lo)
 ((lo) : /print).cvx .def

 (x)
 ((x) : /print).cvx .def

 (chhi)
 ((chhi) : /print).cvx .def

 (chlo)
 ((chlo) : /print).cvx .def

 (printwatchednodes)
 ((printwatchednodes) /print).cvx .def

 (watch)
 ((watch) : /print).cvx .def

 (unwatch)
 ((unwatch) : /print).cvx .def

 (simstep)
 ((simstep) /print).cvx .def

 (microstep)
 ((microstep) /print).cvx .def

.end

(.prompt)(.displayon (>).print).cvx .def

.end

()/print

simmos