picorv32 now runs: debugging outputs

This commit is contained in:
Peter McGoron 2024-02-22 04:58:59 +00:00
parent 67c670cb5c
commit f5b14d51ab
5 changed files with 74 additions and 321 deletions

View File

@ -49,7 +49,7 @@ hardware-get:
docker cp upsilon-hardware:/home/user/upsilon/gateware/build/digilent_arty/gateware/digilent_arty.bit ../boot/
docker cp upsilon-hardware:/home/user/upsilon/gateware/arty.dtb ../boot/
docker cp upsilon-hardware:/home/user/upsilon/gateware/csr.json ../boot/
docker cp upsilon-hardware:/home/user/upsilon/gateware/picorv32.json ../boot/
docker cp upsilon-hardware:/home/user/upsilon/gateware/pico0.json ../boot/
docker cp upsilon-hardware:/home/user/upsilon/gateware/mmio.py ../boot/
hardware-clean:
-docker container stop upsilon-hardware

View File

@ -22,7 +22,7 @@ with open(sys.argv[1], 'rt') as f:
print("from micropython import const")
for key in j["csr_registers"]:
if key.startswith("picorv32"):
if key.startswith("pico0"):
print(f'{key} = const({j["csr_registers"][key]["addr"]})')
print(f'picorv32_ram = const({j["memories"]["picorv32_ram"]["base"]})')
print(f'pico0_ram = const({j["memories"]["pico0_ram"]["base"]})')

View File

