!******************************************************************************!
! Test case for GCONTROL PIPEMON (and is a very simple benchmark of pipe
! performance of various commands (NOOP, WAVEFORM, FFT).
!
! Arguments: tmpfile optional temporary file name to copy srcfile into for used
!                    with noop/wrap defaults to file in ram for optimal performance,
!                    but can be set to file copying from disk to pipe performance
!            srcfile optional source (input) file to use for NOOP/wrap output pipe
!
! NOTE: Increasing the pipe size (for waveform and fft via the /PS= switch or
!       {PS=} file qualifier can dramatically increase the data rate.
!       Increasing the poll time via the /POLL= switch can improve performance
!       of the waveform and fft pipes.
!
! NOTE2: In non-interactive run mode via /interactive=false switch, this runs
!        for /duration seconds.
!
! @author:  Neon Ngo
!******************************************************************************!
startmacro s:tmpfile["ram:ramfile"] s:srcfile["nxm.sys.dat.sinewave.prm"]
  switch INTERACTIVE interAct GET DEF=TRUE  SDEF=TRUE  ! for normal interactive test(s)
  switch BASELINE    baseline GET DEF=FALSE SDEF=TRUE  ! for defects or more obscure test case(s)

  call setDatDir
  invoke srcfile srcfile.replace("nxm.sys.dat",^{datDir})

  ! Switches to control WAVEFORM command
  switch FORMAT      format   GET "SF"
  switch SRATE       sr       GET 1e5
  switch SFREQ       sfreq    GET sr/10
  switch AMP         amp      GET 1e4
  ! Switches to control FFT command
  switch OVER        over     GET 0
  switch NEXP        nexp     GET 1
  switch NAVG        navg     GET 1
  switch NFFT        nfft     GET 1k
  ! Switches for non-interactive benchmarking
  switch DURATION    duration  GET 15
  switch INTERVAL    interval  GET 5
  switch CALCNFORM   calcNForm GET "###0.0###"
  ! Switch to control verbose output
  switch VERBOSE     verbose   GET DEF=FALSE SDEF=TRUE

  ! variables used to calculate average pipe data rate at end
  set count 0
  set noopDataRateSum 0
  set waveDataRateSum 0
  set n2f_DataRateSum 0  ! noop to fft
  set fft_DataRateSum 0

    set instructions &
      "1. Four pipe monitors should be shown below.\n&
       2. All but the third one should have data rate shown (FYI: it is in MBytes/sec)\n&
       3. Right click on it to toggle the data rate.\n&
       4. Middle click on it to toggle the slider bar.\n&
       5. Cycle through pipes by clicking on the up or down arrow (in middle). There should be no Exceptions in terminal.\n&
       6. Click on pipe name (e.g. _NOOP), ramfile should NOT be in the Select Pipe list. Current Pipe should be highlighted."

    noop srcfile tmpfile
    pipe on
      noop/wrap tmpfile _noop
      waveform _wave format inf sin freq=sfreq amp=amp delta=1/sr
      noop/wrap tmpfile _noop_to_fft
      fft/dbf _noop_to_fft _fft nfft=nfft navg=navg over=over

      ! need to grab data rate from existing pipes, as first grab will always be around zero
      set tmp ram._noop.rate
      set tmp ram._wave.rate
      set tmp ram._noop_to_fft.rate
      set tmp ram._fft.rate

if interAct then
      panel/msgid=MAIN/setup/controls=gc
      gcontrol label macro "Test MACRO"
      gcontrol menu  main "Exit with Status =" "PASS,FAIL" TABLE={ItemColors={PASS="GREEN",FAIL="RED"}} /tleft

      gcontrol text  idtext "Instructions" instructions 24 15 /title

      gcontrol pipemon pmon1 _noop /flags=+ShowRate
      gcontrol pipemon pmon2 _wave /flags=+ShowRate
      gcontrol pipemon pmon3 _noop_to_fft
      gcontrol pipemon pmon4 _fft /flags=+ShowRate

      ! in interactive mode, don't have a stop time (so set to infinity)
      set d:stopTime infinity
else
      ! non-interactive benchmark mode
      timex now startTime
      calc stopTime startTime duration +
      info "Benchmarking pipe (NOOP, WAVEFORM, FFT) every ^interval seconds for minimal duration of ^duration seconds."
endif
      set this.timer(0) interval

    pipe off

  ! display average data rate (only if we have at least interval count)
  if count > 0 then
    info "Average pipe data rates (MBytes/sec = 1e6 bytes/sec)"
    if verbose then
      calc/nform=calcNForm/verbose noop_Ave_DataRate noopDataRateSum count /
      calc/nform=calcNForm/verbose wave_Ave_DataRate waveDataRateSum count /
      calc/nform=calcNForm/verbose n2f__Ave_DataRate n2f_DataRateSum count /
      calc/nform=calcNForm/verbose fft__Ave_DataRate fft_DataRateSum count /
    else 
      calc/nform=calcNForm noop_Ave_DataRate noopDataRateSum count /
      calc/nform=calcNForm wave_Ave_DataRate waveDataRateSum count /
      calc/nform=calcNForm n2f__Ave_DataRate n2f_DataRateSum count /
      calc/nform=calcNForm fft__Ave_DataRate fft_DataRateSum count /
    endif
  endif

endmacro

!******************************************************************************!
! Main process message for this macro. Should be right after the ENDMACRO.
!******************************************************************************!
procedure processMessage m:msg
  if msg.name eqs "MAIN" then
    assert/text="^reg.main.name: User indicated tests" msg.data eqss "PASS"
    pipe stop
  elseif msg.name eqs "TIMER" then
    ! convert Pipe's bytes/sec rate to MBytes/sec to match PIPEMON's units
    if verbose then
      calc/verbose noopDataRate ram._noop.rate 1e-6 *
      calc/verbose waveDataRate ram._wave.rate 1e-6 *
      calc/verbose n2f_DataRate ram._noop_to_fft.rate  1e-6 *
      calc/verbose fft_DataRate ram._fft.rate  1e-6 *
    else
      calc noopDataRate ram._noop.rate 1e-6 *
      calc waveDataRate ram._wave.rate 1e-6 *
      calc n2f_DataRate ram._noop_to_fft.rate  1e-6 *
      calc fft_DataRate ram._fft.rate  1e-6 *
    endif
    ! calculations for average data rate at end
    calc count count 1 +
    calc noopDataRateSum noopDataRateSum noopDataRate +
    calc waveDataRateSum waveDataRateSum waveDataRate +
    calc n2f_DataRateSum n2f_DataRateSum n2f_DataRate +
    calc fft_DataRateSum fft_DataRateSum fft_DataRate +
    if msg.data > stopTime then
      ! time to stop benchmark
      pipe stop
    endif
  else
    say "Unhandled message name: ^msg.name from fid: ^msg.fid data: ^msg.data"
  endif
return

!******************************************************************************!
! If an unexpected exception is caught, mark test as failed, unless it is expected
!******************************************************************************!
procedure processException m:emsg
  if expectedException REXISTS then
    assert/text="^reg.main.name: Expected ERROR starts with: ^{expectedException}" expectedException EQSS emsg.data.message
    remove expectedException
  else
    assert/text="^reg.main.name: Caught unexpected exception ^{emsg.data}" "FALSE" isTrue
    if "Trace" SUBS ENV.DEBUG then invoke ,, emsg.data.printStackTrace()
  endif
return

!******************************************************************************!
! Set the dat directory
!******************************************************************************!
procedure setDatDir
  invoke nxmMajor env.nmversion.subString(0,1)
  invoke major java.lang.Integer.valueOf(nxmMajor)
  if major GE 4 then
    invoke s:datDir           nxm.sys.test.DatLocator.getDatDirLocation()
    invoke s:datDirSlash      nxm.sys.test.DatLocator.getDatDirSlashLocation()
    invoke z:sysDatFull       nxm.sys.test.DatLocator.sysDatFull()
    invoke z:sysTestDatExists nxm.sys.test.DatLocator.sysTestDatExists()
  else
    set s:datDir           "nxm.sys.dat"
    set s:datDirSlash      "nxm/sys/dat"
    set z:sysDatFull       true
    set z:sysTestDatExists false
  endif
return
