Finalized tracer support

This commit is contained in:
Clifford Wolf 2016-08-26 14:54:27 +02:00
parent 7094e61af7
commit 98d248d2c2
5 changed files with 34 additions and 10 deletions

View File

@ -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

View File

@ -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).

View File

@ -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;

View File

@ -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

View File

@ -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