@evanh said:
On the other hand, if there is no branch and you execute off the end of lutRAM it will wrap back to cogRAM, albeit with the program counter ticking along above $400, because hubexec will only trigger on a branch.
I think there might be something else apart from PC that wraps around from end of LUT RAM to start of cog RAM, from a discussion a few months ago.
That was running off end of hubRAM I believe. Same story though. The program counter itself is 32-bit, therefore doesn't rollover at 1 MB, but not all bits are decoded so it still maps like it rolled over.
@evanh said:
Testing that it seems to be precisely scaled as longwords below $400 and bytes from $400 up. Which makes sense given that is the documented addressing. So a relative branch of $100 from $380 in lutRAM will land at $480 in hubRAM.
Ha, just read the manual on these instructions, BRANCH ADDRESSING section. When in hubexec, they scale up the meaning of immediate relative encoding to longword steps. Which means that example there is at odds and will explain why I had previously thought there was something quirky at the lutRAM<->hubRAM boundary.
@evanh said:
On the other hand, if there is no branch and you execute off the end of lutRAM it will wrap back to cogRAM, albeit with the program counter ticking along above $400, because hubexec will only trigger on a branch.
I think there might be something else apart from PC that wraps around from end of LUT RAM to start of cog RAM, from a discussion a few months ago.
That was running off end of hubRAM I believe. Same story though. The program counter itself is 32-bit, therefore doesn't rollover at 1 MB, but not all bits are decoded so it still maps like it rolled over.
Actually it was Fast Block Moves wrapping around to start of the same RAM (cog to cog or LUT to LUT), not LUT RAM to cog RAM.
@evanh said:
Testing that it seems to be precisely scaled as longwords below $400 and bytes from $400 up. Which makes sense given that is the documented addressing. So a relative branch of $100 from $380 in lutRAM will land at $480 in hubRAM.
Ha, just read the manual on these instructions, BRANCH ADDRESSING section. When in hubexec, they scale up the meaning of immediate relative encoding to longword steps. Which means that example there is at odds and will explain why I had previously thought there was something quirky at the lutRAM<->hubRAM boundary.
It's not clear from the doc whether relative jumps from cog/LUT to hub are implemented in silicon. If they are, I guess that the hub address must be long-aligned.
It is a little quirky but makes sense to me now. Relative branches from lut to hub are not scaled up in hubram space, ie: they're treated as if landing in lutram. But relative branches back from hub to lut are scaled up even in cog/lut space, ie: treated as if landing in hubram so multiplied by 4. Which means a negative branch from $404 by $100 will branch backwards by $400 and therefore will land at address 4 in cogram!
@ersmith Is there a way to tell FlexBASIC to hold-off on doing garbage collection? I occasionally find it tries to tidy-up the heap right when I’m about to enter a bit of time-critical code. Maybe something like _gc_pause() and _gc_resume() maybe?
@JRoark said:
@ersmith Is there a way to tell FlexBASIC to hold-off on doing garbage collection? I occasionally find it tries to tidy-up the heap right when I’m about to enter a bit of time-critical code. Maybe something like _gc_pause() and _gc_resume() maybe?
Automatic garbage collection only happens when the allocator would otherwise fail, so holding it off would mean failing allocation -- probably not what you want. The best ways to avoid garbage collection during time critical code are:
(1) Avoid anything that requires memory allocation (string operations, mostly) inside the time critical code, or
(2) Call _gc_collect explicitly right before the time critical code to force the collection when you want it done
@ersmith said:
(2) Call _gc_collect explicitly right before the time critical code to force the collection when you want it done
That works wonderfully! Actually, forcing a collection each time thru a slow loop seems to result in much faster, more predictable collection times. Winner!
Eric,
In C, I'm using _setclk() to adjust the sysclock frequency for testing purposes. It works, however, I still want to use printf() down the serial port. What options do I have for updating the baud on each clock change?
PS: I've currently hacked in a _wxpin() for pins P62/P63. Doing the job.
Very interesting. I was just thinking about asking about this, but I was too shy.
Could someone please summarize this in a single paragraph or two, ideally for the documentation.
When can i do relative jumps, Registers, LutRam, HubRam.
I guess that is two 3x3 matrix. One for C programs and one for Assembly programs.
My suspicion is that one can do a lot more in assembly than one can in C.
In particular, I suspect that in Assembly, I can move functions to Registers or LutRam, and do relative
addressing on them, whereas I fear that C does not allow that.
I also suspect that C does not support the skip function.
Is there documentation somewhere on the differences between C and Assembly/Spin?
C, as a language generally, is intended to not be that architecture specific. On the other hand, what the compiler can generate most certainly is allowed to be architecture specific.
That said, the __asm {} directives do provide a way to hand code Propeller specifics.
I've used asm {} to great effect here - https://forums.parallax.com/discussion/comment/1525977/#Comment_1525977 muldiv65() makes use of the 64-bit result of a QMUL and 64-bit dividend of QDIV, but just as importantly it also incorporates round-to-nearest on the resulting 32-bit quotient.
@ersmith I noticed today that FlexBASIC has built-in facilities that allow you to start, query and get the ID of a cog, but there is no "cog stop" command. Would it be possible to round-out the cog control suite with a CPUSTOP() function? Presently I'm using the C function _cogstop(), but it seems odd there is no "native" equiv in FlexBASIC.
@JRoark said:
@ersmith I noticed today that FlexBASIC has built-in facilities that allow you to start, query and get the ID of a cog, but there is no "cog stop" command. Would it be possible to round-out the cog control suite with a CPUSTOP() function? Presently I'm using the C function _cogstop(), but it seems odd there is no "native" equiv in FlexBASIC.
Oh, I didn't realize there was no cpustop() in BASIC. I'll fix that, it really should be there. Thanks!
Seem to have an issue compiling mcufont (from github).
Gives an error on line 397 (see image) when initializing a structure (in all the other font files too).
Doesn't like the brackets inside brackets I guess.
Error message: DejaVuSans12.c:397: error: Variable mf_rlefont_DejaVuSans12 is initialized twice
The code claims to be ansi C...
I've attached the source files. Build line is in build.bat.
@Rayman: thanks for the bug report. The initialization error is fixed in 5.5.2. Unfortunately there are still some other bugs that prevent your program from building. I'm not exactly sure what's going wrong, but it's probably something wrong with flexspin.
@ersmith Thanks!
Looking at the other issues now...
Here's a strange one... It doesn't like the font structure reference in a complex line, but is OK when pulled out separately like this:
MF_EXTERN void mf_character_whitespace(struct mf_font_s *font,
mf_char character,
uint8_t *left, uint8_t *top,
uint8_t *right, uint8_t *bottom)
{
struct whitespace_state state = {255, 255, 0, 0};
mf_render_character(font, 0, 0, character, whitespace_callback, &state);
if (state.min_x == 255 && state.min_y == 255)
{
/* Character is whitespace */
if (left) *left = font->width;
if (top) *top = font->height;
if (right) *right = 0;
if (bottom) *bottom = 0;
}
else
{
int w = font->width; //RJA making line below less complex
int h = font->height; //RJA
if (left) *left = state.min_x;
if (top) *top = state.min_y;
//if (right) *right = font->width - state.max_x - 1;
//if (bottom) *bottom = font->height - state.max_y - 1;
if (right) *right = w - state.max_x - 1;
if (bottom) *bottom = h - state.max_y - 1;
}
}
@ersmith Re: FlexBasic 5.5.2
This code compiles without throwing an error.
OPTION EXPLICIT
CLASS tmpThing
Widgets as single
Widgets as ulong
Widgets as byte
Widgets as short
Widgets as string
Widgets as string
END CLASS
dim NewThing as tmpThing
NewThing.Widgets = 10
print "NewThing:Widgets="; NewThing.Widgets
The above is an extreme example, but in the "real world" I found this while looking for a memory leak/corruptor where I had defined the same var in a CLASS twice. Correcting that duplication seems to have fixed the corruption issue, which is why I'm reporting it.
Grr, my GIT-foo is useless. The output from git pull shows what looks to be a moving of the two branches 'master' and 'release'. But my attempts at selecting the release branch go nowhere. eg: git branch only lists master.
Comments
Patreon has a version 6.0.0… Just sayin!
That was running off end of hubRAM I believe. Same story though. The program counter itself is 32-bit, therefore doesn't rollover at 1 MB, but not all bits are decoded so it still maps like it rolled over.
Ha, just read the manual on these instructions, BRANCH ADDRESSING section. When in hubexec, they scale up the meaning of immediate relative encoding to longword steps. Which means that example there is at odds and will explain why I had previously thought there was something quirky at the lutRAM<->hubRAM boundary.
That crossing is kind of wonky due to the difference in the way the offsets are calculated. So I left the error in for that one.
Right. That fact sunk in for me a little later.
Actually it was Fast Block Moves wrapping around to start of the same RAM (cog to cog or LUT to LUT), not LUT RAM to cog RAM.
It's not clear from the doc whether relative jumps from cog/LUT to hub are implemented in silicon. If they are, I guess that the hub address must be long-aligned.
It is a little quirky but makes sense to me now. Relative branches from lut to hub are not scaled up in hubram space, ie: they're treated as if landing in lutram. But relative branches back from hub to lut are scaled up even in cog/lut space, ie: treated as if landing in hubram so multiplied by 4. Which means a negative branch from $404 by $100 will branch backwards by $400 and therefore will land at address 4 in cogram!
Somewhat of a different category not being instruction fetch. Don't remember seeing it either.
@ersmith Is there a way to tell FlexBASIC to hold-off on doing garbage collection? I occasionally find it tries to tidy-up the heap right when I’m about to enter a bit of time-critical code. Maybe something like _gc_pause() and _gc_resume() maybe?
Automatic garbage collection only happens when the allocator would otherwise fail, so holding it off would mean failing allocation -- probably not what you want. The best ways to avoid garbage collection during time critical code are:
(1) Avoid anything that requires memory allocation (string operations, mostly) inside the time critical code, or
(2) Call _gc_collect explicitly right before the time critical code to force the collection when you want it done
That works wonderfully! Actually, forcing a collection each time thru a slow loop seems to result in much faster, more predictable collection times. Winner!
Eric,
In C, I'm using _setclk() to adjust the sysclock frequency for testing purposes. It works, however, I still want to use printf() down the serial port. What options do I have for updating the baud on each clock change?
PS: I've currently hacked in a _wxpin() for pins P62/P63. Doing the job.
@evanh Have you tried _setbaud(rate)?
That's sounds like an option ... Yep, doing the job too.
Very interesting. I was just thinking about asking about this, but I was too shy.
Could someone please summarize this in a single paragraph or two, ideally for the documentation.
When can i do relative jumps, Registers, LutRam, HubRam.
I guess that is two 3x3 matrix. One for C programs and one for Assembly programs.
My suspicion is that one can do a lot more in assembly than one can in C.
In particular, I suspect that in Assembly, I can move functions to Registers or LutRam, and do relative
addressing on them, whereas I fear that C does not allow that.
I also suspect that C does not support the skip function.
Is there documentation somewhere on the differences between C and Assembly/Spin?
@lozinski If you read the FlexProp main documentation, it says how to force code segments into Cog or LUT RAM.
C, as a language generally, is intended to not be that architecture specific. On the other hand, what the compiler can generate most certainly is allowed to be architecture specific.
That said, the
__asm {}
directives do provide a way to hand code Propeller specifics.I've used
asm {}
to great effect here - https://forums.parallax.com/discussion/comment/1525977/#Comment_1525977muldiv65()
makes use of the 64-bit result of a QMUL and 64-bit dividend of QDIV, but just as importantly it also incorporates round-to-nearest on the resulting 32-bit quotient.@ersmith I noticed today that FlexBASIC has built-in facilities that allow you to start, query and get the ID of a cog, but there is no "cog stop" command. Would it be possible to round-out the cog control suite with a CPUSTOP() function? Presently I'm using the C function _cogstop(), but it seems odd there is no "native" equiv in FlexBASIC.
Oh, I didn't realize there was no cpustop() in BASIC. I'll fix that, it really should be there. Thanks!
Seem to have an issue compiling mcufont (from github).
Gives an error on line 397 (see image) when initializing a structure (in all the other font files too).
Doesn't like the brackets inside brackets I guess.
Error message: DejaVuSans12.c:397: error: Variable mf_rlefont_DejaVuSans12 is initialized twice
The code claims to be ansi C...
I've attached the source files. Build line is in build.bat.
@Rayman: thanks for the bug report. The initialization error is fixed in 5.5.2. Unfortunately there are still some other bugs that prevent your program from building. I'm not exactly sure what's going wrong, but it's probably something wrong with flexspin.
@ersmith Thanks!
Looking at the other issues now...
Here's a strange one... It doesn't like the font structure reference in a complex line, but is OK when pulled out separately like this:
@ersmith Got it to compile!
The other strange error was that it doesn't like a structure element with name "state". Changed to "stated" and it works:
I'm adding some stuff to the above and get errors when partially initializing a structure.
This line gives an error for apparently trying to initialize a structure with nothing:
state_t state = {};
This line gives an error for apparently trying to initialize a structure with just the first element:
struct linelen_s current = { 0 };
Update: I posted the full code in the mcufont thread, in case you need more info...
@ersmith Re: FlexBasic 5.5.2
This code compiles without throwing an error.
The above is an extreme example, but in the "real world" I found this while looking for a memory leak/corruptor where I had defined the same var in a CLASS twice. Correcting that duplication seems to have fixed the corruption issue, which is why I'm reporting it.
Freshly pulled master nets me this error:
make: *** No rule to make target 'backends/bytecode/bcbuffers.c', needed by 'build/bcbuffers.o'. Stop.
Looking in backends/bytecode, there is no bcbuffers.c file.
EDIT: Ah, and looking back at the git pull output I see this:
Grr, my GIT-foo is useless. The output from
git pull
shows what looks to be a moving of the two branches 'master' and 'release'. But my attempts at selecting the release branch go nowhere. eg:git branch
only lists master.@Rayman : thanks for the bug report. It may be a little while before I get to looking at that code.
@JRoark : Hmmm, that is odd, there should have been some kind of warning. I'll try to figure it out.