Add missing 1port SBA change, and update example soc and bus compliance tb to reflect

This commit is contained in:
Luke Wren 2022-07-03 17:57:03 +01:00
parent 9e15cd3485
commit b1225c386c
3 changed files with 126 additions and 20 deletions

View File

@ -1,5 +1,5 @@
/*****************************************************************************\
| Copyright (C) 2021 Luke Wren |
| Copyright (C) 2021-2022 Luke Wren |
| SPDX-License-Identifier: Apache-2.0 |
\*****************************************************************************/
@ -141,8 +141,18 @@ wire [N_HARTS-1:0] hart_instr_data_rdy;
wire [N_HARTS-1:0] hart_instr_caught_exception;
wire [N_HARTS-1:0] hart_instr_caught_ebreak;
wire [31:0] sbus_addr;
wire sbus_write;
wire [1:0] sbus_size;
wire sbus_vld;
wire sbus_rdy;
wire sbus_err;
wire [31:0] sbus_wdata;
wire [31:0] sbus_rdata;
hazard3_dm #(
.N_HARTS (N_HARTS),
.HAVE_SBA (0),
.NEXT_DM_ADDR (0)
) dm (
.clk (clk),
@ -176,7 +186,16 @@ hazard3_dm #(
.hart_instr_data_vld (hart_instr_data_vld),
.hart_instr_data_rdy (hart_instr_data_rdy),
.hart_instr_caught_exception (hart_instr_caught_exception),
.hart_instr_caught_ebreak (hart_instr_caught_ebreak)
.hart_instr_caught_ebreak (hart_instr_caught_ebreak),
.sbus_addr (sbus_addr),
.sbus_write (sbus_write),
.sbus_size (sbus_size),
.sbus_vld (sbus_vld),
.sbus_rdy (sbus_rdy),
.sbus_err (sbus_err),
.sbus_wdata (sbus_wdata),
.sbus_rdata (sbus_rdata)
);
@ -279,6 +298,15 @@ hazard3_cpu_1port #(
.dbg_instr_caught_exception (hart_instr_caught_exception),
.dbg_instr_caught_ebreak (hart_instr_caught_ebreak),
.dbg_sbus_addr (sbus_addr),
.dbg_sbus_write (sbus_write),
.dbg_sbus_size (sbus_size),
.dbg_sbus_vld (sbus_vld),
.dbg_sbus_rdy (sbus_rdy),
.dbg_sbus_err (sbus_err),
.dbg_sbus_wdata (sbus_wdata),
.dbg_sbus_rdata (sbus_rdata),
.irq (uart_irq),
.soft_irq (1'b0),

View File

@ -52,6 +52,16 @@ module hazard3_cpu_1port #(
output wire dbg_instr_caught_exception,
output wire dbg_instr_caught_ebreak,
// Optional debug system bus access patch-through
input wire [W_ADDR-1:0] dbg_sbus_addr,
input wire dbg_sbus_write,
input wire [1:0] dbg_sbus_size,
input wire dbg_sbus_vld,
output wire dbg_sbus_rdy,
output wire dbg_sbus_err,
input wire [W_DATA-1:0] dbg_sbus_wdata,
output wire [W_DATA-1:0] dbg_sbus_rdata,
// Level-sensitive interrupt sources
input wire [NUM_IRQ-1:0] irq, // -> mip.meip
input wire soft_irq, // -> mip.msip
@ -137,6 +147,8 @@ hazard3_core #(
.dbg_instr_caught_exception (dbg_instr_caught_exception),
.dbg_instr_caught_ebreak (dbg_instr_caught_ebreak),
.irq (irq),
.soft_irq (soft_irq),
.timer_irq (timer_irq)
@ -147,28 +159,42 @@ hazard3_core #(
wire bus_gnt_i;
wire bus_gnt_d;
wire bus_gnt_s;
reg bus_hold_aph;
reg [1:0] bus_gnt_id_prev;
reg [2:0] bus_gnt_ids_prev;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
bus_hold_aph <= 1'b0;
bus_gnt_id_prev <= 2'h0;
bus_gnt_id_prev <= 3'h0;
end else begin
bus_hold_aph <= ahblm_htrans[1] && !ahblm_hready && !ahblm_hresp;
bus_gnt_id_prev <= {bus_gnt_i, bus_gnt_d};
bus_gnt_id_prev <= {bus_gnt_i, bus_gnt_d, bus_gnt_s};
end
end
assign {bus_gnt_i, bus_gnt_d} =
bus_hold_aph ? bus_gnt_id_prev :
core_aph_panic_i ? 2'b10 :
core_aph_req_d ? 2'b01 :
core_aph_req_i ? 2'b10 :
2'b00 ;
// Debug SBA access is lower priority than load/store, but higher than
// instruction fetch. This isn't ideal, but in a tight loop the core may be
// performing an instruction fetch or load/store on every single cycle, and
// this is a simple way to guarantee eventual success of debugger accesses. A
// more complex way would be to add a "panic timer" to boost a stalled sbus
// access over an instruction fetch.
// Keep track of whether instr/data access is active in AHB dataphase.
// Note that, often, the sbus will be disconnected: it doesn't provide any
// increase in debugger bus throughput compared with the program buffer and
// autoexec. It's useful for "minimally intrusive" debug bus access(i.e. less
// intrusive than halting the core and resuming it) e.g. for Segger RTT.
reg bus_active_dph_s;
assign {bus_gnt_i, bus_gnt_d, bus_gnt_s} =
bus_hold_aph ? bus_gnt_id_prev :
core_aph_panic_i ? 3'b100 :
core_aph_req_d ? 3'b010 :
dbg_sbus_vld && !bus_active_dph_s ? 3'b001 :
core_aph_req_i ? 3'b100 :
3'b000 ;
reg bus_active_dph_i;
reg bus_active_dph_d;
@ -176,9 +202,11 @@ always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
bus_active_dph_i <= 1'b0;
bus_active_dph_d <= 1'b0;
bus_active_dph_s <= 1'b0;
end else if (ahblm_hready) begin
bus_active_dph_i <= bus_gnt_i;
bus_active_dph_d <= bus_gnt_d;
bus_active_dph_s <= bus_gnt_s;
end
end
@ -200,11 +228,24 @@ wire [3:0] hprot_instr = {
1'b0 // Instruction access
};
wire [3:0] hprot_sbus = {
2'b00, // Noncacheable/nonbufferable
1'b1, // Always privileged
1'b1 // Data access
};
assign ahblm_hburst = 3'b000; // HBURST_SINGLE
assign ahblm_hmastlock = 1'b0;
always @ (*) begin
if (bus_gnt_d) begin
if (bus_gnt_s) begin
ahblm_htrans = HTRANS_NSEQ;
ahblm_hexcl = 1'b0;
ahblm_haddr = dbg_sbus_addr;
ahblm_hsize = {1'b0, dbg_sbus_size};
ahblm_hwrite = dbg_sbus_write;
ahblm_hprot = hprot_sbus;
end else if (bus_gnt_d) begin
ahblm_htrans = HTRANS_NSEQ;
ahblm_hexcl = core_aph_excl_d;
ahblm_haddr = core_haddr_d;
@ -228,27 +269,32 @@ always @ (*) begin
end
end
assign ahblm_hwdata = bus_active_dph_s ? dbg_sbus_wdata : core_wdata_d;
// ----------------------------------------------------------------------------
// Response routing
// Data buses directly connected
assign core_rdata_d = ahblm_hrdata;
assign core_rdata_i = ahblm_hrdata;
assign ahblm_hwdata = core_wdata_d;
assign core_rdata_d = ahblm_hrdata;
assign core_rdata_i = ahblm_hrdata;
assign dbg_sbus_rdata = ahblm_hrdata;
// Handhshake based on grant and bus stall
assign core_aph_ready_i = ahblm_hready && bus_gnt_i;
assign core_dph_ready_i = ahblm_hready && bus_active_dph_i;
assign core_dph_ready_i = bus_active_dph_i && ahblm_hready;
assign core_dph_err_i = bus_active_dph_i && ahblm_hresp;
// D-side errors are reported even when not ready, so that the core can make
// use of the two-phase error response to cleanly squash a second load/store
// chasing the faulting one down the pipeline.
assign core_aph_ready_d = ahblm_hready && bus_gnt_d;
assign core_dph_ready_d = ahblm_hready && bus_active_dph_d;
assign core_dph_err_d = bus_active_dph_d && ahblm_hresp;
assign core_aph_ready_d = ahblm_hready && bus_gnt_d;
assign core_dph_ready_d = bus_active_dph_d && ahblm_hready;
assign core_dph_err_d = bus_active_dph_d && ahblm_hresp;
assign core_dph_exokay_d = bus_active_dph_d && ahblm_hexokay;
assign dbg_sbus_err = bus_active_dph_s && ahblm_hresp;
assign dbg_sbus_rdy = bus_active_dph_s && ahblm_hready;
endmodule
`default_nettype wire

View File

@ -41,6 +41,15 @@ localparam W_DATA = 32;
(* keep *) wire dbg_instr_caught_exception;
(* keep *) wire dbg_instr_caught_ebreak;
(*keep*) wire [31:0] dbg_sbus_addr;
(*keep*) wire dbg_sbus_write;
(*keep*) wire [1:0] dbg_sbus_size;
(*keep*) wire dbg_sbus_vld;
(*keep*) wire dbg_sbus_rdy;
(*keep*) wire dbg_sbus_err;
(*keep*) wire [31:0] dbg_sbus_wdata;
(*keep*) wire [31:0] dbg_sbus_rdata;
(* keep *) wire [31:0] irq;
(* keep *) wire soft_irq;
(* keep *) wire timer_irq;
@ -77,6 +86,15 @@ hazard3_cpu_1port dut (
.dbg_instr_caught_exception (dbg_instr_caught_exception),
.dbg_instr_caught_ebreak (dbg_instr_caught_ebreak),
.dbg_sbus_addr (dbg_sbus_addr),
.dbg_sbus_write (dbg_sbus_write),
.dbg_sbus_size (dbg_sbus_size),
.dbg_sbus_vld (dbg_sbus_vld),
.dbg_sbus_rdy (dbg_sbus_rdy),
.dbg_sbus_err (dbg_sbus_err),
.dbg_sbus_wdata (dbg_sbus_wdata),
.dbg_sbus_rdata (dbg_sbus_rdata),
.irq (irq),
.soft_irq (soft_irq),
.timer_irq (timer_irq)
@ -129,4 +147,18 @@ ahbl_master_assertions d_assertions (
.src_hrdata (ahblm_hrdata)
);
sbus_assumptions sbus_assumptions (
.clk (clk),
.rst_n (rst_n),
.dbg_sbus_addr (dbg_sbus_addr),
.dbg_sbus_write (dbg_sbus_write),
.dbg_sbus_size (dbg_sbus_size),
.dbg_sbus_vld (dbg_sbus_vld),
.dbg_sbus_rdy (dbg_sbus_rdy),
.dbg_sbus_err (dbg_sbus_err),
.dbg_sbus_wdata (dbg_sbus_wdata),
.dbg_sbus_rdata (dbg_sbus_rdata)
);
endmodule