# An RV32IM simulator: fetch a 32-bit word at pc, decode it into an
# instruction, execute it, repeat.
#
# The machine is the 32 integer registers x0..x31, a pc and a byte-addressed
# memory. The encodings and semantics follow "The RISC-V Instruction Set
# Manual, Volume I: Unprivileged ISA" (version 20191213), chapter 2 (RV32I),
# chapter 7 (M: multiply and divide) and chapter 24 (the opcode map). An `ecall` asks the environment for a
# service: a7 = 93 exits with the code in a0 (Linux's number, which the
# riscv-tests suites use too) and a7 = 1 prints a0 as a signed integer
# (the print_int of the RARS and SPIM simulators).
from rv32.bits import WORD, pow2, wrap, signed, bits, sext, and32, or32, xor32
NUM_REGS: Int = 32
MEM_BYTES: Int = 262144 # 256 KiB: code and data from address 0, the stack down from the top
BYTE: Int = 256 # values of one byte
HALF: Int = 65536 # values of a halfword
INSTR_BYTES: Int = 4 # every RV32I instruction is one 32-bit word
# register numbers the environment uses (the standard calling convention)
REG_RA: Int = 1
REG_SP: Int = 2
REG_A0: Int = 10
REG_A7: Int = 17
# ecall services
SYS_PRINT_INT: Int = 1
SYS_EXIT: Int = 93
# the major opcodes, bits 6..0 of every instruction (manual, table 24.1)
OPC_LOAD: Int = 0x03
OPC_MISC_MEM: Int = 0x0f
OPC_OP_IMM: Int = 0x13
OPC_AUIPC: Int = 0x17
OPC_STORE: Int = 0x23
OPC_OP: Int = 0x33
OPC_LUI: Int = 0x37
OPC_BRANCH: Int = 0x63
OPC_JALR: Int = 0x67
OPC_JAL: Int = 0x6f
OPC_SYSTEM: Int = 0x73
F7_ALT: Int = 0x20 # funct7 of sub and sra (and imm[11:5] of srai)
F7_MULDIV: Int = 0x01 # funct7 of the M extension
SHAMT_BITS: Int = 5 # a shift amount is the low five bits
enum Op {
Lui
Auipc
Jal
Jalr
Beq
Bne
Blt
Bge
Bltu
Bgeu
Lb
Lh
Lw