%option "-nonstandard-nocheck-nodiag-nostack-noline"

%include "MOOSE:MOUSE.INC"

%constinteger procs = 16

%constinteger size = 200 * 11 * 16

%systemintegerfnspec freestore
%systemroutinespec phex(%integer i)
%systemroutinespec phex2(%integer i)

!%externalroutinespec start terminal

%externalroutinespec dump(%integer bytes, %bytename buffer)

%externalintegerfnspec partition read(%integer block, %bytename buffer)
%externalintegerfnspec partition write(%integer block, %bytename buffer)
%externalroutinespec partition enquiry(%integername v, s, h)
%externalroutinespec cache enquiry(%integername crh, crm, cwc, cwm)

%externalroutinespec disc stats(%integername r, w, h)

%externalroutinespec create partition table(%integername x)

%owninteger last time = 0

%ownrecord(semaphore fm) logger = 0
%ownrecord(semaphore fm) mutex = 0
%ownrecord(semaphore fm) wait forever = 0;  ! Never signalled

%routine put2(%integer x)
   %integer t, u
      t = x // 10;  u = x - 10 * t
      print symbol(t + '0')
      print symbol(u + '0')
%end

%routine show time(%integer msecs)
   %integer h, m, s
      s = msecs // 1000
      m = s // 60;  s = s - 60 * m
      h = m // 60;  m = m - 60 * h
      put2(h);  print symbol(':')
      put2(m);  print symbol(':')
      put2(s)
%end

%routine do test(%integer us, start block, partition)
   %integer i, j, next block, last block = -1, total, elapsed time, now
   %owninteger n = 0
   %integer crh, crm, cwc, cwm
   %owninteger last crh = 0, last crm = 0, last cwc = 0, last cwm = 0
   %integer reads, writes, HW
   %owninteger last reads = 0, last writes = 0
   %bytearray buffer(0 : 511)
      next block = start block
      partition = partition << 24
      %cycle
         semaphore wait(logger)
         n = (n + 1) & 255
         %if n = 0 %start
            signal semaphore(logger)
            now = real time
            elapsed time = now - last time
            last time = now
            cache enquiry(crh, crm, cwc, cwm)
            disc stats(reads, writes, HW)
            total = crh - last crh + %c
                    crm - last crm + %c
                    cwc - last cwc + %c
                    cwm - last cwm
            show time(now);  spaces(2)
            write(crh - last crh, 0);  printstring(" CRH, ")
            write(crm - last crm, 0);  printstring(" CRM, ")
            write(cwc - last cwc, 0);  printstring(" CWC, ")
            write(cwm - last cwm, 0);  printstring(" CWM, ")
            last cwm = cwm;  last cwc = cwc
            last crm = crm;  last crh = crh
            write(HW, 0);  printstring(" HW, ")
            write(reads - last reads, 0);  printstring(" R, ")
            write(writes - last writes, 0);  printstring(" W, ")
            !!total = reads - last reads + writes - last writes
            last reads = reads;  last writes = writes
            write(total, 0);  printstring(" T, ")
            write(1000 * total // elapsed time, 0)
            printstring(" t/s")
            newline
            !put long(1000 * total // elapsed time)
            !put string(" t/s");  put sym(NL)
         %else
            signal semaphore(logger)
         %finish
         next block = rem((53 * next block + 65539) & 16_7FFFFFFF, size)
         buffer(i) = (next block + i) & 255 %for i = 0, 1, 511
         i = partition write(next block ! partition, buffer(0))
         %if i # 0 %start
            printstring("Write block ");  write(next block, 0)
            printstring(" status ");  phex(i);  newline
            !put string("Write block ");  put long(next block)
            !put string(" status ");  put long(i)
            !put sym(NL)
         %finish
{>>>>>>} last block = next block
         %if last block >= 0 %start
            i = partition read(last block ! partition, buffer(0))
            %if i = 0 %start
               %for i = 0, 1, 511 %cycle
                  %if buffer(i) # (last block + i) & 255 %start
                     printstring("Error: block ");  write(last block, 0)
                     printstring(" byte ");  write(i, 0)
                     printstring(" expecting ")
                     write((last block + i) & 255, 0)
                     printstring(" got ");  write(buffer(i), 0)
                     printstring(" address ");  phex(addr(buffer(i)))
                     printstring(" value ")
                     newline
                     !! dump(512, buffer(0))
                     %exit
                  %finish
               %repeat
            %else
               printstring("Read block ");  write(last block, 0)
               printstring(" status ");  phex(i);  newline
               !put string("Read block ");  put long(next block)
               !put string(" status ");  put long(i)
               !put sym(NL)
            %finish
         %finish
         last block = next block
      %repeat
%end

%routine run one
   %owninteger p = 0
   %owninteger x = 0
   %owninteger n = 0
   %integer pp, xx, us
      open output(0, ":")
      select output(0)
      semaphore wait(mutex)
      x = rem(73 * x + 7654321, size)
      p = p + 1;  p = 1 %if p > 3
      pp = p;  xx = x
      n = n + 1;  us = n
      signal semaphore(mutex)
      !! write(us, 0)
      !! printstring(" starting with ");  write(pp, 0)
      !! printstring(" and ");  write(xx, 0);  newline
      do test(us, xx, pp)
%end

%begin
   %integer v, s, h, i
   %record(process fm)%name p
   %label x
      i = set SR(0);  ! Interrupts on
!      start terminal
      setup semaphore(logger)
      setup semaphore(mutex)
      setup semaphore(wait forever)
      open output(0, ":");  select output(0)
      !! printstring("Priority -> 2");  newline
      set priority(nil, 2)
      !! printstring("Waiting");  newline
      %for i = 1, 1, 80000 %cycle;  %repeat
      !! printstring("Done");  newline
      {} create partition table(s);  !<<<<<<<<<<<<<<<<
      {} printstring("Partition size is ");  write(s, 0)
      {} newline
      signal semaphore(logger)
      printstring("Free store: ");  write(free store, 0)
      newline
      ! Find out what's there
      partition enquiry(v, s, h)
      printstring("Valid:     ")
      %for i = 0, 1, 31 %cycle
         write(i, 1) %if v & (1 << i) # 0
      %repeat
      newline
      printstring("Structured:")
      %for i = 0, 1, 31 %cycle
         write(i, 1) %if s & (1 << i) # 0
      %repeat
      newline
      printstring("Hazarded:  ")
      %for i = 0, 1, 31 %cycle
         write(i, 1) %if h & (1 << i) # 0
      %repeat
      newline
      last time = real time
      show time(last time)
      printstring("  Create ");  write(procs, 0);  newline
      %for i = 1, 1, procs %cycle
         p == create process(8192, addr(x), 2, nil)
         !! write(i, 0);  printstring("th Freestore = ")
         !! write(freestore, 0);  newline
      %repeat
      i = real time
      show time(i);  spaces(2)
      write({real time} i - last time, 0);  printstring("ms for")
      write(procs, 1);  printstring(" procs, free store now ")
      write(free store, 0)
      newline
      signal semaphore(mutex)
      semaphore wait(wait forever)
      %stop;  !<<<<<<<<<<<<<<<
x:    run one
%end %of %program      
