A RISC-V instruction simulator implemented in Python that executes binary machine code generated by a RISC-V assembler. The simulator reads a binary instruction file, decodes each instruction, executes it according to the RISC-V instruction set architecture, and updates registers, program counter, and data memory accordingly.
The simulator models a simplified RISC-V execution environment, including registers, program counter (PC), instruction decoding, and memory operations.
This project implements a RISC-V instruction-level simulator written in Python. It takes binary machine instructions as input and simulates the execution of those instructions step by step.
The simulator decodes each instruction, determines its instruction type, performs the appropriate operation, and updates registers and memory accordingly. It supports multiple instruction formats and maintains an internal representation of registers and data memory.
The simulator outputs the program counter state, register values, and memory contents after instruction execution.
- Executes RISC-V binary machine instructions
- Instruction decoding based on opcode and funct fields
- Supports multiple instruction formats:
- R-Type
- I-Type
- S-Type
- B-Type
- J-Type
- Simulated 32-register RISC-V architecture
- Program Counter (PC) management
- Data memory simulation
- Branch and jump instruction handling
- Load and store memory operations
- Arithmetic and logical operations
- Binary-to-decimal and decimal-to-binary conversions
- Instruction execution trace output
- Command-line execution with input and output file arguments
- add
- sub
- slt
- srl
- or
- and
- mul
- addi
- lw
- jalr
- sw
- beq
- bne
- jal
- rst
- halt
The simulator models the following system components:
- 32 general purpose registers
- Includes standard RISC-V register names:
- zero
- ra
- sp
- gp
- tp
- t0–t6
- s0–s11
- a0–a7
Register values are maintained internally and updated during instruction execution.
- Keeps track of the current instruction address
- Increments by 4 bytes per instruction
- Updated during branch and jump instructions
The simulator includes a memory block starting from address 0x10000 used for load and store operations.
Memory addresses supported include:
0x10000 – 0x1007C
This memory region is used by lw and sw instructions.
The simulator processes instructions using the following steps:
- Read binary instruction file
- Store instructions in memory with addresses
- Fetch instruction using Program Counter
- Decode instruction using opcode
- Identify instruction type
- Execute instruction
- Update registers, memory, and PC
- Write execution state to output file
- Python 3.x
- No external libraries required
Run the simulator using:
python Simulator.py <input_file> <output_file>Example:
python Simulator.py program.bin output.txtThe input file must contain 32-bit binary RISC-V instructions, one per line.
Example:
00000000011001011000010100110011
00000000101000110000001010010011
00000000010100010010000000100011
These instructions are typically generated using the RISC-V Assembler project.
The simulator generates an output file containing:
- Program Counter state
- Register values
- Memory contents
Example output format:
0b00000000000000000000000000000100 0b00000000000000000000000000000000 ...
Final section prints memory contents:
0x00010000:0b00000000000000000000000000000001
The simulator consists of the following components:
Simulator.py
│
├── Simulator Class
│ ├── Register initialization
│ ├── Data memory initialization
│ ├── Instruction dictionary
│
├── Instruction Decoding
│ ├── decode()
│
├── Execution Functions
│ ├── R_Type()
│ ├── I_Type()
│ ├── S_Type()
│ ├── B_Type()
│ ├── J_Type()
│
├── Utility Functions
│ ├── Binary to Decimal conversion
│ ├── Decimal to Binary conversion
│
└── Execution Pipeline
├── Read_File()
├── process_file()
- Write assembly program
- Convert assembly to binary using RISC-V Assembler
- Run the simulator on the binary file
- Observe register and memory state changes