Shop OBEX P1 Docs P2 Docs Learn Events
fastspin C compiler - Page 5 — Parallax Forums

fastspin C compiler

1235»

Comments

  • David Betz wrote: »
    I exchanged some messages with Tubular and it seems the MicroPython project is already in progress. I think I need to come up with a different plan for my P2 work. There is really no point in getting ebasic3 working since it was only supposed to be a stepping stone to MicroPython.

    Hmmm. I guess there's not much point in the attached file. But perhaps @Tubular could play with it a bit if he'd like. No P2 specific features, it's just plain MicroPython talking to a 230400 baud serial terminal. It's also a terrible hack. OTOH it does exist now :).
  • ersmith wrote: »
    David Betz wrote: »
    ersmith wrote: »
    Perhaps these structs are dynamically allocated
    Nope. No calls to malloc in ebasic3. It's all static allocation.
    Sorry, I wasn't clear there... I meant dynamically allocated by ebasic3's internal memory allocation routines (I'm pretty sure it does have some kind of allocator acting on a static heap, doesn't it?)

    Yes, it carves up a static block of memory as it compiles. It always allocates long-aligned blocks of memory though. I guess you're saying that isn't required on P2. Is there any performance penalty for unaligned accesses?
  • Ooh interesting, Eric. I'm tied up preparing for a public event tomorrow but look forward to trying that out soon afterwards
  • ersmith wrote: »
    David Betz wrote: »
    I exchanged some messages with Tubular and it seems the MicroPython project is already in progress. I think I need to come up with a different plan for my P2 work. There is really no point in getting ebasic3 working since it was only supposed to be a stepping stone to MicroPython.

    Hmmm. I guess there's not much point in the attached file. But perhaps @Tubular could play with it a bit if he'd like. No P2 specific features, it's just plain MicroPython talking to a 230400 baud serial terminal. It's also a terrible hack. OTOH it does exist now :).
    Are you saying you've already ported MicroPython to P2?

  • I think this is what is getting ebasic3's ParseCall function in trouble. This statement:
        e = e->next;
    
    gets compiled to this:
    	add	local10, #4
    	rdlong	local10, local10
    	sub	local10, #4
    
    I think the final subtract needs to be suppressed in this case.
  • ersmith wrote: »
    David Betz wrote: »
    I exchanged some messages with Tubular and it seems the MicroPython project is already in progress. I think I need to come up with a different plan for my P2 work. There is really no point in getting ebasic3 working since it was only supposed to be a stepping stone to MicroPython.

    Hmmm. I guess there's not much point in the attached file. But perhaps @Tubular could play with it a bit if he'd like. No P2 specific features, it's just plain MicroPython talking to a 230400 baud serial terminal. It's also a terrible hack. OTOH it does exist now :).
    I tried this and it seems to work fine. Is this compiled with fastspin? I'm surprised fastspin can compile MicroPython successfully but not ebasic3. I figured MicroPython would be a lot more challenging.

  • ersmithersmith Posts: 5,900
    edited 2019-03-01 03:23
    David Betz wrote: »
    I think this is what is getting ebasic3's ParseCall function in trouble. This statement:
        e = e->next;
    
    gets compiled to this:
    	add	local10, #4
    	rdlong	local10, local10
    	sub	local10, #4
    
    I think the final subtract needs to be suppressed in this case.

    Oh! Thank you David, that's a nasty bug that's been in fastspin for a long time! I'm amazed it hasn't bitten us before; I guess in Spin it would only be triggered by class variables used as pointers, which are relatively rare.

    The fix for that (and for Roy's extern problem) is in github now.

    Eric
  • David Betz wrote: »
    ersmith wrote: »
    Hmmm. I guess there's not much point in the attached file. But perhaps @Tubular could play with it a bit if he'd like. No P2 specific features, it's just plain MicroPython talking to a 230400 baud serial terminal. It's also a terrible hack. OTOH it does exist now :).
    I tried this and it seems to work fine. Is this compiled with fastspin? I'm surprised fastspin can compile MicroPython successfully but not ebasic3. I figured MicroPython would be a lot more challenging.

    No, it's not compiled with fastspin, nor with p2gcc. There are at least two other ways to run C code on the P2 (probably more, if you count CSpin, but I didn't use that either).

    I'm kind of wondering if anyone will figure it out, so consider it a kind of puzzle for the moment. :)
  • ersmith wrote: »
    David Betz wrote: »
    ersmith wrote: »
    Hmmm. I guess there's not much point in the attached file. But perhaps @Tubular could play with it a bit if he'd like. No P2 specific features, it's just plain MicroPython talking to a 230400 baud serial terminal. It's also a terrible hack. OTOH it does exist now :).
    I tried this and it seems to work fine. Is this compiled with fastspin? I'm surprised fastspin can compile MicroPython successfully but not ebasic3. I figured MicroPython would be a lot more challenging.

    No, it's not compiled with fastspin, nor with p2gcc. There are at least two other ways to run C code on the P2 (probably more, if you count CSpin, but I didn't use that either).

    I'm kind of wondering if anyone will figure it out, so consider it a kind of puzzle for the moment. :)
    ZPU?

  • ersmith wrote: »
    David Betz wrote: »
    I think this is what is getting ebasic3's ParseCall function in trouble. This statement:
        e = e->next;
    
    gets compiled to this:
    	add	local10, #4
    	rdlong	local10, local10
    	sub	local10, #4
    
    I think the final subtract needs to be suppressed in this case.

    Oh! Thank you David, that's a nasty bug that's been in fastspin for a long time! I'm amazed it hasn't bitten us before; I guess in Spin it would only be triggered by class variables used as pointers, which are relatively rare.

    The fix for that (and for Roy's extern problem) is in github now.

    Eric
    Thanks for the update. The ebasic3 interpreter gets further now but it still fails to execute user defined functions. I'll have to track down the next problem tomorrow.

  • David Betz wrote: »
    ersmith wrote: »
    David Betz wrote: »
    ersmith wrote: »
    Hmmm. I guess there's not much point in the attached file. But perhaps @Tubular could play with it a bit if he'd like. No P2 specific features, it's just plain MicroPython talking to a 230400 baud serial terminal. It's also a terrible hack. OTOH it does exist now :).
    I tried this and it seems to work fine. Is this compiled with fastspin? I'm surprised fastspin can compile MicroPython successfully but not ebasic3. I figured MicroPython would be a lot more challenging.

    No, it's not compiled with fastspin, nor with p2gcc. There are at least two other ways to run C code on the P2 (probably more, if you count CSpin, but I didn't use that either).

    I'm kind of wondering if anyone will figure it out, so consider it a kind of puzzle for the moment. :)
    ZPU?
    Or maybe RISC-V?

  • Back to ebasic3, it looks like it can compile simple functions correctly now. It has trouble with recursive functions though but that seems to be a problem with the ebasic3 compiler not with fastspin. Here is an example of a user defined function:
    loadp2 ebasic -t -p /dev/cu.usbserial-P2EEQXU -b 115200 -CHIP
    Unsupported baudrate 921600. Use ( Entering terminal mode.  Press Ctrl-] to exit. )
    ebasic3 v0.01
    10 def foo(n)
    20  return n+2 
    30 end def
    40 for i=1 to 10
    50  print foo(i)
    60 next i
    run
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    OK
    
  • David BetzDavid Betz Posts: 14,511
    edited 2019-03-02 13:50
    I realized this morning that my GitHub "ebasic" repository is actually an updated version of "ebasic3" so I switched to that. It seems to have the fix for the but I mentioned earlier about recursive functions. Unfortunately, it also has some other changes that are getting me into trouble. In particular, my branch instructions use a 16 bit offset and I think fastspin might be having some trouble with sign extending 16 bit values to 32 bits. I can't see any code to do sign extension in the following generated code.

    This code is in this GitHub repository: https://github.com/dbetz/ebasic.git

    The original C code. The tmpw variable is a VMWORD which is an int16_t and i->pc is a uint8_t *.
            case OP_BR:
                for (tmpw = 0, cnt = sizeof(VMWORD); --cnt >= 0; )
                    tmpw = (tmpw << 8) | VMCODEBYTE(i->pc++);
                i->pc += tmpw;
                break;
    
    The generated code:
    LR__0580
    	mov	local10, #0
    	mov	local11, #2
    LR__0581
    	sub	local11, #1
    	cmps	local11, #0 wcz
     if_b	jmp	#@LR__0582
    	mov	local08, local10
    	shl	local08, #8
    	add	local04, #16
    	rdlong	local12, local04
    	mov	local13, local12
    	add	local13, #1
    	wrlong	local13, local04
    	sub	local04, #16
    	mov	local10, local08
    	rdbyte	local14, local12
    	or	local10, local14
    	jmp	#@LR__0581
    LR__0582
    	mov	local06, local10
    	add	local04, #16
    	rdlong	local07, local04
    	add	local07, local06
    	wrlong	local07, local04
    	sub	local04, #16
    	jmp	#@LR__0635
    
  • Wow... as usual, you've nailed it David! Thank you for the detailed bug report. I had forgotten to do sign extension in pointer arithmetic. That should be fixed in github now.

    Thanks,
    Eric
  • ersmith wrote: »
    Wow... as usual, you've nailed it David! Thank you for the detailed bug report. I had forgotten to do sign extension in pointer arithmetic. That should be fixed in github now.

    Thanks,
    Eric
    That did it! My factorial program now works. I don't know of any more fastspin bugs at this point. I may try porting my PASM byte code interpreter next and then follow that with updating it to use XBYTE.
    loadp2 ebasic -t -p /dev/cu.usbserial-P2EEQXU -b 115200 -CHIP
    Unsupported baudrate 921600. Use ( Entering terminal mode.  Press Ctrl-] to exit. )
    ebasic3 v0.01
    10 def fact(n)
    20  if n=1 then
    30   return 1
    40  else
    50   return fact(n-1) * n
    60  end if
    70 end def
    80 for i=1 to 10
    90  print fact(i)
    95 next i
    run
    1
    2
    6
    24
    120
    720
    5040
    40320
    362880
    3628800
    OK
    
  • jmgjmg Posts: 15,140
    ersmith wrote: »
    ... That should be fixed in github now.
    David Betz wrote: »
    That did it! My factorial program now works. I don't know of any more fastspin bugs at this point. I may try porting my PASM byte code interpreter next and then follow that with updating it to use XBYTE.
    You guys are making impressive progress here :)



  • jmg wrote: »
    ersmith wrote: »
    ... That should be fixed in github now.
    David Betz wrote: »
    That did it! My factorial program now works. I don't know of any more fastspin bugs at this point. I may try porting my PASM byte code interpreter next and then follow that with updating it to use XBYTE.
    You guys are making impressive progress here :)


    All I did was help Eric find a few bugs. The work is all on his side. Thanks, Eric!
  • David Betz wrote: »
    All I did was help Eric find a few bugs. The work is all on his side. Thanks, Eric!

    You're far too modest David -- tracking down bugs is hard work, and you did a lot of the leg work to find them. Thanks for all your help!

  • I'm starting to look at converting my P1 PASM byte code interpreter to P2 and am having some startup problems. Has the syntax for local labels changed? I get a bunch of errors like this:
    ebasic_vm.spin2(616) error: syntax error, unexpected ':'
    
    on lines like this:
    :rcog                   mov     t1, 0-0
    
    How do I do local labels for P2?
  • Local labels in P2 start with a period '.' instead of a ':'. I'm not quite sure why Chip made that change, although it is more similar to how other assemblers work.
  • David BetzDavid Betz Posts: 14,511
    edited 2019-03-06 02:39
    Okay, I admit it. Playing with XBYTE is fun. Here is my translation of the XBYTE sample to run on the P2-Eval board. Is the clock frequency stored at location zero like it is on P1? I'd like to avoid hardcoding the value for half a second.
    '
    ' ** XBYTE Demo **
    ' Automatically executes bytecodes via RET/_RET_ to $1F8..$1FF.
    ' Overhead is 6 clocks, including _RET_ at end of each bytecode routine.
    '
    dat             org
    
                    'hubset  #$FF            'set clock to 80MHz
    
                    setq2   #$FF            'load bytecode table into lut $100..$1FF
                    rdlong  $100,#bytetable
    
                    rdfast  #0,#bytecodes   'init fifo read at start of bytecodes
    
                    push    #$1FF           'push $1FF for xbyte on ret
            _ret_   setq    #$100           'start xbyte with lut base = $100, no stack pop
    '
    ' Bytecode routines
    '
    r0      _ret_   drvnot  #56             'toggle pin 56
    
    r1      _ret_   drvnot  #57             'toggle pin 57
    
    r2      _ret_   drvnot  #58             'toggle pin 58
    
    r3      _ret_   drvnot  #59             'toggle pin 59
    
    r4              rfvars  pa              'get offset
                    add     pb,pa           'add offset
            _ret_   rdfast  #0,pb           'init fifo read at new address
            
    r5      _ret_   waitx	##40000000	'wait half a second
            
    '
    ' Bytecodes that form program in hub
    '
                    orgh
    
    bytecodes       byte    0                       'toggle pin 0
                    byte    5                       'wait half a second
                    byte    1                       'toggle pin 1
                    byte    5                       'wait half a second
                    byte    2                       'toggle pin 2
                    byte    5                       'wait half a second
                    byte    3                       'toggle pin 3
                    byte    5                       'wait half a second
                    byte    4,(bytecodes-$) & $7F   'relative branch, loop to bytecodes
    '
    ' Bytecode EXECF table that gets moved into lut $100..$1FF
    '
    bytetable       long    r0                      '#0     toggle pin 0
                    long    r1                      '#1     toggle pin 1
                    long    r2                      '#2     toggle pin 2
                    long    r3                      '#3     toggle pin 3
                    long    r4                      '#4     relative branch
                    long    r5                      '#5     wait half a second
    
    {
    clock   phase   hidden                          description
    ----------------------------------------------------------------------------------------------------------------------
    1       go      RFBYTE byte                     last clock of instruction which is executing a RET/_RET_ to $1F8..$1FF
    
    2       get     RDLUT @byte, write byte to PA   1st clock of 1st cancelled instruction
    3       go      LUT long --> next D             2nd clock of 1st cancelled instruction
    4       get     EXECF D,                        1st clock of 2nd cancelled instruction
    5       go      EXECF D, write GETPTR to PB     2nd clock of 2nd cancelled instruction
    6       get     flush pipe                      1st clock of 3rd cancelled instruction
    7       go      flush pipe                      2nd clock of 3rd cancelled instruction
    
    8       get                                     1st clock of 1st instruction of bytecode routine, loop to 1 if _RET_
    }
    
  • I see there is an RFVARS instruction that sign extends the result but no RFBYTES or RFWORDS instruction. Is there any way to achieve sign extension for RFBYTE and RFWORD? That would be useful for byte code instructions that take a fixed length argument rather than a variable length one.
  • David Betz wrote: »
    Is the clock frequency stored at location zero like it is on P1? I'd like to avoid hardcoding the value for half a second.
    No, there's no runtime interpreter and the boot code does not store the frequency anywhere (I don't even think it changes it from RCFAST).

    p2gcc, fastspin, and Tachyon have all adopted a convention of placing the frequency at $10, so if your PASM code is started from one of those languages it can find it.
    I see there is an RFVARS instruction that sign extends the result but no RFBYTES or RFWORDS instruction. Is there any way to achieve sign extension for RFBYTE and RFWORD? That would be useful for byte code instructions that take a fixed length argument rather than a variable length one.

    No, you have to use RFBYTE and then the sign extension instruction (I forget the mnemonic for it, maybe EXTEND?) With XBYTE you can combine signed and unsigned loads by providing a SKIPF pattern to skip the sign extension for unsigned loads.

  • TonyB_TonyB_ Posts: 2,108
    edited 2019-03-06 13:20
    ersmith wrote: »
    David Betz wrote: »
    I see there is an RFVARS instruction that sign extends the result but no RFBYTES or RFWORDS instruction. Is there any way to achieve sign extension for RFBYTE and RFWORD? That would be useful for byte code instructions that take a fixed length argument rather than a variable length one.

    No, you have to use RFBYTE and then the sign extension instruction (I forget the mnemonic for it, maybe EXTEND?) With XBYTE you can combine signed and unsigned loads by providing a SKIPF pattern to skip the sign extension for unsigned loads.

    It's SIGNX, which can write the sign bit to C if desired.
  • TonyB_ wrote: »
    ersmith wrote: »
    David Betz wrote: »
    I see there is an RFVARS instruction that sign extends the result but no RFBYTES or RFWORDS instruction. Is there any way to achieve sign extension for RFBYTE and RFWORD? That would be useful for byte code instructions that take a fixed length argument rather than a variable length one.

    No, you have to use RFBYTE and then the sign extension instruction (I forget the mnemonic for it, maybe EXTEND?) With XBYTE you can combine signed and unsigned loads by providing a SKIPF pattern to skip the sign extension for unsigned loads.

    It's SIGNX, which can write the sign bit to C if desired.
    Cool! Thanks!

  • ersmith wrote: »
    p2gcc, fastspin, and Tachyon have all adopted a convention of placing the frequency at $10, so if your PASM code is started from one of those languages it can find it.
    Does the fastspin C compiler provide a built-in symbol like clkfreq at that address?

  • David Betz wrote: »
    ersmith wrote: »
    p2gcc, fastspin, and Tachyon have all adopted a convention of placing the frequency at $10, so if your PASM code is started from one of those languages it can find it.
    Does the fastspin C compiler provide a built-in symbol like clkfreq at that address?

    Yes, it's "_clkfreq" (the same as in PropGCC). And I was wrong about the address, it's 0x14, not 0x10 -- sorry about that.
  • David BetzDavid Betz Posts: 14,511
    edited 2019-03-07 13:06
    ersmith wrote: »
    David Betz wrote: »
    ersmith wrote: »
    p2gcc, fastspin, and Tachyon have all adopted a convention of placing the frequency at $10, so if your PASM code is started from one of those languages it can find it.
    Does the fastspin C compiler provide a built-in symbol like clkfreq at that address?

    Yes, it's "_clkfreq" (the same as in PropGCC). And I was wrong about the address, it's 0x14, not 0x10 -- sorry about that.
    Thanks! I guess the address doesn't matter if I use the symbol. :smile:

  • evanhevanh Posts: 15,126
    edited 2019-03-07 19:34
    David,
    If you want to set the PLL config in your program then you are now required to know the prior config, if any, to reliably return to RCFAST. To do this, byte address 0x18 to 0x1b contains the prior clock mode config, with %SS == %00. This can should be sent verbatim to HUBSET to undo the prior mode.

    Loadp2 has the -PATCH option to fill in this data if/when using its boot-loader. Here's a sample startup I've made for myself - https://forums.parallax.com/discussion/comment/1466528/#Comment_1466528

    Bytes 0x10 through 0x1f are reserved for patching.
Sign In or Register to comment.