The B# embedded virtual machine (B#EVM )interprets and executes the binary code generated by the B# assembler.The B#EVM runs on the target architecture and hides away the hardwareidiosyncrasies from the application developer.
It therefore provides a uniform mechanism to access deviceregisters, create threads, and handle interrupts that would otherwisechange from one hardware platform to another.
This uniformity promotes the development of reusable components(expressed in terms of binary code) that can migrate from onearchitecture to another as long as the B#EVM is available.
The memory devoted to the B#EVM is divided into two fundamental, butmutually dependent components: the data memory space and the codememory space as illustrated in Figure 1 below.
The data memory space stores the binary (virtual) code of anapplication alongwith the necessary descriptors, stacks, objects, and other datastructures that are required to support its execution. The descriptorsfor threads, objects, stacks, console buffers, partitions, byte maps,the ready queue, and segments (both code and data) are preallocatedwhen the virtual machine is compiled.
Other memory that is not preallocated, commonly referred to as theheap, is allocated dynamically either at load time (for literals andapplication code)or at run time (for objects and operand stacks).
|Figure1: Architecture of the B# Embedded Virtual Machine.|
The code memory space of the B#EVM consists of those subsystems thatactually execute the application. These systems provide the B# languagewith the low-level support to access device registers, create threads,and handle interrupts. In the three subsections that follow, we take amore detailed look at the memory manager, the stack machine, and themulti-thread kernel.
Memory Manager. The memory manager allocates and deallocates space for objects,stacks, and other structures within the virtual machine.T o efficientlyallocate this space and to diminish fragmentation, the memory managerof the B#EVM uses a hybrid of static and dynamic allocations.
By default, three partitions of fixed-size blocks are created whenthe B#EVM is compiled:
1 . Small blocks of 8 byteseach, mainly used for non-preallocated descriptors (arrays, strings,and so on).
2. Medium blocks of 32 byteseach, mainly used for default capacity buffers for composite types suchas arrays and strings.
3 . Large blocks of 128 byteseach, mainly used for large buffers.
The partition sizes, however, are configurable, but require therecompilation of the virtual machine.
To help satisfy the bounded time constraints of embedded systems, abyte map is also used to manage the allocation, deallocation and searchfor free blocks. The main advantage of this approach is its relativesimplicity and efficiency in finding the first free block of Nconsecutive free blocks.
Each partition has a byte map and each byte map is implemented as alinked list. Because the linked list has a maximum fixed length, thesearch for availablememory is also deterministic. For example, a request for 256 bytes willprompt the memory manager to examine the byte map associated with thelarge blocks, to select two consecutive available segments (if any),and to return the address of the first one.
Stack Machine .The design of most microcontrollers is based on the von Neumann model:a classic hardware architecture that includes a central processing unit(CPU) with registers for executing instructions, main and secondarymemories, and input/output devices.
Such models are implemented for general register machines that havea set of numbered registers within the CPU and for accumulator machinesthat have a limited number of data accumulators, often just one.
On the other hand, the stack-machine model is an alternativearchitecture where the operand (runtime) stack of the current threadreplaces the accumulatorand other CPU registers used for temporary data storage. The stacktherefore is used to load and store variables, arguments, andaddresses.
Although some compiler optimization may be more difficult with astack architecture, no register numbers or addressing modes need bespecified in an instruction. Therefore, the number of instructions andtheir opcode size can be reduced, an important advantage for smallfootprint embedded systems.
In short, the B#EVM is a stack-machine interpreter that executesvirtual code generated by the B# assembler. Values are pushed onto thestack, operations take values from the stack, and the results arepushed back where they are available for future calculations.
Multi-ThreadKernel. Because the B#EVM supports multithreading, a kernel orsmall operating system is needed to create, schedule, synchronize, andreschedule threads. When a thread is created, preallocated thread andstack descriptors are initialized to control access to the binary codeof the thread and its operand (runtime) stack, respectively.
The operand stack is a collection of stack frames where each framemaintains the context of a method execution. This context includeslocal variables, temporary results, parameters, and return addresses.Therefore, each time a method is invoked, a stack frame is created.Asthe thread executes, the stack grows from low to high addresses toaccommodate temporary results.
The stack descriptor contains the base (frame) address bp of thecurrent frame, the address of the bottom of the stack stackBase, andthe address of the top of the stack sp.
The thread descriptor, on the other hand, contains information onthe base address of the code codeBase, its instruction pointer ip, andlocation of the corresponding stack descriptor.
Figure 2 below presents atypical memory model of the B# multi-thread kernel. In this case, thekernel is pointing to the thread descriptor that is currently running.
Although a single-thread application may contain several namespacesand classes, only one class contains the main entry method andimplicitly becomes the main thread. In a multi-thread application, eachobject (instance of a class) with its own block of code may potentiallybecome a thread (i.e. an active object) and therefore, requires a stackfor saving its own context. Any object that does not become a threadshares the stack of the thread to which it belongs.
|Figure2. Memory Model of the Running Thread in B#.|
TypeRepresentation. The operand stack of B#EVM represents all valuesas 32-bit elements, regardless of their type. Therefore, to convertfrom one type to another is quite simply a question of “tagging” thestack element with a particular type.No descriptors are required sincethe type is set when the value or the reference is allocated on thestack.
To store this information, an additional stack within the B#EVMmaintains the type information of the corresponding elements in theoperand (runtime) stack. In this way, we eliminate the cost of wrappers(in terms of space, access, and allocation time) and avoid thedefinition of an hybrid type system that requires a clear distinctionbetween value types (bool, char, int, uint, and float) and referencetypes (ioregs, arrays, strings, and delegates).
Another important reason for maintaining type information in thisway is to reduce the size of the instruction set.Other virtualmachines, such as the Sun JVM and Microsoft IL, have polluted theirinstruction sets with instructions that embed their information type.
An example of such proliferation is the add instruction which has avariation for each type of information: badd for byte addition, saddfor short addition, iadd for integer addition, and so on.
Seven instructions are required where only one instruction isrequired in B# since arithmetic operations are all promoted to 32 bits.Also, the type conversion instructions that are required before doingany arithmetic calculations are reduced since the add instruction inB#EVM is done within the instruction while checking and promoting (ifnecessary) the operand types. Although there is additional overhead,the instruction set and the generatedcode size are reduced.
In summary, the key and unique ( + ) features of B# as a language forembedded systems applications are:
1) + Tiny (simpleand minimal) in both its language definition (syntax  and semantics)and its code generation
2) Familiar syntax
3) + Full supportfor object-orientation
* Fields and methods (static, instance, virtual, override, andabstract)
* Constructors (static and instance) and destructors
* +Memory defragmenter (deterministic and minimalist garbage collector)
* Field properties (getters, setters, and readonly fields)
* Delegates (callbacks)
* + Device addressing(ISO/IEC Standard)
* + Interrupthandlers
4) + Simplified,optimized, and unified type system
5) + Portablemulti-threaded kernel (included in the virtual machine)
The toolset will be available for download at theBSharpLanguage.org, but in the meantime please contact the first authordirectly at mdec@DeepObjectKnowledge.com.
To read the first part in this series on the basics of the B#language, go to “Anoverview of B# language features.”
Michel is chief scientist of DeepObjectKnowledgeInc., an object-oriented training/mentoring firm located in Montreal,Quebec, Canada. He is also a former associate professor in ComputerEngineering at Concordia University and a regular speaker at theEmbedded Systems Conference. He can be contacted atmdec@DeepObjectKnowledge.com.
Brian is an associate professor of Computer Science/Studies at TrentUniversity located in Peterborough, Ontario, Canada. His main researchinterests are programming languages and parallel job scheduling. Briancan be contacted at firstname.lastname@example.org.
 M.Barr, Is C Passing?, Embedded.com,May 2002.
 J.W. Grenning, Why are you still using C?, Embedded.com,April 2003.
 M.de Champlain, B# Grammar, presents the grammatical summary of theB# programming language. Its syntax is described in a concise fashionusing the EBNF notation. www.DeepObjectKnowledge.comBSharpProjector www.BSharpLanguage.org
 M.de Champlain and B.G Patrick, B# Project: Object Design forDevelopping Small Embedded Systems Applications, will be published byNewnes/Elsevier, Fall 2006.