mirror of https://github.com/YosysHQ/picorv32.git
Finalized tracer support
This commit is contained in:
parent
7094e61af7
commit
98d248d2c2
2
Makefile
2
Makefile
|
@ -14,7 +14,7 @@ test: testbench.vvp firmware/firmware.hex
|
|||
vvp -N testbench.vvp
|
||||
|
||||
testbench.vcd: testbench.vvp firmware/firmware.hex
|
||||
vvp -N $< +vcd +trace
|
||||
vvp -N $< +vcd +trace +noerror
|
||||
|
||||
view: testbench.vcd
|
||||
gtkwave $< testbench.gtkw
|
||||
|
|
|
@ -256,6 +256,13 @@ Set this to 0 to disable support for the `timer` instruction.
|
|||
|
||||
Support for the timer is always disabled when ENABLE_IRQ is set to 0.
|
||||
|
||||
#### ENABLE_TRACE (default = 0)
|
||||
|
||||
Produce an execution trace using the `trace_valid` and `trace_data` output ports.
|
||||
For a demontration of this feature run `make testbench.vcd` to create a trace file
|
||||
and then run `python3 showtrace.py testbench.trace firmware/firmware.elf` to decode
|
||||
it.
|
||||
|
||||
#### REGS_INIT_ZERO (default = 0)
|
||||
|
||||
Set this to 1 to initialize all registers to zero (using a Verilog `initial` block).
|
||||
|
|
|
@ -1236,7 +1236,7 @@ module picorv32 #(
|
|||
latched_trace <= 0;
|
||||
trace_valid <= 1;
|
||||
if (latched_branch)
|
||||
trace_data <= (irq_active ? TRACE_IRQ : 0) | TRACE_BRANCH | current_pc;
|
||||
trace_data <= (irq_active ? TRACE_IRQ : 0) | TRACE_BRANCH | (current_pc & 32'hfffffffe);
|
||||
else
|
||||
trace_data <= (irq_active ? TRACE_IRQ : 0) | (latched_stalu ? alu_out_q : reg_out);
|
||||
end
|
||||
|
@ -1556,7 +1556,7 @@ module picorv32 #(
|
|||
endcase
|
||||
if (ENABLE_TRACE) begin
|
||||
trace_valid <= 1;
|
||||
trace_data <= (irq_active ? TRACE_IRQ : 0) | TRACE_ADDR | (reg_op1 + decoded_imm);
|
||||
trace_data <= (irq_active ? TRACE_IRQ : 0) | TRACE_ADDR | ((reg_op1 + decoded_imm) & 32'hffffffff);
|
||||
end
|
||||
reg_op1 <= reg_op1 + decoded_imm;
|
||||
set_mem_do_wdata = 1;
|
||||
|
@ -1584,7 +1584,7 @@ module picorv32 #(
|
|||
latched_is_lb <= instr_lb;
|
||||
if (ENABLE_TRACE) begin
|
||||
trace_valid <= 1;
|
||||
trace_data <= (irq_active ? TRACE_IRQ : 0) | TRACE_ADDR | (reg_op1 + decoded_imm);
|
||||
trace_data <= (irq_active ? TRACE_IRQ : 0) | TRACE_ADDR | ((reg_op1 + decoded_imm) & 32'hffffffff);
|
||||
end
|
||||
reg_op1 <= reg_op1 + decoded_imm;
|
||||
set_mem_do_rdata = 1;
|
||||
|
|
26
showtrace.py
26
showtrace.py
|
@ -23,6 +23,7 @@ with open(trace_filename, "r") as f:
|
|||
irq_active = (raw_data & 0x800000000) != 0
|
||||
is_addr = (raw_data & 0x200000000) != 0
|
||||
is_branch = (raw_data & 0x100000000) != 0
|
||||
info = "%s %s%08x" % ("IRQ" if irq_active else " ", ">" if is_branch else "@" if is_addr else "=", payload)
|
||||
|
||||
if irq_active and not last_irq:
|
||||
pc = 0x10
|
||||
|
@ -30,18 +31,31 @@ with open(trace_filename, "r") as f:
|
|||
if pc >= 0:
|
||||
if pc in insns:
|
||||
insn_opcode, insn_desc = insns[pc]
|
||||
opname = insn_desc.split()[0]
|
||||
|
||||
if insn_desc.startswith("custom0 0,0,0,2"):
|
||||
opname = "retirq"
|
||||
|
||||
if is_branch and opname not in ["j", "jal", "jr", "jalr", "ret", "retirq",
|
||||
"beq", "bne", "blt", "ble", "bge", "bgt", "bltu", "bleu", "bgeu", "bgtu",
|
||||
"beqz", "bnez", "blez", "bgez", "bltz", "bgtz"]:
|
||||
print("%s ** UNEXPECTED BRANCH DATA FOR INSN AT %08x! **" % (info, pc))
|
||||
|
||||
if is_addr and opname not in ["lb", "lh", "lw", "lbu", "lhu", "sb", "sh", "sw"]:
|
||||
print("%s ** UNEXPECTED ADDR DATA FOR INSN AT %08x! **" % (info, pc))
|
||||
|
||||
opcode_fmt = "%08x" if (insn_opcode & 3) == 3 else " %04x"
|
||||
print(("%s %s%08x | %08x | " + opcode_fmt + " | %s") % ("IRQ" if irq_active else " ",
|
||||
">" if is_branch else "@" if is_addr else "=", payload, pc, insn_opcode, insn_desc))
|
||||
print(("%s | %08x | " + opcode_fmt + " | %s") % (info, pc, insn_opcode, insn_desc))
|
||||
if not is_addr:
|
||||
pc += 4 if (insn_opcode & 3) == 3 else 2
|
||||
else:
|
||||
print("%s %s%08x ** NO INFORMATION ON INSN AT %08x! **" % ("IRQ" if irq_active else " ",
|
||||
">" if is_branch else "@" if is_addr else "=", payload, pc))
|
||||
print("%s ** NO INFORMATION ON INSN AT %08x! **" % (info, pc))
|
||||
pc = -1
|
||||
else:
|
||||
print("%s %s%08x ** SKIPPING DATA UNTIL NEXT BRANCH **" % ("IRQ" if irq_active else " ",
|
||||
">" if is_branch else "@" if is_addr else "=", payload))
|
||||
if is_branch:
|
||||
print("%s ** FOUND BRANCH AND STARTING DECODING **" % info)
|
||||
else:
|
||||
print("%s ** SKIPPING DATA UNTIL NEXT BRANCH **" % info)
|
||||
|
||||
if is_branch:
|
||||
pc = payload
|
||||
|
|
|
@ -48,6 +48,7 @@ module testbench #(
|
|||
$fwrite(trace_file, "%x\n", trace_data);
|
||||
end
|
||||
$fclose(trace_file);
|
||||
$display("Finished writing testbench.trace.");
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -194,6 +195,8 @@ module picorv32_wrapper #(
|
|||
$finish;
|
||||
end else begin
|
||||
$display("ERROR!");
|
||||
if ($test$plusargs("noerror"))
|
||||
$finish;
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue