Devlog 4 Validating The Implementation
November 18, 2022
Validating the implementation
I started this session by validating code that’s been written and ensuring things are where they should be. I’ve also created an TODO list to track my progress.
As mentioned previously, I defined some constants for the RAM size etc, but I’m not sure if they are actually placed at the correct location in memory. Let’s have a look.
First I want to ensure the
__stacktop address, i.e: the top of the stack, is correctly located at 0x20005000:
0x20000000 (start of RAM) + 0x5000 (size of RAM) and placed into the
sp (stack pointer /
grep __stacktop fiveforths.dump la sp, __stacktop 800004c: fb810113 addi sp,sp,-72 # 20005000 <__stacktop>
Perfect! Next, let’s ensure our constants point to the correct location:
make readelf | grep DSP_TOP 18: 20005000 0 NOTYPE LOCAL DEFAULT ABS DSP_TOP make readelf | grep RSP_TOP 19: 20004f00 0 NOTYPE LOCAL DEFAULT ABS RSP_TOP make readelf | grep TIB 20: 20004e00 0 NOTYPE LOCAL DEFAULT ABS TIB_TOP 21: 20004d00 0 NOTYPE LOCAL DEFAULT ABS TIB
DSP_TOP should be at
0x20000000 (start of RAM) + 0x5000 (size of RAM) = 0x20005000, the
RSP_TOP should be at
0x20005000 - 0x100 (256 Bytes) = 0x20004F00, and the
TIB_TOP should be at
0x20004F00 - 0x100 (256 Bytes) = 0x20004E00. Additionally, the lower address of
TIB should be at
0x20004E00 - 0x100 (256 Bytes) = 0x20004D00. So far so good, however..
I realized my stacks are placed at the wrong address, here’s a look:
make readelf | grep _stack 22: 20000100 0 NOTYPE LOCAL DEFAULT 3 data_stack 23: 20000200 0 NOTYPE LOCAL DEFAULT 3 return_stack 24: 20000300 0 NOTYPE LOCAL DEFAULT 3 tib_stack
Oops! They are starting at the bottom of the stack and growing upwards, when in fact they should start at the top and grow downwards. Let’s fix that:
-# reserve 3x 256 Bytes for stacks -.bss -.balign STACK_SIZE -data_stack: - .space STACK_SIZE # reserve 256 Bytes for data stack -return_stack: - .space STACK_SIZE # reserve 256 Bytes for return stack -tib_stack: - .space STACK_SIZE # reserve 256 Bytes for terminal buffer
What? I realized that adding labels for these stacks and “reserving” zero-filled space in RAM was pointless. I also removed other reserved spaces for variables and indexes. The indexes will be added above the pad space, so let’s define that:
-indexes: - .space (CELL * 64) # reserve 64 CELLS zero-filled +.equ INDEXES, NOOP - (CELL * 64) # 64 CELLS between NOOP and INDEXES +.equ PAD, INDEXES - (CELL * 64) # 64 CELLS between INDEXES and PAD
I made some other minor changes such as creating labels for the ‘ok’, ‘?’, and ‘redefined ok’ strings, so we can easily jump to those when needed.
Since the Longan Nano Lite has 64K FLASH and 20K RAM, and both are located in the same MCU chip, I think it makes more sense to keep the entire program and constants in FLASH, and only use the RAM for variables, stacks, and user-defined dictionary words. This is just my assumption the Forth can actually be executed from FLASH instead of RAM.
I’ve made some progress in improving the memory layout and size of the program, but there’s still some work to do there. At least for now I can check off a few things from the TODO list. I planned on testing the current code this session but validating the memory locations/addresses was more work than expected, so I’ll get to that next time before implementing the missing words.