Languages like Java C# etc all use a virtual machine. This is a software package that need to start and interpret some kind assembly code. Languages like C/C++ compile into native assembly code that is much faster, but also tied to the hardware it run’s on.
A virtual machine have the advantage that we extend the platform with build in features made available in C/C++. This high level code occupy less space than binary code and executes under our control. The drawback is that it executes slower than native code, but I plan to challenge that by introducing very high level assembly instructions.
I would like to create a native assembler at some point, but for now I want to play around with a Virtual Machine design.
The diagram above show how we link things together in the firmware. We use easyIPC protocols to communicate, RTOS and HAL + other modules tom access electronics and do complex stuff. The VM executes logic that control what we do.
Our VM needs it’s own assembly language so we can use a 32 bit design as indicated above. A 8 bit Op-Code + 4 bit Category code leaves 16 pages of 256 instructions. Category 0 is the build in one, but other categories can be used for extended instructions. Length is the added number of 32 bit register, meaning an instruction can be 32 x 16 bits long.
This show the MOVE R1, R2 that will copy content of R1 into R2. As this is an array of 31 parameters we can extend this to MOVE R1,R2,R3;R4 etc that copies R1 into R2,R3,R4. Op Code 0 is NOP (No Operation).
This diagram illustrate the internal core of the VM. We have a table holding 32 bit instructions stored in Flash. A Registers table that is located in SRAM for generic use in our logic, and an object table that use address 0x8000 to 0xFFFF to access easyIPC mapped content. Notice that the total register size is 64Kb to make the most of a 16 bit parameter. Stack is located in SRAM at 0x7FFF and up. Each PLAIN Module have it’s own, private stack.
PLAIN contains a set of registers known as easyIPC object registers located between 8000h and FFFFh. These are accessed the same way as stack and generic registers, but are wired to other software or hardware. If these registers are changed events will be generated to allow PLAIN or C/C++ to process changes.
The PLAIN specification allows an application to organize it’s own layout of these objects to guarantee that an application will execute correctly. The issue is that registers for selected hardware need to be located somewhere, and with various hardware/software combinations you end up with far too many registers for the world to be unique. To solve this the Assembler will create a map where all software and hardware is mapped correctly with PLAIN logic. This result in a map that follows the application. The run-time engine will need to map and resolve these calls as the PLAIN application is loaded.
This is work in progress so expect changes as we implement this. The design draft above is based on a proof of concept implementation done about a year ago.