Shop OBEX P1 Docs P2 Docs Learn Events
flexspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler - Page 5 — Parallax Forums

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

12357116

Comments

  • It certainly should be possible -- fastspin just produces PASM code after all. You do have to run the VGA driver in COG 0, since that's the only one that can control VGA in the FPGA, but I see you've done this. At first glance I think your code should work.

    I tried to play around a bit as well, and I couldn't seem to get the image to stabilize after doing coginit to restart the COG. I'm not sure what's going on there, if perhaps there might be another gotcha in the FPGA hardware implementation of the P2?
  • jmgjmg Posts: 15,140
    edited 2018-12-02 19:25
    ersmith wrote: »
    Just a note that I've updated fastspin and its GUI spin2gui. fastspin has some alpha quality support for compiling BASIC programs now, as well as continuing to support Spin for both P1 and P2. The version of the Spin language that fastspin compiles is something like Spin 1.5 (it has some Spin2 features but not all.) The BASIC language supported by fastspin is similar to FreeBasic, but not identical. You can use Spin objects in BASIC, and vice-versa.

    This Multi-language and mixed language approach will have wide appeal.
    Since you have multiple front end parsers working, have you toyed with the idea of a Python-ish parser, to allow users to paste in Python code (with some caveats obviously)
    I've found there are a couple of Python pre-processors, since you would need a means to do a #IFDEF Running_on_P2 type decisions.
  • jmg wrote: »
    Since you have multiple front end parsers working, have you toyed with the idea of a Python-ish parser, to allow users to paste in Python code (with some caveats obviously)
    I've found there are a couple of Python pre-processors, since you would need a means to do a #IFDEF Running_on_P2 type decisions.
    "Some caveats" is an understatement. People keep thinking that because both Spin and Python determine block structure by indenting that they are somehow similar. They aren't really. Python is more like LISP than it is like Spin.
  • jmgjmg Posts: 15,140
    David Betz wrote: »
    jmg wrote: »
    Since you have multiple front end parsers working, have you toyed with the idea of a Python-ish parser, to allow users to paste in Python code (with some caveats obviously)
    I've found there are a couple of Python pre-processors, since you would need a means to do a #IFDEF Running_on_P2 type decisions.
    "Some caveats" is an understatement. People keep thinking that because both Spin and Python determine block structure by indenting that they are somehow similar. They aren't really. Python is more like LISP than it is like Spin.

    Ii was thinking more from already have Multiple parsers angle.

    As an example, below is some code (ESP8266, github, for NeoPixels)

    At a quick glance I'm not seeing any brick-walls there - for loops and if-else look like almost any language.
    Modulus, floor division & masking are used, also nothing too strange.
    Assign of multi-elements is a little more advanced.
    from machine import Pin
    from neopixel import NeoPixel
    import time
    
    
    def demo(pin, n):
        np = NeoPixel(Pin(pin), n)
    
        # cycle
        for i in range(4 * n):
            for j in range(n):
                np[j] = (0, 0, 0)
            np[i % n] = (255, 255, 255)
            np.write()
            time.sleep_ms(25)
    
        # bounce
        for i in range(4 * n):
            for j in range(n):
                np[j] = (0, 0, 128)
            if (i // n) % 2 == 0:
                np[i % n] = (0, 0, 0)
            else:
                np[n - 1 - (i % n)] = (0, 0, 0)
            np.write()
            time.sleep_ms(60)
    
        # fade in/out
        for i in range(0, 4 * 256, 8):
            for j in range(n):
                if (i // 256) % 2 == 0:
                    val = i & 0xff
                else:
                    val = 255 - (i & 0xff)
                np[j] = (val, 0, 0)
            np.write()
    
        # clear
        for i in range(n):
            np[i] = (0, 0, 0)
        np.write()
    
  • The big difference is that there are no declared types in Python. That implies a much more sophisticated runtime than is required for Spin. I guess Eric has a heap manager for BASIC strings so maybe that could be leveraged. However, why not have real MicroPython on the P2 which probably has the resources to run it rather than a severely limited subset? I suppose one thing you could do is convince Chip to align the major Spin syntax better with Python so things like if statements and other control structures are identical.
  • Right.

    MicroPython is it's own thing. Spin should be it's own thing.

    Looks like we can get MicroPython once we've got something reasonable to build it with. Seems to me, that path will make sense in a short while.

  • jmgjmg Posts: 15,140
    David Betz wrote: »
    The big difference is that there are no declared types in Python. That implies a much more sophisticated runtime than is required for Spin. I guess Eric has a heap manager for BASIC strings so maybe that could be leveraged.

    Yes, plus BASIC has inbuilt support for many things, taking a quick look at MicroPython Time functions for possible issues

    utime.localtime([secs]) utime.mktime() - more advanced RTC date/time 8-tuples, could be optional ?

    utime.sleep(seconds) - can take a float, but Eric already has float support. The text suggests float is deprecated, in favour of the utime.sleep_ms(ms) utime.sleep_us(us)

    One easy support would be to limit to allow const float, which then compile time converts and calls either of utime.sleep_ms(u32) utime.sleep_us(u32) ?

    Also :
    utime.ticks_ms() utime.ticks_us() utime.ticks_cpu()
    The only operations available for them are ticks_diff() and ticks_add() functions


    David Betz wrote: »
    However, why not have real MicroPython on the P2 which probably has the resources to run it rather than a severely limited subset?
    Of course, I am sure that will eventually come, but that also looks like consuming a good portion of P2 memory as well. It's unclear of the Speed/memory numbers this will have on P2.
    Will it allow in-line assembler ?

    David Betz wrote: »
    I suppose one thing you could do is convince Chip to align the major Spin syntax better with Python so things like if statements and other control structures are identical.
    That's a whole different topic, but probably more a question for Ken, than Chip.
    Ken will know what Parallax customers are asking for, and what mix of Spin / Python they have/want in their classes etc.

    Maybe there is room for a pragma/switch, that allows a SpinP to exist ? (Spin with the more Python compatible changes you mention)

  • marsman2020marsman2020 Posts: 71
    edited 2018-12-02 22:21
    jmg wrote: »
    David Betz wrote: »
    jmg wrote: »
    Since you have multiple front end parsers working, have you toyed with the idea of a Python-ish parser, to allow users to paste in Python code (with some caveats obviously)
    I've found there are a couple of Python pre-processors, since you would need a means to do a #IFDEF Running_on_P2 type decisions.
    "Some caveats" is an understatement. People keep thinking that because both Spin and Python determine block structure by indenting that they are somehow similar. They aren't really. Python is more like LISP than it is like Spin.

    Ii was thinking more from already have Multiple parsers angle.

    As an example, below is some code (ESP8266, github, for NeoPixels)

    At a quick glance I'm not seeing any brick-walls there - for loops and if-else look like almost any language.
    Modulus, floor division & masking are used, also nothing too strange.
    Assign of multi-elements is a little more advanced.

    Python is a complete object-oriented language. I don't think some kind of bolt-on parser will work. It would have to keep track of the state of all the different objects, while maintaining compatibility with real Python. It would only work as part of a compiler, which would eliminate one of the major positive points of Python - the interactive RPEL prompt where you can play with code in realtime. Those np. calls in the code you posted? They refer to objects in Numpy which is a major Python library with lots of objects and code.

    I don't want a half-baked solution. I want standard MicroPython running on the P2 with extensions to handle the multiple cogs. The hardware is more than capable. MicroPython is a complete re-implementation created specifically to allow Python to fit on microcontrollers. The minimal version is 80 KB of ARM code and can run with 4K of RAM. I don't see it benefiting Parallax to have some special half-baked version of Python that isn't compatible with the version that the rest of the community is using for microcontrollers.

    The entire tool space for P1 is full of no longer active or maintained tools. Please please please don't do this again to P2. If a tool isn't going to be a long term project with multiple contributors driving it to stability - it might be better to just not do it at all.
  • marsman2020,
    You do realize that most of those tools were made by community members of their own accord. You can't stop that.

    Only a few of them are parallax supported, and they for the most part are still working/maintained at least to some level.
  • jmgjmg Posts: 15,140
    It would only work as part of a compiler, which would eliminate one of the major positive points of Python - the interactive RPEL prompt where you can play with code in realtime.
    I guess Ken would need to check how important REPL support was, for his customers.
    I don't want a half-baked solution. I want standard MicroPython running on the P2 with extensions to handle the multiple cogs. The hardware is more than capable. MicroPython is a complete re-implementation created specifically to allow Python to fit on microcontrollers. The minimal version is 80 KB of ARM code and can run with 4K of RAM.
    I think everyone agrees that is the ideal, however that does not exist right now, even as a road-map.

    Fastspin does exist, and seems remarkably flexible, hence my questions for Eric.

    Eric or Chip could also investigate David Betz's suggestion of " to align the major Spin syntax better with Python so things like if statements and other control structures are identical."
    Maybe that's called SpinP ?
  • jmg wrote: »
    Eric or Chip could also investigate David Betz's suggestion of " to align the major Spin syntax better with Python so things like if statements and other control structures are identical."
    Maybe that's called SpinP ?
    I was actually kidding about this. Spin and Python are enough different that there is really no point in making them look superficially similar. That would likely be even more confusing. Let Spin be Spin and port MicroPython to P2 so you have real Python.
  • RaymanRayman Posts: 13,800
    edited 2018-12-03 17:29
    I've been using FastSpin for P2 assembly.
    Noticed 2 differences between this and Pnut.
    1. FastSpin allows symbols > 30 characters
    2. FastSpin allows integers in floating point expressions

    Guess that's pretty good compatibility...

    Also, fastspin gives a warning if you use CMP without setting any flags...
  • jmg wrote: »
    This Multi-language and mixed language approach will have wide appeal.
    Since you have multiple front end parsers working, have you toyed with the idea of a Python-ish parser, to allow users to paste in Python code (with some caveats obviously)

    Unfortunately Python is very different from Spin or BASIC. In Spin, a statement like:
     a = a + b
    
    always translates to something like:
      add a, b
    
    In BASIC or C this might also translate to a function call to string concatentation or a floating point add, depending on the types of a and b; but we can tell this at compile time. That's a key point.

    In Python (or LISP, or Javascript) the decision of which routine to call to perform an add has to be left until run time. That is, the types of a and b are not fixed at compile time and indeed can change during the course of program execution. That's a very different model of language, and requires different handling (which is why those languages are normally implemented with an interpreter rather than a compiler).

    Eric
  • Clock LoopClock Loop Posts: 2,069
    edited 2018-12-03 22:03
    David Betz wrote: »
    I was actually kidding about this.

    :cold_sweat: You have an EXCELLENT poker face.
  • RaymanRayman Posts: 13,800
    edited 2018-12-03 22:47
    Never mind... Had "fit" in the wrong place...
  • RaymanRayman Posts: 13,800
    edited 2018-12-04 14:25
    I think I did just find a real issue...

    PNut checks the assigned value for "orgh" to make sure it is not already exceeded.
    Gives a "Hub origin already exceeds target." error message.


    I had this line in my code:
    orgh    BmpAddressBackground - $436
    

    It was fine until I added a bunch of stuff before this... Then, went off the rails with no warning...
  • When you say it went off the rails, did PNut issue the error message or did it get in a hung state. The error message is the correct thing to do. An ORGH will fill in with zeros from the previous address to the new address. It is an error if the new address is less than the previous address.

    BTW, p2asm issues this message when it happens:
    ERROR: ORGH address 3e8 less than previous address 3ec
    
  • Whoops, yes, it looks like fastspin does not report an error when orgh goes backwards. I'll look into that.

    Thanks for the bug report!
  • There's a new release of fastspin and spin2gui in the usual places:

    https://github.com/totalspectrum/spin2gui/releases
    https://github.com/totalspectrum/spin2cpp/releases

    It has a number of bugfixes and optimization improvements, a completely new and complete C preprocessor (which we may eventually be able to use for the other languages, but for now it's C only), and improved C support in general.

    For those not familiar with it, fastspin is a compiler for Spin, BASIC, and C that can produce P1 or P2 binaries. It works by converting the code to PASM and then compiling the PASM (unlike a regular Spin compiler that produces Spin bytecodes). It's like PropBasic or GCC in that regard. It compiles all of Spin 1, with some Spin 2 extensions. The BASIC dialect it supports is based on FreeBasic/Microsoft Basic rather than PropBasic.

    The Spin and BASIC support is fairly complete now, although the BASIC libraries are still a bit sparse. The C code is still a long way from being usable for everyday work, but I can run simple tests (I even got an earlier version of fft-bench to run). The main missing things from C now are structs/unions (those should be easy to add, we already support classes under the hood), enums, bitfields, and scoped variables.

    I will not pretend that fastspin/C (or "flexC" as it will eventually be called) will be a replacement for GCC -- it will only have a subset of C++, for one thing, and while its propeller specific optimizations are very good, its general optimizations will always lag behind GCC. However, the integrated PASM, Spin, and BASIC support may prove pretty useful.

    This is still a "beta" release, which means you should probably not expect everything to work perfectly. On the other hand the more people who test it, the better it will get, so if you're able to give it a try then please do so!
  • RaymanRayman Posts: 13,800
    Thanks!
    BTW: I really like the warning when you do a P2ASM cmp with no "wcz" .
    Saved me many times already...
  • Oh, and as a sample of fastspin's optimization, here's a simple C program that streams out data over a given pin as fast as it can:
    void streamout(int *buf, unsigned n, int pin)
    {
        int c;
        unsigned i, j;
        unsigned pinmask = 1<<pin;
        
        for (i = 0; i < n; i++) {
            c = *buf++;
            for (j = 0; j < 32; j++) {
                if (c & 1) {
                    OUTA |= pinmask;
                } else {
                    OUTA &= ~pinmask;
                }
                c = c >> 1;
            }
        }
    }
    
    and here is the PASM code that fastspin generates for it:
    _streamout
            mov     _var_06, #1
            shl     _var_06, arg3
            cmp     arg2, #0 wc,wz
     if_be  jmp     #LR__0003
            mov     _var_04, arg2
    LR__0001
            rdlong  _var_03, arg1
            mov     _var_05, #32
            add     arg1, #4
    LR__0002
            sar     _var_03, #1 wc
            muxc    outa, _var_06
            djnz    _var_05, #LR__0002
            djnz    _var_04, #LR__0001
    LR__0003
    _streamout_ret
            ret
    

  • Sounds great! I still wonder whether this could satisfy Parallax's requirements for C. I realize that there might be some customers who want full C++ but are there likely to be enough to justify the huge effort that would be required to bring up the GCC toolchain? How big a subset of C++ do you expect to support?
  • David Betz wrote: »
    Sounds great! I still wonder whether this could satisfy Parallax's requirements for C. I realize that there might be some customers who want full C++ but are there likely to be enough to justify the huge effort that would be required to bring up the GCC toolchain? How big a subset of C++ do you expect to support?

    I honestly don't know whether it will be able to satisfy Parallax's requirements. It almost certainly won't satisfy everyone's requirements :) and GCC is a much bigger and better supported project.

    I hope to support enough C++ to compile the output of spin2cpp (basic classes, no inheritence), which will kind of bring the project full circle.
  • David BetzDavid Betz Posts: 14,511
    edited 2018-12-06 02:43
    I'd almost be willing to bet that if it can compile the Simple Libraries and the output of BlocklyProp it will satisfy Parallax's educational needs and that seems to be their primary focus with P1. I'm not sure if it will be for P2 as well.
  • ersmith,
    If your compiler can compile the Simple Libraries and whatever C/C++ gets spit out of BlocklyProp, then it would certainly be enough for the short term coverage of Parallax's stuff. As far as I am away that code is fairly simple in its usage of C/C++, so it might be easy to cover it.

    I think it's pretty great that you have this all working already. Also, thank you for the effort!

    When your C++ coverage is more complete, I'll try to use this for my future P1 and P2 projects.
  • I don't believe that BlocklyProp emits any C++ code. I think it's all C code.
  • It uses the Simple Libraries, and that might contain some?
    If not, then even easier to get it up and running on P2 using fastspin
  • Roy Eltham wrote: »
    It uses the Simple Libraries, and that might contain some?
    If not, then even easier to get it up and running on P2 using fastspin
    I don't believe that Simple Libraries contains any C++ code.

  • Eric, I'm obviously missing something regarding the use of printf. I took a stroll through the fastspin binary and saw __builtin_printf which works well. As there is no library included with fastspin I did not try to #include anything. Can you help me understand the use of the C compilation abilities of fastspin? Your work is appreciated.
    Mike R.
  • pmrobert wrote: »
    Eric, I'm obviously missing something regarding the use of printf. I took a stroll through the fastspin binary and saw __builtin_printf which works well. As there is no library included with fastspin I did not try to #include anything.
    Actually there were some header files for fastspin, but I forgot to include them in fastspin.zip. Sorry! They are in spin2gui.zip if you download that. They're very incomplete so far though -- for example, stdio.h is just:
    #ifndef _STDIO_H_
    #define _STDIO_H_
    
    #define putchar _tx
    #define printf __builtin_printf
    
    #endif
    
Sign In or Register to comment.