Shop OBEX P1 Docs P2 Docs Learn Events
Spin to C/C++ converter version 0.98 — Parallax Forums

Spin to C/C++ converter version 0.98

ersmithersmith Posts: 5,900
edited 2012-09-27 09:44 in Propeller 1
I've just released version 0.98 of spin2cpp (see http://code.google.com/p/spin2cpp). This version has a better preprocessor (it now understands #include, #undef, #elseifdef, and #elseifndef), more consistent error reporting, and further improvements to the Catalina C output. Catalina can now compile spin2cpp output for the unmodified FullDuplexSerial object and the various floating point objects.

Bug reports are very welcome. I think spin2cpp is getting pretty mature now (particularly when used with PropGCC) and should be able to handle most objects that are found in practice. If you have some Spin code that spin2cpp doesn't work on, please let me know and I'll try to fix it.

Eric
«1

Comments

  • RsadeikaRsadeika Posts: 3,822
    edited 2012-09-04 05:04
    Very interesting program, Thanks Eric.

    For the beginners, this works in the Command Prompt window, if you are using Windows. You have to have a good understanding of how to set up your paths, if you will be using the program as is. I did the Hello.spin conversion to see how it works, make sure you have all the necessary files in the dir that you will be compiling the example. After viewing the hello.cpp file, I noticed there is a lot of stuff going on under the hood of the spin2cpp program. The hello.cpp file also shows how objects are being used, which is a good learning experience.

    Since I use SimpleIDE, a lot, I tried to get the resulting code to compile within the SimpleIDE program. Sorry to say that I did not get it to work. The following errors showed up:
    Project Directory: E:/spin2cpp/Hello/SIDE/
    
    propeller-elf-c++ -o a.out -Os -mlmm -I . -fno-exceptions -fno-rtti hello.cpp
    C:\Users\ray\AppData\Local\Temp\cc2DFWRe.o: In function `helloSpin::Demo()':
    
    (.text+0x24): undefined reference to `FullDuplexSerial::Start(int, int, int, int)'
    
    C:\Users\ray\AppData\Local\Temp\cc2DFWRe.o: In function `helloSpin::Demo()':
    
    (.text+0x38): undefined reference to `FullDuplexSerial::Str(int)'
    
    collect2: ld returned 1 exit status
    
    Done. Build Failed!
    
    Check source for bad function call or global variable name `FullDuplexSerial::Start(int, int, int, int)'
    
    C:\Users\ray\AppData\Local\Temp\cc2DFWRe.o: In function `helloSpin::Demo()':
    
    (.text+0x38): 
    
    
    I thought I had all the necessary files in the dir for SimpleIDE to work with. I did not try the command line version of PropGCC to achieve the same thing. Once I figure out how to get this to work with SimpleIDE I may try to do a conversion of some of the larger Spin programs that I have. Again, a very good teaching tool, so far.

    Ray
  • Heater.Heater. Posts: 21,230
    edited 2012-09-04 05:19
    That is only compiling hello.cpp so it has no FullDuplexSerial to link to.
    You will have to add the FullDuplexSerial.cpp, or whatever it is called, to the project.

    Or on the command line add FullDuplexSerial.cpp to the end of that compilation command.
  • ersmithersmith Posts: 5,900
    edited 2012-09-04 05:25
    Rsadeika wrote: »
    Since I use SimpleIDE, a lot, I tried to get the resulting code to compile within the SimpleIDE program. Sorry to say that I did not get it to work.

    The problem is that we have to add all of the files that spin2cpp produces, not just the top level "hello.cpp". In your example I think you need FullDuplexSerial.cpp to be added to the SimpleIDE project. You can get a list of these files on the command line by adding the "--files" option to spin2cpp.

    I added some preliminary spin2cpp support to SimpleIDE a while back, but Steve has had a whole lot of more important things to work on and he hasn't been able to get to integrating that into the main SimpleIDE release yet.

    In the meantime, an even easier way to do the complete conversion is to use the --elf option of spin2cpp. On the command line type:
    spin2cpp --elf -o hello.elf -O hello.spin
    
    and spin2cpp will automatically invoke propeller-elf-gcc for you with the "-O" option and produce the output in hello.elf. In order for this to work propeller-elf-gcc will have to be on the Windows PATH, which I think it should be in the default SimpleIDE installation.

    Eric
  • RsadeikaRsadeika Posts: 3,822
    edited 2012-09-04 05:43
    OK, I just added FullDuplexSerial.cpp to the Project Manager window, in SimpleIDE, and the program now works, I get a continuous flow of "Hello, world!" on the console window. I also noticed that the program does not use cout/cin, or at least cout in the program. Since I have had a limited exposure to cout/cin, it still seems like those two commands simplify I/O a whole lot, I could be wrong on that assumption.

    Ray
  • Heater.Heater. Posts: 21,230
    edited 2012-09-04 05:45
    cout/cin are very nice but tend to take up a lot of memory. There is nothing wrong with good old printf().
  • ersmithersmith Posts: 5,900
    edited 2012-09-04 05:55
    Rsadeika wrote: »
    OK, I just added FullDuplexSerial.cpp to the Project Manager window, in SimpleIDE, and the program now works, I get a continuous flow of "Hello, world!" on the console window. I also noticed that the program does not use cout/cin, or at least cout in the program. Since I have had a limited exposure to cout/cin, it still seems like those two commands simplify I/O a whole lot, I could be wrong on that assumption.

    spin2cpp just translates Spin to C++ directly. The original Hello.spin calls FullDuplexSerial for I/O, and so that's what the translated Hello.cpp does. There is no real equivalent to cout/cin in Spin -- the language has no standard input/output facilities, nor really a standard library.

    Eric
  • RossHRossH Posts: 5,336
    edited 2012-09-04 06:10
    ersmith wrote: »
    I've just released version 0.98 of spin2cpp (see http://code.google.com/p/spin2cpp). This version has a better preprocessor (it now understands #include, #undef, #elseifdef, and #elseifndef), more consistent error reporting, and further improvements to the Catalina C output. Catalina can now compile spin2cpp output for the unmodified FullDuplexSerial object and the various floating point objects.

    Bug reports are very welcome. I think spin2cpp is getting pretty mature now (particularly when used with PropGCC) and should be able to handle most objects that are found in practice. If you have some Spin code that spin2cpp doesn't work on, please let me know and I'll try to fix it.

    Eric

    Wow, Eric! I'm seriously impressed!

    Your example works a treat. Even more impressive is that a native C version of Fibo compiles down to a code size only a few hundred bytes smaller than the version you automatically generate from Spin! **

    The native C version also runs faster (around 25% when using CMM) but to be honest I'm not exactly sure why that should be - the fibo function is so trivial I would have expected them to be about the same no matter how the function is generated. I'll investigate further when I get some time.

    But you are definitely onto something here. Yet another potential avenue to help Spin users migrate to C!

    Ross.

    ** Actual code sizes (compiled with Catalina 3.7 using -Dprintf=t_printf to prevent Catalina pulling in the stdio I/O functions): native C = 1192 bytes, C generated from Spin to Spin2cpp = 1760 bytes.
  • ersmithersmith Posts: 5,900
    edited 2012-09-04 07:33
    RossH wrote: »
    The native C version runs faster (around 25% when using CMM) but to be honest I'm not exactly sure why that should be - the fibo function is so trivial I would have expected them to be about the same no matter how the function is generated. I'll investigate further when I get some time.
    Thanks for your kind words, Ross! I'm pleased that spin2cpp is working reasonably well with Catalina, although there's still some room for improvement (obviously).

    I suspect the speed issue is because spin2cpp generates some redundant initializations -- for example in the generated Fibo program there's a:
      int32_t result = 0;
    
    even though "result" is never actually used. I'll admit to some laziness there -- I was counting on the compiler to eliminate dead code for such cases, but I should probably do a pass to eliminate obviously dead code from the generated C++ before writing it out.

    Cheers,
    Eric
  • RossHRossH Posts: 5,336
    edited 2012-09-04 07:49
    ersmith wrote: »
    I suspect the speed issue is because spin2cpp generates some redundant initializations -- for example in the generated Fibo program there's a:
      int32_t result = 0;
    
    even though "result" is never actually used. I'll admit to some laziness there -- I was counting on the compiler to eliminate dead code for such cases, but I should probably do a pass to eliminate obviously dead code from the generated C++ before writing it out.

    Cheers,
    Eric

    In such a small function, that would probably be enough to do it - LCC does not eliminate unused variables. This particular case would be easy to detect and I could add a check that would do so - I'll look into doing that when I have time.
  • RsadeikaRsadeika Posts: 3,822
    edited 2012-09-04 09:55
    I just did another test run of spin2cpp, I ran the AssemblyToggle.spin example, page 340 in my Propeller Manual, using SimpleIDE in Spin mode. Then I did the spin2cpp conversion, and ran that code. The code ran in Spin mode, and in C++ mode, the big noticeable difference was that the LED flashed somewhat quicker in the C++ mode, than in the Spin mode. I also used the Propeller tool to run the program, just to make sure it ran from that program. Out of curiosity I looked in Command Prompt window dir to see what the size of the files were.

    SimpleIDE Spin mode : 384 bytes
    Propeller Tool : 407 bytes
    SimpleIDE CPP mode : 861 bytes (This is the size that spin2cpp produced)

    I was expecting that the file size of the PropGCC C++ would be larger, but the real surprise was that the file size that the Propeller tool produced was bigger than what SimpleIDE in Spin mode produced. I am guessing that since SimpleIDE uses some program from BST, that may have something to do with it, not sure what.

    I guess probably the next experiment would be is to clean up the .cpp result by inserting the PASM code as inline, and see if that reduces the .cpp code size, and by how much. Although, I did notice this in the .cpp program:
    uint8_t LED16pasm::dat[] = {
      0x06, 0xec, 0xbf, 0xa0, 0xf1, 0x11, 0xbc, 0xa0, 0x09, 0x10, 0xfc, 0x80, 0x07, 0x10, 0xbc, 0xf8, 
      0x06, 0xe8, 0xbf, 0x6c, 0x03, 0x00, 0x7c, 0x5c, 0x00, 0x00, 0x01, 0x00, 0x80, 0x8d, 0x5b, 0x00, 
    };
    
    This kind of looks like inline asm (binary equivalent), but I am not sure.

    Ray
  • ersmithersmith Posts: 5,900
    edited 2012-09-04 10:36
    Rsadeika wrote: »
    I guess probably the next experiment would be is to clean up the .cpp result by inserting the PASM code as inline, and see if that reduces the .cpp code size, and by how much. Although, I did notice this in the .cpp program:
    Yes, those bytes are the compiled PASM code from the DAT section. spin2cpp converts all of the Spin file, including the PASM. It assembles the PASM into binary rather than trying to put inline assembly into the .cpp file; this allows for better compatibility, since gas and PASM have slightly different syntaxes and features. Trying to juggle inline assembly so that the PASM is translated to GNU assembler, while still preserving all the features that Spin requires (such as access to the bytes of the compiled PASM) would be very difficult, so spin2cpp takes the easier route of converting the PASM to binary and putting the result in the .cpp file.
  • SRLMSRLM Posts: 5,045
    edited 2012-09-04 12:27
    ersmith wrote: »
    Yes, those bytes are the compiled PASM code from the DAT section. spin2cpp converts all of the Spin file, including the PASM. It assembles the PASM into binary rather than trying to put inline assembly into the .cpp file; this allows for better compatibility, since gas and PASM have slightly different syntaxes and features. Trying to juggle inline assembly so that the PASM is translated to GNU assembler, while still preserving all the features that Spin requires (such as access to the bytes of the compiled PASM) would be very difficult, so spin2cpp takes the easier route of converting the PASM to binary and putting the result in the .cpp file.

    On my PropGCC wishlist is the ability to have inline PASM. I wonder if it would be possible to have a preprocessor that scans the CPP file and converts the PASM to binary, and then it's compatible?
  • ersmithersmith Posts: 5,900
    edited 2012-09-04 12:59
    SRLM wrote: »
    On my PropGCC wishlist is the ability to have inline PASM. I wonder if it would be possible to have a preprocessor that scans the CPP file and converts the PASM to binary, and then it's compatible?

    spin2cpp can actually do this, since it supports inline C code. If you have a comment that starts with {++ then it's passed through as verbatim C code.
    For example, you could do an LED toggle program like this:
    { Tell spin2cpp that we do not need any Spin methods to be generated }
    {++!nospin}
    
    ''
    '' PASM LED toggling program
    ''
    
    CON
      pin = 15
    
    DAT
    entry
        or    DIRA, pinmask
        or    OUTA, pinmask
        mov    waittime,CNT
        add    waittime,pausetime
    loop
        waitcnt    waittime,pausetime
        xor    OUTA, pinmask
        jmp    #loop
    
    pinmask      long (1<<pin)
    pausetime long 40_000_000
    waittime  long 0
    
    {++
    
    /*
     * here is the actual C code that runs the PASM example above
     */
    #include <propeller.h>
    #include <stdio.h>
    
    int main()
    {
        cognew(dat, 0);
        for(;;) {
            printf("hello from main\n");
            sleep(4);
        }
    }
    
    }
    

    The result after spin2cpp --ccode led2.c is reproduced below. I see that there is still some cleanup possible -- the #defines and thisobj declarations aren't necessary if {++!nospin} was given -- but overall it's not too bad, I think.
    //
    // automatically generated by spin2cpp on Tue Sep  4 16:54:18 2012
    // spin2cpp --ccode led2.spin 
    //
    
    #include <propeller.h>
    #include "led2.h"
    
    #ifdef __GNUC__
    #define INLINE__ static inline
    #define PostEffect__(X, Y) __extension__({ int32_t tmp__ = (X); (X) = (Y); tmp__; })
    #else
    #define INLINE__ static
    static int32_t tmp__;
    #define PostEffect__(X, Y) (tmp__ = (X), (X) = (Y), tmp__)
    #define waitcnt(n) _waitcnt(n)
    #define locknew() _locknew()
    #define lockret(i) _lockret(i)
    #define lockset(i) _lockset(i)
    #define lockclr(i) _lockclr(i)
    #define coginit(id, code, par) _coginit((unsigned)(par)>>2, (unsigned)(code)>>2, id)
    #define cognew(code, par) coginit(0x8, (code), (par))
    #define cogstop(i) _cogstop(i)
    #endif
    
    static led2 thisobj;
    static uint8_t dat[] = {
      0x07, 0xec, 0xbf, 0x68, 0x07, 0xe8, 0xbf, 0x68, 0xf1, 0x13, 0xbc, 0xa0, 0x08, 0x12, 0xbc, 0x80, 
      0x08, 0x12, 0xbc, 0xf8, 0x07, 0xe8, 0xbf, 0x6c, 0x04, 0x00, 0x7c, 0x5c, 0x00, 0x80, 0x00, 0x00, 
      0x00, 0x5a, 0x62, 0x02, 0x00, 0x00, 0x00, 0x00, 
    };
    
    
    /*
     * here is the actual C code that runs the PASM example above
     */
    #include <propeller.h>
    #include <stdio.h>
    
    int main()
    {
        cognew(dat, 0);
        for(;;) {
            printf("hello from main\n");
            sleep(4);
        }
    }
    
  • RaymanRayman Posts: 13,799
    edited 2012-09-04 13:36
    I thought PropGCC already supported inline assembly... Guess not.
    (Ok, I think I see it supports GNU inline assembly, but not native PASM)
    This looks like a nice way around that though.
  • ersmithersmith Posts: 5,900
    edited 2012-09-04 13:44
    Rayman wrote: »
    I thought PropGCC already supported inline assembly... Guess not.
    (Ok, I think I see it supports GNU inline assembly, but not native PASM)

    Right -- the GCC inline assembly uses the GAS assembler, which is just enough different from PASM that it's a pain to use existing PASM code. But if you're writing code from scratch the GAS inline assembly is quite powerful -- it has ways to interface with the C code directly so you can pass parameters to the assembly and even have the compiler optimizer interact (in very constrained ways) with the assembly.

    I see the spin2cpp inline C code as a convenient way to convert existing PASM, or to provide drivers that can compile either to C or to Spin.

    Eric
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-09-04 16:33
    Hi Eric,

    Nice work. Inline pasm is going to be a great addition. I like the way you can now output C or C++ - that means you can use Catalina or GCC.

    I've been working my way through C tutorials and sometimes the easiest answer is to run some Spin through your program and see what comes out!

    I was wondering if you have some thoughts about structures in C? One very useful thing in any language is to return multiple things from a subroutine. In Spin and early versions of Basic you declare a global variable but in C I understand the better solution is to get pointers to the variables and then pass the pointer, and 'unwrap' that inside the function. But I think structures can make that simpler - eg you can have an integer, and a long, and a string array, and you can bundle that up into a structure and pass the structure and then modify one or more of the values inside the function.

    I'm not entirely sure if a structure can work in Spin though, as I think the compiler would go and put the longs all in one group and the bytes for an array in a different group and they may not be contiguous. But maybe you can force things to stay in groups - perhaps with a big DAT section? Or maybe it does not matter that they are not contiguous in hub ram - all that matters is that as an abstract group they all stay together?

    Thinking it through, maybe Spin has more difficulty with structures than C. I guess thinking in reverse, is there anything in Spin2C that outputs a structure?
  • RaymanRayman Posts: 13,799
    edited 2012-09-04 17:23
    C is infinitely better for structures than Spin... C++ is even better because you can add things like functions to your structure and call it an object...

    But, you can do structures in Spin with some work...

    In VisualSpin, I have structures to represent forms and buttons and text and such...
    Alignment is a major issue though if you want to have byte and word types...
    Here's a "form" structure with bytes and words in it. The words are pointers to strings...
    msgbox   word           'forms need to be word aligned
    'Message Box form info
            byte  10  'top
            byte  15 'left
            byte 14  'height
            byte 30  'width
            word @msgboxTitle
            byte 0  'unused 'title color
            byte 14 'unused 'border color
            byte 0  'default button 'text color
            byte 1   'number of objects
            word @buttonMsgBoxOK  'address of OK button
    

    If everything is the same type, like this button structure, then it's a lot easier:
    buttonMsgBoxOK byte
            byte 1  'type 1=button
            byte  8  'top
            byte  10 'left
            byte 4  'height
            byte 8  'width
            byte 1   'hot-key 1-based index 
            byte 2   'on left up handler
            byte 1   'Text Color
            byte "OK",0  
    

    C is a lot nicer because I could do things like buttonMsgBoxOK.left=5 to change the position of the button...
    In Spin, I have to hard code it byte[@buttonMsgBoxOK+3]:=5
  • ersmithersmith Posts: 5,900
    edited 2012-09-04 17:28
    Dr_Acula wrote: »
    I've been working my way through C tutorials and sometimes the easiest answer is to run some Spin through your program and see what comes out!
    Beware: spin2cpp's C code isn't always very readable. Sometimes it has to do things in a somewhat "un-natural" way in C or C++ in order to get the same behavior as from the original Spin. For example, the normal way to repeat a loop a fixed number of times in C is with a for loop, but spin2cpp instead does a slightly cumbersome variable initialization and then do/while instead, because that was an easier way for me to get it to count in either direction like Spin does.
    I was wondering if you have some thoughts about structures in C? One very useful thing in any language is to return multiple things from a subroutine. In Spin and early versions of Basic you declare a global variable but in C I understand the better solution is to get pointers to the variables and then pass the pointer, and 'unwrap' that inside the function. But I think structures can make that simpler - eg you can have an integer, and a long, and a string array, and you can bundle that up into a structure and pass the structure and then modify one or more of the values inside the function.
    Right. Traditionally in C you group related items together in a structure, and then pass a pointer to the structure to functions (a pointer because it is faster; if you pass the structure instead then it has to be copied into a temporary space on the stack, which might be OK if you need to modify the structure inside the function and preserve it in the caller, but is usually more overhead than necessary).
    I'm not entirely sure if a structure can work in Spin though, as I think the compiler would go and put the longs all in one group and the bytes for an array in a different group and they may not be contiguous. But maybe you can force things to stay in groups - perhaps with a big DAT section?
    Spin really doesn't have structures. I guess the closest thing would be an array of longs, with each one representing a distinct item. You could also consider all the variables inside an object as belonging to a structure, since different instances of the object can have different values of the variables.
    Thinking it through, maybe Spin has more difficulty with structures than C. I guess thinking in reverse, is there anything in Spin2C that outputs a structure?

    spin2cpp outputs all the variables of an object together as a structure (or class, for C++ output, but a class is just a fancy structure :-)). This allows us to guarantee the layout of the variables in memory, since otherwise the C compiler is allowed to re-arrange where the variables are in memory. A lot of Spin programs make assumptions about how things are stored in memory and on the stack, so we have to carefully arrange things in the output C code to make them work.

    Eric
  • jazzedjazzed Posts: 11,803
    edited 2012-09-04 20:37
    ersmith wrote: »
    I added some preliminary spin2cpp support to SimpleIDE a while back, but Steve has had a whole lot of more important things to work on and he hasn't been able to get to integrating that into the main SimpleIDE release yet.

    It's coming. I had already started the spin-side branch (v0-8-x) and it was very before you sent me the v0-7-x diffs. Certain other things are in the way now, but they should be resolved in a few weeks so that I can focus on more important things like spin2c/cpp support.

    Rsadeika wrote: »
    I just did another test run of spin2cpp, I ran the AssemblyToggle.spin example, page 340 in my Propeller Manual, using SimpleIDE in Spin mode. Then I did the spin2cpp conversion, and ran that code. The code ran in Spin mode, and in C++ mode, the big noticeable difference was that the LED flashed somewhat quicker in the C++ mode, than in the Spin mode.

    What memory model ? COG ?

    Rsadeika wrote: »
    Out of curiosity I looked in Command Prompt window dir to see what the size of the files were.

    SimpleIDE Spin mode : 384 bytes
    Propeller Tool : 407 bytes

    As I recall SimpleIDE only counts program size to be consistent with BSTC.

    Rayman wrote: »
    I thought PropGCC already supported inline assembly... Guess not.
    (Ok, I think I see it supports GNU inline assembly, but not native PASM)

    They are very close. GCC users expect GAS syntax.
  • TorTor Posts: 2,010
    edited 2012-09-05 00:34
    Rayman wrote: »
    C is infinitely better for structures than Spin... C++ is even better because you can add things like functions to your structure and call it an object...
    You can add functions to your structs in C as well, and call it what you want.. :) - that's a common Unix device driver model.

    -Tor
  • David BetzDavid Betz Posts: 14,511
    edited 2012-09-05 03:52
    Tor wrote: »
    You can add functions to your structs in C as well, and call it what you want.. :) - that's a common Unix device driver model.

    -Tor
    That's a very good point. C's support of function pointers is another way in which C is more powerful than Spin.
  • RsadeikaRsadeika Posts: 3,822
    edited 2012-09-05 05:14
    jazzed:
    What memory model ? COG ?

    I ran it with all three Memory Models: COG, LMM, XMMC. The LED flashed three to four times faster in these modes, the Spin mode(s) were much slower, LED flashing. The significance of this, is the spin2cpp conversion missing something, or is SimpleIDE CPP mode missing something, or is this just a weird coincedence?

    To bad there are no more PASM examples that could be run to double check the conversion method. I think something like flashing two LEDs at different rates, running on two different COGS, in PASM might be something of interest. Anybody have some code for that kind of example? The QuickStart board would be my choice.

    Ray
  • ersmithersmith Posts: 5,900
    edited 2012-09-05 08:42
    Rsadeika wrote: »
    To bad there are no more PASM examples that could be run to double check the conversion method. I think something like flashing two LEDs at different rates, running on two different COGS, in PASM might be something of interest. Anybody have some code for that kind of example? The QuickStart board would be my choice.
    Not sure what you mean by "no more PASM examples that could be run". spin2cpp should be able to handle pretty much any object in the OBEX, at least, as long as the resulting code fits in memory. I've tried it with FullDuplexSerial, some VGA demos, the graphics demo (to get that one to fit I had to remove one of the buffers and make the demo single buffered) and various float objects.

    The PASM conversion can be tested by doing spin2cpp --dat, which just compiles the DAT section, and comparing the output to bstc's"bstc -c". So far all the examples I've tried have been identical, but there's always the chance of a bug somewhere.

    Eric
  • David BetzDavid Betz Posts: 14,511
    edited 2012-09-05 08:49
    ersmith wrote: »
    ]The PASM conversion can be tested by doing spin2cpp --dat, which just compiles the DAT section, and comparing the output to bstc's"bstc -c". So far all the examples I've tried have been identical, but there's always the chance of a bug somewhere.
    This is interesting. What is the output format produced by --dat? It seems like we should be able to use spin2cpp --dat to compile all of the PASM driver code we use in the loader and the various cache drivers. It might even be possible to use spin2cpp with cmm mode to compile Spin code like serial_helper.spin. Of course, in that case it would be better to rewrite it in C.
  • ersmithersmith Posts: 5,900
    edited 2012-09-05 10:48
    David Betz wrote: »
    What is the output format produced by --dat? It seems like we should be able to use spin2cpp --dat to compile all of the PASM driver code we use in the loader and the various cache drivers.
    It's a binary blob, just like bstc -c. The intention is that spin2cpp --dat could be a drop in replacement for bstc -c. (I was going to name the option "-c" to be even more bstc compatible, but it conflicts with a C compiler option so I changed it to --dat.)

    Yes, using spin2cpp to compile the PASM driver code would probably be an option. It might be nice to replace bstc in the propgcc tree -- not that bstc isn't a great tool (it certainly is!) but it would be kind of nice to use platform independent, C only tools to build the C compiler.

    Eric
  • RsadeikaRsadeika Posts: 3,822
    edited 2012-09-05 11:32
    I do not want to take over this thread, but I did want to double check the timing issue that I had with the first example. This code works as expected in both the Spin mode, and the spin2cpp conversion. The previous example must have been a fluke, unless I am doing something wrong or very different, in the new program below.

    Ray

    Spin code:
    {{
     * @file LED16pasm.spin
     * This is the main LED16pasm program start point.
    }} 
    
    {{
     * Main program function.
    }}
    pub main
    
        cognew(@Toggle, 0)
        cognew(@Blink, 0)
        
    DAT
        ORG  0
    Toggle   mov   dira, Pin
             mov   Time, cnt
             add   Time, #9
    :loop    waitcnt Time, Delay
             xor   outa, Pin
             jmp   #:loop
             
    Pin    long  |< 16
    Delay  long  6_000_000
    Time   res 1
    
    DAT
        ORG 0
    Blink    mov dira, Pin1
             mov Time1, cnt
             add Time1, #9
    :loop    waitcnt Time1, Delay1
             xor outa, Pin1
             jmp #:loop
    Pin1 long |<23
    Delay1 long 10_000_000
    Time1 res 1
    

    spin2cpp conversion code:
    //
    // automatically generated by spin2cpp on Wed Sep 05 14:02:57 2012
    // spin2cpp --elf -Os LED16pasm.spin 
    //
    
    #include <propeller.h>
    #include "LED16pasm.h"
    
    #ifdef __GNUC__
    #define INLINE__ static inline
    #define PostEffect__(X, Y) __extension__({ int32_t tmp__ = (X); (X) = (Y); tmp__; })
    #else
    #define INLINE__ static
    static int32_t tmp__;
    #define PostEffect__(X, Y) (tmp__ = (X), (X) = (Y), tmp__)
    #endif
    
    uint8_t LED16pasm::dat[] = {
      0x06, 0xec, 0xbf, 0xa0, 0xf1, 0x11, 0xbc, 0xa0, 0x09, 0x10, 0xfc, 0x80, 0x07, 0x10, 0xbc, 0xf8, 
      0x06, 0xe8, 0xbf, 0x6c, 0x03, 0x00, 0x7c, 0x5c, 0x00, 0x00, 0x01, 0x00, 0x80, 0x8d, 0x5b, 0x00, 
      0x06, 0xec, 0xbf, 0xa0, 0xf1, 0x11, 0xbc, 0xa0, 0x09, 0x10, 0xfc, 0x80, 0x07, 0x10, 0xbc, 0xf8, 
      0x06, 0xe8, 0xbf, 0x6c, 0x03, 0x00, 0x7c, 0x5c, 0x00, 0x00, 0x80, 0x00, 0x80, 0x96, 0x98, 0x00, 
    };
    int32_t LED16pasm::Main(void)
    {
      int32_t result = 0;
      cognew((int32_t)(&(*(int32_t *)&dat[0])), 0);
      cognew((int32_t)(&(*(int32_t *)&dat[32])), 0);
      return result;
    }
    
    
    LED16pasm MainObj__;
    
    int main() {
      return MainObj__.Main();
    }
    
    
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-09-05 11:54
    You don't specify a clock mode or frequency, so I think you will default to the RCFAST clock, which is about 12 MHz. I believe PropGCC defaults to the 80 MHz crystal-based clock. This will run about 7 times faster.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-09-05 16:32
    @David Betz
    This is interesting. What is the output format produced by --dat? It seems like we should be able to use spin2cpp --dat to compile all of the PASM driver code we use in the loader and the various cache drivers. It might even be possible to use spin2cpp with cmm mode to compile Spin code like serial_helper.spin. Of course, in that case it would be better to rewrite it in C.

    General question here - under the hood with things like printf and serial drivers and sd drivers, are the drivers for GCC written in C or Spin? Is there any spin at all?

    Restating what you are saying, if there is any spin, then everything can be converted to C. Maybe the only spin left is a tiny loader to get things started?
  • ersmithersmith Posts: 5,900
    edited 2012-09-05 17:06
    General question here - under the hood with things like printf and serial drivers and sd drivers, are the drivers for GCC written in C or Spin? Is there any spin at all?

    Restating what you are saying, if there is any spin, then everything can be converted to C. Maybe the only spin left is a tiny loader to get things started?

    The library drivers (and functions like printf) are all written in C. What's left in spin is indeed a tiny (16 byte) loader at the start of programs, which is actually hand crafted spin byte codes; and some board interfaces files and XMM memory drivers used by the propeller-load loader. Those are the drivers David was referring to.

    Eric
  • RsadeikaRsadeika Posts: 3,822
    edited 2012-09-26 03:53
    I just did a spin2cpp --ccode on IR_Remote.spin, a program by Tom Doyle, and it comes up with an error:
    "Unknown identifier used in function call" and lists waitpne, and waitpeq as the culprits. These are listed as legal commands in the manual, and it looks like they are being used correctly in the program. Any ideas?

    Ray
Sign In or Register to comment.