Make rvpy cycle-accurate enough to get the correct Dhrystone score
This commit is contained in:
parent
11596a5bd7
commit
d31b1708db
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
# Minimal RISC-V interpreter, supporting RV32I + Zcsr only, with trace disassembly
|
# Minimal RISC-V interpreter, RV32IM + Zicsr only, with trace disassembly
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
|
@ -160,8 +160,9 @@ class RVCore:
|
||||||
self.mem = mem
|
self.mem = mem
|
||||||
self.pc = reset_vector
|
self.pc = reset_vector
|
||||||
self.csr = RVCSR()
|
self.csr = RVCSR()
|
||||||
|
self.stage3_result = None
|
||||||
|
|
||||||
def step(self, instr=None, log=True):
|
def step(self, instr=None, log=True, cycle_accurate=True):
|
||||||
if instr is None:
|
if instr is None:
|
||||||
instr = self.mem.mem[self.pc >> 2]
|
instr = self.mem.mem[self.pc >> 2]
|
||||||
regnum_rs1 = instr >> 15 & 0x1f
|
regnum_rs1 = instr >> 15 & 0x1f
|
||||||
|
@ -174,6 +175,8 @@ class RVCore:
|
||||||
pc_wdata = None
|
pc_wdata = None
|
||||||
log_disasm = None
|
log_disasm = None
|
||||||
instr_invalid = False
|
instr_invalid = False
|
||||||
|
stall_cycles = 0
|
||||||
|
stage3_result_next = None
|
||||||
|
|
||||||
opc = instr >> 2 & 0x1f
|
opc = instr >> 2 & 0x1f
|
||||||
funct3 = instr >> 12 & 0x7
|
funct3 = instr >> 12 & 0x7
|
||||||
|
@ -239,6 +242,7 @@ class RVCore:
|
||||||
if funct3 != 0b000:
|
if funct3 != 0b000:
|
||||||
mul_result >>= 32
|
mul_result >>= 32
|
||||||
rd_wdata = sext(mul_result, XLEN - 1)
|
rd_wdata = sext(mul_result, XLEN - 1)
|
||||||
|
stage3_result_next = regnum_rd
|
||||||
else:
|
else:
|
||||||
if log:
|
if log:
|
||||||
div_instr_name = {0b100: "div", 0b101: "divu", 0b110: "rem", 0b111: "remu"}[funct3]
|
div_instr_name = {0b100: "div", 0b101: "divu", 0b110: "rem", 0b111: "remu"}[funct3]
|
||||||
|
@ -253,8 +257,11 @@ class RVCore:
|
||||||
rd_wdata = rs1 if rs2 == 0 else sext((rs1 & XLEN_MASK) % (rs2 & XLEN_MASK), XLEN - 1)
|
rd_wdata = rs1 if rs2 == 0 else sext((rs1 & XLEN_MASK) % (rs2 & XLEN_MASK), XLEN - 1)
|
||||||
else:
|
else:
|
||||||
instr_invalid = True
|
instr_invalid = True
|
||||||
|
stall_cycles = 18
|
||||||
else:
|
else:
|
||||||
instr_invalid = True
|
instr_invalid = True
|
||||||
|
if not instr_invalid:
|
||||||
|
stall_cycles += regnum_rs1 == self.stage3_result or regnum_rs2 == self.stage3_result
|
||||||
|
|
||||||
elif opc == OPC_OP_IMM:
|
elif opc == OPC_OP_IMM:
|
||||||
imm = (instr >> 20) - (instr >> 19 & 0x1000) # imm_i(instr)
|
imm = (instr >> 20) - (instr >> 19 & 0x1000) # imm_i(instr)
|
||||||
|
@ -291,19 +298,24 @@ class RVCore:
|
||||||
instr_invalid = True
|
instr_invalid = True
|
||||||
else:
|
else:
|
||||||
instr_invalid = True
|
instr_invalid = True
|
||||||
|
if not instr_invalid:
|
||||||
|
stall_cycles += regnum_rs1 == self.stage3_result
|
||||||
|
|
||||||
elif opc == OPC_JAL:
|
elif opc == OPC_JAL:
|
||||||
rd_wdata = self.pc + 4
|
rd_wdata = self.pc + 4
|
||||||
# pc_wdata = self.pc + imm_j(instr)
|
# pc_wdata = self.pc + imm_j(instr)
|
||||||
pc_wdata = self.pc + (instr >> 20 & 0x7fe) + (instr >> 9 & 0x800) + (instr & 0xff000) - (instr >> 11 & 0x100000)
|
pc_wdata = self.pc + (instr >> 20 & 0x7fe) + (instr >> 9 & 0x800) + (instr & 0xff000) - (instr >> 11 & 0x100000)
|
||||||
if log: log_disasm = f"jal x{regnum_rd}, {pc_wdata & XLEN_MASK:08x}"
|
if log: log_disasm = f"jal x{regnum_rd}, {pc_wdata & XLEN_MASK:08x}"
|
||||||
|
stall_cycles = 1
|
||||||
|
|
||||||
elif opc == OPC_JALR:
|
elif opc == OPC_JALR:
|
||||||
|
stall_cycles += regnum_rs1 == self.stage3_result
|
||||||
imm = imm_i(instr)
|
imm = imm_i(instr)
|
||||||
if log: log_disasm = f"jalr x{regnum_rd}, x{regnum_rs1}, {imm}"
|
if log: log_disasm = f"jalr x{regnum_rd}, x{regnum_rs1}, {imm}"
|
||||||
rd_wdata = self.pc + 4
|
rd_wdata = self.pc + 4
|
||||||
# JALR clears LSB always
|
# JALR clears LSB always
|
||||||
pc_wdata = (rs1 + imm) & -2
|
pc_wdata = (rs1 + imm) & -2
|
||||||
|
stall_cycles = 1
|
||||||
|
|
||||||
elif opc == OPC_BRANCH:
|
elif opc == OPC_BRANCH:
|
||||||
# target = self.pc + imm_b(instr)
|
# target = self.pc + imm_b(instr)
|
||||||
|
@ -330,8 +342,11 @@ class RVCore:
|
||||||
taken = (rs1 & XLEN_MASK) >= (rs2 & XLEN_MASK)
|
taken = (rs1 & XLEN_MASK) >= (rs2 & XLEN_MASK)
|
||||||
else:
|
else:
|
||||||
instr_invalid = True
|
instr_invalid = True
|
||||||
|
if not instr_invalid:
|
||||||
|
stall_cycles += regnum_rs1 == self.stage3_result or regnum_rs2 == self.stage3_result
|
||||||
if taken:
|
if taken:
|
||||||
pc_wdata = target
|
pc_wdata = target
|
||||||
|
stall_cycles += 1
|
||||||
|
|
||||||
elif opc == OPC_LOAD:
|
elif opc == OPC_LOAD:
|
||||||
imm = imm_i(instr)
|
imm = imm_i(instr)
|
||||||
|
@ -357,6 +372,9 @@ class RVCore:
|
||||||
rd_wdata = self.mem.get16(load_addr)
|
rd_wdata = self.mem.get16(load_addr)
|
||||||
else:
|
else:
|
||||||
instr_invalid = True
|
instr_invalid = True
|
||||||
|
if not instr_invalid:
|
||||||
|
stall_cycles += regnum_rs1 == self.stage3_result
|
||||||
|
stage3_result_next = regnum_rd
|
||||||
|
|
||||||
elif opc == OPC_STORE:
|
elif opc == OPC_STORE:
|
||||||
imm = imm_s(instr)
|
imm = imm_s(instr)
|
||||||
|
@ -373,6 +391,8 @@ class RVCore:
|
||||||
self.mem.put32(store_addr, rs2)
|
self.mem.put32(store_addr, rs2)
|
||||||
else:
|
else:
|
||||||
instr_invalid = True
|
instr_invalid = True
|
||||||
|
if not instr_invalid:
|
||||||
|
stall_cycles += regnum_rs1 == self.stage3_result
|
||||||
|
|
||||||
elif opc == OPC_LUI:
|
elif opc == OPC_LUI:
|
||||||
imm = imm_u(instr)
|
imm = imm_u(instr)
|
||||||
|
@ -404,6 +424,7 @@ class RVCore:
|
||||||
rd_wdata = self.csr.read(csr_addr)
|
rd_wdata = self.csr.read(csr_addr)
|
||||||
if csr_write_op == RVCSR.WRITE or rs2 != 0:
|
if csr_write_op == RVCSR.WRITE or rs2 != 0:
|
||||||
self.csr.write(csr_addr, rs2, op=csr_write_op)
|
self.csr.write(csr_addr, rs2, op=csr_write_op)
|
||||||
|
stall_cycles += regnum_rs1 == self.stage3_result
|
||||||
elif funct3 in (0b101, 0b110, 0b111):
|
elif funct3 in (0b101, 0b110, 0b111):
|
||||||
if log:
|
if log:
|
||||||
instr_name = {0b101: "csrrwi", 0b110: "csrrsi", 0b111: "csrrci"}[funct3]
|
instr_name = {0b101: "csrrwi", 0b110: "csrrsi", 0b111: "csrrci"}[funct3]
|
||||||
|
@ -451,6 +472,9 @@ class RVCore:
|
||||||
print(f"Invalid instruction at {self.pc:08x}: {instr:08x}")
|
print(f"Invalid instruction at {self.pc:08x}: {instr:08x}")
|
||||||
|
|
||||||
self.csr.step()
|
self.csr.step()
|
||||||
|
if cycle_accurate:
|
||||||
|
self.csr.mcycle += stall_cycles
|
||||||
|
self.stage3_result = stage3_result_next if stage3_result_next != 0 else None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue