rvfi_trace.py
# Print the instructions a riscv-formal counterexample retires, one per line.
# Usage: python3 rvfi_trace.py trace.vcd
# Reads the RVFI signals under rvfi_testbench.wrapper; standard library only.
# Names register-register and register-immediate ALU instructions; prints
# other instructions as their machine code in hexadecimal.
import sys
NAMES = {"rvfi_valid", "rvfi_order", "rvfi_pc_rdata", "rvfi_insn",
"rvfi_rs1_addr", "rvfi_rs1_rdata", "rvfi_rs2_addr", "rvfi_rs2_rdata",
"rvfi_rd_addr", "rvfi_rd_wdata"}
R_TYPE = {(0, 0): "add", (32, 0): "sub", (0, 1): "sll", (0, 2): "slt",
(0, 3): "sltu", (0, 4): "xor", (0, 5): "srl", (32, 5): "sra",
(0, 6): "or", (0, 7): "and"}
I_TYPE = {0: "addi", 2: "slti", 3: "sltiu", 4: "xori", 6: "ori", 7: "andi"}
def name(insn):
if insn & 3 != 3:
return "0x%04x" % insn # 16-bit compressed instruction
opcode, funct3, funct7 = insn & 0x7f, (insn >> 12) & 7, insn >> 25
if opcode == 0x33 and (funct7, funct3) in R_TYPE:
return R_TYPE[funct7, funct3]
if opcode == 0x13 and funct3 in I_TYPE:
return I_TYPE[funct3]
return "0x%08x" % insn
ids, scope, now, seen = {}, [], {}, {}
def sample():
if now.get("rvfi_valid") == 1 and now["rvfi_order"] not in seen:
seen[now["rvfi_order"]] = dict(now)
for line in open(sys.argv[1]):
t = line.split()
if not t:
continue
if t[0] == "$scope":
scope.append(t[2])
elif t[0] == "$upscope":
scope.pop()
elif t[0] == "$var" and scope == ["rvfi_testbench", "wrapper"] and t[4] in NAMES:
ids[t[3]] = t[4]
elif t[0].startswith("#"):
sample()
elif t[0][0] in "01" and t[0][1:] in ids:
now[ids[t[0][1:]]] = int(t[0][0])
elif t[0][0] == "b" and len(t) > 1 and t[1] in ids:
now[ids[t[1]]] = int(t[0][1:].replace("x", "0"), 2)
sample()
for order in sorted(seen):
v = seen[order]
print("%3d pc %08x %-10s rs1 x%-2d = %08x rs2 x%-2d = %08x rd x%-2d = %08x" % (
order, v["rvfi_pc_rdata"], name(v["rvfi_insn"]),
v["rvfi_rs1_addr"], v["rvfi_rs1_rdata"], v["rvfi_rs2_addr"],
v["rvfi_rs2_rdata"], v["rvfi_rd_addr"], v["rvfi_rd_wdata"]))Each line shows the instruction's position in program order, its program counter, the instruction, and the registers it read and wrote, in hexadecimal. The script names register-register and register-immediate ALU instructions; it prints the others as their machine code.