From 98d248d2c2f785f1b35ce7a08df7705e1945597f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 26 Aug 2016 14:54:27 +0200 Subject: [PATCH] Finalized tracer support --- Makefile | 2 +- README.md | 7 +++++++ picorv32.v | 6 +++--- showtrace.py | 26 ++++++++++++++++++++------ testbench.v | 3 +++ 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index bb73fd9..c585588 100644 --- a/Makefile +++ b/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 diff --git a/README.md b/README.md index 51eb17e..2ebf19a 100644 --- a/README.md +++ b/README.md @@ -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). diff --git a/picorv32.v b/picorv32.v index a2dc8a2..1400e0c 100644 --- a/picorv32.v +++ b/picorv32.v @@ -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; diff --git a/showtrace.py b/showtrace.py index 56c91ff..7d7316a 100644 --- a/showtrace.py +++ b/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 diff --git a/testbench.v b/testbench.v index dc7a7f3..18cce40 100644 --- a/testbench.v +++ b/testbench.v @@ -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