PASM2 noob issue

It's been a while since I wetted my toes in PASM2 and I wanted to create a seemingly simple program just to go over some concepts of PASM2. So, I created this small program to calculate the length of a zero terminating string in hub memory.
I expected STRSIZE to give the same result as the counter value in the PASM program running on the other cog, but they are not. If anyone could point out what's wrong I would appreciate it (I'm 99% sure it's a misconception on my part)
CON
_CLKFREQ = 160_000_000
MAX_CHARACTERS = 10
VAR
byte size
byte text[MAX_CHARACTERS+1]
PUB main()
set_text(String("Hello"))
coginit(COGEXEC_NEW, @sizeof, @size)
waitms(1)
debug(ZSTR(@text))
debug(udec(STRSIZE(@text)))
debug(UDEC(size))
PUB set_text(addr)|c,i
'Clear text
repeat i from 0 to MAX_CHARACTERS
text[i] := 0
'Set new text
repeat i from 0 to MAX_CHARACTERS-1 'Reserve last character place for the terminating 0
c := BYTE[addr][i]
debug(udec(c))
if c <> 0
text[i] := c
else
quit
text[i] := 0
DAT
ORG
sizeof
'get the address of size
MOV retpointer, PTRA
'get the address of text[0]
MOV pointer, PTRA
ADD pointer, #1
.loop
'checks if text[pointer] is 0, if it is jumps to .return
RDBYTE charvalue, pointer '<--- Read the value of the hub memory location pointer and copy it to charvalue
TJZ charvalue, #.return
ADD pointer, #1
ADD counter, #1
JMP #.loop
.return
'copy the value of counter to the address of the return value variable
WRBYTE counter, retpointer
' local variables
counter byte 0
ALIGNL
charvalue byte 0
pointer res 1
retpointer res 1
FIT 496
Comments
Your program is missing an ending, so it's running off and executing garbage. Put a
JMP #$
at the end to trap it in an infinite loop.Also, all cog ram variables must be long, since that's how the CPU addresses them (unless you use the special GETBYTE/SETBYTE instructions)
Thank you @Wuerfel_21 !
Added the
JMP #$
at the end of the program and it worked as expected.I'll get into the GETBYTE/SETBYTE instructions next.
Also, you if you wanted to do this same thing but better:
DAT ORG sizeof 'get the address of size MOV retpointer, PTRA 'get the address of text[0] MOV pointer, PTRA ADD pointer, #1 RDFAST #0,pointer ' subsequent RFxxxx will read from pointer .loop RFBYTE charvalue wz '<--- Read the value of the hub memory location pointer, copy it to charvalue and set zero flag if_nz IJNZ counter,#.loop ' increment counter and jump if result not zero (never happens) .return 'copy the value of counter to the address of the return value variable WRBYTE counter, retpointer COGID PA COGSTOP PA ' local variables counter long 0 charvalue res 1 pointer res 1 retpointer res 1 FIT 496
When reading memory at incrementing addresses, use the RDFAST mechanism where possible, it saves you from having to increment the pointer and is also significantly faster. You can also combine the increment of the counter with the branch.
Actually, there's a really cracked way to do a count like this that's even more fasterer (4 cycles per byte instead of 6).
DAT ORG sizeof 'get the address of size MOV retpointer, PTRA 'get the address of text[0] MOV pointer, PTRA ADD pointer, #1 RDFAST #0,pointer ' subsequent RFxxxx will read from pointer REP #2,#0 ' loop next two instructions forever until a jump breaks out of it RFBYTE charvalue wz '<--- Read the value of the hub memory location pointer, copy it to charvalue and set zero flag if_z IJNZ pointer,#$+1 ' if zero, increment pointer by 1 (to compensate for the zero we just read) and break out of loop GETPTR counter ' get current FIFO pointer SUB counter,pointer ' subtract start pointer + 1 to get length .return 'copy the value of counter to the address of the return value variable WRBYTE counter, retpointer COGID PA COGSTOP PA ' local variables counter long 0 charvalue res 1 pointer res 1 retpointer res 1 FIT 496
Nice, thanks!
I got another noob question.
I don't understand why this wont work:
My assumption was that once I have the hub address of the variable
send_value
, if I add 4 to it I would get the address of the next long which isreturn_value
.However, if I just refer to PTRA[0] and PTRA[1] in the RDLONG and WRLONG instructions respectively it does work as expected:
If someone knows what I'm doing wrong, please let me know. Thanks.
It acts like an array index. It's built into the RDLONG/WRLONG instructions themselves. PTRA holds the base address, the index is then multiplied by 4 before being added to the base. RDWORD/WRWORD are x2. RDBYTE/WRBYTE are x1.
However, this feature is limited to PTRA/PTRB special registers, and also max index of +31 -32 I think.
Further reading under HubRAM Interface sub-section RANDOM ACCESS INTERFACE in the Silicon Doc.
EDIT: Oh, I see. You already know that. You're right, the first approach should also work. Dunno why it doesn't.
EDIT2: Found it after typing each line in and getting a compile error because I'd renamed "services" to "loop". The
coginit(COGEXEC_NEW, @services, @send_value)
call is not correct as is. You need a label for starting the cog at the ORG point. It didn't matter for the second example since that part of the code was redundant then.Oh right! I suspected it was something trivial!! Thanks @evanh !!