Micro Vibe

My Micro Hobby Projects

  • Increase font size
  • Default font size
  • Decrease font size
Home MV4th Forth Documents Inside MV4th16

Inside MV4th16

This article contains technical information related to the internal operation of MV4th16. MV4th16 is a version of the Forth language implemented for the Parallax Propeller chip. MV4th16 is based on the 1993 ANS Forth draft standard and supports the ANS CORE, CORE-EX, and BLOCK Forth extensions. The MV4th16 dictionary is based on a number of open source Forth implementations for embedded systems written around the time of the ANS 93 standard. The entire project can be compiled using just the Parallax Spin IDE.
The Parallax Propeller chip does not support code execution from its 32K of global memory. Instead each execution unit known as a COG has its own internal 2K of memory for code execution. It is possible to develop a version of the Forth language that could be implemented in the 2K of COG memory. This COG memory version of Forth would not have the complete ANS Forth core dictionary due to a limit on available memory. Instead I choose to use the COG memory to implement a virtual CPU that executed code from global memory.

The virtual CPU performs the three basic steps implemented in most CPU designs;
1)  Fetch the next execution token from the instruction pointer (IP) address then increment the IP address to point to the next execution token.
2)  Decode the execution token so that it may be executed by the CPU.
3) Execute the execution token then repeat from step 1.

The virtual CPU in MV4th16 alters step 3, if the execution token is not an internal CPU execution token assume it is the address to a code thread. In this case the virtual CPU will save the current instruction pointer value to a return stack (FIFIO) then set the instruction pointer to the new execution address and begin execution from the new address. It is assumed at some point the code thread will contain a virtual CPU EXIT op-code. The EXIT op-code moves the top value on the return stack back to the instruction pointer and execution resumes from the restored address. Think of this as an implied CALL instruction.

Under MV4th16 an execution token is 16 bits in size and must reside at a word aligned address. Execution token values 0...$1FF are reserved for native CPU op codes all other values are assumed to be the address of a code thread to execute. The value of a native CPU op-code is the long aligned address in COG memory of the COG code to execute.

For MV4th16 I chose a cell size of 16 bits for the native integer value and.double precision numbers are 32 bits in size. I chose a cell size of 16 bits due to the limited size of the global memory available on the Propeller chip and the fact that the global memory space is 16 bits in size.

The following COG code is the virtual CPU main execution loop;
'Execute the next opcode
NextOp                  rdword  T1, IP
                        add     IP, #2
                        cmp     T1, #c_MaxLocalCode       wc
              if_c      jmp     T1
                        'We want to execute a code thread
                        'Push current IP to return stack.
                        sub     RetStkPtr, #2
                        wrword  IP, RetStkPtr
                        mov     IP, T1
OP_NOP                  jmp     #NextOp

When the MV4th16 spin object is started the default forth dictionary implemented in the DAT section of the object  must be processed before it is used by the virtual CPU.

The first step is to correct code addresses in the forth dictionary. When addresses are calculated in the DAT section of a Spin object using the "@" operator they are relative to the start of the object not to the start of the object's global memory address. This means the code execution addresses in the forth dictionary in the DAT section must be adjusted to reflect there true memory address in global memory.

The virtual CPU in MV4th directly implements over seventy of the common forth words as native op-codes. In order for the forth compiler to work properly the native CPU forth words must still be listed in the forth dictionary. The second step in processing the dictionary is to replace any execution tokens in the dictionary code with there native execution tokens. This is required because the Spin IDE can not create constants for the virtual CPU op-code addresses that can latter be used as word aligned values. The MV4th16 compiler does a similar optimization when compiling forth code.

Once the dictionary is processed the forth system variables are initialized and the MV4th16 COG is started. The virtual CPU begins execution at the forth word COLD.

The MV4th16 code will reclaim the nearly 2k of ram used to hold the COG memory image by Spin for its return stack and internal buffers. The memory used by the spin code for the object is also reclaimed to extend the memory available to the dictionary by about 1k. This means the MV4th16 Spin object can not be stopped and then restarted under Spin you must reset the Propeller chip to restart MV4th16 forth.

The following image shows the memory layout used by MV4th16 The lowest memory address is equal to the start of the COG memory for the Mv4th Spin object DAT section.
MV4th16 Memory Layout
The return stack is by default set to 1K or 512 words. This is used by the virtual CPU and the forth code to PUSH/POP values.

The temporary output buffer is 80 bytes in size and is used by the core forth words that convert a numeric value into a string representation.

The PAD buffer is 128 bytes in size by default and is not used by the forth core words. The PAD buffer can be used by a forth program.

The terminal input buffer (TIB) is 160 bytes in size and is used to hold the next line of characters read from the forth console to be .evaluated.

The USER memory area is 544 bytes under the default settings and is not  used by the forth core words. The USER area can be used by a forth program and the forth word USER can create variables whose address resides in the USER area.

The forth internal variables memory area contains forth implementation variables that should not be used by forth programs directly. Most of the internal variables can be accessed via a forth word. The area is about 1.1k in size and included the 1k block device buffer. The block buffer will move in future versions of MV4th16.

The forth dictionary is next in memory and will grow up in memory as more words are added to the dictionary be the forth compiler.

The forth data stack often called the parameter stack starts at the highest memory address usable and grows down in memory as values are pushed to the stack.

The MV4th dictionary is built from a list of linked objects. All forth words in the dictionary must start on a 16 bit aligned address. All words in the dictionary start with a 16 bit link field that contains the address of the prior word's name field. The first word in the dictionary will have a value of 0 for the link field. Directly following the link field is the 16 bit flag field. Currently only two of the bits are used bit 0 indicates if a word is an "immediate" word, and bit 1 indicates if the word is a native virtual CPU op-code. After the link field is the word's name field. The first byte of the name field contains the length of the word's name. The next length bytes contain the ASCII characters for the name. The forth word's first execution address follows the end of the name field on the next word aligned address.

This image shows the layout of a forth word under MV4th16;

MV4th16 dictionary word layout

Note: If you are going to modify the core dictionary in the MV4th spin object you must keep the following in mind;
1) All native virtual CPU op-codes must be defined at the start of the dictionary.
2) The forth word NOP must be the first non-native forth word in the dictionary after the last native forth word.
3) The forth word COLD must be the last word defined in the core dictionary in the spin object.

There is a constant at the start of the MV4th16 spin object code called "c_ReservedWords" that controls the amount of memory available to expand the dictionary and data stack. The larger this value the more memory available to MV4th16 object's dictionary and the smaller this value the more memory that can be used for other spin objects. Remember that you must leave about 100 longs of memory free when the entire spin project compiles for the spin code stack.

The MV4th16 spin object does not include code to implement the console device or the block IO device. These devices must be implemented in Spin or in a second COG. To facilitate the implementation of these devices MV4th16 uses a callback mechanism. The callback is controlled by two word sized memory locations. The first word is used to specify the I/O command to be executed and the second word is used to pass the address of the top value on the data stack. The address to these word values is passed to the COG via the PAR register value. When the Spin code or second COG completes the request it will adjust the data stack address to reflect any values added or removed from the data stack and the set the first word to zero indicating that the request is completed. Forth programs can use the core dictionary word SYSTEM to execute a callback.

For a complete list of the currently used system I/O callback command identifiers see the comments in the MV4th16 spin object source code. The system command codes 0..31 are reserved for use by the core forth words, user programs are free to use any other command numbers.

Last Updated on Saturday, 22 May 2010 07:04