Jump to content

Photo

Camel99 Forth Information goes here

Camel99 Forth Concatentive Programming ANS Forth

180 replies to this topic

#176 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 703 posts
  • Location:The Great White North

Posted Wed Sep 5, 2018 1:41 PM

 

28649 (>6FE9) is, indeed, prime, but >6FE5 (28645) is not.  It is the latter that TI used.  The number (>7AB9) TI used to add to the product of >6FE5 and the value at >83C0 is not prime either.  They do not have any primes in common, however.  I always thought the bit pattern of the two numbers might be important, but I am not sure.

 

It is kind of interesting that the second number is π to 5 places with 1 added to the last place—as though to insure the lowest bit is 1.  In fact the lowest bit of both numbers is 1.

 

...lee

 

 

Good catch.  Moving too fast this morning. I was looking for a close prime number to 6FE5 for the experiment.

 

So the evidence is point to the fact the choosing these internal numbers is important.  


Edited by TheBF, Wed Sep 5, 2018 1:41 PM.


#177 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 703 posts
  • Location:The Great White North

Posted Wed Sep 5, 2018 2:04 PM

Here is a much faster version of your PRNG-testing program that avoids copying the screen from VRAM to CRAM every iteration:

\ Random Screen Fill that avoids using SCAN and whole-screen copying.

VARIABLE BLANK_CNT
VARIABLE ITERATIONS
VARIABLE DUPLICATES 

: WAIT-KEY   BEGIN KEY? UNTIL ;

: UNTILFULL ( -- )
      PAGE
      C/SCR @ BLANK_CNT !     \ initialize to screenfull of blanks
      DUPLICATES OFF
      ITERATIONS OFF
      BEGIN
          C/SCR @ RND DUP VC@
          DUP BL =
          IF
               DROP
               [CHAR] A SWAP VC!
               -1 BLANK_CNT +!      \ decrement blank count
          ELSE
               1+ SWAP VC!
               1 DUPLICATES +!
          THEN
         1 ITERATIONS +!
         BLANK_CNT @ 0=          \ did we hit all the blanks?
      UNTIL
      BEEP
      WAIT-KEY
      PAGE ." Random Screen Fill"
      CR
      CR ITERATIONS @ U. ." iterations"
      CR DUPLICATES @ U. ." duplicates"
;

and here it is converted to fbForth:

Spoiler

 

...lee

 

Not only is it faster, it seems to be accurate.  Back to people management I go.  :_(

Thanks Lee.



#178 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 703 posts
  • Location:The Great White North

Posted Wed Sep 5, 2018 2:30 PM

Here is the little program I use to check the repetition frequency of the PRNG under test.

It uses a 32bit counter because I didn't want to have an overflow.

CREATE DCNT   0 , 0 ,   \ 32bit integer variable, 4 bytes

: DCNT++    ( -- ) DCNT 2@ 1 M+ DCNT 2! ;     \ incr. 32 bit counter
: CLRCNT    ( -- ) 0 0 DCNT 2! ;              \ clear counter
: UD.       ( d -- )  <# #S #>  TYPE SPACE ;  \ print double, unsigned
: .DCNT     ( -- )  DCNT 2@ UD. ;             \ print counter

: NEXTREP    \ find next repetition of Random number
        CLRCNT
        CR ." Searching for:" RNDW DUP  U.
        CR        
         BEGIN
            DCNT++
            RNDW
            OVER =
        UNTIL
        CR  ." Duplicate after "  .DCNT  ." random no.s"  ;

If this is working as I expect, which under Lee's watchful eye am learning is not always the case, :) 

the TI Forth PRNG repeats after 20,000 or so and the GForth method shows 65,536 before a duplicate.

I think using the circular shift limits the TI Forth method, but again, I don't have the math to prove my intuition.

 

Comments welcome.

 

I would never have suspected the intricacies of a PRNG were so great.

I should probably have looked up the current state of the art on testing... oh well, it's a hobby after all.



#179 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 703 posts
  • Location:The Great White North

Posted Fri Sep 7, 2018 3:13 PM

Handle Base File Access Change

 

A while back I discovered a problem with my ANS/ISO File system not selecting properly from one file handle to another file handle.

This is required for example if you wanted to copy data from one file to another file.

 

The files opened correctly, the code was selecting the correct PAB for each open file, but I was not changing the O/S address >8356

(which is called DSRNAM from what I can discover)

 

I did  a kludge fix that involved string processing (yuk!) but the real fix meant adding a new field to the standard PAB.

 

Per the E/A Manual the standard PAB in CAMEL99 Forth is:

 

byte   : opcode

byte   : flag/status

cell    : data buffer address

byte   : record length

byte  : character count (read or written)

cell   : record number

byte  : screen offset (unused)

string: filename  (byte counted string) MAX length in CAMEL99=32 bytes

 

CAMEL99 now has this new field 

cell: DSRNAM   

 

The magic number that the O/S needs in DRSNAM to "select" a file, is the VDP address of the filename string after the  '.' character.

I was doing that correctly  when I created the PAB, but the number was not stored anywhere for fast retrieval.

 

In version 2.0.23 I have added a DSRNAM field to the PAB after the file name buffer. 

When selecting via file handle it is now very simple.

The word SELECT takes the handle and  "selects" the correct VDP PAB address from an array of PABs.

Now it also reaches into the PAB to retrieve the DSR name  and put it into >8356

 

Here is the new code for SELECT with extra comments.

: SELECT  ( hndl -- )
           DUP ?FILES                                   \ test if hndl<= max files
           ]PTAB @ DUP 0= ABORT" Cannot select hndl 0"  \ ]PTAB is array of PAB addresses
           ^PAB !                                       \ store correct PAB in pab pointer 
           [PAB DSRNAM] V@  DSRNAM !  ;                 \ fetch dsrnam from VDP ram, store in CPU ram 

