| From 05cf125bc39f3416c5113180d4b98493812d3305 Mon Sep 17 00:00:00 2001 |
| From: Michael Schaffner <msf@google.com> |
| Date: Tue, 25 Oct 2022 19:38:49 -0700 |
| Subject: [PATCH 3/4] Add access error signal to dm_mem |
| |
| Signed-off-by: Michael Schaffner <msf@google.com> |
| |
| diff --git a/src/dm_mem.sv b/src/dm_mem.sv |
| index 09fc919..889193d 100755 |
| --- a/src/dm_mem.sv |
| +++ b/src/dm_mem.sv |
| @@ -20,7 +20,8 @@ module dm_mem #( |
| parameter int unsigned NrHarts = 1, |
| parameter int unsigned BusWidth = 32, |
| parameter logic [NrHarts-1:0] SelectableHarts = {NrHarts{1'b1}}, |
| - parameter int unsigned DmBaseAddress = '0 |
| + parameter int unsigned DmBaseAddress = '0, |
| + localparam int unsigned BeWidth = BusWidth/8 |
| ) ( |
| input logic clk_i, // Clock |
| input logic rst_ni, // debug module reset |
| @@ -55,8 +56,9 @@ module dm_mem #( |
| input logic we_i, |
| input logic [BusWidth-1:0] addr_i, |
| input logic [BusWidth-1:0] wdata_i, |
| - input logic [BusWidth/8-1:0] be_i, |
| - output logic [BusWidth-1:0] rdata_o |
| + input logic [BeWidth-1:0] be_i, |
| + output logic [BusWidth-1:0] rdata_o, |
| + output logic err_o |
| ); |
| localparam int unsigned DbgAddressBits = 12; |
| localparam int unsigned HartSelLen = (NrHarts == 1) ? 1 : $clog2(NrHarts); |
| @@ -82,6 +84,11 @@ module dm_mem #( |
| localparam logic [DbgAddressBits-1:0] ResumingAddr = 'h110; |
| localparam logic [DbgAddressBits-1:0] ExceptionAddr = 'h118; |
| |
| + localparam logic [DbgAddressBits-1:0] RomBaseAddr = dm::HaltAddress; |
| + // The size is arbitrarily set to 0x800, so as to make the dm_space exactly 0x900 long. This is |
| + // more than eough to cover the 19 x 64bit = 0x98 bytes currenty allocated in the debug ROM. |
| + localparam logic [DbgAddressBits-1:0] RomEndAddr = dm::HaltAddress + 'h7FF; |
| + |
| logic [dm::ProgBufSize/2-1:0][63:0] progbuf; |
| logic [7:0][63:0] abstract_cmd; |
| logic [NrHarts-1:0] halted_d, halted_q; |
| @@ -231,6 +238,7 @@ module dm_mem #( |
| rdata_d = rdata_q; |
| data_bits = data_i; |
| rdata = '0; |
| + fwd_rom_d = 1'b0; |
| |
| // write data in csr register |
| data_valid_o = 1'b0; |
| @@ -282,7 +290,7 @@ module dm_mem #( |
| end |
| end |
| end |
| - default ; |
| + default: ; |
| endcase |
| |
| // this is a read |
| @@ -339,6 +347,11 @@ module dm_mem #( |
| end |
| rdata_d = rdata; |
| end |
| + // Access has to be forwarded to the ROM. The ROM starts at the HaltAddress of the core |
| + // e.g.: it immediately jumps to the ROM base address. |
| + [RomBaseAddr:RomEndAddr]: begin |
| + fwd_rom_d = 1'b1; |
| + end |
| default: ; |
| endcase |
| end |
| @@ -353,6 +366,54 @@ module dm_mem #( |
| data_o = data_bits; |
| end |
| |
| + // This flags subword writes that are shorter than the defined width of the register. |
| + // Other writes are ignored. |
| + function automatic logic gen_wr_err(logic we, logic [BeWidth-1:0] be, logic [BeWidth-1:0] mask); |
| + return we && (|(~be & mask)); |
| + endfunction |
| + |
| + // Relevant bus error cases |
| + // - access unmapped address |
| + // - write a CSR with unaligned address, e.g. `a_address[1:0] != 0` |
| + // - write a CSR less than its width, e.g. when CSR is 2 bytes wide, only write 1 byte |
| + // - write a RO (read-only) memory |
| + localparam logic[BeWidth-1:0] FullRegMask = {BeWidth{1'b1}}; |
| + localparam logic[BeWidth-1:0] OneBitMask = BeWidth'(1'b1); |
| + localparam logic[BeWidth-1:0] HartSelMask = BeWidth'(2**HartSelLen-1); |
| + logic err_d, err_q; |
| + always_comb begin |
| + err_d = 1'b0; |
| + if (req_i) begin |
| + unique case (addr_i[DbgAddressBits-1:0]) inside |
| + WhereToAddr: err_d = gen_wr_err(we_i, be_i, FullRegMask); |
| + HaltedAddr: err_d = gen_wr_err(we_i, be_i, HartSelMask); |
| + GoingAddr: err_d = gen_wr_err(we_i, be_i, OneBitMask); |
| + ResumingAddr: err_d = gen_wr_err(we_i, be_i, HartSelMask); |
| + ExceptionAddr: err_d = gen_wr_err(we_i, be_i, OneBitMask); |
| + [DataBaseAddr:DataEndAddr]: err_d = gen_wr_err(we_i, be_i, FullRegMask); |
| + [ProgBufBaseAddr:ProgBufEndAddr]: err_d = gen_wr_err(we_i, be_i, FullRegMask); |
| + [AbstractCmdBaseAddr:AbstractCmdEndAddr]: err_d = gen_wr_err(we_i, be_i, FullRegMask); |
| + [FlagsBaseAddr:FlagsEndAddr]: err_d = gen_wr_err(we_i, be_i, FullRegMask); |
| + [RomBaseAddr:RomEndAddr]: err_d = we_i; // Writing ROM area always errors. |
| + default: err_d = 1'b1; |
| + endcase |
| + // Unaligned accesses |
| + if (addr_i[$clog2(BeWidth)-1:0] != '0) begin |
| + err_d = 1'b1; |
| + end |
| + end |
| + end |
| + |
| + always_ff @(posedge clk_i or negedge rst_ni) begin : p_err_reg |
| + if (!rst_ni) begin |
| + err_q <= 1'b0; |
| + end else begin |
| + err_q <= err_d; |
| + end |
| + end |
| + |
| + assign err_o = err_q; |
| + |
| always_comb begin : p_abstract_cmd_rom |
| // this abstract command is currently unsupported |
| unsupported_command = 1'b0; |
| @@ -517,10 +578,6 @@ module dm_mem #( |
| ); |
| end |
| |
| - // ROM starts at the HaltAddress of the core e.g.: it immediately jumps to |
| - // the ROM base address |
| - assign fwd_rom_d = logic'(addr_i[DbgAddressBits-1:0] >= dm::HaltAddress[DbgAddressBits-1:0]); |
| - |
| always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs |
| if (!rst_ni) begin |
| fwd_rom_q <= 1'b0; |
| diff --git a/src/dm_top.sv b/src/dm_top.sv |
| index c21e58d..6188b28 100644 |
| --- a/src/dm_top.sv |
| +++ b/src/dm_top.sv |
| @@ -44,6 +44,7 @@ module dm_top #( |
| input logic [BusWidth/8-1:0] slave_be_i, |
| input logic [BusWidth-1:0] slave_wdata_i, |
| output logic [BusWidth-1:0] slave_rdata_o, |
| + output logic slave_err_o, |
| |
| output logic master_req_o, |
| output logic [BusWidth-1:0] master_add_o, |
| @@ -224,7 +225,8 @@ module dm_top #( |
| .addr_i ( slave_addr_i ), |
| .wdata_i ( slave_wdata_i ), |
| .be_i ( slave_be_i ), |
| - .rdata_o ( slave_rdata_o ) |
| + .rdata_o ( slave_rdata_o ), |
| + .err_o ( slave_err_o ) |
| ); |
| |
| endmodule : dm_top |