blob: 70f20c56d9ca9e29a092324c975783280436b5e3 [file] [log] [blame]
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