+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 20 of 36

Thread: Spin to C/C++ converter version 0.98

  1. #1

    Default Spin to C/C++ converter version 0.98

    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

  2. #2

    Default Re: Spin to C/C++ converter version 0.98

    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:
    Code:
    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

  3. #3

    Default Re: Spin to C/C++ converter version 0.98

    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.

  4. #4

    Default Re: Spin to C/C++ converter version 0.98

    Quote Originally Posted by Rsadeika View Post
    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:
    Code:
    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

  5. #5

    Default Re: Spin to C/C++ converter version 0.98

    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

  6. #6

    Default Re: Spin to C/C++ converter version 0.98

    cout/cin are very nice but tend to take up a lot of memory. There is nothing wrong with good old printf().

  7. #7

    Default Re: Spin to C/C++ converter version 0.98

    Quote Originally Posted by Rsadeika View Post
    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

  8. #8

    Default Re: Spin to C/C++ converter version 0.98

    Quote Originally Posted by ersmith View Post
    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.
    Last edited by RossH; 09-04-2012 at 03:40 PM. Reason: added actual code sizes
    Catalina - a FREE ANSI C compiler for the Propeller.
    Download it from http://catalina-c.sourceforge.net/

  9. #9

    Default Re: Spin to C/C++ converter version 0.98

    Quote Originally Posted by RossH View Post
    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:
    Code:
      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

  10. #10

    Default Re: Spin to C/C++ converter version 0.98

    Quote Originally Posted by ersmith View Post
    I suspect the speed issue is because spin2cpp generates some redundant initializations -- for example in the generated Fibo program there's a:
    Code:
      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.
    Catalina - a FREE ANSI C compiler for the Propeller.
    Download it from http://catalina-c.sourceforge.net/

  11. #11

    Default Re: Spin to C/C++ converter version 0.98

    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:
    Code:
    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

  12. #12

    Default Re: Spin to C/C++ converter version 0.98

    Quote Originally Posted by Rsadeika View Post
    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.

  13. #13

    Default Re: Spin to C/C++ converter version 0.98

    Quote Originally Posted by ersmith View Post
    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?

  14. #14

    Default Re: Spin to C/C++ converter version 0.98

    Quote Originally Posted by SRLM View Post
    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:
    Code:
    { 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.

    Code:
    //
    // 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);
        }
    }

  15. #15

    Default Re: Spin to C/C++ converter version 0.98

    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.

  16. #16

    Default Re: Spin to C/C++ converter version 0.98

    Quote Originally Posted by Rayman View Post
    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

  17. #17

    Default Re: Spin to C/C++ converter version 0.98

    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?

  18. #18

    Default Re: Spin to C/C++ converter version 0.98

    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...
    Code:
    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:
    Code:
    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

  19. #19

    Default Re: Spin to C/C++ converter version 0.98

    Quote Originally Posted by Dr_Acula View Post
    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

  20. #20

    Default Re: Spin to C/C++ converter version 0.98

    Quote Originally Posted by ersmith View Post
    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.


    Quote Originally Posted by Rsadeika View Post
    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 ?


    Quote Originally Posted by Rsadeika View Post
    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.


    Quote Originally Posted by Rayman View Post
    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.

+ Reply to Thread

Similar Threads

  1. CSPIN - A C-to-Spin Converter
    By Dave Hein in forum Propeller 1 Multicore Microcontroller
    Replies: 67
    Last Post: 06-20-2014, 11:55 PM
  2. Spin to PASM converter !!!!
    By karakiko in forum Propeller 1 Multicore Microcontroller
    Replies: 4
    Last Post: 12-22-2013, 02:46 AM
  3. New version of spin to C++ translator
    By ersmith in forum Propeller GCC
    Replies: 49
    Last Post: 09-11-2012, 09:59 AM
  4. Spin converter for Unix time
    By Phil Pilgrim (PhiPi) in forum Propeller 1 Multicore Microcontroller
    Replies: 3
    Last Post: 03-28-2012, 09:19 PM
  5. Simple Spin to PASM converter?
    By Philldapill in forum Propeller 1 Multicore Microcontroller
    Replies: 4
    Last Post: 06-16-2008, 10:13 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts