Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hw/top_chip/dv/tb/chip_hier_macros.svh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
`define SYSTEM_HIER tb.dut
`define CPU_HIER `SYSTEM_HIER.i_cva6
`define SRAM_MEM_HIER `SYSTEM_HIER.u_axi_sram.u_ram.mem
`define TAG_MEM_HIER `SYSTEM_HIER.u_axi_sram.u_tag_mem_prim.mem
`define TAG_MEM_HIER `SYSTEM_HIER.u_axi_sram.u_tag_ram.mem

// Testbench related
`define SIM_SRAM_IF u_sim_sram.u_sim_sram_if
35 changes: 35 additions & 0 deletions hw/top_chip/dv/top_chip_sim_cfg.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,30 @@
sw_images: ["mailbox_smoketest_cheri_bare:5"]
run_opts: ["+ChipMemSRAM_image_file={run_dir}/mailbox_smoketest_cheri_bare.vmem"]
}
{
name: axi_sram_smoke
uvm_test_seq: top_chip_dv_base_vseq
sw_images: ["axi_sram_smoketest_vanilla_bare:5"]
run_opts: ["+ChipMemSRAM_image_file={run_dir}/axi_sram_smoketest_vanilla_bare.vmem"]
}
{
name: axi_sram_smoke_cheri
uvm_test_seq: top_chip_dv_base_vseq
sw_images: ["axi_sram_smoketest_cheri_bare:5"]
run_opts: ["+ChipMemSRAM_image_file={run_dir}/axi_sram_smoketest_cheri_bare.vmem"]
}
{
name: axi_sram_tag_test
uvm_test_seq: top_chip_dv_base_vseq
sw_images: ["axi_sram_tag_test_vanilla_bare:5"]
run_opts: ["+ChipMemSRAM_image_file={run_dir}/axi_sram_tag_test_vanilla_bare.vmem"]
}
{
name: axi_sram_tag_test_cheri
uvm_test_seq: top_chip_dv_base_vseq
sw_images: ["axi_sram_tag_test_cheri_bare:5"]
run_opts: ["+ChipMemSRAM_image_file={run_dir}/axi_sram_tag_test_cheri_bare.vmem"]
}
]

// List of regressions.
Expand All @@ -212,6 +236,8 @@
"gpio_smoke",
"mailbox_smoke",
"mailbox_smoke_cheri",
"axi_sram_smoke",
"axi_sram_smoke_cheri",
]
}
{
Expand Down Expand Up @@ -286,5 +312,14 @@
"mailbox_smoke_cheri"
]
}
{
name: axi_sram
tests: [
"axi_sram_smoke",
"axi_sram_smoke_cheri",
"axi_sram_tag_test",
"axi_sram_tag_test_cheri"
]
}
]
}
170 changes: 72 additions & 98 deletions hw/top_chip/rtl/axi_sram.sv
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ module axi_sram #(
input top_pkg::axi_req_t axi_req_i,
output top_pkg::axi_resp_t axi_resp_o
);
// Local parameters
localparam int unsigned TagAw = AddrWidth - 1;
localparam int unsigned CapSizeBits = 128; // Size of capability excluding valid bit

// Every tag entry can store AxiDataWidth capability tags
localparam int unsigned TagBitAddrWidth = AddrWidth - $clog2(top_pkg::CapSizeBits / 8);
localparam int unsigned TagAddrWidth = TagBitAddrWidth - $clog2(top_pkg::AxiDataWidth);
localparam int unsigned TagBitWith = $clog2(top_pkg::AxiDataWidth);

// 64-bit memory format signals
logic sram_req;
Expand All @@ -30,115 +32,86 @@ module axi_sram #(
logic [top_pkg::AxiDataWidth-1:0] sram_rdata;
logic [AddrWidth-1:0] sram_word_addr;
logic [top_pkg::AxiDataWidth-1:0] sram_wmask;

