fastspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler

1585961636466

Comments

  • JRoark wrote: »
    @ersmith (or anyone): Is there any way, at runtime, to determine the type of a variable that is passed to a SUB or FUNCTION in FlexBASIC?

    No. The "any" type is just an undifferentiated 32 bit value (it's what everything is in the Spin language, if you're familiar with that). Once something is cast to "any" then all information about it is lost.

    It might be possible to distinguish types in template functions, like:
    ANY(T) FUNCTION WhatAmI(a as T) as string
    
    if T = string then return "It's a string"
         ... (more of the same) ...
    if T = long then return "It's a long"
    END FUNCTION
    
    In templated functions the type does exist (and may be referred to with a variable name, like "T" above), so the compiler could figure out what type is associated. That ability to do this test does *not* exist now, but since the type information is available then in theory we could implement something like that. It'd be some work though.

    What are you trying to accomplish?
  • @ersmith I got to noodling on the SWAP function found in other BASICs and realized my library needed this to let new FlexBASIC coders have a leg up with a BASIC syntax they already know. (The construct x,y = y,x isnt something they will get until they’ve cracked the manual). So I wrapped the swap into a SWAP() subroutine:
    SUB Swap(byref x as any, byref y as any)
        x,y = y,x
    END SUB
    
    The problem of course is that ANY just tells the compiler not to enforce any type. But what if the user tries to feed it a ulong and a string to swap? SWAP() faithfully does it with that ANY, and garbage is the result with no error thrown.

    So my thought was to make sure the two incoming types were at least of the same ilk (ie. Both numeric types, or both strings). If they are different but could be made compatible, then perhaps try to coerce them into something useful with a CAST, and if not then throw an error.




  • That's exactly the sort of thing that templates are supposed to solve. That is, you should be able to write Swap as:
    Any(MyType) SUB Swap(byref x as MyType, byref y as MyType)
      x,y = y,x
    END SUB
    
    and then just use it as Swap(x, y); if x and y are not the same types the compiler will complain.

    Unfortunately "byref" confuses the template parser and leads to a whole rats nest of incomprehensible errors. I'll try to get that fixed.
  • Thanks, Eric. But unless you think differently, this seems to be an oddball case, so if time is precious I’d put this on the “get to it someday” list.
  • OK, the fix wasn't too hard. The updated fastspin.zip is attached.

    Templates are still probably a bit fragile, but at least swap works right now:
    ' template function demo
    
    any(T1) sub swap(byref x as T1, byref y as T1)
      dim tmp as T1
      tmp = x
      x = y
      y = tmp
    end sub
    
    var a = "hello"
    var b = "goodbye"
    
    swap(a, b)
    print "a, b = ", a, b
    
    var c = 10
    var d = 20
    swap(c, d)
    print "c, d =", c, d
    swap(c, d)
    print "now c, d =", c, d
    
    'swap(a, c) ' causes an error
    
  • Holy cow! 17 minutes. Dude, you rock!
  • JRoarkJRoark Posts: 549
    edited 2020-08-11 - 18:13:45
    @ersmith Any interest in making a modification to the PRINT statement that would arbitrate between competing print requests from multiple cogs?

    As it currently exists, all cogs share the USB channel. If two cogs attempt to print at the same time, a bit of a trainwreck occurs. It seems to me that a PRINT-like variant that first checked, and then sets a global semaphore before it pushed any characters out, and then reset the semaphore when the last character was out on the wire, would allow competing PRINT requests to happen in an orderly manner. The downside is printing from one cog would stall printing from all other cogs, but this isnt necessarily a show-stopper.

    I started coding this myself in a function wrapper called “PrintM()” (Print, managed), but realized this might be something that could be included as part of the FlexBASIC language.

    Thoughts?
  • Parallax: Can we please make this a "sticky" in the P2 section???
  • JRoark wrote: »
    @ersmith Any interest in making a modification to the PRINT statement that would arbitrate between competing print requests from multiple cogs?

    The overall idea of allowing prints from multiple COGs is a good one, and I'd like to support it some day. But it actually opens quite a can of worms. For example, what should the granularity be: per-item, per PRINT statement, or per line of text? How should this work for other languages that don't have PRINT but do have similar functionality (like C's printf)? What if the COGs are printing to different devices (using PRINT #); one would think they should be able to do so in parallel, but how do we detect this? Etc.

    We definitely need to think about this, but I don't have good answers for all of these questions yet.
  • Yikes. Good points.

    My interim function just does it by each Print statement. Just really basic (pardon the pun) stuff. I hadnt even thought about how other languages would work, or the possibility of a PRINT # implementation, or the granularity aspects.

    Sounds like some contemplation over an adult beverage is in order!
  • I've uploaded fastspin 4.3.0 to github, and the corresponding FlexGUI to my patreon page (a binary release to github will follow soon). There are some significant changes:

    - P2 API Change: use call/ret instead of calla/reta
    - Added finer-grained control over optimizations
    - Added per-function control over optimizations
    - Added preliminary implementation of DEBUG() for Spin2
    - Fixed some bugs in cse and loop optimizations
    - Fixed byref parameters in BASIC template functions
    - Improved dead code removal

    The optimizer bug fixes and new call/ret calling convention have improved the performance on CoreMark from 30 iterations/sec to 37 iterations/sec. so these are definitely wins. There are now options for individual optimizations, so for example you can compile with all optimizations except common sub expression removal by giving a command line option like "-Oall,!cse". And there is some primitive support for Chip's DEBUG() facility, which is enabled with the "-g" command line flag (if there's no -g then all the DEBUG() lines in Spin2 are silently ignored).
  • David BetzDavid Betz Posts: 14,179
    edited 2020-08-14 - 02:03:54
    Deleted
  • Your improvements sound good Eric. What will happen once the internal stack capacity is reached? Does Fastspin somehow know the call depth will then exceed 8 and then move to a hub based stack? Are there any restrictions here to deal with, like when using recursive functions etc?
  • rogloh wrote: »
    Your improvements sound good Eric. What will happen once the internal stack capacity is reached? Does Fastspin somehow know the call depth will then exceed 8 and then move to a hub based stack? Are there any restrictions here to deal with, like when using recursive functions etc?

    Non-leaf functions pop the address off the internal stack and save it to the HUB stack along with the other registers. Since the HUB stack write uses SETQ+WRLONG, this is (almost) free, and it means there are no limits to recursion, etc.
  • Is "reg" a reserved word now? An older code is giving an error on it...

    Also, is there a list of reserved words somewhere? In source or docs?
  • Rayman wrote: »
    Is "reg" a reserved word now? An older code is giving an error on it...

    "reg" is a reserved word in Spin2, so it will produce an error in files with a ".spin2" extension (but not in files with a ".spin" extension).
    Also, is there a list of reserved words somewhere? In source or docs?

    For BASIC it's all documented. For Spin it's spread across Chip's various documents (for Spin1 and Spin2) and I haven't had a chance to consolidate these for the fastspin documents. In the source it's in frontends/lexer.c, arrays "init_spin_words" (common keywords), "init_spin1_words" (Spin1 additional reserved words) and "init_spin2_words" (Spin2 additional reserved words).
  • What is Reg used for? I searched Chip's spin doc and couldn't find it...
  • REG[x] refers to COG memory address x ("register"). It's described in the Spin2 document under "Variables".
  • I've released fastspin 4.3.1 to fix the SEND problem @rogloh discovered. It also fixes some DEBUG() problems and adds a few more missing Spin2 functions.
  • roglohrogloh Posts: 2,705
    edited 2020-08-16 - 13:54:57
    Eric, I found a difference in the behaviour of SPIN2 precedence rules between PNut and FastSpin when tracking down something that wasn't working.

    In FastSpin this code behaved differently to PNut and actually worked as I wanted (maybe coded incorrectly for SPIN2, but I'm used to this from C):
    mode |= (1<<24) + (crystalHz < 16000000) ? %1111 : %1011
    

    however when porting over to PNut I found I needed to add the extra parentheses for it to do what I want. e.g. I always want bit 24 OR'd into the mode variable, independent of the crystalHz check being less than 16M or not (which only OR's the bottom 4 bits):
    mode |= (1<<24) + ((crystalHz < 16000000) ? %1111 : %1011)
    

    So it looks like the precedence of the ternary operator a?b:c differs in the two toolchains and it has the lowest priority in the PNut toolchain but something higher in Fastspin.

    This was with an older Fastspin v4.2.5 so you might have it working differently now. I'm thinking it's probably good to have the precedence working the same way if possible to avoid issues.
  • @ersmith You had mentioned that you needed to renew/replace your existing code signing certificate and were getting hammered on the price. I found these guys a while back and figured I'd pass it on. They are $80/yr, no matter if its new/renew/transfer, etc.

    https://www.ksoftware.net/code-signing-certificates

    I have no relationship with them, financial or otherwise.
  • Thanks for the bug report, Roger. I'll look into it.

    Jeff: thanks for the pointer, that looks promising!

  • I'm trying to compile the generic C code that ST provides for the LSM9DS1 from here:
    https://www.st.com/content/st_com/en/products/embedded-software/mems-and-sensors-software/drivers-for-mems/c-driver-mems.html

    I seems to be choking on the "float_t" data type declarations...
    Can it be that not defined?

    Seems OK with "int32_t"...
  • RaymanRayman Posts: 11,290
    edited 2020-08-17 - 19:29:00
    I did this and maybe fixed it?
     #define float_t float
    

    Had to add a fake main() to the .c file. Not sure why it doesn't include one...

    I'm impressed that this code actually compiles... Got a lot going on in it... Bitfields and such...
    Wonder if it actually works...
  • In the "mandelbrot" example, I'm not seeing the P2 clock being set anywhere...

    Does this mean it's just set to whatever loadp2 is set to?
    Looks like the default is 80 MHz, right?
  • The default for C and BASIC is 160 MHz (both of those languages will set the clock if none is specified explicitly).

    BTW, thanks for noticing that float_t and double_t were missing. I'll add those, but you're right, for now just do #define float_t float.
  • Is there an SD card filesystem driver in FlexC yet?
    I know you were working on one, but I don't see anything about it in docs or examples...
  • I know Eric has a filesystem-over-serial thingy.

  • Does debug work in Fastspin now?
    I was just testing it with a C program that calls a Spin2 object.
    This in the Spin2 code works:
    debug("Message from Spin2!.")
    
    It shows up in the output terminal window of loadp2, along with the C printf output.
    But, these don't work:
        i:=string("Testing Strings...",0)  
        debug(10)
        debug(ZSTR(i))
    

    Should it? Or, am I doing it wrong? I get no output other than "Cog0"...
  • RaymanRayman Posts: 11,290
    edited 2020-08-29 - 17:42:08
    Questions about debug:

    Can you add "-g" to the docs?

    I seem to be seeing that it only works when baud is 230400.
    Is this correct?

    Also, my very first debug command seems to be producing gibberish. After that, it seems to work...
Sign In or Register to comment.