Shop OBEX P1 Docs P2 Docs Learn Events
SpinWrap - a tool for allowing C or C++ to use Spin Objects - Page 3 — Parallax Forums

SpinWrap - a tool for allowing C or C++ to use Spin Objects

135

Comments

  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-25 05:05
    I tried building the C code under Catalina but got undefined symbols for cognew and cogstop. Which header/library do I need to include to get the definitions of these functions?
    david-betzs-macbook-pro:spinwrap dbetz$ catalina test_main.c test.c -lc 
    Catalina Compiler 3.13
    test_main.c:
    test.c:
    
    Undefined or Redefined symbols:
     cogstop undefined
     cognew undefined
    
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-25 06:10
    David Betz wrote: »
    I tried building the C code under Catalina but got undefined symbols for cognew and cogstop. Which header/library do I need to include to get the definitions of these functions?
    david-betzs-macbook-pro:spinwrap dbetz$ catalina test_main.c test.c -lc 
    Catalina Compiler 3.13
    test_main.c:
    test.c:
    
    Undefined or Redefined symbols:
     cogstop undefined
     cognew undefined
    

    As a temporary fix I added the following lines to the start of the generated test.c file:
    #define cognew(code, params) _coginit((int)(params)>>2, (code)>>2, ANY_COG)
    #define cogstop(n)
    
    The Catalina version of the test program now runs! I will wait for RossH to tell me the correct way to fix this problem before pushing an update.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-25 07:05
    This seems to work for building under Catalina:
    #ifdef __CATALINA__
    #define cognew(code, params)    _coginit((int)(params) >> 2, (code) >> 2, ANY_COG)
    #define cogstop(id)             _cogstop(id)
    #endif
    
    Here is an example C program:
    #include "test.h"
    
    int main(void)
    {
        test obj;
        test obj2;
    
        init_test(&obj);
        
        test_start_blinker(&obj);
        
        test_set_pins(&obj, 16, 17);
        test_blink(&obj);
        test_set_pin(&obj, 18);
        test_blink(&obj);
    
        init_test(&obj2);
        
        test_set_pins(&obj2, 20, 21);
        test_blink(&obj2);
        test_set_pin(&obj2, 22);
        test_blink(&obj2);
        
        test_blink(&obj);
        test_blink(&obj2);
    
        while (1)
            ;
     
        return 0;
    }
    
    Here is test.spin:
    VAR
    	long my_pin
    	long my_other_pin
    	
    OBJ
    	blinker : "blinker"
    	
    PUB set_pin(pin)
        my_other_pin := my_pin
    	my_pin := pin
    
    PUB set_pins(pin1, pin2)
    	my_pin := pin1
    	my_other_pin := pin2
    
    PUB swap_pins | tmp
    	tmp := my_pin
    	my_pin := my_other_pin
    	my_other_pin := tmp
    
    PUB show_pins
    	outa[my_pin] := 1
    	outa[my_other_pin] := 0
    	dira[my_pin] := 1
    	dira[my_other_pin] := 1
    	
    PUB blink
    	repeat 5
    	    show_pins
    	    waitcnt(clkfreq / 2 + CNT)
    	    swap_pins
    
    PUB start_blinker
    	blinker.start
    
    And here is blinker.spin:
    PUB start
    	delta := clkfreq / 2
    	cognew(@cog_code, 0)
    	    
    DAT
    
    cog_code
    		or		dira, mask
    		mov		target, delta
    		add		target, cnt
    loop	xor		outa, mask
    		waitcnt	target, delta
    		jmp		#loop
    
    mask	long	1 << 23
    target	long	0
    delta	long	0
    
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-25 07:32
    FYI, I've decided to keep the current source in the top post of this thread. The version that works with Catalina as well as PropGCC is now attached to the top post.
  • mindrobotsmindrobots Posts: 6,506
    edited 2014-02-25 07:51
    David,

    This is really cool! Hopefully, it will cause some folks to grab some Spin modules from OBEX and play with them in a C environment. Maybe what is needed to start a C snowball (not a SNOBOL) effect!!
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-02-25 08:10
    Thanks for adding the C option. The generated C++ code is probably a more elegant way to handle Spin objects, but I am more comfortable working with C. With spinwap and spin2cpp we now have a couple a ways to interface C/C++ to Spin. Even though spin2cpp may be a good solution in a lot of cases, there are times when it's better to compile Spin as Spin, such as when the object is tuned to the timing of the Spin interpreter.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-25 08:13
    Dave Hein wrote: »
    Thanks for adding the C option. The generated C++ code is probably a more elegant way to handle Spin objects, but I am more comfortable working with C. With spinwap and spin2cpp we now have a couple a ways to interface C/C++ to Spin. Even though spin2cpp may be a good solution in a lot of cases, there are times when it's better to compile Spin as Spin, such as when the object is tuned to the timing of the Spin interpreter.
    I think spin2cpp will usually be a better option but, as you say, spinwrap can be used in places where Spin execution timing must be maintained or when there are complex relationships between multiple Spin objects which cause problems when translated to C/C++ because of shared variables that need to be marked as "volatile" in the Spin code.
  • RossHRossH Posts: 5,462
    edited 2014-02-25 14:18
    David Betz wrote: »
    FYI, I've decided to keep the current source in the top post of this thread. The version that works with Catalina as well as PropGCC is now attached to the top post.

    Hi David,

    Thanks - I'll have a play with this tonight. If it compiles, it is probably because you are already including <propeller.h> somwehere.

    If that is not always guaranteed, I'd suggest including <catalina_cog.h> - for example:
    #ifdef __CATALINA__
    #include <catalina_cog.h>
    #define cognew(code, params)    _coginit((int)(params) >> 2, (code) >> 2, ANY_COG)
    #define cogstop(id)             _cogstop(id)
    #endif
    
    Ross.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-25 14:21
    RossH wrote: »
    Hi David,

    Thanks - I'll have a play with this tonight. If it compiles, it is probably because you are already including <propeller.h> somwehere.

    If that is not always guaranteed, I'd suggest including <catalina_cog.h> - for example:
    #ifdef __CATALINA__
    #include <catalina_cog.h>
    #define cognew(code, params)    _coginit((int)(params) >> 2, (code) >> 2, ANY_COG)
    #define cogstop(id)             _cogstop(id)
    #endif
    
    Ross.
    Yes I include propeller.h because it's needed by PropGCC. It would probably be better to put the PropGCC-specific code in a separate ifdef like I've done with Catalina. When I do that I'll take your suggestion of including <catalina_cog.h> in the Catalina section. Thanks for the suggestion.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-25 15:09
    I added an ifdef for PropGCC along with the one from Catalina and put the include of propeller.h under the PropGCC conditional and catalina_cog.h under the Catalina conditional. I also added a "runcatalina" target to the Makefile that should build the test program with Catalina and download and run it.
  • RossHRossH Posts: 5,462
    edited 2014-02-26 03:23
    David Betz wrote: »
    I added an ifdef for PropGCC along with the one from Catalina and put the include of propeller.h under the PropGCC conditional and catalina_cog.h under the Catalina conditional. I also added a "runcatalina" target to the Makefile that should build the test program with Catalina and download and run it.

    Hi David,

    Looks very promising - it works ok if I just use it to invoke a spin object, but I have been unable to get a method to return a result to the C program - is that supported yet? The code to do so looks a little odd - I'm not exactly sure what this code is trying to do:
    test_mailbox = params;
      while (test_mailbox)
        ;
      return params[0];
    

    Also, if you have an empty VAR block (or no VAR block) you get a compile error (illegal array size 0 on 'variables').

    Finally, Catalina's version of openspin is called spinnaker (the maintainers of openspin wanted me to call it something else). If you don't want to hard code this name specifically for Catalina, could you make the name of the spin compiler a parameter? That way, you could also use it with bstc or homespun.

    Ross.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-26 03:39
    RossH wrote: »
    Hi David,

    Looks very promising - it works ok if I just use it to invoke a spin object, but I have been unable to get a method to return a result to the C program - is that supported yet? The code to do so looks a little odd - I'm not exactly sure what this code is trying to do:
    test_mailbox = params;
      while (test_mailbox)
        ;
      return params[0];
    
    The proxy code is supposed to place its return value in the first element of the params array although there may be some problem with that. I'll look at it.
    Also, if you have an empty VAR block (or no VAR block) you get a compile error (illegal array size 0 on 'variables').
    Good catch! I guess I'll have to allocate one long just so the variables array isn't empty.
    Finally, Catalina's version of openspin is called spinnaker (the maintainers of openspin wanted me to call it something else). If you don't want to hard code this name specifically for Catalina, could you make the name of the spin compiler a parameter? That way, you could also use it with bstc or homespun.
    Why does Catalina need a different version of OpenSpin? I'm just using it here to compile Spin code not the output of Catalina. Shouldn't I be able to use the generic version? Or are you saying that Catalina users won't have the generic version installed? Can't we work with Roy to make it so the generic version works with Catalina?
  • RossHRossH Posts: 5,462
    edited 2014-02-26 03:59
    David Betz wrote: »
    Why does Catalina need a different version of OpenSpin? I'm just using it here to compile Spin code not the output of Catalina. Shouldn't I be able to use the generic version? Or are you saying that Catalina users won't have the generic version installed? Can't we work with Roy to make it so the generic version works with Catalina?

    Catalina's version adds some stuff I needed that I don't think openspin supports yet, such as the ability to generate an output listings (I submitted the changes, but I'm not sure if they have made their way in to the "official" release yet - I should check!). Roy asked me to change the name to prevent confusion between the two versions.

    So the answer is Catalina users may not have a "generic" version of openspin installed. But they will have spinnaker and homespun, and may also have bstc, all of which will do the job required here - i.e. just compiling Spin code to a binary.

    Ross.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-26 04:12
    I just updated the top post and the Google Code repository to fix the problem with Spin objects that don't have any variables. I also added a test of using return values from Spin functions and it seems to work with the current version of spinwrap. If you're still having trouble could you post your code so I have an example where return values fail?

    Edit: I forgot to mention that the revised test code that tests return values is in the zip file attached to the top post.

    Thanks!
    David
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-26 04:14
    RossH wrote: »
    Catalina's version adds some stuff I needed that I don't think openspin supports yet, such as the ability to generate an output listings (I submitted the changes, but I'm not sure if they have made their way in to the "official" release yet - I should check!). Roy asked me to change the name to prevent confusion between the two versions.

    So the answer is Catalina users may not have a "generic" version of openspin installed. But they will have spinnaker and homespun, and may also have bstc, all of which will do the job required here - i.e. just compiling Spin code to a binary.

    Ross.
    I would think generating a listing file would be something anyone would want. Maybe Roy just hasn't had a chance to integrate your change yet. OpenSpin is an open source project. I wonder if you could ask to be added to the committers list so you can submit changes directly? It would be nice not to have multiple versions of OpenSpin floating around.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-26 09:16
    RossH: I just updated the zip file attached to the top post to support a compile time option "CATALINA" to use spinnaker instead of openspin for compiling Spin programs.

    Just add this to the command line you use to compile spinwrap.c:
    -DCATALINA
    
  • RossHRossH Posts: 5,462
    edited 2014-02-26 14:48
    David Betz wrote: »
    RossH: I just updated the zip file attached to the top post to support a compile time option "CATALINA" to use spinnaker instead of openspin for compiling Spin programs.

    Just add this to the command line you use to compile spinwrap.c:
    -DCATALINA
    

    Thanks, Davids - I'll check it out tonight.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-26 15:02
    RossH wrote: »
    Thanks, Davids - I'll check it out tonight.
    No problem. Also, could you post an example of a case where return values are not returned correctly? I was unable to duplicate that.
  • RossHRossH Posts: 5,462
    edited 2014-02-26 15:05
    David Betz wrote: »
    I would think generating a listing file would be something anyone would want. Maybe Roy just hasn't had a chance to integrate your change yet. OpenSpin is an open source project. I wonder if you could ask to be added to the committers list so you can submit changes directly? It would be nice not to have multiple versions of OpenSpin floating around.

    I just checked, and the current released version still doesn't have the capability to produce listings. Can't say as I blame them for not using my code - it is ... errr .... inelegant (to say the least!) :lol:

    I don't really have time to assist on the openspin project, and it is a bit unfair of me to impose new requirements on them (the original Spin compiler had no listing capability, and the original purpose of the openspin project was just to reproduce the original in open source).

    But when they do decide there is a need to add a listing capability, I'll look at moving back to it again instead of having my own version.

    Ross.
  • RossHRossH Posts: 5,462
    edited 2014-02-26 16:06
    David Betz wrote: »
    No problem. Also, could you post an example of a case where return values are not returned correctly? I was unable to duplicate that.

    Will do. Did you test yours with a C++ version, or a C version of the spinwrap?

    Ross.
  • pmrobertpmrobert Posts: 675
    edited 2014-02-26 16:18
    Ross, do the extensions you've added to openspin to create spinnaker support @@@?
  • RossHRossH Posts: 5,462
    edited 2014-02-26 17:11
    pmrobert wrote: »
    Ross, do the extensions you've added to openspin to create spinnaker support @@@?

    No. You should request the openspin maintainers to add it to the "official" Spin language.

    Ross.
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2014-02-26 17:21
    RossH,
    Can you remind me what Catalina needs the listing files for? What's it getting out of them? Maybe I can provide that data in some other way? Also, when I do get to adding listing file output to OpenSpin, it's not going to be in the same format/layout that you have (and likely not like any of the others, sorry).

    pmrobert,
    No, his extensions do not add support for @@@. I looked into adding @@@ to OpenSpin a while ago, and it was not feasible to do without significant reworking of how the compiler works. The way Chip's compiler (and thus OpenSpin) compiles objects is that each one is essentially compiled in isolation from it's parent. It only knows about itself and it's children, and child objects are compiled to binary first. Child objects with @@@ in them will not know their absolute address until their parents and grandparents, and so on up the chain until you get to the top object are compiled, and by then they are already compiled down to binary. So you say, just keep track of their locations in the binary and fix them up! I started down that path, but it doesn't work, because @@@ can be involved in math operations and such, so you essentially have to recompile a portion of the child object again after the everything up to the top object is compiled in order to "fix up" the value, and there's even more stuff, like multiple instances of the same child object being distilled away, that make it even trickier. It's still on my list to try and add support for @@@ at some point in the future, but other things are higher priority. I personally, have never found the need to use @@@ in anything I've coded, and I wish others would just stop writing code that requires it. :D (I'm sort of kidding.)
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-26 17:37
    RossH wrote: »
    Will do. Did you test yours with a C++ version, or a C version of the spinwrap?

    Ross.
    I tested it with both and Catalina as well as PropGCC. Look at test_main.c and test_main.cpp.
  • RossHRossH Posts: 5,462
    edited 2014-02-26 18:37
    Roy Eltham wrote: »
    RossH,
    Can you remind me what Catalina needs the listing files for? What's it getting out of them? Maybe I can provide that data in some other way? Also, when I do get to adding listing file output to OpenSpin, it's not going to be in the same format/layout that you have (and likely not like any of the others, sorry).

    pmrobert,
    No, his extensions do not add support for @@@. I looked into adding @@@ to OpenSpin a while ago, and it was not feasible to do without significant reworking of how the compiler works. ...

    Oddly enough, one thing Catalina uses the listing for is exactly what "@@@" is supposed to do - i.e. find the absolute address of something in Hub RAM.

    And also, oddly enough, you could implement @@@ by looking at what I ended up doing to implement the listing capability - it is essentially the same problem that has to be solved in both cases - i.e. figuring out where the &%#$#@ the Spin compiler has put the objects in Hub RAM!

    For this reason, the main purpose for the listing is for debugging - of both Spin and C programs. Catalina has a source level C debugger, but even so there are times when you just need to know exactly how things are laid out in RAM to understand why your program is not working the way it should.

    Spin is particularly problematic in this area - Spin has no structures and feels free to re-organize your VAR statements as it sees fit, so you have no real idea where things actually are in RAM. To see where they end up you need a listing.

    Ross.

    P.S. If you do add a listing capability, I don't see why you wouldn't adopt Homespun's format - after all, there is no standard here, and Michael Park did a very good job of coming up with a well-laid out and perfectly logical format for representing Spin's rather peculiar object layout - better even than bstc (which is I think the only other one?).

    In my view, Michael Park is an under-appreciated hero for helping to make Spin a usable language. Brad Campbell (justifiably) gets a lot of the credit, but for many things Michael was either there first, or came up with a better solution.
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2014-02-26 20:07
    RossH,
    I see. It still doesn't solve the @@@ problem completely, because it doesn't account for @@@ stuff being used as terms in an expression. I still need to recompile the expression after finding out what the value is for the @@@ term. For example, (@@@label >> 2) + 1 is valid, and can't be fixed up in a 3rd pass without recompiling/evaluating the expression, especially when it comes to more complex expressions. I need to be able to properly identify the entire expression involving the @@@ term, and then in the 3rd pass recompile the expression and plug the results back into the binary object.

    I have not looked at homespun's listing files. It may be possible to make it similar or the same. I think the main thing I want, is to show more information when possible. We'll see.

    I'm in the process of making a command line option to output a list of symbols with information that will make David's SpinWrap stuff work "better". Symbols includes CON stuff, PUB/PRIs, VARs, DATs stuff, and so on. I have all of this info available in the symbol table at the end of compiling a given object, and since David only needs it for the top object it's pretty easy. This information contains enough to let you figure out the location of anything in the final compiled result, similarly to the listing stuff.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-26 20:20
    Roy Eltham wrote: »
    RossH,
    I see. It still doesn't solve the @@@ problem completely, because it doesn't account for @@@ stuff being used as terms in an expression. I still need to recompile the expression after finding out what the value is for the @@@ term. For example, (@@@label >> 2) + 1 is valid, and can't be fixed up in a 3rd pass without recompiling/evaluating the expression, especially when it comes to more complex expressions. I need to be able to properly identify the entire expression involving the @@@ term, and then in the 3rd pass recompile the expression and plug the results back into the binary object.
    Does your parser generate an abstract syntax tree or something like that? If so, couldn't you just remember a pointer to the expression node in that tree along with the location that needs to be fixed up? I guess you'd have to keep the state of the symbol table at that point as well though so it might not be that easy.
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2014-02-26 20:35
    David,
    No it's not like that at all. It just parses the text and creates results. It does two passes currently, the first just identifies symbols, mainly, without resolving them. Remember, it was written in x86 asm by Chip and I ported that.

    Anyway, we've sidetracked the thread topic enough here, we can discuss it elsewhere at another time.
  • RossHRossH Posts: 5,462
    edited 2014-02-26 20:44
    Roy Eltham wrote: »
    RossH,
    I see. It still doesn't solve the @@@ problem completely ...

    True. But (being simplistic) if you already do two passes (and from memory, I seem to recall you do) then all you need to do is disallow the use of @@@ in places where it might affect the absolute address of something else (e.g. BYTE 0[@@@symbol] would have to be disallowed) - then after the first pass you know the absolute address where everything will end up, and so every expression can be completely evaluated on the second pass. No need to generate and store parse trees or partially evaluated expressions.

    Ross.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-26 20:47
    RossH wrote: »
    True. But (being simplistic) if you already do two passes (and from memory, I seem to recall you do) then all you need to do is disallow the use of @@@ in places where it might affect the absolute address of something else (e.g. BYTE 0[@@@symbol] would have to be disallowed) - then after the first pass you know the absolute address where everything will end up, and so every expression can be completely evaluated on the second pass. No need to generate and store parse trees or partially evaluated expressions.

    Ross.
    That's true. Storing parse trees and fixups is a technique for single-pass compilers mainly.
Sign In or Register to comment.