I'm trying to pass a small auto array to inline assembly. But the pointer still seems to be a hub address.
{
long data[10] = {1,2,3,4,5,6,7,8,9,10};
long *addr = data;
int len = sizeof(data) / 4 - 1;
printf( "addr = %lx, len = %d\n", addr, len );
__asm { ... }
}
The print is giving me values above 0x1000. What's wrong?
Pointers are always hub addresses. The hub and cog address spaces are disjoint for data (for code the COG and LUT address space is mapped to 0x000-0x400
In Fastspin C, how to force some assembly to cogexec? I'm guessing best way is make a callable function.
There's no way to do that yet. The closest you can come is to enable FCACHE and wrap the inline assembly in code to load it into FCACHE. At some point I'd like to implement attributes to force functions into cog or lut memory, but I haven't had time to do that yet.
Is there any C documentation? I've not found any.
doc/c.md is all there is (in FlexGUI it's compiled to a .pdf and a .html).
getqx has a side effect (clearing an internal register), which the optimizer hasn't been told about, I missed that.
It might not be a bad idea to add a "volatile" option to __asm (like GCC does) to tell the optimizer not to touch anything in it. The bad part of this is that a lot of people will use "__asm volatile" when they really should just use "__asm" . Unfortunately I think people are likely to overuse __asm in general; using the macros from propeller2.h and/or limiting asm use to just a few key functions will make the code more readable and more portable to other P2 C compilers.
getqx has a side effect (clearing an internal register), which the optimizer hasn't been told about, I missed that.
It might not be a bad idea to add a "volatile" option to __asm (like GCC does) to tell the optimizer not to touch anything in it. The bad part of this is that a lot of people will use "__asm volatile" when they really should just use "__asm" . Unfortunately I think people are likely to overuse __asm in general; using the macros from propeller2.h and/or limiting asm use to just a few key functions will make the code more readable and more portable to other P2 C compilers.
"__asm volatile" in GCC means something very different - it tells the compiler that the asm has side effects (and thus, it can not eliminated or moved outside a loop). This of course only makes sense when using GCC's nice extended inline ASM syntax with defined inputs and outputs.
GCC never actually touches your inline ASM, except for replacing certain escape sequences. It just pastes it right into the output ASM, including inconsistent indentation.
Eric,
That last case, where I used GETQX in a precautionary way, isn't as effective as I'd first thought. If there is nothing in-progress in the pipeline when a new op is issued, then the hardware discards any dead results anyway.
So, that use of GETQX is only effective if there is a cordic op actually still making its way through the pipeline at the time.
@ersmith Does FlexBASIC attempt any optimizations in ASM...END ASM blocks? Or is what you enter exactly what you get?
All the languages use the same output routines, and those optimize inline assembly along with everything else. Usually this is what you want: it improves both the generated code and (potentially) your code, e.g. if you write:
function sum(a, b)
asm
add a, b
end asm
return a
end function
function sum1(a)
return sum(a, 1)
end function
the optimizer can turn calls to "sum1(x)" into "x+1", because it knows what the "add" instruction does. It can also do the basic transformations (like turning "xor reg, ##(1<<n)" into "bitnot reg, #n") on your code that it does on the generated code.
The next version of fastspin will allow you to type "asm const" to suppress optimization on asm blocks. It's usually a bad idea to use this; the only time it's useful, I think, is to work around an optimizer bug or when timing is critical (and you for some reason cannot use waitct or waitx to synchronize the timing; the optimizer does know about those).
"__asm volatile" in GCC means something very different - it tells the compiler that the asm has side effects (and thus, it can not eliminated or moved outside a loop).
I wouldn't say it's "very" different; without volatile the asm block does participate in the optimization, it's just that GCC treats the whole block as a single instruction, whereas fastspin knows about what the individual instructions within the block mean.
@ersmith While coding in FlexBASIC on Win10 using FlexGUI V4.1.2:
I have a puzzlement about array declarations and assignments in FlexBASIC. There are several syntaxes to declare a SHARED array variable in FlexBASIC, and I find myself using them interchangably:
dim shared as ulong a 'works
dim shared as ulong b(10) 'works
dim shared c as ulong 'works
dim shared d(10) as ulong 'works
dim shared as ulong e(10) = { 1,2,3,4,5,6,7,8,9,10 } 'works
dim shared f(10) as ulong = { 1,2,3,4,5,6,7,8,9,10 } 'does NOT work
dim shared as ulong g = 100 'works
dim shared h as ulong = 100 'does NOT work
print "done"
But it seems that when using an initializer with a SHARED var, only one of the syntaxes works (see above). The other throws the error: "error: syntax error, unexpected '=', expecting $end or end of line or end or ':'
Bug or feature? Or is this one of those "loose nut behind the user keyboard" things?
@ersmith While coding in FlexBASIC on Win10 using FlexGUI V4.1.2:
I have a puzzlement about array declarations and assignments in FlexBASIC. There are several syntaxes to declare a SHARED array variable in FlexBASIC, and I find myself using them interchangably:
dim shared as ulong g = 100 'works
dim shared h as ulong = 100 'does NOT work
But it seems that when using an initializer with a SHARED var, only one of the syntaxes works (see above). The other throws the error: "error: syntax error, unexpected '=', expecting $end or end of line or end or ':'
Bug or feature? Or is this one of those "loose nut behind the user keyboard" things?
The initialization has to go next to the variable, as if it were an assignment statement, since more than one variable may be declared in a dim:
dim shared as ulong g=100, h=200
dim shared x=100, y=200 as ulong
Do other BASICs allow it to go after the "as ulong" clause? I guess freebasic does, but it also only allows one variable to be declared at a time when the "as type" comes after the variable
I've released fastspin 4.1.3 (and flexgui 4.1.3). The only fastspin change is the "const" attribute for inline assembly blocks, to prevent the optimizer from changing them. I do urge people to use "asm const" sparingly; there are a lot of useful optimizations (like constant propagation and folding) that can be applied to inline assembly and which are suppressed by "asm const".
I think I was able to trick fastspin into checking my assembly driver code...
It wasn't checking it before because Spin code started with "Stop" routine that didn't do anything.
I had to compile the main Spin file for it to check for errors...
I think I was able to trick fastspin into checking my assembly driver code...
It wasn't checking it before because Spin code started with "Stop" routine that didn't do anything.
I had to compile the main Spin file for it to check for errors...
But, I did this and now it checks everything:
PUB Stop
repeat
start(pTiles, pColors)
Even better than that is to make the first method a test harness for the rest of them. Then you can compile the object stand-alone to test it, or if it's used as an object the compiler will just remove the unused test method.
Maybe this is more of a loader question... But, anyway...
With P1, you can modify your code in eeprom very easily by just writing to the location where variable data is stored...
Can we do this with the flash on P2?
Is there a way to figure out where the code is actually stored in flash?
Maybe this is more of a loader question... But, anyway...
With P1, you can modify your code in eeprom very easily by just writing to the location where variable data is stored...
Can we do this with the flash on P2?
Is there a way to figure out where the code is actually stored in flash?
For PNut.exe, you can compile flash_loader.spin2 and get this in the list (via Ctrl-L):
TYPE: 49 VALUE: 024001C8 NAME: APP_START
The $024 is the long-index offset to the start of user code. So, you should be able to do "@dat_asset + $024 << 2" to get the address in flash of where the data of interest is. Remember, though, that is a flash, and not an EEPROM, so you would have to erase the pertinent block and rewrite it with changed data. That's not practical, so it would be better to wait for (or develop) a file system that uses the upper part (past the first 1MB, perhaps) of the 16MB flash for general file use. Then, you could do whatever you want. Gosh, this needs to exist. If we just develop the object to handle it, the upper 15MB of the flash can become a persistent file system that survives flash reprogramming of the application code.
ersmith,
I am a dummy, trying to get flexgui up and running in the latest linux mint 19.3. can you offer an assist?
Jim
Probably easiest to do this by building from source. You'll need git, the build-essentials package, bison, tcl, and tk to be installed (at least). To build do:
git clone --recursive https://github.com/totalspectrum/flexgui.git
cd flexgui
make install
You may get some warnings about pandoc and/or latex being missing; those will affect the documentation build (it'll prevent the doc/*.md files from being converted to .html and .pdf) but won't otherwise affect the functionality. Install pandoc and pdflatex if you want the docs converted (the .md files are plain text, so conversion isn't strictly necessary).
The procedure above will install flexgui to $HOME/flexgui; to run it do:
cd ~/flexgui
./flexgui.tcl
I think probably using the flexgui.zip Windows binary and running under wine will work too, but I haven't tried that.
It looks like the comments after "asm" mess it up.
When I remove the comments, it works...
Wait, I may be wrong about that...
Hmm... Seems that even a space character after ASM, makes it not work...
Yes, unfortunately there's a bug that causes anything after an ASM to mess things up. That'll be fixed in the next release (and is fixed in github) but for now the ASM has to be alone on a line.
Has anybody already reported this issue? fastspin doesn't report any missing symbols (or any syntax errors at all?) in a PUB or PRI function if that function is not called in the current file. So if I write an object that is to be used as library for other objects and press "compile" to check if I've made any typos then nothing is checked at all because nothing except the first (main) function is called.
I know, this is not really a bug. When I compile the main object that calls the library functions every error is found. It's just a bit surprising. I think syntax should be checked even for functions that are currently unused and are optimized away (dead code).
Has anybody already reported this issue? fastspin doesn't report any missing symbols (or any syntax errors at all?) in a PUB or PRI function if that function is not called in the current file. So if I write an object that is to be used as library for other objects and press "compile" to check if I've made any typos then nothing is checked at all because nothing except the first (main) function is called.
I know, this is not really a bug. When I compile the main object that calls the library functions every error is found. It's just a bit surprising. I think syntax should be checked even for functions that are currently unused and are optimized away (dead code).
If you don't want the compiler to optimize away unused functions, then turn off optimization (at least for fastspin 4.1.3 and later).
Has anybody already reported this issue? fastspin doesn't report any missing symbols (or any syntax errors at all?) in a PUB or PRI function if that function is not called in the current file. So if I write an object that is to be used as library for other objects and press "compile" to check if I've made any typos then nothing is checked at all because nothing except the first (main) function is called.
I know, this is not really a bug. When I compile the main object that calls the library functions every error is found. It's just a bit surprising. I think syntax should be checked even for functions that are currently unused and are optimized away (dead code).
If you don't want the compiler to optimize away unused functions, then turn off optimization (at least for fastspin 4.1.3 and later).
I agree that the compiler ought to parse all of the source code even if it eventually decides not to include code in the final executable. Is there a reason not to do this?
Has anybody already reported this issue? fastspin doesn't report any missing symbols (or any syntax errors at all?) in a PUB or PRI function if that function is not called in the current file. So if I write an object that is to be used as library for other objects and press "compile" to check if I've made any typos then nothing is checked at all because nothing except the first (main) function is called.
I know, this is not really a bug. When I compile the main object that calls the library functions every error is found. It's just a bit surprising. I think syntax should be checked even for functions that are currently unused and are optimized away (dead code).
If you don't want the compiler to optimize away unused functions, then turn off optimization (at least for fastspin 4.1.3 and later).
I agree that the compiler ought to parse all of the source code even if it eventually decides not to include code in the final executable. Is there a reason not to do this?
It does parse all of the source code and creates an abstract syntax tree for all methods, so syntax errors are definitely caught. However, some other errors (e.g. undefined symbols, in many cases) are not detected until the compilation phase, and the compiler never even tries to compile unused methods. To be more explicit, "x := 1" is (usually) valid syntax in a Spin method, but if "x" isn't defined then it may not produce an error if the code is never compiled.
Changing this behavior is possible, obviously, but it's work. I'd be happy to accept pull requests (or payment) to do it. In the meantime, either use -O0 or else actually use the methods that you want to test.
Comments
Is there any C documentation? I've not found any.
Pointers are always hub addresses. The hub and cog address spaces are disjoint for data (for code the COG and LUT address space is mapped to 0x000-0x400
There's no way to do that yet. The closest you can come is to enable FCACHE and wrap the inline assembly in code to load it into FCACHE. At some point I'd like to implement attributes to force functions into cog or lut memory, but I haven't had time to do that yet.
doc/c.md is all there is (in FlexGUI it's compiled to a .pdf and a .html).
Or have a way to signal not to optimise a particular block.
It might not be a bad idea to add a "volatile" option to __asm (like GCC does) to tell the optimizer not to touch anything in it. The bad part of this is that a lot of people will use "__asm volatile" when they really should just use "__asm" . Unfortunately I think people are likely to overuse __asm in general; using the macros from propeller2.h and/or limiting asm use to just a few key functions will make the code more readable and more portable to other P2 C compilers.
GCC never actually touches your inline ASM, except for replacing certain escape sequences. It just pastes it right into the output ASM, including inconsistent indentation.
That last case, where I used GETQX in a precautionary way, isn't as effective as I'd first thought. If there is nothing in-progress in the pipeline when a new op is issued, then the hardware discards any dead results anyway.
So, that use of GETQX is only effective if there is a cordic op actually still making its way through the pipeline at the time.
All the languages use the same output routines, and those optimize inline assembly along with everything else. Usually this is what you want: it improves both the generated code and (potentially) your code, e.g. if you write: the optimizer can turn calls to "sum1(x)" into "x+1", because it knows what the "add" instruction does. It can also do the basic transformations (like turning "xor reg, ##(1<<n)" into "bitnot reg, #n") on your code that it does on the generated code.
The next version of fastspin will allow you to type "asm const" to suppress optimization on asm blocks. It's usually a bad idea to use this; the only time it's useful, I think, is to work around an optimizer bug or when timing is critical (and you for some reason cannot use waitct or waitx to synchronize the timing; the optimizer does know about those). I wouldn't say it's "very" different; without volatile the asm block does participate in the optimization, it's just that GCC treats the whole block as a single instruction, whereas fastspin knows about what the individual instructions within the block mean.
I have a puzzlement about array declarations and assignments in FlexBASIC. There are several syntaxes to declare a SHARED array variable in FlexBASIC, and I find myself using them interchangably:
But it seems that when using an initializer with a SHARED var, only one of the syntaxes works (see above). The other throws the error: "error: syntax error, unexpected '=', expecting $end or end of line or end or ':'
Bug or feature? Or is this one of those "loose nut behind the user keyboard" things?
The initialization has to go next to the variable, as if it were an assignment statement, since more than one variable may be declared in a dim:
Do other BASICs allow it to go after the "as ulong" clause? I guess freebasic does, but it also only allows one variable to be declared at a time when the "as type" comes after the variable
It wasn't checking it before because Spin code started with "Stop" routine that didn't do anything.
I had to compile the main Spin file for it to check for errors...
But, I did this and now it checks everything:
Even better than that is to make the first method a test harness for the rest of them. Then you can compile the object stand-alone to test it, or if it's used as an object the compiler will just remove the unused test method.
With P1, you can modify your code in eeprom very easily by just writing to the location where variable data is stored...
Can we do this with the flash on P2?
Is there a way to figure out where the code is actually stored in flash?
Of course, Brian's EEPROM programming code uses different placement to Chip's new one.
For PNut.exe, you can compile flash_loader.spin2 and get this in the list (via Ctrl-L):
TYPE: 49 VALUE: 024001C8 NAME: APP_START
The $024 is the long-index offset to the start of user code. So, you should be able to do "@dat_asset + $024 << 2" to get the address in flash of where the data of interest is. Remember, though, that is a flash, and not an EEPROM, so you would have to erase the pertinent block and rewrite it with changed data. That's not practical, so it would be better to wait for (or develop) a file system that uses the upper part (past the first 1MB, perhaps) of the 16MB flash for general file use. Then, you could do whatever you want. Gosh, this needs to exist. If we just develop the object to handle it, the upper 15MB of the flash can become a persistent file system that survives flash reprogramming of the application code.
Seems the fastspin I have now (4.0.5) still uses things like "=>" instead of ">="...
Edit: ENCOD is another one...
Not yet. Spin2 just got released, so fastspin still has some catching up to do.
I am a dummy, trying to get flexgui up and running in the latest linux mint 19.3. can you offer an assist?
Jim
Probably easiest to do this by building from source. You'll need git, the build-essentials package, bison, tcl, and tk to be installed (at least). To build do: You may get some warnings about pandoc and/or latex being missing; those will affect the documentation build (it'll prevent the doc/*.md files from being converted to .html and .pdf) but won't otherwise affect the functionality. Install pandoc and pdflatex if you want the docs converted (the .md files are plain text, so conversion isn't strictly necessary).
The procedure above will install flexgui to $HOME/flexgui; to run it do:
I think probably using the flexgui.zip Windows binary and running under wine will work too, but I haven't tried that.
When switching back from Spin2 to Fastspin, this section gives an error:
It looks like the comments after "asm" mess it up.
When I remove the comments, it works...
Wait, I may be wrong about that...
Hmm... Seems that even a space character after ASM, makes it not work...
Yes, unfortunately there's a bug that causes anything after an ASM to mess things up. That'll be fixed in the next release (and is fixed in github) but for now the ASM has to be alone on a line.
I know, this is not really a bug. When I compile the main object that calls the library functions every error is found. It's just a bit surprising. I think syntax should be checked even for functions that are currently unused and are optimized away (dead code).
If you don't want the compiler to optimize away unused functions, then turn off optimization (at least for fastspin 4.1.3 and later).
It does parse all of the source code and creates an abstract syntax tree for all methods, so syntax errors are definitely caught. However, some other errors (e.g. undefined symbols, in many cases) are not detected until the compilation phase, and the compiler never even tries to compile unused methods. To be more explicit, "x := 1" is (usually) valid syntax in a Spin method, but if "x" isn't defined then it may not produce an error if the code is never compiled.
Changing this behavior is possible, obviously, but it's work. I'd be happy to accept pull requests (or payment) to do it. In the meantime, either use -O0 or else actually use the methods that you want to test.