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

16465666769

Comments

  • ersmith wrote: »
    FlexC is the language (the C dialect that the FlexProp tools accepts). It will eventually be C99 compatible, with some C++ extensions and support for external modules.

    flexcc.exe is the command line tool that can compile FlexC programs. It's designed to be command line compatible with other C compilers, like cc (the standard Unix C compiler), gcc (the GNU C compiler), tcc (the Tiny C Compiler) and so on. flexcc also happens to be able to compile FlexSpin and FlexBASIC programs too, but perhaps some users won't care about that.

    Similarly, flexspin.exe is the command line tool for compiling Spin and Spin2 programs within FlexProp. It's designed to be mostly command line compatible with openspin and bstc. It can compile FlexBASIC and FlexC programs too.

    Hi Eric. Having Makefile and .o support sounds useful. Do you think at some point we'll be able to use FlexC it to compile MicroPython natively? Is that sort of where you are heading with these tools? That build environment certainly wants to build each file separately with Makefiles etc. And if so, do you expect it could hope to ultimately offer better performance to the translated compiled P1 code in terms of code size or speed?
  • rogloh wrote: »
    ersmith wrote: »
    FlexC is the language (the C dialect that the FlexProp tools accepts). It will eventually be C99 compatible, with some C++ extensions and support for external modules.

    flexcc.exe is the command line tool that can compile FlexC programs. It's designed to be command line compatible with other C compilers, like cc (the standard Unix C compiler), gcc (the GNU C compiler), tcc (the Tiny C Compiler) and so on. flexcc also happens to be able to compile FlexSpin and FlexBASIC programs too, but perhaps some users won't care about that.

    Similarly, flexspin.exe is the command line tool for compiling Spin and Spin2 programs within FlexProp. It's designed to be mostly command line compatible with openspin and bstc. It can compile FlexBASIC and FlexC programs too.

    Hi Eric. Having Makefile and .o support sounds useful. Do you think at some point we'll be able to use FlexC it to compile MicroPython natively? Is that sort of where you are heading with these tools? That build environment certainly wants to build each file separately with Makefiles etc. And if so, do you expect it could hope to ultimately offer better performance to the translated compiled P1 code in terms of code size or speed?

    Eventually I hope so.
  • ersmith wrote: »

    Eventually I hope so.

    Cool. It will be a fine thing to see MP running pure P2 code with your tools and the SPIN2 integration. If it can outdo translated P1 GCC that will be even better.
  • JRoarkJRoark Posts: 566
    edited 2020-10-24 - 17:34:43
    @ersmith When coding in BASIC using FlexGUI/FlexSpin V5.0.0-Beta:

    Compare these two lines of code:
    	print " Sin(x) = "; using "#.#####"; sin(x)  '<-- throws error
    	print using "#.#####"; sin(x); " = Sin(x)"   '<-- works fine
    
    The first line gives the error: "syntax error, unexpected USING, expecting $end or end of line or end or ':'". The second line compiles and runs fine. In other words the compiler wants any USING argument(s) to come before anything else in a PRINT statement.

    In most BASIC's i've used, the first example is considered legal syntax. I'm bumping this up not as an error, but as a difference. It may not be worth the time to "fix" this unless your intentions were to have both syntaxes work.

    Another oddity:
    	dim i as long
    	print (i = i+1)  ' compiles, but always returns 0
    	print (i += 1)   ' throws a compiler error
    
    I don't think either of these syntaxes passes the giggle-test. BASIC doesn't permit assignments within a PRINT. Again, maybe an edge case not worth spending too much time on.

    BTW: the fixed-point math is fast! A quick benchmark:
    	x = 0.707
    	a = sin(x)
    	b = cos(x)
    	c = tan(x)
    
    Using floating-point this takes 12060 cycles.
    Using fixed-point this takes just 2447 cycles.
    That's a 5:1 speed improvement for applications that use fixed-point math! Love it.

  • JRoark wrote: »
    @ersmith When coding in BASIC using FlexGUI/FlexSpin V5.0.0-Beta:

    Compare these two lines of code:
    	print " Sin(x) = "; using "#.#####"; sin(x)  '<-- throws error
    	print using "#.#####"; sin(x); " = Sin(x)"   '<-- works fine
    
    The first line gives the error: "syntax error, unexpected USING, expecting $end or end of line or end or ':'". The second line compiles and runs fine. In other words the compiler wants any USING argument(s) to come before anything else in a PRINT statement.

    The BASICs I'm used to require just one using clause, right after the print, and that's what I was thinking of. That kind of "print using" is pretty much like printf() in C, so you can do:
      print using "Sin(x) = #.####"; sin(x)
    

  • JRoarkJRoark Posts: 566
    edited 2020-10-24 - 19:05:33
    Got it. Given the C-relationship, that makes sense. It's even less work to write:
    	print using "#.##### X-position, #.##### Y-position"; x, y
    
    instead of
    	print using "#.#####"; x; " X-position, "; using "#.#####"; y; " Y-position"
    
    I like your way better.
  • Setting clock to 297 MHz in C messes up serial output...
    297 MHz is best match for 1080p video, but FlexProp C doesn't seem to like it...

    This works when is 300 instead of 297, but 297 gives garbage in the terminal window
    #define P2_TARGET_MHZ 297
    

    This is with the latest, 4.5.0 version.

    Also, just a thought... If loadp2.exe was included in the fastspin.zip package, it'd be all there. For those not using the FlexProp GUI, that is.
  • The smartpin mode uses a 16.6 fixed point format for the bit timing. What baud are you requesting? 300MHz / 2400baud = 125000, too big to fit in 16 bits. Or Eric has ignored the .6 fractional component. 297MHz / 115200baud = 2578.125

    Or maybe it's still bit-bashed and needs some love. :)

  • Rayman wrote: »
    Setting clock to 297 MHz in C messes up serial output...
    297 MHz is best match for 1080p video, but FlexProp C doesn't seem to like it...

    This works when is 300 instead of 297, but 297 gives garbage in the terminal window
    #define P2_TARGET_MHZ 297
    
    Hmmm, interesting. Obviously the bit mode calculation is off somewhere -- the problem is that the clock is not actually be set to 297 MHz, I think.

    There's an alternative way to specify the clock frequency in C, which is to define an enum constant called _clkfreq:
    enum { _clkfreq = 297000000 };
    
    That does seem to work correctly. I'll try to figure out what's wrong with the clock macro version.
    Also, just a thought... If loadp2.exe was included in the fastspin.zip package, it'd be all there. For those not using the FlexProp GUI, that is.

    Well, FlexProp is the all in one package, so that's what people should get if they want binaries for everything. loadp2 doesn't change very often, so I don't think it really needs to be released with flexspin.

    Cheers,
    Eric
  • FlexSpin version 5.0.0 has been released. Note that the executable file is called flexspin.exe now instead of fastspin.exe. There's also a new front end flexcc.exe which has gcc-like command line arguments, intended for use in Makefiles.

    Newcomers will probably find FlexProp (a GUI that's packaged with flexspin and loadp2) easier to get started with. See the link in my .signature for the FlexProp release.
  • Thanks Eric! I'm becoming more and more convinced the C is the way to go with P2 thanks to FlexProp.

    BTW: Regarding the 297 MHz issue, I'm able to fix it by getting the values to use from Spin2 like this:
    int main()
    {    //set the clock using setting in Platform.h
        //Regular way doesn't currently seem to work for 297 MHz, so getting settings from VGA driver
        //_clkset(_SETFREQ, _CLOCKFREQ);
        _clkset(vga.GetClockMode(), vga.GetClockFreq());
    
    PUB GetClockMode():r
        return _clkmode
    
    PUB GetClockFreq():r
        return  _clkfreq   
    

    Serial now works right too.
  • I just figured out how to use:
    _pinstart(LeftPin, p_dac_dither_rnd | p_dac_600r_2v | p_oe, _clockfreq() / SAMPLE_RATE, 0);
    

    in FlexProp C today...

    But, where are things like "p_dac_600r_2v" defined? I'm wondering where to find other values that can go there...
  • those P_nnn constants are in the SPin2 documentation
  • Ok, thanks. I get it now, same as Spin2...
  • Rayman,
    If you have the source for spin2cpp, then you can look in frontends/lexer.c, it has all the constants defined in there with their hex values.
  • Are there any tricks I need to do to share global variables between cogs?

    Have to mark them as volatile or anything?
  • This has worked in an earlier version of flexspin:
    #define pwmFreq  500
    #define pwmFrame 240
    #define pwmBase  freqPll / (pwmFreq * pwmFrame)
    
      __asm {
        fltl  #pinFan
        wrpin #0b01_01001_0,#pinFan
        wxpin ##(pwmFrame<<16+pwmBase),#pinFan
        drvl  #pinFan
        wypin #120,#pinFan
      }
    
    but now it throws an error "Operand too complex for inline assembly" at the wxpin line. The expression should actually collapse to a constant number. I don't know how I could simplify the expression. If I add one more #define it wouldn't help because the macro would expand to the original text, again.
  • Never mind. It was my fault, again. freqPll was not defined. But as often... a more precise error message would have helped. :wink:
  • RaymanRayman Posts: 11,493
    edited 2020-11-11 - 18:59:47
    @ersmith Just wanted to let you know that the mandelbrot.c example seems to be broken (if I'm seeing it right...) I'm pretty sure this used to work about a month ago...

    Here's what I'm seeing now:


    Nevermind, I updated to latest FlexSpin and it works now...
    4032 x 3024 - 4M
  • I recently go a p2 Edge product and was working with it and moving code over from the P1 in C.

    I thought I would try the code out on my P2 EVAL rev A board and found nothing works. I did pick the Rev A compile option but that doesn't seem to work.

    What instructs are different between the Propeller Rev A and Rev B that I could search through the listing for to determine what instruction maybe causing the issue?

    Mike
  • Rayman wrote: »
    Are there any tricks I need to do to share global variables between cogs?

    Have to mark them as volatile or anything?

    It would be prudent to mark them as volatile. "volatile" doesn't do anything in FlexC now, but in other compilers it may be necessary.
  • iseries wrote: »
    I recently go a p2 Edge product and was working with it and moving code over from the P1 in C.

    I thought I would try the code out on my P2 EVAL rev A board and found nothing works. I did pick the Rev A compile option but that doesn't seem to work.

    What instructs are different between the Propeller Rev A and Rev B that I could search through the listing for to determine what instruction maybe causing the issue?

    Mike

    The Rev A support may have bit-rotted. The main difference is in the PTRA accesses (including push and pop) which are not compatible between the processors.

    Unfortunately I barely have time to support the P1 and P2 rev B/C, so I think I'll have to drop the rev A support.
  • evanhevanh Posts: 10,088
    edited 2020-11-19 - 05:52:11
    iseries wrote: »
    What instructs are different between the Propeller Rev A and Rev B that I could search through the listing for to determine what instruction maybe causing the issue?
    Looks like the sign-extension fix also affected ALTx instructions.

    There is a large amount of non-instruction changes. Any streamer use is dead without careful editing of the mode values and even how the modes get set. Smartpins have a number of new modes and some have been moved.

    Final revA FPGA files was v32i I think.

    Further reading - https://forums.parallax.com/discussion/169282/list-of-changes-in-next-p2-silicon/p1

    EDIT: RevB/C has extra stages in the I/O paths of the verilog. That'll throw off timing for code that expects tight constraints on responses.

  • I realize there are code differences since Rev A and I am willing to live with them to use it as a development platform.

    The problem is that the code that doesn't work right now is the PushRegs and PopRegs which is used throughout all C code. If that one piece of code could be fixed I could work around the rest.

    I believe the fix is simply to add a NOP after the instruction modified by the SETQ instruction. It seems the SETQ acts on two instructions instead of just the one that was intended on Rev A chips.
       SETQ #2
       RDLONG startingReg, ptra
       NOP
       .....
    

    Mike
  • evanhevanh Posts: 10,088
    edited 2020-11-20 - 07:33:12
    I don't think the functioning of that combo changed from revA the revB. But the encoding for PTRA in the RDLONG did. Presuming there is a .lst file when compiling C, examining the RDLONG instruction encoding might shine some light.

    Err, maybe not. Comparing v32 google doc against latest doc, the simple case above seems would be the same encoding on both revA and revB.

  • RaymanRayman Posts: 11,493
    edited 2020-11-20 - 15:05:46
    Just ran into a major bug with structures and booleans...

    Seems you can have one boolean in a structure and you can have two sequential booleans in a structure.
    But, if you have two booleans, separated by an int, all the pointers after declaration of this structure are off, and my program explodes...

    Here is the structure that breaks the compiler:
    typedef struct
    {
        int type;               //Object type check=6
        int top;                //Top tile #
        int left;               //Left tile #
        int width;              //Width in tiles
        int height;             //Height in tiles
        int data;               //user data
        int status;             //status: Lowest bit of status is invisible flag, Second lowest bit is disabled flag
        int textforecolor;      //Text foreground color
        int textbackcolor;      //Text background color
        int buttoncolor0;       //button color 0
        int buttoncolor1;       //button color 1
        int buttoncolor2;       //button color 2
        int buttoncolor3;       //button color 3
        int value;              //value
        int min;                //min. value
        int max;                //max. vlaue
        int digits;             //#digits
        bool bShowSign1;         //Show sign?
        int base1;               //base (10,2,16)
        bool bShowButtons1;      //show buttons?
        bool bOnlyClicked1;      //Affect only clicked digit?
    } FormNumberEdit;
    

    I've attached the source that shows this...
  • Wow, that's gonna be tough to execute if booleans and non-booleans are packed together. I assume C standard doesn't pack booleans with non-booleans though.

  • There's a pack keyword that tell the compiler what to do with the structure. By default they are not packed. So each value would be on a word boundary leaving holes in memory.

    Packed would put each value one after the other in memory leaving no holes.

    Mike
  • bool is usually implemented as a byte in size (or char), but sometimes (for older compilers) is 4 bytes (int).

    You normally only get smaller than a byte using bitfields...
  • evanhevanh Posts: 10,088
    edited 2020-11-20 - 18:52:59
    iseries wrote: »
    By default they are not packed. So each value would be on a word boundary leaving holes in memory.
    Ah, and that'll be word size dependant I guess. As in, if the word size of the declared value is a byte then non-packed will be on byte boundaries, right?

    EDIT: It's funny, I've used C a bit before but never thought about any of this. When I have shared complex structures between programs it's been config/display setups in the form of text files.

Sign In or Register to comment.