// AXI response from SRAM before inserting cap valid bit
top_pkg::axi_resp_t tag_pre_insert_resp;

// Tag memory signals
logic tag_mem_a_req_i;
logic [TagAw-1:0] tag_mem_a_addr_i;
top_pkg::user_t tag_mem_a_wdata_i;
logic tag_mem_b_req_i;
logic [TagAw-1:0] tag_mem_b_addr_i;
top_pkg::user_t tag_mem_b_rdata_o;

// Capability valid bit insertion

// Assume AW data unchanged until W finished
assign tag_mem_a_req_i = axi_resp_o.w_ready && axi_req_i.w_valid && axi_req_i.w.last;
assign tag_mem_a_addr_i = TagAw'((axi_req_i.aw.addr & top_pkg::SRAMMask) >> $clog2(CapSizeBits / 8));
assign tag_mem_a_wdata_i = axi_req_i.w.user;
assign tag_mem_b_req_i = axi_resp_o.ar_ready && axi_req_i.ar_valid;
assign tag_mem_b_addr_i = TagAw'((axi_req_i.ar.addr & top_pkg::SRAMMask) >> $clog2(CapSizeBits / 8));

// Tag memory
prim_ram_2p #(
.Width ( 1 ),
.Depth ( 2 ** TagAw ),
.DataBitsPerMask ( 1 )
) u_tag_mem_prim (
// Write port
.clk_a_i (clk_i),
.a_req_i (tag_mem_a_req_i),
.a_write_i (1'b1),
.a_addr_i (tag_mem_a_addr_i),
.a_wdata_i (tag_mem_a_wdata_i),
.a_wmask_i ('1),
.a_rdata_o ( ),

// Read port
.clk_b_i (clk_i),
.b_req_i (tag_mem_b_req_i),
.b_write_i (1'b0),
.b_addr_i (tag_mem_b_addr_i),
.b_wdata_i ('0),
.b_wmask_i ('1),
.b_rdata_o (tag_mem_b_rdata_o),

.cfg_i ('0),
.cfg_rsp_o ()
);

// Replace only user field with cap valid bit read from tag memory
always_comb begin
axi_resp_o = tag_pre_insert_resp;
axi_resp_o.r.user = tag_mem_b_rdata_o;
end

// Partial read of capability not currently supported
// Not using assert macro since prim_assert.sv selects dummy macros in verilator, and
// trying to override this causes macro redefinition errors

// SRAM R channel response starts 1 cycle after AR channel request (assumed by NoPartialCapRead assertion)
SRAMLatency1Cycle: assert property (
@(posedge clk_i) disable iff (rst_ni === '0) (
$rose(axi_resp_o.r_valid)
|-> $past(axi_resp_o.ar_ready && axi_req_i.ar_valid)
)
) else begin
`ASSERT_ERROR(SRAMLatency1Cycle)
end

// All reads that return valid capability tag must not be partial reads
NoPartialCapRead: assert property (
@(posedge clk_i) disable iff (rst_ni === '0) (
axi_resp_o.ar_ready &&
axi_req_i.ar_valid &&
axi_req_i.ar.len < 1
|=> axi_resp_o.r_valid && axi_resp_o.r.user == '0
)
) else begin
$display("ERROR: Partial capability read not supported!");
`ASSERT_ERROR(NoPartialCapRead)
end
logic [TagBitAddrWidth-1:0] sram_tag_bit_addr;
logic [TagAddrWidth-1:0] sram_tag_word_addr;
logic [TagBitWith-1:0] sram_tag_bit_select;
logic [top_pkg::AxiDataWidth-1:0] sram_tag_wmask;
logic [top_pkg::AxiDataWidth-1:0] sram_tag_wdata;
logic [top_pkg::AxiDataWidth-1:0] sram_tag_rdata;
logic sram_cheri_w_tag;
logic sram_cheri_r_tag;

// AXI to 64-bit mem for SRAM
axi_to_mem #(
axi_to_detailed_mem #(
.axi_req_t ( top_pkg::axi_req_t ),
.axi_resp_t ( top_pkg::axi_resp_t ),
.AddrWidth ( top_pkg::AxiAddrWidth ),
.DataWidth ( top_pkg::AxiDataWidth ),
.IdWidth ( top_pkg::AxiIdWidth ),
.NumBanks ( 1 )
) u_sram_axi_to_mem (
) u_axi_to_detailed_mem (
.clk_i (clk_i),
.rst_ni (rst_ni),

// AXI interface.
.busy_o ( ),
.axi_req_i (axi_req_i),
.axi_resp_o (tag_pre_insert_resp),
.axi_resp_o (axi_resp_o),

// Memory interface.
.mem_req_o (sram_req),
.mem_gnt_i (1'b1),
.mem_addr_o (sram_addr),
.mem_wdata_o (sram_wdata),
.mem_strb_o (sram_be),
.mem_atop_o ( ),
.mem_we_o (sram_we),
.mem_rvalid_i (sram_rvalid),
.mem_rdata_i (sram_rdata)
.mem_req_o (sram_req),
.mem_gnt_i (1'b1),
.mem_addr_o (sram_addr),
.mem_wdata_o (sram_wdata),
.mem_strb_o (sram_be),
.mem_atop_o ( ),
.mem_lock_o ( ),
.mem_id_o ( ),
.mem_user_o ( ),
.mem_cache_o ( ),
.mem_prot_o ( ),
.mem_qos_o ( ),
.mem_region_o ( ),
.mem_err_i ('0),
.mem_exokay_i ('0),
.mem_we_o (sram_we),
.mem_cheri_tag_o (sram_cheri_w_tag),
.mem_rvalid_i (sram_rvalid),
.mem_rdata_i (sram_rdata),
.mem_cheri_tag_i (sram_cheri_r_tag)
);

// Tag bit address calculation
assign sram_tag_bit_addr = TagBitAddrWidth'((sram_addr & top_pkg::SRAMMask) >>
$clog2(top_pkg::CapSizeBits / 8));
assign sram_tag_word_addr = TagAddrWidth'(sram_tag_bit_addr >>
$clog2(top_pkg::AxiDataWidth));
assign sram_tag_bit_select = sram_tag_bit_addr[$clog2(top_pkg::AxiDataWidth)-1:0];

// Shift tag bit to proper position within SRAM word
assign sram_tag_wmask = 1'b1 << sram_tag_bit_select;
assign sram_tag_wdata = { {top_pkg::AxiDataWidth-1{1'b0}}, sram_cheri_w_tag } <<
sram_tag_bit_select;
assign sram_cheri_r_tag = sram_tag_rdata[sram_tag_bit_select];

// Tag RAM
prim_ram_1p #(
.Width ( top_pkg::AxiDataWidth ),
.DataBitsPerMask ( 1 ),
.Depth ( 2 ** TagAddrWidth )
) u_tag_ram (
.clk_i (clk_i),
.rst_ni (rst_ni),

.req_i (sram_req),
.write_i (sram_we),
.addr_i (sram_tag_word_addr),
.wdata_i (sram_tag_wdata),
.wmask_i (sram_tag_wmask),
.rdata_o (sram_tag_rdata),

.cfg_i ('0),
.cfg_rsp_o ( )
);

// Remove base offset and convert byte address to 64-bit word address
Expand All @@ -156,8 +129,8 @@ module axi_sram #(
.Depth ( 2 ** AddrWidth ),
.MemInitFile ( MemInitFile )
) u_ram (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),

.req_i (sram_req),
.write_i (sram_we),
Expand All @@ -175,4 +148,5 @@ module axi_sram #(
if (!rst_ni) sram_rvalid <= '0;
else sram_rvalid <= sram_req; // Generate rvalid strobes even for writes
end

endmodule
Loading