Shop OBEX P1 Docs P2 Docs Learn Events
A proposal to develop a standard for communicating with cogs from any language! - Page 7 — Parallax Forums

A proposal to develop a standard for communicating with cogs from any language!

1457910

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-12-07 20:12
    Well, I've had enough of all this posturing and pontificating about standards. How about letting the "standard" be defined and limited only by the hardware architecture? Any language ported to the Propeller should be able to support all aspects of the architecture and communicate with ... whatever, rendering more limiting software standards superfluous. IOW, I don't see the point of this thread. Artificial standards are made to be broken, and they will be -- with alacrity, regularity, and impunity. Iconoclastic creativity will always trump conformism, so why bother? It's not like there's an OS running things. It's just a freaking microcontroller, for heaven's sake!

    -Phil
  • mindrobotsmindrobots Posts: 6,506
    edited 2011-12-07 20:37
    +1 PhiPi

    COG Interaction GUIDELINES for now.
  • pjvpjv Posts: 1,903
    edited 2011-12-07 20:54
    A bit of humor at this point would be to recall what our software engineering manager used to say:

    "Ahhhhh, standards...... I love them....... there are so many to chose from!"

    Cheers,

    Peter (pjv)
  • Mike GreenMike Green Posts: 23,101
    edited 2011-12-07 20:58
    It's too early to suggest a standard for a way to communicate with cogs from any language, but it's a good time to document a standard way to communicate with cogs, used in Catalina C and possibly others, but designed for use with multiple language implementations including Spin. That's the way standards start. If it's flexible enough and satisfies a variety of needs, people developing new programming systems or revisiting old ones will adopt it rather than inventing their own.

    This is a great discussion and should continue along the vein of discussing what features are currently in use, how well do they work, what are the costs, what might be added or changed at this early date to meet currently understood needs, what might be anticipated in terms of future needs, etc.

    It's obvious to me that there are at least two types of devices / drivers that need to be supported ... 1) stream devices where most of the communications is in terms of streams of data values, whether read or to be written, but some control information has to be communicated as well including repositioning the stream; 2) other devices where most of the communications is through a shared data area of some device specific size and organization.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-12-07 21:55
    @pjv, I like that!

    @Ross, I'm still a bit confused about what this thread is about, though I am fairly clear about the things that it is not about.

    But I had a brainwave. Ok, let's say you wanted to recycle all of your hub ram after loading up the cogs. This is a *good thing* and saves 14k of ram. So what you do is write a bootloader which loads up all the cogs. And then you load up your main program, either in Spin or C or whatever.

    If you did this, how would the cogs know how to talk to each other? They wouldn't because all of the PAR parameters were only valid for the first program, not the second.

    So - you think, how about we set up one long for each cog in a fixed location in high memory? Problem solved. Now the cogs can access something from a known location. They can read a long from that fixed location and it can reference data in other places, and I guess you can add on other things like whether a cog is loaded or not, what type of code is running in that cog and the like.

    Is this "the standard"? Or is there more to it?
  • RossHRossH Posts: 5,512
    edited 2011-12-07 23:13
    My goodness, what's wrong with these forums these days?

    Do people actually read before they post? Let's start with the title of this thread. It is ...
    1) A proposal
    as in "I am putting this idea forward for discussion - what do you think?"
    2) to develop a standard
    as in "I would like us to work together to develop something that doesn't already exist - so that we can all benefit"
    3) for communicating with cogs
    as in ... no, wait ... I don't think I can make that any clearer!
    4) from any language
    as in "something that is equally applicable to Spin, PASM, C, C++ Basic, Forth etc"
    There have been some good contributions to this thread, and there are some that are obviously motivated primarily by fear, jealousy, ego, animosity or just a desire to stir. However, on the basis that I think most people can I tell the difference, I will persevere.

    First, to Mike's point - I disagree it is too early to standardize. The Propeller 1 has been available for how many years now? How much longer should we wait? Till it is obsoleted? Well, you probably don't have long to wait. In my view, this is exactly the right time. The OBEX has grown a little unwieldy, with multiple instances of incompatible implementations of exactly the same types of objects. Now we are adding objects to support new languages to it - but there doesn't seem to be any effort to make these interoperable even with the existing Parallax languages - and yet we could easily do so! We are also adding a new "gold standard" objects to it, which will consist of a smaller set of better designed, better documented and better supported objects - surely they at least could be designed to a common standard, and to be interoperable between languages? But I can't even see an effort to make the "gold standard" objects compatible with Parallax's new languages - why not?

    To Phil's points - "it's just a freakin' microcontroller". True - but it's a microcontroller that is extremely advanced, yet has singularly failed to make any appreciable inroads in the wider commercial domain. Why not? Could it possibly be that very lack of standardization? Phil also apparently believes conformity stifles creativity. But is it really creative to have 14 different VGA drivers? (I just made that number up, by the way - in reality I suspect there are actually more than that!). Is it creative to have 250 different languages available on the Propeller (but with most of them not actually used to create anything?) How is this creative? Just for a moment look at the competition - take the Arduino, for instance - now that's one heck of a creative platform - and do you know why a chip that is less advanced is more creative? It's because it has standards.

    To jazzed's point - if I thought you were serious about wanting a list of requirements, I would generate one - but I would prefer we worked together to develop one, as the title of this thread suggests. However, at present, I think your only intent in posting in this thread is to derail it and confuse people, and I wish you would stop. Others are interested.

    To Ariba's point - No, I don't want to rerwrite existing Spin/PASM objects, but I would certainly prefer that any more that are written be written in such a way that they could be used from any language, not just Spin. In most cases, the PASM cog programs can be extracted from their Spin wrapper functions and re-used from another language (we all do this already) but this currently requires a lot of work because the internals of each are different in pointless ways - most people don't care about this because they think of them as Spin objects - but with the multitude of new languages arriving on the Prop, we really should think of them as cog programs within a Spin wrapper object - and that Spin wrapper could be replaced with an equivalent written in any language. If we had a standard for how to communicate with the cog programs themselves, they could be re-used with no modification. The Sphinx rendezvous concept you refer to sounds interesting - but from my perspective it is only interesting if we can get others to agree to use it. However, I disagree with your last point (about the thread title) - drivers are only one model of interaction that such a standard could support - if designed properly, it could support many different types of concurrent programming.

    To Dr_A's point - I don't know why you say you don't understand this thread - you seem to have a better grasp of it than most! If you added "a mechanism for communication with the loaded cogs", then your summary is pretty good!

    Ross.
  • Ron SutcliffeRon Sutcliffe Posts: 420
    edited 2011-12-08 01:38
    I normally avoid getting these sorts of threads, they inevitably get nowhere.
    It is simply not possible to set standards when the protagonists do not have a detailed knowledge
    of the other languages available for the Prop ( "all languages", forms part of the title)

    Take Forth for example

    1 Par always points to the area partioned for use by the current cog (80 bytes for the pad and 12 logs for par vectors ) All hub ram is partitioned by the forth Kernel.
    There are 8 hub partitions, the rest is assigned to the dictionary.

    2 Cogs shares a common dictionary where less volatile variables reside. Assigned (longs, words or bytes)

    3 Forth can issue commands to other cogs from any cog (AKA, c" Do this!" 4 cog ) this command to cog 4 from the current cog can be issued from any cog.

    4 I/O to cog 4 can be set 4 >con or even Prop1 4 >con >prop2 5>con. If you want more pins add another Prop.

    5 Cog ram is addressable $abcd cogadr COG! (save to cog adr) of COG@ (read long at cogadr)

    6 Forth assembler (with macros) makes linking pasm code to Forth a breeze,

    To my knowledge there are four different Forths for the propeller. JD Forth, Propforth, CB's Forth and MRT4, all partition Hub differently.

    "C" is not the only game in town.

    cheers

    Ron
  • RossHRossH Posts: 5,512
    edited 2011-12-08 02:39
    It is simply not possible to set standards when the protagonists do not have a detailed knowledge
    of the other languages available for the Prop ( "all languages", forms part of the title)

    ...

    "C" is not the only game in town.

    Hi Ron,

    You may note I did include Forth - precisely in the hope of getting someone like you to contribute. You're correct that I don't know Forth, so I'm not qualified to judge what it needs - but you probably are, so I hope you'll stick around and help us develop a language-independent solution. Even if you ultimately choose not to use it, your contribution may assist others.

    As you point out, there are several Forths for the Propeller - just as there are several C compilers, several Basic compilers/interpreters and at least one Java virtual machine. There are even multiple PASM assemblers. Every one of the language developers here has had to face the problem of how to communicate with cog programs, and all of us have solved it in our own way.

    Surely there is enough experience by now to see if we can come up with a solution that would allow us to pool (rather than duplicate) our efforts?

    I don't particularly care what language you use - all languages have common needs when executed on the Propeller - i.e. TV, VGA, Keyboard, Mouse, File System, Clock, I2C, SPI, Serial drivers etc etc (as a class, these would probably all be called "stream" drivers). Then there are other things that some (but perhaps not all) languages will need - like ADC packages and floating point libraries. I wonder just how many man years of Propeller development time have been wasted by forcing everyone to redevelop the basic infrastructure for themselves? Of course, we all probably re-use large chunks of the PASM cog programs that already exists (I know I do!) - but we all have to develop a means of communicating with these cog programs from our particular language.

    I freely admit that developing drivers is not my area of expertise (or interest!) and I would have gladly used existing drivers if I could have done so. - but I couldn't, because no such beast as I have proposed in this thread existed when I needed it, But surely the Propeller community as a whole now has enough experience to save the next generation of language developer having to do it all over again?

    Anyway - to specifics - could you give us a bit more detail about the mechanism(s) Forth uses to do the following (they seem very relevant to this thread):
    3 Forth can issue commands to other cogs from any cog (AKA, c" Do this!" 4 cog ) this command to cog 4 from the current cog can be issued from any cog.

    4 I/O to cog 4 can be set 4 >con or even Prop1 4 >con >prop2 5>con. If you want more pins add another Prop.

    5 Cog ram is addressable $abcd cogadr COG! (save to cog adr) of COG@ (read long at cogadr)

    Thanks!

    Ross.

    P.S. I do agree that threads like this often tend to go nowhere - that's because there seems to be a (very small, but very vocal) minority of people in these forums who seem determined to make sure they don't. I've nevr really understood why - but I think we should just ignore them and proceed anyway. Perhaps we will come up with something everyone will find useful.
  • Heater.Heater. Posts: 21,230
    edited 2011-12-08 02:41
    Dr_A,

    Interesting brain wave re: a bootloader loading COG then starting application.

    What this means is that we have to decouple loading of a COG with code, at boot time, from the COG actually
    starting it's work, at application run time.

    So it could go like this:
    0) Let's write all our COG codes such that they sit in an endless
    loop doing nothing until the LONG pointed at by their PAR becomes non-zero.
    
    1) Boot loader starts.
    
    2) For each "device" COG the boot loader:
        a) Reads a binary blob from SD or whatever.
        b) Loads and starts the blob in a COG with PAR pointing to some fixed LONG
           in high HUB space with a value of zero. This ensures the COG does not
           start real work yet because of 0) above. 
    
    3) Loads and run the main application code.
       (Spin interpreter + Spin code, LMM kernel + C code, whatever)
    
    4) The application now has control so for each COG "device" it:
        a) Sets up all the usual parameters, buffers, commands,
           whatever would normally be passed by PAR.
           They can be anywhere in HUB the app likes them to be.
        b) Sets the appropriate LONG for that COG to point to that parameter block.
    

    With that last step the device COG sees that it now has parameters, jumps out of it's initial wait loop,
    reads the param block and starts work.

    I hate to say this but it sounds like we might need some kind of registry to contain those COG controlling longs
    and whatever other infor is required.

    Can we come up with some othe rname? "registry" has such bad associations in all sorts of ways.
  • Heater.Heater. Posts: 21,230
    edited 2011-12-08 02:57
    Ron Sutcliffe,

    I can see that Forth may have its own way of communicating process to process and COG to COG or even Prop to Prop when each end of the link is more Forth code.

    However I don't see why Forth cannot handle a language neutral interface like any other language.

    As an example, if you build a system with a hardware UART chip that is controlled by a bunch or registers mapped into memory space I'm sure Forth is as capable of poking values into and reading from those UART registers as any other language.

    So...A UART implemented in software in a COG working through a memory space in HUB is as usable from Forth as any other language.

    Hardware devices are language neutral, and so are "soft devices" in COGs. Forth needs no special consideration here. Although the mechanisms adopted by Forth developers may well be helpful in the general case.
  • RossHRossH Posts: 5,512
    edited 2011-12-08 03:56
    Heater. wrote: »
    Dr_A,

    Interesting brain wave re: a bootloader loading COG then starting application.
    You do realize that Dr_A was only restating what Catalina already does, don't you?

    This is what Catalina's two-phase load options (such as EEPROM and SDCARD) are all about - all 32k of Hub RAM is available to be used for program code, because the program code is loaded after the cog programs have been loaded - effectively allowing programs up to 48kb on a normal Propeller.
    Heater. wrote: »

    ...

    I hate to say this but it sounds like we might need some kind of registry to contain those COG controlling longs
    and whatever other infor is required.
    Aha! - can I say "I told you so" yet? :).
    Heater. wrote: »

    Can we come up with some othe rname? "registry" has such bad associations in all sorts of ways.

    You don't like the word registry? Micros$oft has polluted the language that much?

    How about "catalog" instead?

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-12-08 04:04
    0) Let's write all our COG codes such that they sit in an endless
    loop doing nothing until the LONG pointed at by their PAR becomes non-zero.

    1) Boot loader starts.

    2) For each "device" COG the boot loader:
    a) Reads a binary blob from SD or whatever.
    b) Loads and starts the blob in a COG with PAR pointing to some fixed LONG
    in high HUB space with a value of zero. This ensures the COG does not
    start real work yet because of 0) above.

    3) Loads and run the main application code.
    (Spin interpreter + Spin code, LMM kernel + C code, whatever)

    4) The application now has control so for each COG "device" it:
    a) Sets up all the usual parameters, buffers, commands,
    whatever would normally be passed by PAR.
    They can be anywhere in HUB the app likes them to be.
    b) Sets the appropriate LONG for that COG to point to that parameter block.

    Heater, yes I think that is the idea.

    Here is a problem I've come across; by the time you add all the essentials to a typical Spin program - a TV text driver with buffer, keyboard, mouse, sd card driver, there is very little space left to write your actual program.

    So - preloading cogs saves a lot of memory. Ross cunningly uses this in Catalina, but you need to have delved into the Catalina code to understand or appreciate the cleverness of this. Not so many Spin programs do this though and if they did, it would free up a lot of memory.

    Next thing - if anyone wants to call it something different to "registry", fine by me.

    Now - if we are going to talk standards, let's drill down into some code and see what happens after heater's step 4. The next thing that generally happens is you have a parameter list in hub and this gets copied to a parameter list in the cog. Sometimes this is not done very efficiently with separate lines of code. Maybe this can be done in a loop and save some precious cog space? For instance, I want to pass seven variables, so the first bit of pasm code does a loop 7x.

    But it may not be quite so simple - there might be some variables that can be discarded once they have been passed (eg pin numbers) and some that you actually use to communicate with the cog. So you might need two lists - the discardable variables and the variables that remain linked to a location in hub. There are extreme cases either way eg cog code that shares nothing with hub once it is started like a led flasher, and at the other end, a TV driver that shares 20k of hub space.

    I don't know if trying to standardise that helps or not? I suppose one thing you might end up doing with typical cog code is passing more parameters at startup rather than including those parameters as hard coded pasm instructions.

    I continue to have my doubts about any standard that adds extra cog code, as I have seen a number of objects that are full to almost the last long. And I'm guilty as charged, because I just added a loop that scans the PAR long at startup waiting for an instruction to start so that gobbles another two or three longs.

    I am interested in standards that might reduce cog code, if this is possible. Passing variables via a loop might achieve that.

    As I delve into Ross' ideas I am finding I have concerns about his common_definition file that defines things like pins. Such a file has to be included at compile time, which means you can't have cog binaries preloaded on an sd card. It seems to me that if you want pasm cog code that is truly language independent (and hardware independent) then you have to pass all the variables like pins when the cog starts up.

    Passing those variables does use some more cog code.

    I suspect that if you want pasm cog plugins that are language and hardware agnostic, you are always going to need to pass some variables. So you have to put that variable list somewhere. So somewhere in our registry (probably the first place the cog looks, which is PAR, to save code space) that needs to point to our variable list. I think that process needs to be optimised to use the absolute minimum cog code. I'd even go as far as saying that if you are passing 7 variables, you never pass the number 7. The cog knows it needs to read 7 variables so it has a loop that iterates 7x. The code in hub (Spin/C etc) also knows that this is the number of variables to pass.

    So maybe you have 8 longs and they point to 8 locations in hub with a variable number of longs. As an example of all this and a nice standard I'd like to copy in my own code, the Chip Gracey keyboard driver has 19 contiguous longs:
      long  par_tail        'key buffer tail        read/write      (19 contiguous longs)
      long  par_head        'key buffer head        read-only
      long  par_present     'keyboard present       read-only
      long  par_states[8]   'key states (256 bits)  read-only
      long  par_keys[8]     'key buffer (16 words)  read-only       (also used to pass initial parameters)
    

    and these get read in a loop by the cog
    entry                   movd    :par,#_dpin             'load input parameters _dpin/_cpin/_locks/_auto
                            mov     x,par
                            add     x,#11*4
                            mov     y,#4
    :par                    rdlong  0,x
                            add     :par,dlsb
                            add     x,#4
                            djnz    y,#:par
    

    This demonstrates a number of things. Discarded temporary initial variables are passed via the buffer and this is a cunning way of saving memory. The longs are contiguous and there are no other shared variables. The cog code to unwrap the package is very compact and uses a loop. If you were to define a standard, maybe start with trying to obey all those rules?

    Overall, this meant that this piece of code was by far the easiest one to split into separate pasm and spin parts.

    My next question though - is adding anything more to a "standard" going to add more of a constraint rather than add flexibility? We talk to the keyboard at the moment via that list of longs. The program running in hub and the program running in the cog can change those variables and the two parts interact in this way.

    I believe (and correct me if this is wrong) that Ross' standard also defines four types of service request. This is an additional part of a standard. It would involve a rewrite of the keyboard code.

    I am thinking that the keyboard system, as it is, is a good enough standard. The longs are contiguous so you can point to the list with one variable. The data in the longs is documented. What compelling reasons exist for adding service requests? Or interacting with that cog via Unix type pseudo files? Or some other standard?
  • RossHRossH Posts: 5,512
    edited 2011-12-08 04:28
    Dr_Acula wrote: »
    As I delve into Ross' ideas I am finding I have concerns about his common_definition file that defines things like pins. Such a file has to be included at compile time, which means you can't have cog binaries preloaded on an sd card. It seems to me that if you want pasm cog code that is truly language independent (and hardware independent) then you have to pass all the variables like pins when the cog starts up.

    Passing those variables does use some more cog code.
    That's a fair point, Dr_A - as I said in a previous post (in response to one from potatohead, I believe) the initialization of cog programs is a closely related issue to comunicating with the cog program - i.e. if you can do the latter, you can in fact use the same technique to do the former.

    In Catalina, I actually use several techniques to initialize cog programs, including passing pins and clock frequency etc to the cog program at run-time via an "initialization" service - the actual technique used often depends on what the PASM code I "borrowed" originally did - so I agree this is also an area that is ripe for standardization.

    It is also true that the "common definitions" file is required at compile time, However, the contents - i.e. the pin, clock and memory definitions - are for compiling the cog programs. The C programs don't use them (or not many of them - which I could separate out). Such these things need to be defined somewhere, but I'd be happy to use a better technique if we can agree on one (I've actually changed Catalina several times in this area - another change wouldn't be a problem).

    Ross.
  • Heater.Heater. Posts: 21,230
    edited 2011-12-08 04:29
    RossH,
    You do realize that Dr_A was only restating what Catalina already does, don't
    you?

    Don't overestimate my understanding of anything:)
    Aha! - can I say "I told you so" yet?

    Yeah, yeah, you told me.

    That clinking sound you hear is the sound of a pile of pennies dropping. Well a
    few anyway:)

    All very cunning. Now I'm even more at a loss to think how one might standardize
    such a thing.

    "registry" Well the MS connection is bad enough. But "register" has always had
    a bad ring to it to me. Starting with the "register" that school teachers used
    to tick you name off in every day. Moving on to the "registra of births, deaths
    and marriages" and so on. Officious all down the line....
  • 4x5n4x5n Posts: 745
    edited 2011-12-08 07:16
    This thread is starting to sound like a debating society although it has accomplished it's goal in bringing most here to agree that some type of standard would be useful. That said I think it's served it's purpose and can end. The next step is for people far more knowledgeable to sit down and write such a standard. Since the people working on compilers for languages other then spin and pasm are the most effective and probably aware of the needs of a C, Forth, Basic, etc (I didn't list the languages in any significant order :-)) it would be nice if they sat down and wrote something out. The "competing ideas" could then be discussed, debated, argued over, and finally probably combined to something they can agree on. From there the process begins again at a very nuts and bolts level of actually implementing the higher level standards. My hope is that when people like me sit down and write code using C, Forth, Basic, etc that those standards will be transparent to me. The bottom line is we shouldn't need to know how one object communicates with another. There would be functions that did it and that's how I would have objects communicate.

    This is all along the lines of the RFC process used for most things involving the internet and has worked well for a lot of years. Adherence isn't required but if you want to communicate with other then you follow the RFCs. Same thing with these standards. If a developer writing a perl compiler wants to ignore the standards that's fine but then the libraries of C, Forth, Basic, etc routines would be very difficult to use!

    Just my $.02 worth.
  • TinkersALotTinkersALot Posts: 535
    edited 2011-12-08 08:03
    First : kudos to 4x5n for trying to corrall the cats :)

    I think this was mentioned somewhere too wasn't it? It is one thing to have a standard calling method between coglets, but seems to me that part of this standard could also use standard messages (start, stop, restart, pause, change-param-value). In other words a set of commands that compliant chunks of code could (if it made sense for them) respond / react to.

    Another thing that could help (and I don't know how to do this) is to select the "best of the best" of some OBEX entities for inclusion in a "reference design" and make them interoperate in a hardware system (maybe the C3 board or something) so that as the spec/standard emerges/evolves -- in order to serve as both a reference and a model for how things could be done.

    and no I still can't take any of this on until after Christmas!
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-12-08 08:54
    4x5n wrote:
    If a developer writing a perl compiler wants to ignore the standards that's fine but then the libraries of C, Forth, Basic, etc routines would be very difficult to use!
    That's the part I don't get. There already is a standard; it's very simple, and it's very open: cogs communicate through the hub. That's it. A Spin program that includes objects having six or seven variants of that "standard" is able to run harmoniously without those objects stepping on each other or miscommunicating. So how does adding another language to the mix change anything? If that language provides the ability for programs to read and write to the hub, interaction with modules of any language should be possible.

    If you want to standardize something, create a standard format for relocatable, linkable load modules. With such a standard in place, compiler writers for any language -- including Spin -- will have a way to output code that a common loader will know what to do with. But I don't believe that such a standard necessarily entails standard communication conventions once the modules are loaded. That would, as it is now, be dictated by the requirements of whatever modules you're using and will work, just as it does now, as long you're able to pass pointers between modules.

    So the "standard" is, "Here's a pointer (or two, or three, or an array of pointers) into some hub memory I own. The docs for his module explain what to do with it." Or, in the case of cog-resident code, "Give me the address of a block of your hub memory. My docs explain how it needs to be structured and how to communicate." It doesn't have to be any more limiting than that.

    -Phil
  • ericballericball Posts: 774
    edited 2011-12-08 10:18
    I'm with Phil here, or maybe I'm just not seeing the use case.

    COGINIT (PASM) has 4 parameters: new & cogid to select between coginit & cognew function, a HUB RAM pointer to the 496 long cog code and a second 14 bit value to set PAR and typically used as a pointer to a block of longs in HUB RAM used for configuration & communication. Although another possibility is to set values in the cog code prior to coginit (source code mods effectively do this), which may be necessary in cases where space is at an absolute premium.

    That brings up one problem if PAR points to a "coginfo block" - it requires additional instructions for the cog code to perform the necessary lookups to find the configuration block and for some drivers that extra space may simply not be available.

    And as Phil says, as long as the format and usage of the HUB RAM block is adequately documented (either directly or indirectly via the SPIN wrapper), there's no reason that another language couldn't interface with the cog driver via same HUB RAM block - the cog code doesn't care, it only knows that PAR points to the data it needs.

    Now, I can see some value for OS style code to track which cogs contain which drivers and the location and size of any HUB RAM usage for each driver, but the cog code itself doesn't have to care. And there's probably value to have pseudo-stdio interfaces for each driver - but that's a job for wrapper code, not the cog code itself.
  • Kevin WoodKevin Wood Posts: 1,266
    edited 2011-12-08 10:25
    That's the part I don't get. There already is a standard; it's very simple, and it's very open: cogs communicate through the hub. That's it.

    Well, there you go... the one method guaranteed to always be available.
  • 4x5n4x5n Posts: 745
    edited 2011-12-08 10:31
    ericball wrote: »
    I'm with Phil here, or maybe I'm just not seeing the use case.

    COGINIT (PASM) has 4 parameters: new & cogid to select between coginit & cognew function, a HUB RAM pointer to the 496 long cog code and a second 14 bit value to set PAR and typically used as a pointer to a block of longs in HUB RAM used for configuration & communication. Although another possibility is to set values in the cog code prior to coginit (source code mods effectively do this), which may be necessary in cases where space is at an absolute premium.

    That brings up one problem if PAR points to a "coginfo block" - it requires additional instructions for the cog code to perform the necessary lookups to find the configuration block and for some drivers that extra space may simply not be available.

    And as Phil says, as long as the format and usage of the HUB RAM block is adequately documented (either directly or indirectly via the SPIN wrapper), there's no reason that another language couldn't interface with the cog driver via same HUB RAM block - the cog code doesn't care, it only knows that PAR points to the data it needs.

    Now, I can see some value for OS style code to track which cogs contain which drivers and the location and size of any HUB RAM usage for each driver, but the cog code itself doesn't have to care. And there's probably value to have pseudo-stdio interfaces for each driver - but that's a job for wrapper code, not the cog code itself.

    I may be making things more complicated then I need to but passing a "PAR" to a cog/pasm program may work to pass info into a program but makes finding that data by other objects difficult. I don't think the "standard" needs to be very large or a burden. Simply agree on 8 longs in hub ram someplace that would have a slot for each cog. That long would then have a pointer to a block of hub ram and other info like the size of the data block, etc used by that cog. What's interesting is that in the process of pointing out that a standard way of allocating/locating hub ram for cogs isn't needed he provides a very simple and workable "standard" :-)

    This doesn't need to be complicated!!
  • jazzedjazzed Posts: 11,803
    edited 2011-12-08 10:38
    That's the part I don't get. There already is a standard; it's very simple, and it's very open: cogs communicate through the hub. That's it. A Spin program that includes objects having six or seven variants of that "standard" is able to run harmoniously without those objects stepping on each other or miscommunicating. So how does adding another language to the mix change anything? If that language provides the ability for programs to read and write to the hub, interaction with modules of any language should be possible.
    Phil,

    The only real problem I've seen for using COG code "as is" from a language other than Spin is that some PASM drivers cog interfaces have to be re-written to operate without Spin. For example, the Graphics demo Graphics.spin file has a variable in it that the user needs to set before starting a cog on line 1596:
    fontptr                 long    0                       'font pointer (set before cognew command)
    
    


    If you want to standardize something, create a standard format for relocatable, linkable load modules. With such a standard in place, compiler writers for any language -- including Spin -- will have a way to output code that a common loader will know what to do with.
    True, but this is probably more work than just submitting to Ross.

    If Parallax liked the idea, they would not have rejected it.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-12-08 10:50
    jazzed wrote:
    True, but this is probably more work than just submitting to Ross.
    More work for whom, though? It would be preferable to place the burden on a handful of compiler writers, rather than upon everyone who writes code that they want to share.

    -Phil
  • ericballericball Posts: 774
    edited 2011-12-08 11:33
    4x5n wrote: »
    I may be making things more complicated then I need to but passing a "PAR" to a cog/pasm program may work to pass info into a program but makes finding that data by other objects difficult. I don't think the "standard" needs to be very large or a burden. Simply agree on 8 longs in hub ram someplace that would have a slot for each cog. That long would then have a pointer to a block of hub ram and other info like the size of the data block, etc used by that cog. What's interesting is that in the process of pointing out that a standard way of allocating/locating hub ram for cogs isn't needed he provides a very simple and workable "standard" :-)

    Let me see if I understand the use case you are trying to describe. You have three processes: A, B and C. A invokes coginit to start B and C. B needs to pass data to C directly. C is a driver and doesn't have dependencies on any other processes. Therefore when A invokes coginit for C via it's start wrapper PAR is the address of the HUB block C uses for configuration & communication. If A is an OS it may track additional information.

    The question is how does B get the address for both it's own c&c block along with the address of the c&c block used by C? The same way a graphics driver knows where the graphics data is - a pointer in the c&c block which can be passed in the it's start wrapper (or via some kind of stdio open parameter). Could it pick it up via a coginfo block? Yes, but that is only necessary if it has to dynamically seek out C. i.e. command says write to SDFAT:\\output, is an SDFAT driver connected? Yes. The coginfo block says there's one running on cog #5; okay, do an open(SDFAT:\\output), write( data )....

    A coginfo block may not be complicated (although if it was simple I doubt there would be 10+ pages of discussion on it), but we are dealing with a microcontroller with limited memory soany additional complexity should be avoided when possible.
    jazzed wrote: »
    The only real problem I've seen for using COG code "as is" from a language other than Spin is that some PASM drivers cog interfaces have to be re-written to operate without Spin. For example, the Graphics demo Graphics.spin file has a variable in it that the user needs to set before starting a cog on line 1596:

    And this is the case I mentioned where values are set in the cog code prior to coginit. And there's no reason the start / open wrapper code couldn't do this. Or the driver could be re-written to include the parameter in the c&c block, if there's space.
  • jazzedjazzed Posts: 11,803
    edited 2011-12-08 11:46
    ericball wrote: »
    And this is the case I mentioned where values are set in the cog code prior to coginit. And there's no reason the start / open wrapper code couldn't do this. Or the driver could be re-written to include the parameter in the c&c block, if there's space.

    Eric, I didn't mean to ignore your comment. I just didn't see it before I posted.

    Yes, I had to include the parameter in the c&c parameter block for it to work with C. I could have parsed Brad's wonderful BSTC list file and used a pointer, but at the time of the first port, BSTC was not available. The port of Graphics I did the other day for GCC was just a copy of the first one mainly.
  • 4x5n4x5n Posts: 745
    edited 2011-12-08 11:54
    ericball wrote: »
    Let me see if I understand the use case you are trying to describe. You have three processes: A, B and C. A invokes coginit to start B and C. B needs to pass data to C directly. C is a driver and doesn't have dependencies on any other processes. Therefore when A invokes coginit for C via it's start wrapper PAR is the address of the HUB block C uses for configuration & communication. If A is an OS it may track additional information.

    The question is how does B get the address for both it's own c&c block along with the address of the c&c block used by C? The same way a graphics driver knows where the graphics data is - a pointer in the c&c block which can be passed in the it's start wrapper (or via some kind of stdio open parameter). Could it pick it up via a coginfo block? Yes, but that is only necessary if it has to dynamically seek out C. i.e. command says write to SDFAT:\\output, is an SDFAT driver connected? Yes. The coginfo block says there's one running on cog #5; okay, do an open(SDFAT:\\output), write( data )....

    A coginfo block may not be complicated (although if it was simple I doubt there would be 10+ pages of discussion on it), but we are dealing with a microcontroller with limited memory soany additional complexity should be avoided when possible.


    I think that having a standard way of passing data between cogs/obj could reduce the amount of the limited memory. The problem with you scenario as I see it is that if cog A doesn't know about cog C then how is it going to pass on the info of where the data for that cog is to be stored? In any case for the most part I think we're agreeing more then we're disagreeing and there's been a lot of talking past each other and preaching to the choir. In reality this is more of an issue for the "compiler people" to sort out among themselves. For those of us that write our own spin/pasm code it's not much of an issue since we already know where the various objects store their data in HUB ram. :-) I do see issues for people writing libraries and getting code compiled by one compiler or written in one language to work with code compiled by another compiler.
  • Dave HeinDave Hein Posts: 6,347
    edited 2011-12-08 12:29
    Data that needs to be preset before starting a cog could be located at the beginning of the hub cog image, just after a "jmp #entry" instruction at hub location zero. This way the Spin or C program knows exactly where the data is. The code would look something like this:
    pub start(parm1, parm2)
      long[@cogstart][1] = parm1
      long[@cogstart][2] = parm2
      cognew(@cogstart, 0)
    
    dat
             org 0
    
    cogstart jmp #entry
    cogparm1 long 0
    cogparm2 long 
    entry ...
    
  • David BetzDavid Betz Posts: 14,516
    edited 2011-12-08 12:38
    Dave Hein wrote: »
    Data that needs to be preset before starting a cog could be located at the beginning of the hub cog image, just after a "jmp #entry" instruction at hub location zero. This way the Spin or C program knows exactly where the data is. The code would look something like this:
    pub start(parm1, parm2)
      long[@cogstart][1] = parm1
      long[@cogstart][2] = parm2
      cognew(@cogstart, 0)
    
    dat
             org 0
    
    cogstart jmp #entry
    cogparm1 long 0
    cogparm2 long 
    entry ...
    
    That is exactly what I do in the PropGCC loader. Actually, I patch COG images on the PC side before downloading them so I don't have to waste hub memory space with the initialization code. That only works for a serial loader though. Ross's scheme of having a two-stage loader works well for loading without a serial connection. In fact, I use that scheme in my loader for writing a first-stage loader to eeprom.
  • ctwardellctwardell Posts: 1,716
    edited 2011-12-08 12:45
    What is so wrong with having A need to set the address of B's PAR as a parameter to C via C's PAR c & c block?

    With only 496 longs available in a cog it seems like a waste of resources for a cog to need to have extra code so it can search the registry itself for something that the code that initialized it could have just provided.

    This all seems like an attempt to turn something simple into something difficult.

    C.W.
  • RossHRossH Posts: 5,512
    edited 2011-12-08 13:55
    4x5n wrote: »
    This thread is starting to sound like a debating society although it has accomplished it's goal in bringing most here to agree that some type of standard would be useful. That said I think it's served it's purpose and can end. The next step is for people far more knowledgeable to sit down and write such a standard. Since the people working on compilers for languages other then spin and pasm are the most effective and probably aware of the needs of a C, Forth, Basic, etc (I didn't list the languages in any significant order :-)) it would be nice if they sat down and wrote something out. The "competing ideas" could then be discussed, debated, argued over, and finally probably combined to something they can agree on. From there the process begins again at a very nuts and bolts level of actually implementing the higher level standards. My hope is that when people like me sit down and write code using C, Forth, Basic, etc that those standards will be transparent to me. The bottom line is we shouldn't need to know how one object communicates with another. There would be functions that did it and that's how I would have objects communicate.

    This is all along the lines of the RFC process used for most things involving the internet and has worked well for a lot of years. Adherence isn't required but if you want to communicate with other then you follow the RFCs. Same thing with these standards. If a developer writing a perl compiler wants to ignore the standards that's fine but then the libraries of C, Forth, Basic, etc routines would be very difficult to use!

    Just my $.02 worth.

    Hi 4x5n,

    Shut the thread down? Why? Looking at the most recent posts here, it seems that people are just beginning to discuss the actual issue. Or do you mean shut this thread down so we can start another "clean" thread? I could probably agree with that suggestion.

    One thing though - you seem to think that there is some "other" place where this stuff should be discussed and agreed by "people far more knowledgeable" - but (frightening as it may seem!) I'm afraid the participants in this forum are those people! - there is no other place, and there are no other people. If we don't do this, and do this here, then it won't happen. Isn't this what these forums are for? Parallax certainly won't do it - quite understandably, they are snowed under with other things, and anyway have little experience with this stuff - software is not their core business.

    As you suggested, each of us compiler developers here could all go away and "write something out" - but look where that has got us over the past 5 years! And also, look at the vitriol that the only documented proposal attracts - much of which seems to be objection to the choice of one single word!

    I think it is interesting that you raise the RFCs (that form the basis of the internet) as an analogy. Yes, it's true those started as academic discussion documents, and you didn't have to comply with them. Two points, though: (1) an RFC is usually the output of a bunch of discussion in forums like this, not the input (they are described as "after the fact" standards) and (2) where are those people who chose not to comply with the various RFCs now?

    Apart from the inevitable "nay-sayers" who seem to frequent every thread in these forums that proposes something a little different, I think this thread is doing just fine.

    Ross.
  • RossHRossH Posts: 5,512
    edited 2011-12-08 14:06
    jazzed wrote: »
    True, but this is probably more work than just submitting to Ross.

    If Parallax liked the idea, they would not have rejected it.

    Jazzed, I think everyone here realizes you have issues both with me and with Catalina. If you must contribute to this thread, please try not to let your prejudices extend to ideas proposed just because some of them may originate from the same source.

    Also, if Parallax wants to express an opinion, I'm sure they do not need you to act as a mouthpiece.

    Ross.
Sign In or Register to comment.