With a simulator, you can 1) easily verify your ISA without actually implementing hardware, 2) debug your application without having actual hardware, and 3) improve your ISA by spotting performance bottlenecks in benchmark programs. Your simulator operates instruction by instruction; you must be able to execute instructions one by one and watch all the programmer visible states (eg. register, memory, ...) at a certain time when the execution of an instruction is completed. Assume that your simulator starts executing at address 0x0 upon power-on.
The source for the simulator for our toy ISA is here
You may add whichever commands you find useful. However, your simulator must support the following commands:
loads *.coe files at $start_addr of the instruction memory
loads *.coe files at $start_addr of the data memory
simulates next $number instructions
prints values in all registers
sets the register $reg_num with the value $value
disassembles instructions in the instruction memory from $addr to $addr + $size, which might not be exactly the same with the assembly instruction appeared in your assembly file
sets the value at $addr of the instruction memory with the value $value
prints data memory values from $addr to $addr + $size
sets the value at $addr of the data memory with the value $value
prints values put on channel $channel by out instruction
discards all values written to channel $channel so that out instruction can proceed
puts $value on channel $channel so that in instruction can get a value
changes the buffer size for each channel to $value. the initial size is 32
shows the number of executed instructions
Among provided benchmarks, SuperGarbage uses in and out instructions. To make these instructions work, you should use put_channel and dump_channel commands which emulate actual I/O operations of hardware. If an out instruction blocks due to the lack of buffer space, you should use clear_channel command to make space so that out instructions could succeed. You can set the buffer space for each channel by using set_buf_size command before starting a simulation.
After executing a benchmark program, you should check whether your program behaved as you expected. You can easily validate the simulation result by examining register and memory values. In specific, the return register should have an appropriate value when a Fibonacci simulation ends. Similarly, memory values should be properly updated when Program Loader or SuperGarbage are executed.
To create your own simulator, you may modify the switch statement in the "execute" method in the provided ISASimulator class. The input of the switch statement is the opcode of an instruction. For example, if you define opcode 0 for "add" operation, you may perform all the required operations for the add under "case 0:". The reg_file and data_mem array store the register and memory values, respectively. The two arrays are Int34 type, and you may use the methods in the Int34 class or transform them into "long" to update their values.