Shop OBEX P1 Docs P2 Docs Learn Events
Catalina - ANSI C and Lua for the Propeller 1 & 2 - Page 12 — Parallax Forums

Catalina - ANSI C and Lua for the Propeller 1 & 2

11012141516

Comments

  • RossHRossH Posts: 5,477

    @evanh said:
    Isn't that just using the system ticks variable, after waiting on human input, to produce a seed? That shouldn't be hard to replicate.

    After a P1 reset the system ticks variable is always the same when the program starts executing. Asking for user input adds some randomness to the timing before the system timer is consulted. The P2 has a source of randomness I could use - but the P1 doesn't have such a thing (AFAIK).

    Ross.

  • evanhevanh Posts: 16,029
    edited 2024-04-13 01:24

    I'm lost. Is the user input not an option?

    PS: The Prop2's startup seed comes from ADC sampling noise I think.

    EDIT: Yep ... Ha, it just samples the bitstream direct. 50 x 31 bits = 1550 random bits.

    ' Seed xoroshiro 128** using delta-sigma ADC bits from calibration mode
    '
            wrpin   ##$00100000,#rx_pin 'put rx pin in adc gio calibration mode
    
            mov x,#50           'ready to seed 50 times with 31 bits
    
    .seed       rep #2,#31          'get 31 bits (31*4 clocks = 124/20 = ~6us)
            testp   #rx_pin     wc
            rcl y,#1
    
            bith    y,#31           'seed via hubset
            hubset  y
    
            djnz    x,#.seed
    
            wrpin   #0,#rx_pin      'return rx pin to normal mode
    

    EDIT2: I think Xoroshiro 128** is a typo on Chip's behave. I'm pretty sure that was the original Xoroshiro 128+ algorithm used to make the free-running global generator. Dunno why he typed a double asterisk.

    EDIT3: The mark-space ratio of GIO level will be around 20% ones to 80% zeros. There will be aliasing beat patterns with patches of all zeros in the sysclock/4 sampling. Still, no two will be the same.

  • RossHRossH Posts: 5,477
    edited 2024-04-13 01:41

    @evanh said:
    I'm lost. Is the user input not an option?

    Yes, that's why I do it.

    But I would like not to have to add a line like that to every P1 program that needs random numbers.

    EDIT: For instance, what if the program does not otherwise require any user input? How to seed a random number generator on the P1 in that case?

  • evanhevanh Posts: 16,029
    edited 2024-04-13 02:26

    Right, I thought you were targetting compatibility for those old programs is all.

    Using only built-in features of the Prop1 might be tricky alright .... maybe trying spamming a counter's PLL divider to keep it unstable ... but that would need to use a pin for output I suspect ... could momentarily use the comms TX pin if no other was suitable.

    EDIT: Ah, not the divider, that's just a post-VCO divider. It's the PLL's input coming from the main PHSx counter that is important for stability of the VCO in the PLL. So spamming lots of changes to FRQx to upset the PLL's reference frequency should then keep the PLL unstable. Just toggling between two target frequencies should be enough.

  • evanhevanh Posts: 16,029

    Then just have to collect the output. It could be done like Chip did in the Prop2 - treat the pin as bitstream directly. Or another way might be take timing measurements with the second counter.

  • @evanh said:
    Using only built-in features of the Prop1 might be tricky alright .... maybe trying spamming a counter's PLL divider to keep it unstable ... but that would need to use a pin for output I suspect ... could momentarily use the comms TX pin if no other was suitable.

    EDIT: Ah, not the divider, that's just a post-VCO divider. It's the PLL's input coming from the main PHSx counter that is important for stability of the VCO in the PLL. So spamming lots of changes to FRQx to upset the PLL's reference frequency should then keep the PLL unstable. Just toggling between two target frequencies should be enough.

    This sounds like what Chip's RealRandom object does: https://obex.parallax.com/obex/real-random/

  • evanhevanh Posts: 16,029
    edited 2024-04-13 04:28

    Huh, yeah, same idea but different implementation. Also somehow is extracting the random bits from the PHSx register. That implies PHSx is in some way integral to the VCO loop inside the PLL. Or is maybe looped back from the PLL output. I don't know enough about the Prop1 to understand the detail.

    EDIT: Ahhh, the video out can be driven by a counter. So it's the WAITVID instruction that is sampling the counter's PLL jitter. Chip is just looping that back in with the ADD PHSA,CNT

  • RossHRossH Posts: 5,477

    @Electrodude said:

    This sounds like what Chip's RealRandom object does: https://obex.parallax.com/obex/real-random/

    Aha! I didn't know about that object. I'll investigate incorporating it. Thanks.

    Ross.

  • RossHRossH Posts: 5,477
    edited 2024-04-24 23:11

    Catalina 7.3 has been released here.

    This is a full release. I was embarrassed not to have known about Chip's RealRandom object so I thought I had better put out a new release to incorporate it. The addition of the new RANDOM plugin is the only significant new feature, and it is only required on the Propeller 1. I use it in Dumbo Basic to eliminate the need to ask for user input when seeding the random number generator.

    Here is the relevant extract from the README.TXT:

    RELEASE 7.3
    
    New Functionality
    -----------------
    
    1. A new random number plugin has been added for the Propeller 1, based on
       Chip Gracey's RealRandom.spin. The plugin is enabled by defining the 
       Catalina symbol RANDOM. For example:
    
          catalina ex_random.c -lci -C RANDOM
    
       Note that a random number generator is built into the Propeller 2, so the 
       plugin is not required on that platform. The RANDOM plugin occupies a
       cog on the Propeller 1. It generates random data continuously, and writes
       a new 32 bit random number to the second long in its registry entry 
       approximately every 100us (at 80Mhz).
    
       C provides a pseudo random number generator called rand() and this must
       be seeded using the srand() function, otherwise it will always return
       the same sequence of pseudo random numbers.
    
       In previous releases, the getrand() function was a "stopgap" function -
       it generated true random data on the Propeller 2, but on the Propeller 1 
       it only generated pseudo random data, seeded by the system clock. However, 
       there are good reasons to have both a pseudo random number generator and 
       a true random number generator, so with the addition of the new Propeller 
       1 RANDOM plugin, getrand() has been modified to always generate 32 bit 
       pseudo random numbers seeded by the system clock on both the Propeller 1 
       and 2, and a new getrealrand() function has been added which returns a 32
       bit true random number on both the Propeller 1 and 2 (provided the RANDOM 
       plugin has been loaded on the Propeller 1). If the RANDOM plugin has not 
       been loaded (which may be because there is not a spare cog available) on 
       the Propeller 1 then getrealrand() uses the same technique as getrand().
    
       The new getrealrand() function will generate unique random numbers in 
       situations where the Propeller 1 previously would not, such as if a 
       program was automatically started immediately after power up. In such 
       situations the system clock would be reset, so the previous technique 
       of seeding a pseudo random number generator with the system clock would 
       always generate the same sequence of pseudo random numbers. 
    
       Here is a summary of the random number routines:
    
         rand(), srand()      -> rand() generates pseudo random numbers, in the
                                 range 0 to MAX_RAND (32767), and srand() can
                                 be used to seed the random number generator
    
         getrand()            -> getrand() generates 32 bits of pseudo random
                                 data using rand(). On first call it also seeds 
                                 the random number generator using srand() and
                                 the current system clock. This avoids the need
                                 to explicitly call srand()
    
         getrealrand()        -> getrealrand() returns 32 bits of random data. 
                                 On the Propeller 1 this will be true random data
                                 if the RANDOM plugin is loaded, otherwise it
                                 will use the same technique as getrand(). On the
                                 Propeller 2 it always returns true random data.
    
       The program ex_random.c in demos/examples has been updated to demonstrate 
       both rand() and getrand() (which both generate pseudo random numbers) as 
       well as the getrealrand() function (which generates true random numbers).
    
    2  Dumbo Basic has been updated to allow the use of the new getrealrand()
       function (described in point 1, above). A new RANDOM option has been
       added to the RANDOMIZE statement to seed Basic's built in pseudo random 
       number generator with getrealrand(). 
    
       Here are all the RANDOMIZE options:
    
          RANDOMIZE            -> prompt for the seed
          RANDOMIZE TIMER      -> use the the current time as the seed
          RANDOMIZE <expr>     -> use <expr> as the seed
          RANDOMIZE RANDOM     -> use getrealrand() as the seed (on the P2,
                                  or when compiled with RANDOM on the P1) or 
                                  else prompt for the seed (note this is an
                                  extension to GW Basic).
    
       The RND function has been extended to allow for the generation of either
       pseudo random or true random numbers. Instead of just RND, use RND(x) 
       where ...
         x > 0 generates the next pseudo random number
         x = 0 returns the last random number generated (pseudo or true)
         x < 0 generates a true random number (note this is an extension to GW 
               Basic, where x < 0 reseeds the random number generator - but
               that can also be done using the RANDOMIZE statement).
    
       Dumbo Basic now enables the RANDOM plugin by default when built for the
       Propeller 1, and the basic demo programs poker.bas, blackjck.bas, 
       startrek.bas and ut-trek.bas have been updated to use the RANDOM option
       of the RANDOMIZE statement instead of the TIMER option, which depended 
       on variations in user input to generate a random seed.
    
    3. Dumbo Basic's USING clause (used in PRINT, PRINT# and LPRINT statements)
       now accepts more GW Basic format options:
    
          + : a '+' indicates a leading sign will be printed (i.e. '+' or '-')
              except as noted for '-' (below). The '+' also counts as another 
              digit in the output. In GW Basic the '+' must be in the first 
              position of the USING clause, but in Dumbo Basic it can appear 
              in any position before any decimal point (the actual position
              makes no difference - the sign will always be printed immediately
              before the number). Note that (unlike GW Basic) Dumbo Basic always
              prints a sign for negative numbers - adding '+' makes it also 
              include a leading sign for positive numbers.
    
          - : a '-' anywhere in the clause indicates a trailing sign will be
              printed for negative numbers. The '-' does NOT count as another
              digit in the output - if the number is not negative, a space
              will be printed in its place. In GW Basic the '-' must be
              in the last position of the USING clause, but in Dumbo Basic 
              it can be in any position (the actual position makes no 
              difference - the '-' will always be printed immediately after 
              the number). If both '+' and '-' are included in the same USING 
              clause then the '+' is just treated as another digit position. 
    
          ^^^^ : a '^^^^' anywhere in the clause indicates an exponent of form
              'ESNN' will be used, where E is the letter 'E', S is the sign 
              of the exponent and NN is the 2 digit exponent. The '^' 
              characters do NOT count as additional digits - they always
              indicate an exponent. In GW Basic the '^^^^' must appear at 
              the end of the USING clause, but in Dumbo Basic it can be in 
              any 4 consecutive positions. The actual position makes no
              difference.
    
       For example, the statements:
          PRINT USING "##.#^^^^"; 0.001 
          PRINT USING "+#.#^^^^"; 0.001 
          PRINT USING "##.#^^^^"; -0.001 
          PRINT USING "+#.#^^^^"; -0.001 
          PRINT USING "+#.#^^^^-"; 0.001 
          PRINT USING "##.#^^^^-"; -0.001 
          PRINT USING "+#.#^^^^-"; -0.001 
    
       would result in the following output:
           1.0E-03
          +1.0E-03
          -1.0E-03
          -1.0E-03
          +1.0E-03
           1.0E-03-
           1.0E-03-
    
    Other Changes.
    --------------
    
    1. The pseudo random number generator getrand() was returning only 31 bits
       of random data, not 32. Affected the Propeller 1 only.
    
    2. Dumbo Basic was not correctly keeping track of the current position in the 
       current line of output, which meant using ',' as a separator to move to 
       the next 14 character print zone did not always end up with the output in 
       the correct position. Affected Dumbo Basic on the Propeller 1, Propeller 2,
       and also on Windows and Linux.
    
    3. All the Dumbo Basic example programs are now UNIX format files, not DOS
       format files. This makes them easier to edit using vi on Catalyst, which 
       expects UNIX format files by default. Affected Dumbo Basic on the Propeller
       1, Propeller 2, and also on Windows and Linux.
    

    It's been so long since I added a new Propeller 1 plugin that I made notes as I figured out how to do it all over again. Catalina's registry architecture is well suited to this kind of plugin, so this was possibly the easiest one I have ever added - which makes it ideal to document for future reference:

    These instructions show the steps used in creating the new RANDOM plugin and
    making it accessible via a new C library function.
    
    Note that these instructions only include details for adding the plugin to
    the Propeller 1 default target (which is in the directory 'target\p1'), but
    similar steps apply to other other targets that also need to include the new 
    plugin (such as the embedded target which is in directory 'embedded\p1'). 
    
    Also note that the details for adding new plugins to Propeller 2 targets are
    similar in concept but differ in detail, but are not included because the 
    RANDOM plugin is only applicable to the Propeller 1.
    
    Step 1. Create the plugin from the existing Spin file
    
       In this case the file target\p1\Catalina_RND_plugin.spin
       was created from RealRandom.spin by adding code to register 
       the plugin on start up, and to write the results back to the 
       registry instead of a Spin variable. Examine these two files 
       for more details.
    
    Step 2. Define a constant for the plugin
    
       Plugin constants are defined in the Spin file:
    
          target\p1\Catalina_Common.spin
    
       where the following was added:
    
          LMM_RND = 32      ' Random Number Generator
    
       and also in the C file:
    
          source\lib\include\plugin.h
    
       where the following was added:
    
          #define LMM_RND 32
    
    Step 3. Define a name for the plugin
    
       Plugin names (e.g. used when printing the registry)
       are defined in:
    
          source\lib\catalina\plugname.c
    
       where the following was added:
    
          case LMM_RND  : return "Random Number Generator";
    
    Step 4. Add the plugin to Extras.spin
    
       Extra plugins are loaded from the file:
    
         target\p1\Extras.spin
    
       where the following was added to the OBJ declarations:
    
          #ifdef RANDOM
            RND : "Catalina_RND_Plugin"
          #endif
    
       and the following was added to the Setup function:
    
          #ifdef RANDOM
            RND.Setup
          #endif
    
       and the following was added to the Start function:
    
          #ifdef RANDOM
            RND.Start
          #endif
    
    Step 5. Define a function to access the plugin
    
       In this case, the function was defined in:
    
          source\lib\include\prop.h
    
       where the following was added:
    
          int getrealrand();
    
    Step 6. Write a function to access the plugin
    
       In this case the function was created in:
    
          source\lib\catalina\getrealrand.c
    
       where the following code was added to locate the plugin in the 
       registry and (if found) read a new random number from the 
       appropriate registry entry:
    
          #include <prop.h>
          #include <plugin.h>
    
          int getrealrand() {
             static int cog = -1;
             static request_t *request_block = NULL;
             static int last_random = 0;
             int new_random = 0;
    
             if (cog == -1) {
                cog = _locate_plugin(LMM_RND);
                if (cog >= 0) {
                   request_block = REQUEST_BLOCK(cog);
                }
             }
             if (request_block) {
                // RANDOM plugin loaded - wait for a new random
                while ((new_random == 0) || (new_random == last_random)) {
                  new_random = request_block->response;
                }
                last_random = new_random;
             }
             else {
                // RANDOM not loaded - fall back to getrand()
                new_random = getrand();
                last_random = new_random;
             }
             return new_random;
          }
    
    Step 7. Modify the relevant Makefile to build the library function
    
       In this case the relevant Makefile is:
    
          source\lib\catalina\Makefile
    
       where the following line was added:
    
          getrealrand.s \
    
    Step 8. Rebuild the C library
    
       In the directory:
    
          source\catalina\lib
    
       execute the following command:
    
          build_all
    

    Ross.

  • RossHRossH Posts: 5,477
    edited 2024-04-27 03:55

    Deleting this post as it has been superseded by the Catalina 7.3.1 patch release.

    Ross.

  • RossHRossH Posts: 5,477

    Catalina 7.3.1 has been released here.

    This is a patch release that must be installed over an existing Catalina 7.3 installation.

    Here is the relevant extract from the README.TXT:

    RELEASE 7.3.1
    
    New Functionality
    -----------------
    
    1. None.
    
    Other Changes.
    --------------
    
    1. When the alloca() function was added (release 7.0) it increased the stack
       requirements for all programs very slightly, but the stack sizes allocated
       for Factories in the Multi-Processing version of Lua was not updated. This
       led to various issues but the most obvious was that Lua programs that tried
       to use the sbrk function to defragment the C heap would not run correctly. 
       Affected the Propeller 2 only.
    
  • evanhevanh Posts: 16,029
    edited 2024-04-27 06:12

    It would be quite feasible to make the random routine into a library only call without the need for another cog. Obviously such an implementation will consume processing time and use the counterA+vid hardware of the cog it runs on, but I'd suspect those will generally not be in use on the primary C cog anyway.

  • RossHRossH Posts: 5,477
    edited 2024-04-27 22:16

    Something I have meant to do on every release, and keep forgetting ...

    The two Lua versions of Startrek (star.lua and star-tos.lua) both contain code that deliberately slows down the program output. The intention is to simulate how the game would have appeared on an old slow teletype terminal. Amusing, but a nuisance on a screen. To disable this, use the vi text editor and find the line that says:

    DisableTeleprint = false

    and change it to ...

    DisableTeleprint = true

    Now, go save the Federation! :)

  • RossHRossH Posts: 5,477

    @evanh said:
    It would be quite feasible to make the random routine into a library only call without the need for another cog. Obviously such an implementation will consume processing time and use the counterA+vid hardware of the cog it runs on, but I'd suspect those will generally not be in use on the primary C cog anyway.

    Yes. Also, it would be good enough for most purposes to just generate one truly random number on startup, to use as a seed for the pseudo random number generator. Then re-use the cog.

    Either or both of these might make it into a release at some point. But at least Catalina now has an option for a real random number generator on the Propeller 1, which was something that was missing.

  • RaymanRayman Posts: 14,754

    @RossH Did you ever take a stab at compiling Micropython? Or, is it not ansi compliant enough for that?

  • RossHRossH Posts: 5,477

    @Rayman said:
    @RossH Did you ever take a stab at compiling Micropython? Or, is it not ansi compliant enough for that?

    No, I've not tried it. My understanding (but keep in mind that I am not a Python expert) is that Python is written in ANSI C, but Micropython is not.

    Ross.

  • RaymanRayman Posts: 14,754

    Ok, I'm pretty sure it's C, but haven't seen the term ANSI there...

  • RossHRossH Posts: 5,477
    edited 2024-05-17 12:42

    @Rayman said:
    Ok, I'm pretty sure it's C, but haven't seen the term ANSI there...

    If it's coded in what is commonly referred to as 'clean C' (which is the subset of C and C++ that any C or C++ compiler will compile successfully) then it could be converted to ANSI C without much effort.

    But if you want a modern multi-paradigm scripting language, I'd choose Lua over Python any day. And we already have Lua on the Propeller.

    Ross.

  • evanhevanh Posts: 16,029

    Moved from topic - https://forums.parallax.com/discussion/comment/1559583/#Comment_1559583

    @RossH said:
    One more question - did you follow all the instructions in BUILD.TXT? In particular, before doing ./build_all, did you build awka? The version of awka in the distribution may depend on GLIBC 2.34 but you should be able to rebuild it to use whatever version you have installed:

       cd $LCCDIR/source/catalina/awka-0.7.5
       ./configure CFLAGS="-m32"
       make
    

    Thanks, no, I'd only read the README.Linux file at that stage. Got it compiled now. :)

    Testing with "hello_world.c" and I've managed to upset Payload in two ways already:

    • First, I used my usual way of exiting from terminal mode in Loadp2, which is CTRL-Z, and this leaves the comport dangling and can't be used again. Power-cycling the USB connection to the Prop2 Eval Board reassigns a new port to the device and can be used there.
    • Second, Payload only appears to work with /dev/ttyXXXX port names. If I try to specify something like /dev/serial/by-id/usb-XXXX then it won't find the port.
  • RossHRossH Posts: 5,477

    @evanh said:
    Moved from topic - https://forums.parallax.com/discussion/comment/1559583/#Comment_1559583

    @RossH said:
    One more question - did you follow all the instructions in BUILD.TXT? In particular, before doing ./build_all, did you build awka? The version of awka in the distribution may depend on GLIBC 2.34 but you should be able to rebuild it to use whatever version you have installed:

       cd $LCCDIR/source/catalina/awka-0.7.5
       ./configure CFLAGS="-m32"
       make
    

    Thanks, no, I'd only read the README.Linux file at that stage. Got it compiled now. :)

    Testing with "hello_world.c" and I've managed to upset Payload in two ways already:

    • First, I used my usual way of exiting from terminal mode in Loadp2, which is CTRL-Z, and this leaves the comport dangling and can't be used again. Power-cycling the USB connection to the Prop2 Eval Board reassigns a new port to the device and can be used there.
    • Second, Payload only appears to work with /dev/ttyXXXX port names. If I try to specify something like /dev/serial/by-id/usb-XXXX then it won't find the port.

    The CTRL-Z issue is not to do with payload. In a linux bash shell, CTRL-Z puts the active process in the background (i.e. it suspends it). To resume it, use the command "fg".

    You should be able to use the -p option of payload to specify the port by name. For instance, I can say:

    payload -i hello_world -p /dev/ttyUSB0

    Try the command payload -v and tell me if it prints your ports correctly. For instance, here is what I get:

    Catalina Payload 7.0
    verbose mode
    
    usage: payload [options] propeller_file [catalina_file ...]
    
    options:  -? or -h  print this helpful message and exit (-v for more help)
              -a port   find ports automatically, starting from specified port
              -A key    set attention key (default is 1, 0 disables)
              -b baud   use specified baudrate
              -B baud   same as -b
              -c cpu    cpu destination for catalina download (default is 1)
              -d        diagnostic mode (-d again for more diagnostics)
              -e        program the EEPROM with the program loaded
              -f msec   set interfile delay in milliseconds (default is 500)
              -g c,r    set terminal columns and rows - default is 80,24
              -i        interactive mode - act as terminal after load
              -I term   interactive mode - run program 'term' after load
              -j        disable lfsr check altogether
              -k msec   set interpage delay in milliseconds (default is 0)
              -K msec   set key delay time in milliseconds (default is 25)
              -l        use old style lfsr check (slower) 
              -L name   execute the named Lua script after opening the port
              -m max    set max_attempts (default is 5)
              -n msec   set sync timeout in milliseconds (default is 100)
              -o vers   override Propeller version detection (vers 1 = P1, 2 = P2)
              -p port   use port for downloads (just first download if -s used)
              -q mode   line mode (1=ignore CR,2=ignore LF,4=CR to LF,8=LF to CR,
                                   16=CR to LF on output - modes can be combined!)
              -r msec   set reset delay in milliseconds (default is 0)
              -s port   switch to port for second and subsequent downloads
              -S msec   set YModem char delay time in milliseconds (default is 0)
              -t msec   set read timeout in milliseconds (default is 1000)
              -T msec   set YModem timeout in milliseconds (default is 3000)
              -u msec   set reset time in milliseconds (default is 15)
              -v        verbose mode (or include port numbers in help message)
              -w        wait for a keypress between each load
              -x        do catalina download only (boot loader already loaded)
              -y        do not display download progress messages
              -z        double reset
    
    port can be:
               1 = /dev/ttyS0
               2 = /dev/ttyS1
               3 = /dev/ttyS2
               4 = /dev/ttyS3
               5 = /dev/ttyS4
               6 = /dev/ttyS5
               7 = /dev/ttyS6
               8 = /dev/ttyS7
               9 = /dev/ttyS8
              10 = /dev/ttyS9
              11 = /dev/ttyS10
              12 = /dev/ttyS11
              13 = /dev/ttyS12
              14 = /dev/ttyS13
              15 = /dev/ttyS14
              16 = /dev/ttyS15
              17 = /dev/ttyUSB0
              18 = /dev/ttyUSB1
              19 = /dev/ttyUSB2
              20 = /dev/ttyUSB3
              21 = /dev/ttyUSB4
              22 = /dev/ttyUSB5
    

    So I can also use the command:

    payload -i hello_world -p 17

  • RossHRossH Posts: 5,477
    edited 2024-05-19 06:37

    Catalina 7.4 has been released here.

    This is a full release. The main purpose of this release is to include some performance enhancements that I have been working on in the background. The enhancements are specific to Propeller 2 XMM programs. Speed improvements of between 10% and 25% are typical, depending on the program itself.

    I have hopes for further improvements, but I was getting tired of trying to keep multiple streams of development going, and I thought the enhancements had reached a point where it was worth bringing them into the main release stream so that I did not have to do that any more.

    See the README.TXT for more details. Note that the improvements are not enabled by default - you have to explicitly enable them when you compile your program.

    Here is the relevant extract from the README.TXT:

    RELEASE 7.4
    
    New Functionality
    -----------------
    
    1. Two new benchmarks (Whetstone & Dhrystone) have been added in the
       demos\benchmarks folder.These are used to help assess the improvements 
       in XMM performance and also the new XMM options added in this release 
       (see point 2 below). The existing benchmarks (fibo.c and ackerman.c) were 
       not very useful for assessing XMM programs because they are so small they 
       typically fit entirely in the cache, so are not representative of programs
       that require XMM RAM. They also did not test floating point performance.
    
       The benchmarks have been modified very slightly from the originals, 
       primarily to remove the need to interact with them.
    
       They are applicable to both the Propeller 1 and the Propeller 2.
    
    2. The overall XMM speed has been increased on the Propeller 2, and new
       XMM related compile-time options have been added that can be used to 
       increase the speed further in specific instances. These changes are 
       applicable to the Propeller 2 only.
    
       The basic speed of all XMM (SMALL or LARGE) programs has been increased 
       by between 4% and 8% (the exact improvement depends on the program, the 
       memory model used and the size of the cache used). 
    
       Additional speed improvements (up to 25% in some cases) can be achieved 
       by defining one or more of the following new Catalina symbols:
    
          LUT_PAGE   : Use the LUT to hold the current cache page and execute XMM 
                       code from there instead of from Hub RAM. The page size can
                       be up to 1k (the second 1k of LUT is used as a common code
                       library). The page size limit of 1k constrains the cache 
                       geometries that can be used. More details on this are given
                       in target\p2\constant.inc
    
          LUT_CACHE  : Use the LUT to hold the entire XMM cache. This must be
                       combined with CACHED_1K. It gives good performance with 
                       a very small cache size, and frees up valuable Hub RAM 
                       for other purposes. Only one of LUT_PAGE and LUT_CACHE
                       can be specified.
    
          CACHE_PINS : Use 2 pins in repository mode to communicate between the
                       XMM kernel and the XMM cache, instead of communicating via
                       Hub RAM. The pins used are specified in the platform 
                       configuration file (e.g. P2EDGE.inc) and cannot be used 
                       for any other purpose.
    
          FLOAT_PINS : Use 4 pins in repository mode to communicate between the
                       XMM kernel and the Floating point plugin instead of via
                       Hub RAM. The pins used are specified in the platform 
                       configuration file (e.g. P2EDGE.inc) and cannot be used 
                       for any other purpose. FLOAT_PINS is only supported by 
                       the Float_C plugin, which is the one loaded by default 
                       when the XMM kernel is used, or when the -lmc option is 
                       specified on the command line.
    
       Unfortunately, no single combination of the above options gives the "best"
       performance in all possible circumstances - the results depend on the 
       program, the memory model and cache size used, and how much floating 
       point is used by the program.
    
       In general, specifying all of LUT_PAGE, CACHE_PINS and FLOAT_PINS gives 
       good results in most cases, and will typically result in a speed increase
       of around 10% for XMM LARGE programs, and 20% for XMM SMALL programs. A 
       real-world example of this is that when these options are applied to the 
       self-hosted version of the Catalina compiler itself (which is compiled in 
       LARGE mode) it results in an increase in compilation speed of about 10%. 
    
       Below are some actual numbers from the benchmark programs.
    
       First, the following common options were set in CATALINA_DEFINE:
    
          set CATALINA_DEFINE=LARGE CACHED_64K OPTIMIZE MHZ_200 CLOCK
    
       then the fibo, dhrystone and whetstone benchmarks were compiled as follows:
    
          cd demos\benchmarks
          catalina -p2 -lci fibo.c <plus other options - see table below>
          catalina -p2 -lc -lmc whetstone.c <plus other options - see table below>
          catalina -p2 -lc -lmc -D MSC_CLOCK -DCLK_TCK=1000 dhry_1.c dhry_2.c 
                   <plus other options - see table below>
    
       This gives the following results (Release 7.3 is included in the table
       as a baseline):
    
       Catalina  Other Options                    fibo     drystone   whetstone
       Release   (added using -C)                (msecs)  (VAX KIPS)   (KWIPS)
       ========  ==============================  =======  ==========  =========
         7.3                                      3064        677         877
         7.4                                      2828        719         917
         7.4     CACHE_PINS                       2828        746         951
         7.4     FLOAT_PINS                       2828        721         980
         7.4     CACHE_PINS FLOAT_PINS            2828        746        1000
         7.4     LUT_PAGE                         2412        671         862
         7.4     LUT_PAGE CACHE_PINS              2412        710         909
         7.4     LUT_PAGE FLOAT_PINS              2412        686         917
         7.4     LUT_PAGE CACHE_PINS FLOAT_PINS   2412        710         970
    
       Another result worth noting is that the LUT_CACHE option can be used to
       free up to an additional 63k of Hub RAM - i.e. it requires only 1k for 
       the XMM cache, yet gives performance quite comparable with Release 7.3 
       when using 64k for the cache (as shown in the table above):
    
       Catalina  Other Options                    fibo     drystone   whetstone
       Release   (added using -C)                (msecs)  (VAX KIPS)   (KWIPS)
       ========  ==============================  =======  ==========  =========
         7.4     LUT_CACHE CACHE_PINS FLOAT_PINS  3145        512         847
    
       Note that none of these options are enabled by default because they depend
       on the LUT not being required for other purposes, and also on the platform
       having sufficient unused pins available. A good choice for the pins to use
       are the unused pins when the RTC add-on board is used (which uses only 2 
       pins out of the 8 pins the board physically occupies) - these are the 
       defaults used in the platform files.
    
    3. A new Propeller 1 demo program (random.c) has been added in demos\random. 
       This program demonstrates the RANDOM plugin, and also demonstrates how
       to manually load and unload plugins at run-time.
    
    Other Changes.
    --------------
    
    1. The _unregister_plugin() library function was putting zero in the plugin 
       type in the registry (which actually means LMM_VMM - i.e. an LMM kernel) 
       instead of putting in the value 255 (which is LMM_NUL). This made no 
       difference when a new plugin was loaded into a free cog using ANY_COG
       (which is the usual way to load plugins) but may have given the wrong 
       results when the registry was displayed, or if the registry was searched 
       for a free cog to load based on the plugin type in the registry. 
       Affected both the Propeller 1 and Propeller 2.
    
    2. The Propeller 2 PSRAM and HyperRAM demo programs in demos/p2_ram were 
       broken by the addition of environment variables, which prevented some
       programs from building because the initialization code was too large.
       Affected the Propeller 2 only.
    

    EDIT: Something that is perhaps not made clear enough in the documentation of the new cache options is that when you use the LUT as part of the cache, the XMM Kernel cog and the XMM Cache cog have to be in the same cog pair so that they share the same LUT - e.g. cogs 0 and cog 1. For instance, the XMM Cache cog may write a page of code to the LUT which the XMM kernel cog then executes, or the XMM Kernel cog may write data to the LUT which the XMM Cache cog will later write back to the XMM RAM. In previous releases the cache cog (if required) was always loaded in cog 7. This is all handled internally, and I have not found any instances where this change makes any difference, but it is possible that some programs may still expect the cache to always be in cog 7, in which case they will not work with the new options.

  • evanhevanh Posts: 16,029
    edited 2024-05-18 12:49

    @RossH said:
    The CTRL-Z issue is not to do with payload. In a linux bash shell, CTRL-Z puts the active process in the background (i.e. it suspends it). To resume it, use the command "fg".

    Oh, ha, I guess Eric has a hook or something setup in Loadp2 to quit instead.

    You should be able to use the -p option of payload to specify the port by name. For instance, I can say:

    payload -i hello_world -p /dev/ttyUSB0

    Yeah, those work fine. I would like, however, to use alternative port paths that are device tied rather than the order of connection/discovery. Then I can have multiple Prop2's plugged in together and load specific programs to specific boards. Handy for testing.

    Not a biggie though. I've found I can happily use Loadp2 in place of Payload.

  • RossHRossH Posts: 5,477
    edited 2024-05-19 02:10

    @evanh said:

    Yeah, those work fine. I would like, however, to use alternative port paths that are device tied rather than the order of connection/discovery. Then I can have multiple Prop2's plugged in together and load specific programs to specific boards. Handy for testing.

    Not a biggie though. I've found I can happily use Loadp2 in place of Payload.

    Ok, I see what you mean now. But you will need to use payload to load XMM programs, so here is a solution:

    First, see this page, which describes what we will do ...

    https://inegm.medium.com/persistent-names-for-usb-serial-devices-in-linux-dev-ttyusbx-dev-custom-name-fd49b5db9af1

    I followed those instructions to create /dev/PropPlug1 by adding the following line to /etc/udev/rules.d/99-usb-serial.rules ....

    SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{product}=="PropPlug", ATTRS{manufacturer}=="Parallax Inc", SYMLINK+="PropPlug1"

    Then, I made the following changes in /source/catalina/rs232.c ...

    ...
    
    #define PORT_COUNT 23 // was 22 !!!
    
    ...
    
    char comports[PORT_COUNT][NAME_LENGTH+1]={
       "/dev/ttyS0","/dev/ttyS1","/dev/ttyS2","/dev/ttyS3","/dev/ttyS4","/dev/ttyS5",
       "/dev/ttyS6","/dev/ttyS7","/dev/ttyS8","/dev/ttyS9","/dev/ttyS10","/dev/ttyS11",
       "/dev/ttyS12","/dev/ttyS13","/dev/ttyS14","/dev/ttyS15","/dev/ttyUSB0",
       "/dev/ttyUSB1","/dev/ttyUSB2","/dev/ttyUSB3","/dev/ttyUSB4","/dev/ttyUSB5",
       "/dev/PropPlug1" // added this one!
    };
    
    ...
    

    Then execute ./build_all script in /source/catalina to rebuild payload, and now whenever you plug a Parallax prop-plug in, you can just say something like ...

    payload -i hello_world -p /dev/PropPlug1

    A variation on this should get you what you need. For instance, you could add PropPlug2 ... etc etc.

    Note that my example rule file will assign any Parallax PropPlug to /dev/PropPlug1 - to make sure the same PropPlug is always assigned to the same name, you need to find a unique identifier for it and add that to the rules file.

    Ross.

  • evanhevanh Posts: 16,029
    edited 2024-05-19 01:59

    I tried adding the pre-existing /dev/serial/... symlinks to Payload but it didn't work for whatever reason. Following your instructions works. New /etc/udev/rules.d/99-usb-serial.rules rule file made:

    SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{serial}=="DN43WU6I", SYMLINK+="ttyPropRevB"
    SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{serial}=="P23YOO42", SYMLINK+="ttyPropGlobTop"
    SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{serial}=="P2EEL5N", SYMLINK+="ttyPropRevA"
    SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{serial}=="A4001xIP", SYMLINK+="ttyPropClip"
    
  • RossHRossH Posts: 5,477

    @evanh said:
    I tried adding the pre-existing /dev/serial/... symlinks to Payload but it didn't work for whatever reason. Following your instructions works. New /etc/udev/rules.d/99-usb-serial.rules rule file made:

    SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{serial}=="DN43WU6I", SYMLINK+="ttyPropDN43WU6I"
    SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{serial}=="P23YOO42", SYMLINK+="ttyPropP23YOO42"
    SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{serial}=="A4001xIP", SYMLINK+="ttyPropA4001xIP"
    

    Well, I would probably have just called them something like "PropPlug1", "PropPlug2" & "PropPlug3" to save typing - but then I'm just lazy! :)

    Glad you got it working!

    Ross.

  • evanhevanh Posts: 16,029
    edited 2024-05-19 02:10

    Done :)

    I had become used to the existing naming so wasn't too phased by working with the serial numbers. And I use name completion of course.

    Any idea why the existing symlinks don't work?

  • evanhevanh Posts: 16,029
    edited 2024-05-19 03:27

    Next step. I don't know what my options are here ... I have an existing Spin object that I use as a library function within Flexspin C projects. The primary function of it is called pllset(). https://obex.parallax.com/obex/pllset/

    I'd like to make it useable as a function in Catalina too. There is Spin2 specific things in it that are important - namely the compiler created symbols clkmode_ and clkfreq_ which provides the compile time board crystal config. I could make a backup copy at boot time but since these have always been provided by Spin2 I make use of them.

    And the accompanying Cordic maths would be a nice to have as well.

    A notable side effect of pllset() is any attached serial port connected with a serial terminal will also need its baud recomputed. This used to be coded explicitly in Flexspin but these days is incorporated in _clkset() now I think. I no longer have to do anything for printf() to function across runtime dynamic sysclock frequencies. Presumably happened when Spin2's debug gained the same.

  • RossHRossH Posts: 5,477
    edited 2024-05-19 04:36

    @evanh said:
    Done :)

    I had become used to the existing naming so wasn't too phased by working with the serial numbers. And I use name completion of course.

    Any idea why the existing symlinks don't work?

    No. I was going to suggest that myself as a possible alternative. Perhaps a permissions problem? Does stty -F work on the symlinks?

  • ElectrodudeElectrodude Posts: 1,660
    edited 2024-05-19 04:06

    @RossH said:

    @evanh said:
    Done :)

    I had become used to the existing naming so wasn't too phased by working with the serial numbers. And I use name completion of course.

    Any idea why the existing symlinks don't work?

    No. I was going to suggest that myself as a possible alternative. Perhaps a permissions problem? Does stty -F work on the symlinks?

    The permissions bits on symlinks are ignored on Linux. Only the permissions bits on the symlink's referent can ever have any effect.

  • RossHRossH Posts: 5,477
    edited 2024-05-19 06:16

    @evanh said:
    Next step. I don't know what my options are here ... I have an existing Spin object that I use as a library function within Flexspin C projects. The primary function of it is called pllset(). https://obex.parallax.com/obex/pllset/

    I'd like to make it useable as a function in Catalina too. There is Spin2 specific things in it that are important - namely the compiler created symbols clkmode_ and clkfreq_ which provides the compile time board crystal config. I could make a backup copy at boot time but since these have always been provided by Spin2 I make use of them.

    And the accompanying Cordic maths would be a nice to have as well.

    A notable side effect of pllset() is any attached serial port connected with a serial terminal will also need its baud recomputed. This used to be coded explicitly in Flexspin but these days is incorporated in _clkset() now I think. I no longer have to do anything for printf() to function across runtime dynamic sysclock frequencies. Presumably happened when Spin2's debug gained the same.

    The Spin2 code can be converted directly to C. I usually do this manually, but Eric had a tool to do it automatically called spin2cpp, which I have used, but I don't remember the details. I do remember that things like the _clkmode and _clkfreq symbols needed to be converted into Catalina calls to _clockmode() and _clockfreq() - I wrote a header file to do this automatically - see the file /include/spin2cpp.h - all I have to do is remember how to use it! **

    PASM code can generally be translated fairly directly into Catalina's inline PASM - at least for NATIVE mode programs that do not have multi-threading, which I think is the only mode that Flexspin C supports.

    The main "gotcha" to be aware of with inline PASM when multi-threading is enabled, or when the program is compiled in other Catalina modes (i.e. COMPACT, TINY, XMM SMALL or XMM LARGE) is the setq instruction - because there is no guarantee that the setq and the instruction that uses the Q register (usually the immediately following instruction) will end up being executed sequentially - and an intervening instruction may disrupt the Q register. You can solve this when multi-threading by adding stalli and allowi instructions to prevent context switching. Solving it for the other modes is a little more difficult, but certainly possible - for instance, for LMM TINY mode kernel, I added some new kernel primitives - see the file /target/p2/lmmklib.inc

    The capability to automatically recalculate the serial baud rate "on the fly" would have to be added to the serial plugin. None of my serial plugins do that, but it would certainly be possible to create one that does.

    Ross.

    ** It is used automatically when you #include propeller2.h - see next post!

Sign In or Register to comment.