GithubHelp home page GithubHelp logo

mikaelpatel / arduino-fvm Goto Github PK

View Code? Open in Web Editor NEW
37.0 11.0 7.0 343 KB

Byte Token Threaded Forth Virtual Machine (FVM) for Arduino

Home Page: https://mikaelpatel.github.io/Arduino-FVM

C++ 100.00%
virtual-machine forth compiler interpreter tail-call-optimization tokenizing-parser arduino-library

arduino-fvm's Introduction

Arduino-FVM

This library provides a token threaded Forth kernel that may be embedded in Arduino sketches. The kernel can be used as a debug shell or even full scale Forth applications.

shell-screenshot

The Forth Virtual Machine allows multi-tasking which makes it easy to integrate with the Arduino core library functions. Context switch to and from the virtual machine is as low as 8 us (halt) and 10 us (yield/branch).

compiler-screenshot

A code generator, token compiler, example sketch is available. Forth declarations are translated to the Forth Virtual Machine instruction set and dictionary format. The token compiler is also an excellent example of mixing forth, C/C++ and Arduino library functions in the same sketch.

The Forth Virtual Machine (FVM) with 130 instructions is approx. 5.4 Kbyte without kernel dictionary table and strings. This adds approx. 1 Kbyte. The instruction level trace adds an additional 500 bytes. Many of the kernel instructions are defined in both C++ and FVM instructions. This allows tailoring for speed and/or size.

Tokens

The Forth Virtual Machine is byte token threaded. Most kernel and application tokens are a single byte. A prefix token is used to extend beyond 256 tokens. A total of 512 tokens are allowed; 0..255 are kernel tokens and 256..511 are application tokens. Kernel tokens are operations codes. These can be C++ code and/or threaded code (in FVM.cpp). The application tokens are always threaded code.

Kernel tokens 0..127 are direct operation codes while tokens 128..255 require a prefix token (OP_KERNEL). Application tokens 256..383 (-1..-128) are direct nested by the kernel. The token value are the one-complement index to threaded code in a table in program memory.

Application tokens 384..511 require a token prefix (OP_CALL) to the mapped values 0..127 which are the index to threaded code in a table in data memory (i.e. token minus 384).

Optimizations

The token threading inner interpreter uses several optimizations to reduce calls, i.e. return stack push and pop of return addresses.

The first optimization, the token mapping (-1..-128) allows the inner interpreter to directly handle calls of threaded code. The inner interpreter will perform the nesting.

The second optimization, tail call reduction, allows the inner interpreter to perform a jump to threaded code instead of call when the succeeding operation is EXIT. This reduces return stack depth, pushing and poping return address. The optimization is also used for prefix operations (OP_KERNEL and OP_CALL).

Install

Download and unzip the Arduino-FVM library into your sketchbook libraries directory. Rename from Arduino-FVM-master to FVM.

The FVM library and examples should be found in the Arduino IDE File>Examples menu.

arduino-fvm's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

arduino-fvm's Issues

Missing words

This issue is a list of missing words (Forth94 Core).

' NAME ( -- xt )
['] NAME ( -- xt )
unloop ( -- )
*/mod ( n1 n2 n3 -- n4 n5 )
2! ( x1 x2 a-addr -- )
2@ ( a-addr -- x1 x2 )
2>r ( x1 x2 -- )
2r> ( -- x1 x2 )
2r@ ( -- x1 x2 )
cell+ ( a-addr1 -- a-addr2 )
count ( c-addr1 -- c-addr2 u )
c>s ( c-char -- n )
fill ( c-addr u char -- )
fm/mod ( d1 n1 -- n2 n3 )
m* ( n1 n2 -- d )
um* ( u1 u2 -- ud )
um/mod ( ud u1 -- u2 u3 )
scan => word ( char -- )
compile NAME => postpone NAME 
lookup => find ( c-addr -- c-addr 0 | xt 1 | xt -1 )
>number ( ... )
:noname ( -- xt )
marker NAME ( -- )
value NAME ( x -- )
[compile] NAME 

Allow more than 128 kernel words

The current token mapping allows for at most 128 kernel and 128 application words. Byte positive values (0..127) are for kernel implementation and negative (-128..-1) for application.

Add callback on illegal token/operation code

The VM is byte coded and allows for 256 tokens. The inner interpreter uses signed byte to determine if the token is executed direct (C++) or threaded call. To extend two special tokens are used. These allow the token value to exceed -128..127.

Kernel tokens are 0..127 direct, 128..255 extended.
User tokens are 256..383 direct (mapped to -1..-128), 384..511 extended.

The token space is not continues. There exists illegal tokens that needs to be captured.

Add local echo

Allow the scanner to be configured to echo all characters read during the parsing of a word.

Compiler failure in Arduino IDE 1.8.12 (current)

/home/ga/Arduino/sketches/libraries/FVM/src/FVM.cpp: In function 'int8_t fetch_byte(FVM::code_P)':
/home/ga/Arduino/sketches/libraries/FVM/src/FVM.cpp:105:31: internal compiler error: in type_hash_canon, at tree.c:7158
if (ip < (FVM::code_P) FVM::CODE_P_MAX)
^~~~~~~~~~
Please submit a full bug report,

The bug has been logged with GCC: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94437
In the meantime, I have a patch available to work around it.

Allow threaded code in SRAM and/or EEPROM

The AVR is a Harvard Architecture with separate memory spaces (SRAM, EEMEM, PROGMEM). To allows threaded code in all memory spaces a synthetic unified address spaces is needed. This will impose a run-time penalty on the inner interpreter and any operation that access the instruction pointer, i.e. branch, literals, etc.

Consider symmetry in context switch

tos is pushed and poped from parameter stack on context switch. ip is not, it is stored in the context struct, but should for symmetry be also pushed and poped from the return stack.

Allow call to C/C++ functions

Add virtual machine instruction to allow call of C/C++ function. Use same structure as for CREATE-DOES>, VARIABLE and CONSTANT.

Support SAM/SAMD based Arduino boards

Support 32-bit MCU based on ARM core such as Arduino Due. These have the advantage of much more memory and allow symmetrical memory model (i.e. data structures in RAM).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.