Help with include files
mynet43
Posts: 644
I have a program that includes two files, like this example:
Both the main program and the included program (Calc) need to use the Float32 routines for their processing.
I haven't been able to figure out how to make Float32 available for use by the Calc routine.
If I 'include' it in Calc, the program gets too big because it loads two copies of it [noparse]:([/noparse]
I tried to pass the address as a calling parameter like: cal.init(@fp). But this didn't work either.
Can someone please give me an example of how to solve this problem?
Thanks for your help.
Jim
OBJ fp : "Float32" cal : "Calc"
Both the main program and the included program (Calc) need to use the Float32 routines for their processing.
I haven't been able to figure out how to make Float32 available for use by the Calc routine.
If I 'include' it in Calc, the program gets too big because it loads two copies of it [noparse]:([/noparse]
I tried to pass the address as a calling parameter like: cal.init(@fp). But this didn't work either.
Can someone please give me an example of how to solve this problem?
Thanks for your help.
Jim
Comments
It shouldn't. There may be a slight increase in size but an entire copy of the object is not included.
But, I still have a problem [noparse]:)[/noparse]
Note the 'return' in the code shown below:
If I move the return statement to after the last line, it never returns. This indicates that it's getting lost in the fp module.
The same line of code works perfectly if I put it in the main program.
Any thoughts?
I figured it out...
You have to call fp.start in the second one too, duh...
Thanks
But it would be the simple solution, however it costs you another COG!
You have now 2 COGs loaded with the Float32 machine code, NOT working in parallel.
There are some threads discussing this situation in detail, and I posted a modification for Float32 somewhere, shifting some variables from VAR to DAT... Maybe I can find it.
Note that this a proplem of many driver authors: Shall they prepare their drivers for multiple use in parallel COGs, or shall they support the more frequent need of use from different objects....
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
The more I know, the more I know I don't know.· Is this what they call Wisdom?
Thanks for the reply. Very good point! I really don't want to start another COG here, I know there's a better way!
If you can find the method for doing this, I'd really appreciate it!
If we can fix this, I'd like to coordinate it with Cam Thompson, the author, so we can fix the basic module.
Thanks again,
Jim
I came across one of your posts from a while back:
[noparse][[/noparse]quote]
I complained some months ago about the tricky co-operation between Float32 (1.3) and FloatString.
Using Float32 from your main program and from Float32 needs patching Float32 (put the VAR cells into DAT) and you have to know what you are doing!) It is nonsense to start another Float32-COG just for the needs of FloatString.
This seems still to be an issue.
It's not Cam's fault; it's a design flaw with SPIN.
P.S.: Efficient multi COG Math32 is in fact very tricky as it needs so much overhead within a SPIN programm that the speed-up is mainly lost; there seems to be little interest in Floating Point Math here in the forum. Should it be otherwise, I am interested in disussing improvements there (e.g. chain computations avoiding the intermediate packing and unpacking, complex operations or matrix multiplication,... ) See also Micromega's FPU which for twice the price is not faster than a COG but has much more program space in its ROM....
This seems to refer to a way to do it, but no details.
Also, I'd be very interested in discussing the improvements you mentioned to the floating point routines. I'm familiar with the assembly code and I'd like to see a better way than constantly packing and unpacking the numbers. I'd also like to see matrix math. These changes shouldn't be difficult. Let me know what you think.
Jim
There is a "communication block" near the beginning; just change the VAR into a DAT
I explained at another place that I used 6 COGs loaded with FLOAT32 to work in parallel.
It was not that easy, as a call to FLOAT32 blocks the calling routine.
So although I tried to utilize the Multi-COG feature, it was not possible without some further modifications (removing the wait) which made this modified Float32deSILVA quite tricky to use.....
I tried your change but it didn't work.
I loaded Float32 and made the change you suggested: change VAR to DAT. And then saved it.
When I compiled the main program, I got the error message: "Undefined symbol." and the word "cog" was highlighted in the new DAT block.
What am I doing wrong?
Jim
Also, when this works, do I still call fp.start in the second object? If I do this, won't it still load another cog?
DAT has a different syntax..It should read:
To your question. No you need not but it won't do any harm... Have a look at the Float32 code:
You understand?
It works fine now.
Is there an easy way to tell that I've loaded fewer cogs than I had before?
I THINK, the COG logic will always allocated the COG with the lowest ID...
So you could check:
Post Edited (deSilva) : 10/1/2007 8:23:59 PM GMT
Let's see, I cut the power trace to the prop, insert a 1 ohm resistor, measure the voltage at each end of the resistor with two of my adc ports, take the difference and that's my current, right? Then all I have to do is run the program both ways to prove that I've saved a cog. Ingenious!
Just kidding!
Thanks,
Jim
I opened a new cog after opening Float32 in the second object.
I printed out the new cog number.
With the original Float32, the new cog was 5.
With the modified Fload32 (DAT instead of VAR), the new cog was 4.
It works!
This isn't really the fix I'd like to see. I'd rather have it controlled.
Tomorrow I'll send an email to Cam, the author, to see if he'll agree to incorporate these changes into a permanent version upgrade. Then we can all track any other changes he makes.
I'll try to post progress...
Jim
The Float32 cog waits for the command variable to be non-zero, then executes the code for the operation specified, returns the result in the cmdReturn variable, and clears the command variable. If command is defined by DAT, and multiple COGs are calling the Float32 routines, and they're running simultaneously, there will be collisions with the shared command variable. I'm guessing that in the multiple cog examples discussed above, one cog was calling another, which did its thing before returning to the caller, so the contention was avoided. But if the cogs were operating independently, things could fall apart. Putting mutual exclusion protection in the calling mechanism would add excessive overhead. It would be better to put it around blocks of code in the application (e.g. a complete calculation) rather than at the Float32 call level.
I'm not sure what the right solution is. As it sits now, multiple cog access works for the casual user, at the expense of extra cogs. Power users can change VAR to DAT if they know their application doesn't have a problem with simultaneous access, or they can change it and also add some mutual exclusion code. By making the changes, the power user is acknowledging responsibility for the mutual exclusion issues.
Cam
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Cam Thompson
Micromega Corporation
As I also said, there were more changes necessary to use 6 COGs with Float32
The main application wil lremain to call Float32 from different objects from ONE COG.
This is already the case when you use FloatString and ask yourself: Why should I load all the code for FloatMath when I have a fast COG with Float32 waiting eagerly for any operation?
You edit the OBJ in FloatString, and - bingo!
Maybe a short piece of explanation will already help?
Does anyone know how to summarize the results and post them somewhere that will save other people from this same problem?
I agree with Cam (and deSilva).
For now, I'll continue to use a modified, uncontrolled version of Float32[noparse]:([/noparse]
I wish there were a better way...
Jim
if someone were dedicated to compiling such information into a reference, we could request that a particular thread by summarized in the reference. There are stickies, but even that can get out of hand.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
The more I know, the more I know I don't know.· Is this what they call Wisdom?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker
Propeller Applications Engineer
Parallax, Inc.
Thanks
September: deSilva posted his 1,000th article
They're included as attachments below.
The first FAQ is:
How do I use an included object in more than one object?
The second is:
How do I prevent an included object from using multiple COGs for the same code?
Phil said he would include a link to this thread in Graham's thread index.
Thanks for all the help and great ideas.
Jim
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker
Propeller Applications Engineer
Parallax, Inc.
Among other answers: The Propeller design doesn't use interrupts because they expect you to use polling via a COG to get events. If you need low latency, you can use the waitpne or waitpeq commands within a COG to monitor the designated interrupt input (kind of a waste of a COG). If you don't need low latency, your interrupt COG could do other things and periodically run the pin monitor. The other reason to use an interrupt for multi-tasking ticks is not of much interest in the Propeller community, but this can be done too with some special coding ....
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
propeller.wikispaces.com/Interrupts