The core of any simulator is the process of interpreting the bits that make up a machine instruction, deciding what that instruction is and executing some code that simulates the function. Simulators essentially are comprised of a big loop that interprets each instruction in turn and gives some feedback of the state of the machine to the user.
The simplest form of instruction simulation uses a switch statement to match the bit pattern of the instruction to a few lines of code to simulate the function. Though compilers can dramatically improve the execution of a switch statement, the basic behaviour is 'Is it this instruction? No.. Is it this instruction? No..' and so on until a match is found. In C we can explicity do what a compiler might do for us, making the whole process more efficient by using a lookup table.
The lookup table matches an instruction against a function that will simulate it. The code simply has to lookup the function for a given instruction and call it. Unfortunately this is not possible in Java, because we don't have the equivalent of function pointers and can't produce an lookup table as we would in C.
However, there is a neat solution. We can represent an instruction as an object that knows how to simulate itself. Instead of a table that allows us to lookup functions, we have a table that allows us to lookup Instruction objects. We can then just ask the relevant Instruction to 'simulate yourself' and we have quickly called the right code.
miSim DE uses exactly this approach. An abstract class 'Instruction' provides all the common things that an instruction needs to know about and do. For each of the different processor instructions, we can then extend that class and implement the missing 'simulate yourself' method that will be specific to that instruction.
As the PIC® MCU uses a Harvard Architecture, our simulation job is easy. The machine cannot change the code that it runs, so we can read the program, transform it into an array of Instructions and we are then ready to simulate the processor. To run the simulation, we start at the beginning of the array, ask the first Instruction to simulate itself, then the next, then the next and so on..
We get some things 'for free' from this approach. With a few simple additions, an instruction can know what it looks like to a programmer (its Mnemonic), how to display itself in a listing and even how to build itself from source code. Our Instruction class can then do more than simulate the processor, it can act as a disassembler and an assembler. Suddenly we have a complete development environment.
What Is Missing
The Simulator and the Development Environment are constantly being updated and
improved. Though not exhaustive, this is a list of the items that are not
currently part of the software:
At present, the EEProm write hardware is simulated, but the related write-complete interrupt is not simulated. EEProm read is fully functional.
The Watchdog timer and MCU Reset hardware are not simulated.
![]() |
![]() |