@ -90,7 +90,6 @@ module picorv32 #(
parameter [31:0] STACKADDR = 32'h ffff_ffff
) (
input clk, resetn,
output reg trap,
output reg mem_valid,
output reg mem_instr,
@ -156,10 +155,24 @@ module picorv32 #(
output reg [63:0] rvfi_csr_minstret_wdata,
`endif
/* Debugging interface */
`define TRAP_RS1_ILLINSN 7'd1
`define TRAP_RS2_ILLINSN 7'd2
`define TRAP_MAL_WORD 7'd3
`define TRAP_MAL_HWORD 7'd4
`define TRAP_MAL_INS 7'd5
`define TRAP_EBREAK 7'd6
output reg [7:0] trap,
output reg [31:0] dbg_insn_addr,
output reg [31:0] dbg_insn_opcode,
// Trace Interface
output reg trace_valid,
output reg [35:0] trace_data
);
reg [7:0] trap_type;
localparam integer irq_timer = 0;
localparam integer irq_ebreak = 1;
localparam integer irq_buserror = 2;
@ -179,8 +192,6 @@ module picorv32 #(
reg [4:0] reg_sh;
reg [31:0] next_insn_opcode;
reg [31:0] dbg_insn_opcode;
reg [31:0] dbg_insn_addr;
wire dbg_mem_valid = mem_valid;
wire dbg_mem_instr = mem_instr;
@ -1486,7 +1497,7 @@ module picorv32 #(
(* parallel_case, full_case *)
case (cpu_state)
cpu_state_trap: begin
trap <= 1;
trap <= trap_type;
end
cpu_state_fetch: begin
@ -1609,8 +1620,10 @@ module picorv32 #(
if (ENABLE_IRQ && !irq_mask[irq_ebreak] && !irq_active) begin
next_irq_pending[irq_ebreak] = 1;
cpu_state <= cpu_state_fetch;
end else
end else begin
trap_type <= `TRAP_RS1_ILLINSN;
cpu_state <= cpu_state_trap;
end
end
end else begin
cpu_state <= cpu_state_ld_rs2;
@ -1620,8 +1633,10 @@ module picorv32 #(
if (ENABLE_IRQ && !irq_mask[irq_ebreak] && !irq_active) begin
next_irq_pending[irq_ebreak] = 1;
cpu_state <= cpu_state_fetch;
end else
end else begin
trap_type <= `TRAP_RS1_ILLINSN;
cpu_state <= cpu_state_trap;
end
end
end
ENABLE_COUNTERS && is_rdcycle_rdcycleh_rdinstr_rdinstrh: begin
@ -1781,8 +1796,10 @@ module picorv32 #(
if (ENABLE_IRQ && !irq_mask[irq_ebreak] && !irq_active) begin
next_irq_pending[irq_ebreak] = 1;
cpu_state <= cpu_state_fetch;
end else
end else begin
trap_type <= `TRAP_RS2_ILLINSN;
cpu_state <= cpu_state_trap;
end
end
end
is_sb_sh_sw: begin
@ -1925,25 +1942,32 @@ module picorv32 #(
`debug($display("MISALIGNED WORD: 0x%08x", reg_op1);)
if (ENABLE_IRQ && !irq_mask[irq_buserror] && !irq_active) begin
next_irq_pending[irq_buserror] = 1;
end else
end else begin
trap_type <= `TRAP_MAL_WORD;
cpu_state <= cpu_state_trap;
end
end
if (mem_wordsize == 1 && reg_op1[0] != 0) begin
`debug($display("MISALIGNED HALFWORD: 0x%08x", reg_op1);)
if (ENABLE_IRQ && !irq_mask[irq_buserror] && !irq_active) begin
next_irq_pending[irq_buserror] = 1;
end else
end else begin
trap_type <= `TRAP_MAL_HWORD;
cpu_state <= cpu_state_trap;
end
end
end
if (CATCH_MISALIGN && resetn && mem_do_rinst && (COMPRESSED_ISA ? reg_pc[0] : |reg_pc[1:0])) begin
`debug($display("MISALIGNED INSTRUCTION: 0x%08x", reg_pc);)
if (ENABLE_IRQ && !irq_mask[irq_buserror] && !irq_active) begin
next_irq_pending[irq_buserror] = 1;
end else
end else begin
trap_type <= `TRAP_MAL_INS;
cpu_state <= cpu_state_trap;
end
end
if (!CATCH_ILLINSN && decoder_trigger_q && !decoder_pseudo_trigger_q && instr_ecall_ebreak) begin
trap_type <= `TRAP_EBREAK;
cpu_state <= cpu_state_trap;
end
@ -2510,302 +2534,6 @@ module picorv32_pcpi_div (
end
endmodule
/***************************************************************
* picorv32_axi
***************************************************************/
module picorv32_axi #(
parameter [ 0:0] ENABLE_COUNTERS = 1,
parameter [ 0:0] ENABLE_COUNTERS64 = 1,
parameter [ 0:0] ENABLE_REGS_16_31 = 1,
parameter [ 0:0] ENABLE_REGS_DUALPORT = 1,
parameter [ 0:0] TWO_STAGE_SHIFT = 1,
parameter [ 0:0] BARREL_SHIFTER = 0,
parameter [ 0:0] TWO_CYCLE_COMPARE = 0,
parameter [ 0:0] TWO_CYCLE_ALU = 0,
parameter [ 0:0] COMPRESSED_ISA = 0,
parameter [ 0:0] CATCH_MISALIGN = 1,
parameter [ 0:0] CATCH_ILLINSN = 1,
parameter [ 0:0] ENABLE_PCPI = 0,
parameter [ 0:0] ENABLE_MUL = 0,
parameter [ 0:0] ENABLE_FAST_MUL = 0,
parameter [ 0:0] ENABLE_DIV = 0,
parameter [ 0:0] ENABLE_IRQ = 0,
parameter [ 0:0] ENABLE_IRQ_QREGS = 1,
parameter [ 0:0] ENABLE_IRQ_TIMER = 1,
parameter [ 0:0] ENABLE_TRACE = 0,
parameter [ 0:0] REGS_INIT_ZERO = 0,
parameter [31:0] MASKED_IRQ = 32'h 0000_0000,
parameter [31:0] LATCHED_IRQ = 32'h ffff_ffff,
parameter [31:0] PROGADDR_RESET = 32'h 0000_0000,
parameter [31:0] PROGADDR_IRQ = 32'h 0000_0010,
parameter [31:0] STACKADDR = 32'h ffff_ffff
) (
input clk, resetn,
output trap,
// AXI4-lite master memory interface
output mem_axi_awvalid,
input mem_axi_awready,
output [31:0] mem_axi_awaddr,
output [ 2:0] mem_axi_awprot,
output mem_axi_wvalid,
input mem_axi_wready,
output [31:0] mem_axi_wdata,
output [ 3:0] mem_axi_wstrb,
input mem_axi_bvalid,
output mem_axi_bready,
output mem_axi_arvalid,
input mem_axi_arready,
output [31:0] mem_axi_araddr,
output [ 2:0] mem_axi_arprot,
input mem_axi_rvalid,
output mem_axi_rready,
input [31:0] mem_axi_rdata,
// Pico Co-Processor Interface (PCPI)
output pcpi_valid,
output [31:0] pcpi_insn,
output [31:0] pcpi_rs1,
output [31:0] pcpi_rs2,
input pcpi_wr,
input [31:0] pcpi_rd,
input pcpi_wait,
input pcpi_ready,
// IRQ interface
input [31:0] irq,
output [31:0] eoi,
`ifdef RISCV_FORMAL
output rvfi_valid,
output [63:0] rvfi_order,
output [31:0] rvfi_insn,
output rvfi_trap,
output rvfi_halt,
output rvfi_intr,
output [ 4:0] rvfi_rs1_addr,
output [ 4:0] rvfi_rs2_addr,
output [31:0] rvfi_rs1_rdata,
output [31:0] rvfi_rs2_rdata,
output [ 4:0] rvfi_rd_addr,
output [31:0] rvfi_rd_wdata,
output [31:0] rvfi_pc_rdata,
output [31:0] rvfi_pc_wdata,
output [31:0] rvfi_mem_addr,
output [ 3:0] rvfi_mem_rmask,
output [ 3:0] rvfi_mem_wmask,
output [31:0] rvfi_mem_rdata,
output [31:0] rvfi_mem_wdata,
`endif
// Trace Interface
output trace_valid,
output [35:0] trace_data
);
wire mem_valid;
wire [31:0] mem_addr;
wire [31:0] mem_wdata;
wire [ 3:0] mem_wstrb;
wire mem_instr;
wire mem_ready;
wire [31:0] mem_rdata;
picorv32_axi_adapter axi_adapter (
.clk (clk ),
.resetn (resetn ),
.mem_axi_awvalid(mem_axi_awvalid),
.mem_axi_awready(mem_axi_awready),
.mem_axi_awaddr (mem_axi_awaddr ),
.mem_axi_awprot (mem_axi_awprot ),
.mem_axi_wvalid (mem_axi_wvalid ),
.mem_axi_wready (mem_axi_wready ),
.mem_axi_wdata (mem_axi_wdata ),
.mem_axi_wstrb (mem_axi_wstrb ),
.mem_axi_bvalid (mem_axi_bvalid ),
.mem_axi_bready (mem_axi_bready ),
.mem_axi_arvalid(mem_axi_arvalid),
.mem_axi_arready(mem_axi_arready),
.mem_axi_araddr (mem_axi_araddr ),
.mem_axi_arprot (mem_axi_arprot ),
.mem_axi_rvalid (mem_axi_rvalid ),
.mem_axi_rready (mem_axi_rready ),
.mem_axi_rdata (mem_axi_rdata ),
.mem_valid (mem_valid ),
.mem_instr (mem_instr ),
.mem_ready (mem_ready ),
.mem_addr (mem_addr ),
.mem_wdata (mem_wdata ),
.mem_wstrb (mem_wstrb ),
.mem_rdata (mem_rdata )
);
picorv32 #(
.ENABLE_COUNTERS (ENABLE_COUNTERS ),
.ENABLE_COUNTERS64 (ENABLE_COUNTERS64 ),
.ENABLE_REGS_16_31 (ENABLE_REGS_16_31 ),
.ENABLE_REGS_DUALPORT(ENABLE_REGS_DUALPORT),
.TWO_STAGE_SHIFT (TWO_STAGE_SHIFT ),
.BARREL_SHIFTER (BARREL_SHIFTER ),
.TWO_CYCLE_COMPARE (TWO_CYCLE_COMPARE ),
.TWO_CYCLE_ALU (TWO_CYCLE_ALU ),
.COMPRESSED_ISA (COMPRESSED_ISA ),
.CATCH_MISALIGN (CATCH_MISALIGN ),
.CATCH_ILLINSN (CATCH_ILLINSN ),
.ENABLE_PCPI (ENABLE_PCPI ),
.ENABLE_MUL (ENABLE_MUL ),
.ENABLE_FAST_MUL (ENABLE_FAST_MUL ),
.ENABLE_DIV (ENABLE_DIV ),
.ENABLE_IRQ (ENABLE_IRQ ),
.ENABLE_IRQ_QREGS (ENABLE_IRQ_QREGS ),
.ENABLE_IRQ_TIMER (ENABLE_IRQ_TIMER ),
.ENABLE_TRACE (ENABLE_TRACE ),
.REGS_INIT_ZERO (REGS_INIT_ZERO ),
.MASKED_IRQ (MASKED_IRQ ),
.LATCHED_IRQ (LATCHED_IRQ ),
.PROGADDR_RESET (PROGADDR_RESET ),
.PROGADDR_IRQ (PROGADDR_IRQ ),
.STACKADDR (STACKADDR )
) picorv32_core (
.clk (clk ),
.resetn (resetn),
.trap (trap ),
.mem_valid(mem_valid),
.mem_addr (mem_addr ),
.mem_wdata(mem_wdata),
.mem_wstrb(mem_wstrb),
.mem_instr(mem_instr),
.mem_ready(mem_ready),
.mem_rdata(mem_rdata),
.pcpi_valid(pcpi_valid),
.pcpi_insn (pcpi_insn ),
.pcpi_rs1 (pcpi_rs1 ),
.pcpi_rs2 (pcpi_rs2 ),
.pcpi_wr (pcpi_wr ),
.pcpi_rd (pcpi_rd ),
.pcpi_wait (pcpi_wait ),
.pcpi_ready(pcpi_ready),
.irq(irq),
.eoi(eoi),
`ifdef RISCV_FORMAL
.rvfi_valid (rvfi_valid ),
.rvfi_order (rvfi_order ),
.rvfi_insn (rvfi_insn ),
.rvfi_trap (rvfi_trap ),
.rvfi_halt (rvfi_halt ),
.rvfi_intr (rvfi_intr ),
.rvfi_rs1_addr (rvfi_rs1_addr ),
.rvfi_rs2_addr (rvfi_rs2_addr ),
.rvfi_rs1_rdata(rvfi_rs1_rdata),
.rvfi_rs2_rdata(rvfi_rs2_rdata),
.rvfi_rd_addr (rvfi_rd_addr ),
.rvfi_rd_wdata (rvfi_rd_wdata ),
.rvfi_pc_rdata (rvfi_pc_rdata ),
.rvfi_pc_wdata (rvfi_pc_wdata ),
.rvfi_mem_addr (rvfi_mem_addr ),
.rvfi_mem_rmask(rvfi_mem_rmask),
.rvfi_mem_wmask(rvfi_mem_wmask),
.rvfi_mem_rdata(rvfi_mem_rdata),
.rvfi_mem_wdata(rvfi_mem_wdata),
`endif
.trace_valid(trace_valid),
.trace_data (trace_data)
);
endmodule
/***************************************************************
* picorv32_axi_adapter
***************************************************************/
module picorv32_axi_adapter (
input clk, resetn,
// AXI4-lite master memory interface
output mem_axi_awvalid,
input mem_axi_awready,
output [31:0] mem_axi_awaddr,
output [ 2:0] mem_axi_awprot,
output mem_axi_wvalid,
input mem_axi_wready,
output [31:0] mem_axi_wdata,
output [ 3:0] mem_axi_wstrb,
input mem_axi_bvalid,
output mem_axi_bready,
output mem_axi_arvalid,
input mem_axi_arready,
output [31:0] mem_axi_araddr,
output [ 2:0] mem_axi_arprot,
input mem_axi_rvalid,
output mem_axi_rready,
input [31:0] mem_axi_rdata,
// Native PicoRV32 memory interface
input mem_valid,
input mem_instr,
output mem_ready,
input [31:0] mem_addr,
input [31:0] mem_wdata,
input [ 3:0] mem_wstrb,
output [31:0] mem_rdata
);
reg ack_awvalid;
reg ack_arvalid;
reg ack_wvalid;
reg xfer_done;
assign mem_axi_awvalid = mem_valid && |mem_wstrb && !ack_awvalid;
assign mem_axi_awaddr = mem_addr;
assign mem_axi_awprot = 0;
assign mem_axi_arvalid = mem_valid && !mem_wstrb && !ack_arvalid;
assign mem_axi_araddr = mem_addr;
assign mem_axi_arprot = mem_instr ? 3'b100 : 3'b000;
assign mem_axi_wvalid = mem_valid && |mem_wstrb && !ack_wvalid;
assign mem_axi_wdata = mem_wdata;
assign mem_axi_wstrb = mem_wstrb;
assign mem_ready = mem_axi_bvalid || mem_axi_rvalid;
assign mem_axi_bready = mem_valid && |mem_wstrb;
assign mem_axi_rready = mem_valid && !mem_wstrb;
assign mem_rdata = mem_axi_rdata;
always @(posedge clk) begin
if (!resetn) begin
ack_awvalid <= 0;
end else begin
xfer_done <= mem_valid && mem_ready;
if (mem_axi_awready && mem_axi_awvalid)
ack_awvalid <= 1;
if (mem_axi_arready && mem_axi_arvalid)
ack_arvalid <= 1;
if (mem_axi_wready && mem_axi_wvalid)
ack_wvalid <= 1;
if (xfer_done || !mem_valid) begin
ack_awvalid <= 0;
ack_arvalid <= 0;
ack_wvalid <= 0;
end
end
end
endmodule
/***************************************************************
* picorv32_wb
***************************************************************/
@ -2837,7 +2565,9 @@ module picorv32_wb #(
parameter [31:0] PROGADDR_IRQ = 32'h 0000_0010,
parameter [31:0] STACKADDR = 32'h ffff_ffff
) (
output trap,
output [7:0] trap,
output [31:0] dbg_insn_addr,
output [31:0] dbg_insn_opcode,
// Wishbone interfaces
input wb_rst_i,
@ -2981,6 +2711,8 @@ module picorv32_wb #(
.rvfi_mem_rdata(rvfi_mem_rdata),
.rvfi_mem_wdata(rvfi_mem_wdata),
`endif
.dbg_insn_addr(dbg_insn_addr),
.dbg_insn_opcode(dbg_insn_opcode),
.trace_valid(trace_valid),
.trace_data (trace_data)

View File

@ -367,7 +367,17 @@ class PicoRV32(Module, AutoCSR):
self.masterbus = Interface(data_width=32, address_width=32, addressing="byte")
self.resetpin = CSRStorage(1, name="enable", description="PicoRV32 enable")
self.trap = CSRStatus(1, name="trap", description="Trap bit")
self.trap = CSRStatus(8, name="trap", description="Trap condition")
self.d_adr = CSRStatus(32)
self.d_dat_w = CSRStatus(32)
self.dbg_insn_addr = CSRStatus(32)
self.dbg_insn_opcode = CSRStatus(32)
self.comb += [
self.d_adr.status.eq(self.masterbus.adr),
self.d_dat_w.status.eq(self.masterbus.dat_w),
]
# NOTE: need to compile to these extact instructions
self.specials += Instance("picorv32_wb",
@ -404,10 +414,13 @@ class PicoRV32(Module, AutoCSR):
o_trace_valid = Signal(),
o_trace_data = Signal(36),
o_debug_state = Signal(2),
o_dbg_insn_addr = self.dbg_insn_addr.status,
o_dbg_insn_opcode = self.dbg_insn_opcode.status,
)
def do_finalize(self):
self.mmap.dump_json(self.name)
self.mmap.dump_json(self.name + ".json")
self.submodules.decoder = self.mmap.bus_submodule(self.masterbus)
# Clock and Reset Generator

View File

@ -5,21 +5,29 @@ def read_file(filename):
with open(filename, 'rb') as f:
return f.read()
def check_running():
print("Running:", machine.mem32[pico0_enable])
print("Trap status:", machine.mem32[pico0_trap])
print("Bus address:", hex(machine.mem32[pico0_d_adr]))
print("Bus write value:", hex(machine.mem32[pico0_d_dat_w]))
print("Instruction address:", hex(machine.mem32[pico0_dbg_insn_addr]))
print("Opcode:", hex(machine.mem32[pico0_dbg_insn_opcode]))
def run_program(prog, cl_I):
# Reset PicoRV32
machine.mem32[picorv32_enable] = 0
machine.mem32[picorv32_ram_iface_master_select] = 0
machine.mem32[pico0_enable] = 0
machine.mem32[pico0ram_iface_master_select] = 0
offset = picorv32_ram
offset = pico0_ram
for b in prog:
machine.mem8[offset] = b
offset += 1
for i in range(len(prog)):
assert machine.mem8[picorv32_ram + i] == prog[i]
assert machine.mem8[pico0_ram + i] == prog[i]
machine.mem32[picorv32_ram_iface_master_select] = 1
assert machine.mem8[picorv32_ram] == 0
machine.mem32[picorv32_params_cl_I] = cl_I
machine.mem32[picorv32_enable] = 1
return machine.mem32[picorv32_params_zset]
machine.mem32[pico0_params_cl_I] = cl_I
machine.mem32[pico0ram_iface_master_select] = 1
assert machine.mem8[pico0_ram] == 0
machine.mem32[pico0_enable] = 1
return machine.mem32[pico0_params_zset]