Shop OBEX P1 Docs P2 Docs Learn Events
New Spin - Page 34 — Parallax Forums

New Spin

13031323436

Comments

  • kwinnkwinn Posts: 8,697
    +1 for the great value and usefulness of Spin.
  • RaymanRayman Posts: 14,762
    Was just thinking about one area where Spin1 was nicer than C++ --> Bitfields

    In Spin1 you can use OUTB, INB, etc.. to easily set individual bits in a long, e.g., OUTB[10]~~, and so forth.

    I guess this will be gone in Spin2 because Port B will actually exist.

    C++ has bitfields, but they don't look as easy to use...
  • cgraceycgracey Posts: 14,208
    edited 2017-06-20 23:16
    Rayman wrote: »
    Was just thinking about one area where Spin1 was nicer than C++ --> Bitfields

    In Spin1 you can use OUTB, INB, etc.. to easily set individual bits in a long, e.g., OUTB[10]~~, and so forth.

    I guess this will be gone in Spin2 because Port B will actually exist.

    C++ has bitfields, but they don't look as easy to use...

    Spin2 will have even better bit field support - not just for I/O registers, but for ALL variables:

    x[.31]!
    OUTA[16..23]++
    result[31..28] := byte[index][3..0]

    XBYTE/SKIPF allowing CALLs really makes this efficient.
  • cgracey wrote: »
    Rayman wrote: »
    Was just thinking about one area where Spin1 was nicer than C++ --> Bitfields

    In Spin1 you can use OUTB, INB, etc.. to easily set individual bits in a long, e.g., OUTB[10]~~, and so forth.

    I guess this will be gone in Spin2 because Port B will actually exist.

    C++ has bitfields, but they don't look as easy to use...

    Spin2 will have even better bit field support - not just for I/O registers, but for ALL variables:

    x[.31]!
    OUTA[16..23]++
    result[31..28] := byte[index][3..0]

    XBYTE/SKIPF allowing CALLs really makes this efficient.
    Nice! It always bothered me that the bit field syntax only worked with registers.

  • +1

    Mike
  • I was thinking about the need of functions/methods in Spin to be used as a parameter to some other function.

    Basically like a new COG in SPIN1, using the function/method name as parameter.

    There where a lot of discussions, but no finally conclusion.

    Maybe a full-fledged implementation of this is to complicated, but how about some mechanism in the interpreter allowing to just execute a function/method with given parameters and returning the result. Maybe add something alike 'PRI', 'PUB', 'PEX' to define if you want to have a external calling point/address.

    Make it simple, a 'PEX' can provide a long as identifier. One generic function in the interpreter can be called, providing that identifier, so the interpreter can find that function/method.

    One would just need some Hub Exec PASM to push Parameter on the spin stack, push identifier, interpreter calls function/method, returns RESULT, Hub Exec PASM pops from the Spin stack.

    Now we can call SPIN from PASM and all is well. Spin can call Spin from Inline-Pasm and C/C++ can also call Spin from inline-Pasm.

    The other way around, calling C/C++ from Spin2 is quite simple, inline PASM in Spin can call C stuff without problem, I guess.

    No need to build complicated additions to the Spin language. Just offer to provide a callback to specific named functions/methods. Just provide a PASM access to push parameter, call into the interpreter and pop the result out.

    No need to worry about creating interface table, move around pbase, dbase and whatnot, just a compiler generated long as identifier for the function/method to call.

    Its up to the programmer to push parameters and pop them again.

    I really think it is important to provide a standard way to communicate between COGS running PASM/SPIN and COGS running C.

    We will have up to 16 COGs and some of them could run SPIN, some PASM and some C generated PASM, CMM, LMM?, XMM?

    To make this feasible, besides some Linker support, we just need to be able to call into any Spin-Interpreter from PASM.

    Enjoy!

    Mike
  • I didn't quite follow everything you said, but it seems like the easiest solution for mixing Spin and C is to just use spin2cpp. I don't see a need for a complicated interface between Spin and C. spin2cpp works just fine.
  • Although Parallax might need C to sell the Propeller, serious users will always need Spin/PASM to get the most from it.

    That seems like a bit of a shortcoming...

    "We have this great chip we'd like you to use in your next product but unless you get your programmers to learn a whole new language, and as well as that to program in assembler, you may as well buy an ARM and continue to use stuff you already know."
  • I think Phil's statement is accurate for the P1, but the P2 will be different. Parallax will need C to sell the P2, and serious users will need C and PASM to get the most from it. Spin is needed for novices, but they can also learn C as well. Just look at how successful the Arduino has been teaching musicians and artists how to program in C/C++. Oh and Spin will also be needed for those stubborn Spin programmers that just can't force themselves to accept C. :)
  • One nice thing about Spin is that it's not constrained by C's preordained (i.e. limited) operator and intrinsic function sets. So the unique features of the Propeller, such as starting/stopping cogs, can be woven directly into the language, rather than relying on external function calls. As a result, Spin is "closer to the metal" than other pre-defined languages can possibly be.

    -Phil
  • Intrinsics can overcome much of that difference.

    I don't think Spin will be needed to get the most out of the P2, in fact I'd bet that at maturity more will be gotten out of the P2 with C than anything else.
  • ...constrained by C's preordained (i.e. limited) operator and intrinsic function sets.

    I might be wrong but isn't it the case that 'C' has NO intrinsics as standard and that it's down to a specific compiler implementation for a specific target that deals with them? So that...

    void __builtin_p2_cog_start (int, int, int)

    ...is quite possible and will be just as easy to use as the Spin equivalent.
  • Phil, you made a similar comment on June 4. Here it is just in case you forgot it.
    I would rather see C extended to accommodate the P2's functionality via native operators, rather than being shoehorned into awkward function calls. Otherwise, you're just looking at a kludge.

    But if C is, by definition, non-extensible, why use it at all?
    I carefully explained to you how C can be extended through function calls, and that many of the P2-specific functions would be compiled inline into a single PASM instruction. C can be as close to the metal as Spin. The only argument against C on the P1 is that the standard libraries just don't quite fit in 32K. Of course it is possible to write C that looks just like Spin using FDS and FSRW routines, but one loses a lot of the power of C when using such simple routines. C on the P2 won't have the same memory limitations, and should be lots of fun to program.

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2017-06-21 17:51
    Okay, but I would much rather just say

    cognew(my_cog, @my_stack)

    than

    __builtin_p2_cog_start (int, int, int)

    Good grief! The latter is just plain ugly, not to mention a PITA to type.

    -Phil
  • For C/C++ intrinsics, it could be as simple as cognew(...) and coginit(...). The naming is implementation dependent, and usually contains some prefix to avoid collisions. Perhaps an under bar or two would be added to differentiate it from normal functions?

    You can make C/C++ as ugly or pretty as you like. It's largely a matter of preference and readability.

    Also, Phil, your preference is Spin, so why not just use that and let those of us that want to use C/C++ do what we want?
  • Language wars are not productive, IMO. What a person is used to is likely the most important factor for any one person. Syntactically, my point of view is that I'm equally comfortable with both cognew(my_cog, @my_stack) or cogstart(&readadc, NULL, readadc_stack, sizeof(readadc_stack)); // Start adc cog - but that's only my viewpoint.
  • Heater.Heater. Posts: 21,230
    I'm all for abolishing underscores. In all languages. They make an ugly mess. Especially leading and trailing underscores.
  • TorTor Posts: 2,010
    Okay, but I would much rather just say

    cognew(my_cog, @my_stack)

    than

    __builtin_p2_cog_start (int, int, int)

    Good grief! The latter is just plain ugly, not to mention a PITA to type.

    -Phil
    You shouldn't have to - normally the compiler will pick an intrinsic function if one exists for the particular compiler. So you'll write, for example, 'strcpy()' in your source, but that may be translated to __builtin_strcpy() on certain platforms.

  • cgraceycgracey Posts: 14,208
    Heater. wrote: »
    I'm all for abolishing underscores. In all languages. They make an ugly mess. Especially leading and trailing underscores.

    _RET_

    I kind of like that one.
  • Roy Eltham wrote:
    Also, Phil, your preference is Spin, so why not just use that and let those of us that want to use C/C++ do what we want?
    I'm obviously fine with that, Roy, but it works the other way, too. Besides, this thread is titled, "New Spin." So it's entirely appropriate of me or anyone else to point out Spin's advantages here in an effort to ensure that Spin2 development is given the priority and energy it truly deserves.

    -Phil
  • re:underscores

    I sometimes use a leading underscore to differentiate PRIvate method names from PUBlic ones in Spin. They do have a place if used frugally.

    -Phil
  • re:underscores

    I sometimes use a leading underscore to differentiate PRIvate method names from PUBlic ones in Spin. They do have a place if used frugally.

    -Phil

    +1
  • In the C Simple Libraries to run a function in a new cog is:
    cog_run(function, address of par , stack size).

    Simple libraries are designed to be simple for new learners to use. There is also the Propeller library (propeller.h) that is "closer to the metal" and executes faster.

    One thing I don't like about Spin is printing output to the terminal. I realize that it is a object that could be rewritten, but the amount of typing is annoying. I find C ' printf (or the Simple library's print) much easier to use.

    In general I like Spin because it is concise, except for printing.

    Tom
  • I had the same issue with the lack of formatted printing in Spin, so I wrote the CLIB object. It provides printf and other C-like functions in the Spin language. Of course, it's not as easy to use in Spin as it is in C because Spin does not allow for variable argument lists, and the format string has to be wrapped in a STRING() instrinsic. A print such as printf("This is loop %d. The value of x is %d.\n", i, x) is done as c.printf2(string("This is loop %d. The value of x is %d.\n"), i, x). The usual way to do this in Spin is:
      ser.str(string("This is loop "))
      ser.dec(i)
      ser.str(string(".  The value of x is "))
      ser.dec(x)
      ser.str(string(".", 13))
    
    It surprises me a bit that seasoned Spin programmers prefer doing it that way versus using a formatted print method.
  • since spin does not allow variable number of parameter for functions/methods, how do you would implement a
    printf("abc %d def %d", p1,p2) versus printf("abc %d def %d ghi %d", p1,p2,p3)?

    Seasoned Spin programmer would like and use it, if there would be a way to do this.

    But Spin does not provide parameter overloading for functions/methods.

    So we would end up with

    printf1(string, p1)
    printf2(string,p1,p2)
    printf3(string,p1,p2,p3) and so on.

    is that feasible?

    I personally tend to write stuff like that different, (the COBOL way?) by having a data block like
    displayBlocks byte "Z "
    dZapos        byte "           ", "Y "
    dYapos        byte "           ", "X "
    dXapos        byte "           ", "Zn "
    dZaclk        byte "           ", "Yn "
    dYaclk        byte "           ", "Xn "
    dXaclk        byte "           ", "Zc "
    dZacnt        byte "           ", "Yc "
    dYacnt        byte "           ", "Xc "
    dXacnt        byte "           ", 13, 0
    

    writing decimal (or other values) to hub-ram and then do a xxx.str(@displayBlocks )

    Enjoy!

    Mike
  • Yes, we end up using multiple methods to handle the different number of arguments. In the CLIB object each of the methods then pass their arguments as a list to vprintf, which then reads the arguments off of a list.
  • Dave Hein wrote: »
    Yes, we end up using multiple methods to handle the different number of arguments. In the CLIB object each of the methods then pass their arguments as a list to vprintf, which then reads the arguments off of a list.
    Maybe varargs is something that can be addressed in Spin2?

  • msrobotsmsrobots Posts: 3,709
    edited 2017-06-22 03:02
    Dave Hein wrote: »
    I didn't quite follow everything you said, but it seems like the easiest solution for mixing Spin and C is to just use spin2cpp. I don't see a need for a complicated interface between Spin and C. spin2cpp works just fine.

    Here I think you are missing the point I am aiming at.

    I do not want to translate spin to c to execute.

    The goal should be, to be able to have different modules (objects) running in one P2 program.

    Some written in C, some written in PASM, some written in Spin. Grab the module out of the OBEX, combine with other ones. Should not matter if written in c, SPIN, PASM or Propbasic.

    If you prefer to program in C, do so but be able to call Pasm Stuff, included like PASM in Spin, from C. Be able to call single Spin functions/methods out of a spin interpreter running in cog x, using a simple PASM stub. That might be not far away, SPIN needs to support some way to be called from PASM to get there. Then C can handle this.

    If you prefer to program in Spin, do so but be able to call Pasm Stuff, included like PASM in Spin, from Spin. Be able to call single C functions/methods out of any C program running in HUB/COG/LMM/CMM/XMM from your Spin Program using a simple inline PASM stub. - That might be already possible, SPIN needs to support ELF files somehow to get there.

    And if you prefer to program in PASM, do so and be able to call C and SPIN functions/methods with some Hub-Exec PASM stub.

    Same would go for PropBasic.

    I am nagging about this for a while now, because NOW Spin gets written and hopefully Parallax gets a official C project started soon. Peter J. will have no problems to adapt Tachyon, and PropBasic for P2 is not there, yet.

    The goal is to be able to run all of the languages at the same time on the same prop, just in different COGs.

    The ELF linker has no problem to do stuff like this. A smart loader could handle the needed actions.

    By now the boot-process is already a 2 stage thing. Read loader, decrypt, run, read main program, decrypt, run. Since the support of WIFY even the P1 has a 2 stage loader.

    Now we have 16 Cogs, up to 4K each, that's a whooping 64K already for COG images. Sure on P1 we reuse that as buffers, load it from upper EEPROM, all crutches.

    A smart loader could read a first stage, putting COG images into HUB and loading them. COGS do not need to get loaded to get started anymore, so this IS possible.

    Then the main programs can get loaded. And yes plural.

    If SPIN/PASM/C/Tachyon/PropBasic/whoever would have a consistent and agreed upon HUB layout that could happen.

    And that is, why I ask for a simple HUB-Exec call interface for any running SPIN interpreter to reach some (PEX) marked methods/functions.

    That is all what is needed to be ABLE to do that.

    And it would be a good time to do that interface thing now, before Spin is ready and C is ready.

    And it would also solve completely the callback problem in Spin itself, No language change needed, just mark function/method as PEX not PRI or PUB. provide compiler generated identifier for instance of the method to let the Spin-interpreter find it.

    Even inside Spin we then can call methods of other objects by a small inline PASM block, if they are marked PEX

    tl;dr;

    what is needed is that any COG running PASM is able to ask a running SPIN interpreter on COG X to push some parameters on its Stack, execute some PEX marked method and pop the results from its Stack.

    That would solve all callback problems in Spin and provide a nice way for interoperability between different programs running on one P2 at the same time, if generally adapted as concept.

    just push, call xxx, pop no type checking in compiler, no additional language changes in Spin, just a simple call interface in PASM.

    Enjoy!

    Mike
  • I second the need for variable-length arg lists in Spin2. Printing to the terminal could then be so much easier.

    -Phil
  • jmgjmg Posts: 15,175
    I second the need for variable-length arg lists in Spin2. Printing to the terminal could then be so much easier.
    This likely comes down to size. printf is famous for bloat effects on the smallest MCUs.

    To have the least impact, and best performance, Spin 2 should ideally fit into a single COG, with no overflow/bleed effects to worry about & manage.
    I'm not sure where Chip is up to on the 'features list' vs 'code size' trade offs....

Sign In or Register to comment.