Once I made the decision to alter the PAB structure the rest went quickly.

 

It will get up on GITHUB this weekend.



#180 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 703 posts
  • Location:The Great White North

Posted Wed Sep 12, 2018 2:25 PM

The Ultimate Cure for Your Insomnia

 

The latest version of the manual for Camel99 Forth is up on GitHub.

https://github.com/b...mers Rev1.3.pdf

 

The improvements include

  • Reorganizing sections for clarity
  • Expanded discussion on programming tools and disk utilities
  • Expanded discussion on using Forth Assembler including the use of BLWP from within Forth
  • Expanded discussion on multi-tasking

And oh so much more!

 

It's now 158 pages of fun fun fun!   ;-)

 

That is all.


Edited by TheBF, Wed Sep 12, 2018 2:26 PM.


#181 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 703 posts
  • Location:The Great White North

Posted Mon Sep 17, 2018 4:08 PM

30 Tasks + the Console Running on Camel99 Forth

I have wanted to trying this for a while on this little system.  I always envisioned the multi-tasker to be able to "spawn"  a new task.  That means I need to be able to allocate some memory from somewhere and then setup a new task in that memory block.  In version 2 of the CAMEL99 I wanted a low overhead way to use the low-memory block on the expansion RAM so I did what any Forther would do and turned the memory into a manually controlled stack of memory.  :)

 

Anytime you need some memory you say " n MALLOC" where n is the number of bytes.  Later you can say "n MFREE" to give it back. It's very crude. You can't remove a memory block from the middle of the stack alhough you could re-used it.  Anyway, armed with that I realized I could create as many tasks as the low-memory could hold, up until it smashed into the Forth stacks at the top of low memory.

I can get a maximum of 32.

 

Each task needs 192 bytes and that is called the USER Area.  The constant USIZE returns 192

  • FORK is routine that simply copies the current USER area into a new USER area and sets the 2 stack pointers to the new space.
  • ASSIGN give the task the address of a program to run
  • WAKE sets a flag in the task that it should run.

 

Using the simple MALLOC the routine to SPAWN a new task, with a program passed to it to run, is very simple.

\ create a task in heap, fork it, assign Execution token and run it
: SPAWN  ( xt -- )  
         USIZE MALLOC ( pid) 
         DUP >R FORK
         R@ ASSIGN  
         R> WAKE ;

The spoiler has the demo code which just puts the numbers >DEAD >BEEF on the local stack of each task and increments a global variable called X.

 

The 30tasks video shows the me typing at the console starting everything up and killing it all and doing it again.

You can see how much the console slows down with 30 jobs running.

Each task is set to behave "NICE"ly and not hogging the system too much.  (NICE is a UNIX command that nobody uses. You lookup why) ;)

 

The lowmemtasks video just shows the CLASSIC99 debugger window with all the DEAD BEEF numbers going onto the local stacks of each task as I scroll through a few task blocks.

 

It's a useable thing now.

 

Spoiler

 

Attached Files







Also tagged with one or more of these keywords: Camel99, Forth, Concatentive Programming, ANS Forth

0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users