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
|
vvp -N testbench.vvp
|
||||||
|
|
||||||
testbench.vcd: testbench.vvp firmware/firmware.hex
|
testbench.vcd: testbench.vvp firmware/firmware.hex
|
||||||
vvp -N $< +vcd +trace
|
vvp -N $< +vcd +trace +noerror
|
||||||
|
|
||||||
view: testbench.vcd
|
view: testbench.vcd
|
||||||
gtkwave $< testbench.gtkw
|
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.
|
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)
|
#### REGS_INIT_ZERO (default = 0)
|
||||||
|
|
||||||
Set this to 1 to initialize all registers to zero (using a Verilog `initial` block).
|
Set this to 1 to initialize all registers to zero (using a Verilog `initial` block).
|
||||||
|
|
|
@ -1236,7 +1236,7 @@ module picorv32 #(
|
||||||
latched_trace <= 0;
|
latched_trace <= 0;
|
||||||
trace_valid <= 1;
|
trace_valid <= 1;
|
||||||
if (latched_branch)
|
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
|
else
|
||||||
trace_data <= (irq_active ? TRACE_IRQ : 0) | (latched_stalu ? alu_out_q : reg_out);
|
trace_data <= (irq_active ? TRACE_IRQ : 0) | (latched_stalu ? alu_out_q : reg_out);
|
||||||
end
|
end
|
||||||
|
@ -1556,7 +1556,7 @@ module picorv32 #(
|
||||||
endcase
|
endcase
|
||||||
if (ENABLE_TRACE) begin
|
if (ENABLE_TRACE) begin
|
||||||
trace_valid <= 1;
|
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
|
end
|
||||||
reg_op1 <= reg_op1 + decoded_imm;
|
reg_op1 <= reg_op1 + decoded_imm;
|
||||||
set_mem_do_wdata = 1;
|
set_mem_do_wdata = 1;
|
||||||
|
@ -1584,7 +1584,7 @@ module picorv32 #(
|
||||||
latched_is_lb <= instr_lb;
|
latched_is_lb <= instr_lb;
|
||||||
if (ENABLE_TRACE) begin
|
if (ENABLE_TRACE) begin
|
||||||
trace_valid <= 1;
|
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
|
end
|
||||||
reg_op1 <= reg_op1 + decoded_imm;
|
reg_op1 <= reg_op1 + decoded_imm;
|
||||||
set_mem_do_rdata = 1;
|
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
|
irq_active = (raw_data & 0x800000000) != 0
|
||||||
is_addr = (raw_data & 0x200000000) != 0
|
is_addr = (raw_data & 0x200000000) != 0
|
||||||
is_branch = (raw_data & 0x100000000) != 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:
|
if irq_active and not last_irq:
|
||||||
pc = 0x10
|
pc = 0x10
|
||||||
|
@ -30,18 +31,31 @@ with open(trace_filename, "r") as f:
|
||||||
if pc >= 0:
|
if pc >= 0:
|
||||||
if pc in insns:
|
if pc in insns:
|
||||||
insn_opcode, insn_desc = insns[pc]
|
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"
|
opcode_fmt = "%08x" if (insn_opcode & 3) == 3 else " %04x"
|
||||||
print(("%s %s%08x | %08x | " + opcode_fmt + " | %s") % ("IRQ" if irq_active else " ",
|
print(("%s | %08x | " + opcode_fmt + " | %s") % (info, pc, insn_opcode, insn_desc))
|
||||||
">" if is_branch else "@" if is_addr else "=", payload, pc, insn_opcode, insn_desc))
|
|
||||||
if not is_addr:
|
if not is_addr:
|
||||||
pc += 4 if (insn_opcode & 3) == 3 else 2
|
pc += 4 if (insn_opcode & 3) == 3 else 2
|
||||||
else:
|
else:
|
||||||
print("%s %s%08x ** NO INFORMATION ON INSN AT %08x! **" % ("IRQ" if irq_active else " ",
|
print("%s ** NO INFORMATION ON INSN AT %08x! **" % (info, pc))
|
||||||
">" if is_branch else "@" if is_addr else "=", payload, pc))
|
|
||||||
pc = -1
|
pc = -1
|
||||||
else:
|
else:
|
||||||
print("%s %s%08x ** SKIPPING DATA UNTIL NEXT BRANCH **" % ("IRQ" if irq_active else " ",
|
if is_branch:
|
||||||
">" if is_branch else "@" if is_addr else "=", payload))
|
print("%s ** FOUND BRANCH AND STARTING DECODING **" % info)
|
||||||
|
else:
|
||||||
|
print("%s ** SKIPPING DATA UNTIL NEXT BRANCH **" % info)
|
||||||
|
|
||||||
if is_branch:
|
if is_branch:
|
||||||
pc = payload
|
pc = payload
|
||||||
|
|
|
@ -48,6 +48,7 @@ module testbench #(
|
||||||
$fwrite(trace_file, "%x\n", trace_data);
|
$fwrite(trace_file, "%x\n", trace_data);
|
||||||
end
|
end
|
||||||
$fclose(trace_file);
|
$fclose(trace_file);
|
||||||
|
$display("Finished writing testbench.trace.");
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -194,6 +195,8 @@ module picorv32_wrapper #(
|
||||||
$finish;
|
$finish;
|
||||||
end else begin
|
end else begin
|
||||||
$display("ERROR!");
|
$display("ERROR!");
|
||||||
|
if ($test$plusargs("noerror"))
|
||||||
|
$finish;
|
||||||
$stop;
|
$stop;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue