Interactive Spin to Pasm or C converter

24567

Comments

  • cavelamb wrote: »

    I've been waiting about a year on this, er.
    So I'm waiting as fast as I can?

    So you just keep plugging along at it. :)
    If you can make it work you will have created something very useful.
    Basically it would be a SPIN compiler.
    Like I said, something VERY useful.

    I will keep plugging away, and all the feedback and testing that others are doing helps a lot.

    While you're waiting, you could try converting your program to C and using PropGCC to compile it. That will actually produce better code than the PASM output of Spin Converter, and it's available now. The disadvantage is that it does require PropGCC, which is pretty big.

    (The C and C++ conversion in Spin Converter is complete, as far as I know, so it should be able to handle any program.)

  • I made a living coding inner loops for C-hags.

    This is a karma payback?
  • ersmith wrote: »
    ...(The C and C++ conversion in Spin Converter is complete, as far as I know, so it should be able to handle any program.)

    Just wow. This basically opens LMM and CMM for spin?

    So can I now write spin programs bigger then 32K, convert them to C or C++ and run thru PropGCC/SimpleIDE and use external memory like SPI-RAM for more space? Even with sub objects and PASM?

    If so this is very cool.

    Mike


    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • msrobots wrote: »
    ersmith wrote: »
    ...(The C and C++ conversion in Spin Converter is complete, as far as I know, so it should be able to handle any program.)

    Just wow. This basically opens LMM and CMM for spin?

    So can I now write spin programs bigger then 32K, convert them to C or C++ and run thru PropGCC/SimpleIDE and use external memory like SPI-RAM for more space? Even with sub objects and PASM?

    Yes.

    The caveat is that the GUI is very new, and mostly oriented towards single file at a time operation. But the command line version of the program (spin2cpp) has been working for quite a while now, and has been used to do a lot of Spin to C/C++ conversions. It automatically converts subobjects, and has a PASM assembler built in. And yes, compiling to XMM is also possible.
  • I pulled all the foolishness out of the TFT driver and cleaned up some.
    And coded some simple (minded) PASM to wiggle the control pins.

    The TFT_2016.ZIP file only has TFT_CLS in the main program.
    Can you use this as a (Way More Involved) test file?


  • cavelamb wrote: »
    I pulled all the foolishness out of the TFT driver and cleaned up some.
    And coded some simple (minded) PASM to wiggle the control pins.

    The TFT_2016.ZIP file only has TFT_CLS in the main program.
    Can you use this as a (Way More Involved) test file?
    That one already launches a COG (there's a coginit in the init function; see TFT_PASM_IMAGE). Also, having the CS_HIGH, CS_LOW and so on routines in the DAT section doesn't help anything (the spn compiler can't call functions in DAT; as it turns out those functions aren't used anyway in the version you posted).

    Here's a TFT2.spin that has everything except the initialization cut out. The next preview release (that I'll be putting up shortly) can compile it. Whether it will work correctly is another question entirely! It probably won't work right, but I'd like to hear your experience.
  • I've uploaded a new preview release. This fixes a number of bugs, both in the GUI and in the compiler itself. The GUI Options menu now as a "Make Binary" option which if checked causes spin2cpp to be run twice, once to produce the PASM and then again to produce a .binary file. There are a few simple examples that can be run (hello world, blinking led, and some basic math functions).

    In C/C++ mode all of Spin is supported. For PASM output we still only support one object (see the demos for a way to kind of get around this with #include). Many builtin functions like coginit/cognew, lockset/lockclr, longmove, etc. are not supported yet. DAT sections are supported now, but they're output as "binary blobs", which seems counterintuitive but is a consequence of the compiler implementation. (On the other hand if you already have PASM in a DAT section why do you need to make new PASM form it? :) )

    I'd love to hear any feedback / suggestions. This release is still very limited, but it can produce executable programs, and I think we're getting close to the point where OBEX objects can be converted.
  • Eric,

    Any chance that you can modify the Makefile to allow building just the command line portions? Building on Mac OS X requires Tk/Tcl (I believe) and I'm not thrilled to have to install ports or homebrew in order to get Tk/Tcl (my app build system does not get along with changes that those package systems)...

    dgately
    Livermore, CA (50 miles SE of San Francisco)
  • dgately wrote: »
    Any chance that you can modify the Makefile to allow building just the command line portions? Building on Mac OS X requires Tk/Tcl (I believe) and I'm not thrilled to have to install ports or homebrew in order to get Tk/Tcl (my app build system does not get along with changes that those package systems)...

    Actually the GUI isn't built by default -- the regular make just builds spin2cpp, the command line portion. To get the GUI requires "make spincvt.zip", and that's kind of specialized because it builds a Windows only GUI.

    I'm on Linux and I usually use the command line version for testing and such. I don't build a GUI app on Linux; for testing the GUI I either run spinconvert.tcl "by hand" or else build the Windows GUI and run it with Wine.
  • OK, so then there are some errors that show up on make that appear to be related to Mac OS X's use of clang.

    These are just two of the errors. The compiler shuts down after about 30 of these, stating "too many errors"...
    backends/asm/outasm.c:280:18: error: implicit conversion from enumeration type 'Operandkind' (aka 'enum Operandkind') to different enumeration type 'enum IROpcode'
          [-Werror,-Wenum-conversion]
      IR *ir = NewIR(code);
               ~~~~~ ^~~~
    backends/asm/outasm.c:290:16: error: implicit conversion from enumeration type 'enum IROpcode' to different enumeration type 'Operandkind' (aka 'enum Operandkind')
          [-Werror,-Wenum-conversion]
      EmitOp1(irl, OPC_LABEL, op);
      ~~~~~~~      ^~~~~~~~~
    

    All displayed errors are based in "backends/asm/outasm.c". Can these enumeration errors be removed?

    Thank you for your consideration,
    dgately
    Livermore, CA (50 miles SE of San Francisco)
  • ersmith wrote: »
    cavelamb wrote: »
    I pulled all the foolishness out of the TFT driver and cleaned up some.
    And coded some simple (minded) PASM to wiggle the control pins.

    The TFT_2016.ZIP file only has TFT_CLS in the main program.
    Can you use this as a (Way More Involved) test file?
    That one already launches a COG (there's a coginit in the init function; see TFT_PASM_IMAGE). Also, having the CS_HIGH, CS_LOW and so on routines in the DAT section doesn't help anything (the spn compiler can't call functions in DAT; as it turns out those functions aren't used anyway in the version you posted).
    those bit-wigglers are only called by the PASM code in the DAT, so no har - no foul.
    But not a speedup either.
    Here's a TFT2.spin that has everything except the initialization cut out. The next preview release (that I'll be putting up shortly) can compile it. Whether it will work correctly is another question entirely! It probably won't work right, but I'd like to hear your experience.

    I dropped it into RAM and it looks like it INITed.
    At least it cleared the previous contents from the screen.

    I confused myself again. I mistakenly thought the Propeller Tool had variable trace capability.
    It has been most of a year since I played around with it.
    I think I was mistaken.

    So I tried to drop the rest of the (prior) SPIN code in place.
    It compiled ok, but something didn't work right.
    Never cleared the display.

    Let me look at it more carefully.
    See i f I can get the terminal thingie working and see if I can see InitTime.
    Don't have any more time tonight...

  • dgately:

    I've fixed at least some of the enumeration errors, although gcc is not too concerned about enumeration conversions in C mode (only in C++) so it's hard to track them all down.

    I also changed the Makefile to remove -Werror, so at least you should be getting warnings instead of errors.
  • dgatelydgately Posts: 927
    edited March 2016 Vote Up0Vote Down
    I've now built the latest source on Mac OS X...

    I do get a crash when I run "spin2cpp --asm hello.spin" (in: "spinconvert/examples/") where the code includes: "#include "serial.def"...

    Building a more simple example (led.spin) completes without segmentation fault. Removing that #include and reference to ser_str provides a completion. So, something about the #include (I think).

    Crash dump info:
    Crashed Thread:        0  Dispatch queue: com.apple.main-thread
    
    Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
    Exception Codes:       KERN_INVALID_ADDRESS at 0xffffffffebc0f700
    
    VM Regions Near 0xffffffffebc0f700:
    --> shared memory          00007fffffeff000-00007ffffff00000 [    4K] r-x/r-x SM=SHM  
        
    
    Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
    0   spin2cpp                      	0x0000000103cd2210 PrintOperandAsValue + 16 (p1ir.c:73)
    1   spin2cpp                      	0x0000000103cd28f5 P1AssembleIR + 949 (p1ir.c:318)
    2   spin2cpp                      	0x0000000103cd31c3 IRAssemble + 99 (p1ir.c:396)
    3   spin2cpp                      	0x0000000103ccf6fc OutputAsmCode + 156 (outasm.c:1976)
    4   spin2cpp                      	0x0000000103cb6ea9 main + 5049 (spin2cpp.c:980)
    5   libdyld.dylib                 	0x00007fff858385ad start + 1
    
    Thread 0 crashed with X86 Thread State (64-bit):
      rax: 0x00007f81ec006000  rbx: 0x0000000000000000  rcx: 0x00007f81ebc14e70  rdx: 0x00007fff5bf4c030
      rdi: 0x00007fff5bf4c030  rsi: 0xffffffffebc0f700  rbp: 0x00007fff5bf4beb0  rsp: 0x00007fff5bf4be50
       r8: 0x0000000000000000   r9: 0x0000000000000030  r10: 0x00007fff5bf4bc10  r11: 0x00007f80e8324a1e
      r12: 0x0000000000000000  r13: 0x0000000000000000  r14: 0x0000000000000000  r15: 0x0000000000000000
      rip: 0x0000000103cd2210  rfl: 0x0000000000010206  cr2: 0xffffffffebc0f700
      
    Logical CPU:     6
    Error Code:      0x00000004
    Trap Number:     14
    
    

    dgately
    Livermore, CA (50 miles SE of San Francisco)
  • It appears that PrintOperandAsValue is receiving a null 'reg' argument in this example... (This takes place on the 17th execution of PrintOperandAsValue).

    seg_fault.png

    I hope this helps...

    dgately
    758 x 392 - 158K
    Livermore, CA (50 miles SE of San Francisco)
  • Thanks for the bug report, @dgately. I haven't been able to reproduce exactly the bug you described, but I did fix some other bugs in the DAT section output that perhaps might be causing issues, so it's probably worth updating to the latest sources and trying again. Also, I've made a few build system changes lately and it's possible that some dependencies aren't being caught correctly by the Makefile, so I'd recommend doing a "make clean" before the make after you update this time.

    I hope these changes help!
  • ersmithersmith Posts: 2,122
    edited March 2016 Vote Up0Vote Down
    I've published a new preview release (number 6). This one considerably expands support for PASM output; it can now handle VAR and OBJ sections. Most builtin functions are supported now. The mechanism for doing that was kind of elegant (if I do say so myself): I've added support for inline assembly, and so the builtins are actually written in Spin. For example, the waitcnt function is just:
    pri waitcnt(x)
      asm
        waitcnt x, #0
      endasm
    
  • ersmith wrote: »
    I've published a new preview release (number 6). This one considerably expands support for PASM output; it can now handle VAR and OBJ sections. Most builtin functions are supported now. The mechanism for doing that was kind of elegant (if I do say so myself): I've added support for inline assembly, and so the builtins are actually written in Spin. For example, the waitcnt function is just:
    pri waitcnt(x)
      asm
        waitcnt x, #0
      endasm
    

    Very cool!

  • The spin to PASM converter supports recursive functions now, and has more of Spin implemented (to the point that it can compile FullDuplexSerial.spin). So we can now run many small benchmarks and tests, including the famous fibonacci demo. Here's how spincvt (i.e. spin2cpp --asm --binary) stacks up on fibo(8), based on results from an old benchmark thread:
                        Time     Size
    PASM                 3940     80
    GCC -Os -mcog        5444    100
    spincvt              9108    104
    GCC -Os -mlmm       10992     84
    GCC -Os -mxmm       57552     84
    GCC -Os -mcmm       58800     26
    Catalina LMM        65392    100
    Catalina CMM -O3   102960     46
    Tachyon Forth      106784     18
    OpenSpin   	   137360     25
    
    Time is cycles for fibo(8), size is size in bytes of the fibo function itself, ignoring all support and library functions.

    The size is nothing to write home about, but it's in the same range as other PASM compiled solutions. The speed is nice: a 15x speed up over interpreted spin. GCC does better in COG mode, but I never expected to match the GCC optimizer. All in all I think things are coming along well.
  • Fabulous progress, er.
    It's really coming together now.
  • ersmith wrote: »
    I've published a new preview release (number 6). This one considerably expands support for PASM output; it can now handle VAR and OBJ sections. Most builtin functions are supported now. The mechanism for doing that was kind of elegant (if I do say so myself): I've added support for inline assembly, and so the builtins are actually written in Spin. For example, the waitcnt function is just:
    pri waitcnt(x)
      asm
        waitcnt x, #0
      endasm
    

    That's nice - is there a limit to what can go between asm..endasm ?
    you mention builtin functions, but general expectation is asm..endasm is linline-asm.
  • ersmithersmith Posts: 2,122
    edited March 2016 Vote Up0Vote Down
    jmg wrote: »
    ersmith wrote: »
    I've published a new preview release (number 6). This one considerably expands support for PASM output; it can now handle VAR and OBJ sections. Most builtin functions are supported now. The mechanism for doing that was kind of elegant (if I do say so myself): I've added support for inline assembly, and so the builtins are actually written in Spin. For example, the waitcnt function is just:
    pri waitcnt(x)
      asm
        waitcnt x, #0
      endasm
    

    That's nice - is there a limit to what can go between asm..endasm ?
    you mention builtin functions, but general expectation is asm..endasm is linline-asm.

    Almost anything can go between asm...endasm. I mentioned builtins because this is *how* the builtins are implemented; most of the standard Spin functions like lockclr, lockset, waitcnt, and so on are implemented as ordinary functions that happen to use inline assembly. The compiler always includes a special "global" object that has definitions for all of these. But you can also write other functions that way too. The limitation is that only local variables and immediate constants can be operands in the inline assembly; you can't directly access anything else. So to increment an object variable you could write:
    var
      long value
    pub incvalue(x) | ptr, tmp
      ptr := @value '' want to access object variable in inline asm
      asm
        rdlong tmp, ptr  ' read value
        add     tmp, x   ' add x to it; that's OK, x is a local variable
        wrlong tmp, ptr  ' update value
      endasm
    
    This is a contrived example, of course, since it's a lot simpler to just write "value += 1", but it illustrates the principle: the inline asm cannot directly access "value" but it can access the variables of the function it is within.
  • Preview 8 is out, with LMM support. Lots of programs work now. @Cavelamb, I think TFT.spin should work for you as long as you select "LMM Mode" under the Options menu. I get the following timing results on SS_TFT.spin:
    openspin:
    Initialization time: 20095 ms
    Text print time:      1591 ms
    
    spincvt (LMM mode):
    Initialization time:  1349 ms
    Text print time:        75 ms
    
    (Beware: I don't actually have hardware to test whether the TFT is working correctly!)

    @Heater, you'll be pleased to hear that fft_bench works now:
    openspin:
    1024 point bit-reversal and butterfly run time = 1465 ms
    
    spincvt (LMM mode):
    1024 point bit-reversal and butterfly run time = 270 ms
    

    For those of you using the command line, LMM mode is activated by the switch "--code=hub", so to produce a binary from a .spin file you do something like:
    spin2cpp --asm --binary --code=hub fft_bench.spin
    

    Eric
  • cavelambcavelamb Posts: 645
    edited March 2016 Vote Up0Vote Down
    I'll try it this weekend, er.
    Will let you know how it goes.

    Where on earth are you?
    Might want to ship the run-time machine to you for test, if you'd be interested.
    Might be with the trouble to test your project - and get mine advanced.
  • cavelamb wrote: »
    I'll try it this weekend, er.
    Will let you know how it goes.

    Please do. I've uploaded a new preview (version 9). I think it's feature complete now; all of my regular Spin tests work for it, including launching a new COG with a Spin method. There are still a few rough edges (e.g. I'd like to implement a suggestion from @jmg that the original source code be added as comments) and I guess it would be nice to integrate the compiler with a proper IDE like PropellerIDE. But the basic functionality should all be there.
    Where on earth are you?
    Might want to ship the run-time machine to you for test, if you'd be interested.
    Might be with the trouble to test your project - and get mine advanced.

    I'm in Nova Scotia, Canada... but I don't have a lot of spare time, I'm afraid (this project has already eaten up more of what little I have than it should have!). But I'd be happy to help out here on the forums.

    Thanks,
    Eric
  • Here is the latest version, which I've labeled a "beta" release. It's now feature complete; it's able to compile all the Spin I've thrown at it, although admittedly that is a small set so far. I've implemented @jmg's suggestion to include the original source as comments in the output PASM.

    I'll probably focus on adding P2 support next, unless there's some P1 features that aren't working and that someone needs.

    Any/all feedback is welcome.

    Eric
  • Eric,
    Thanks. I will not get around to checking it out just yet. Working on USB.
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • Thank you for your development efforts. I hope to soon be able to check it out myself!

    Mekkatronix@yahoo.com
  • dgatelydgately Posts: 927
    edited March 2016 Vote Up0Vote Down
    Not sure of this is actually a bug or more a case of an incorrect but very common usage issue... These are showing up as I run spinconvert.rcl & test as much spin code as possible).

    Trying to build a number of .spin files that I've either written or downloaded, results in a syntax error on the following code (when a preceding 'CON' is missing):
    content of dubious.spin:
    
        {{ Dubious Spin program example }}
        _clkmode = xtal1 + pll16x                               ' Setting Clock Mode to Crystal 1 with 16 multiplier 
        _xinfreq = 5_000_000                                    ' Propeller set to run at 80MHz
    
        PUB main
    
            repeat
    
    build of dubious.spin:
    
        $spin2cpp --asm dubious.spin
    
            dubious.spin:3: error: syntax error
    

    Of course this code works:
        {{ Correct Spin code example }}
        CON
    
        _clkmode = xtal1 + pll16x                               ' Setting Clock Mode to Crystal 1 with 16 multiplier 
        _xinfreq = 5_000_000                                    ' Propeller set to run at 80MHz
    
        PUB main
        
            repeat
    

    The first example is probably NOT correct Spin syntax but compiles with openspin (as used by: SimpleIDE and PropellerIDE). It could be that openspin assumes declarations preceding VAR or PUB are always CON declarations.

    Should spin2cpp follow openspin's allowance of this syntax or is openspin in error?


    dgately

    Livermore, CA (50 miles SE of San Francisco)
  • Eric,

    Since I'm actually finding issues/exceptions that concern spin2cpp more than spinconveri.tcl, should I just write these up as issues in git on the master branch of spin2cpp? Looks like spin2cpp still does not know to handle the 'abort' expression, yet:
    spinconveri Compiler Output:
    
        spin2cpp --noheader -g --asm --code=cog --data=hub -o /Users/altergator/PropSpinCode/ADXL345ObjectDemo/ADXL345ObjectDemo.pasm
        /Users/altergator/PropSpinCode/ADXL345ObjectDemo/ADXL345ObjectDemo.spin
        /Users/altergator/PropSpinCode/ADXL345ObjectDemo/ADXL345ObjectDemo.spin:98: error: Cannot handle expression yet
        /Users/altergator/PropSpinCode/ADXL345ObjectDemo/ADXL345ObjectDemo.spin:202: error: Cannot handle expression yet
        child process exited abnormally
    
    code in question (ADXL345ObjectDemo.spin:):
    
        lines 96-98:
        if adxl.ReadDeviceID <> -1
            debug.str(string(16, "ADXL345 Chip Not Present...Aborting!"))
            abort
    
    
        lines 195-202:
        temp := adxl.ReadDataFormat
        case temp & %0000_0011
            0: debug.str(string(13, "2g format initiated!"))
            1: debug.str(string(13, "4g format initiated!"))
            2: debug.str(string(13, "8g format initiated!"))
            3: debug.str(string(13, "16g format initiated!"))
            OTHER: debug.str(string(13, "Unknown format initiated...Aborting!"))
                abort
    

    dgately
    Livermore, CA (50 miles SE of San Francisco)
  • dgately wrote: »
    Not sure of this is actually a bug or more a case of an incorrect but very common usage issue... These are showing up as I run spinconvert.rcl & test as much spin code as possible).

    Trying to build a number of .spin files that I've either written or downloaded, results in a syntax error on the following code (when a preceding 'CON' is missing):

    Ah, interesting... I hadn't seen that missing 'CON' before, but if openspin accepts it then spin2cpp should too. I've changed the grammar to accept it; fortunately it was pretty easy. The fix is checked in to the master branch now (which has been merged with spin2pasm).

    Thanks for trying out so many spin files, and reporting the problems. That's really helpful!
    Eric
Sign In or Register to comment.