mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-22 21:17:46 -04:00
unified fetch and load-store sub_unit interfaces
Signed-off-by: Eric Matthews <ematthew@sfu.ca>
This commit is contained in:
parent
1f0a43e5f1
commit
90c9dd6343
11 changed files with 205 additions and 291 deletions
|
@ -31,20 +31,16 @@ module avalon_master
|
|||
input logic rst,
|
||||
|
||||
avalon_interface.master m_avalon,
|
||||
output logic[31:0] data_out,
|
||||
|
||||
input data_access_shared_inputs_t ls_inputs,
|
||||
ls_sub_unit_interface.sub_unit ls
|
||||
|
||||
memory_sub_unit_interface.responder ls
|
||||
);
|
||||
//implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (ls.new_request) begin
|
||||
m_avalon.addr <= ls_inputs.addr;
|
||||
m_avalon.byteenable <= ls_inputs.be;
|
||||
m_avalon.writedata <= ls_inputs.data_in;
|
||||
m_avalon.addr <= ls.addr;
|
||||
m_avalon.byteenable <= ls.be;
|
||||
m_avalon.writedata <= ls.data_in;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -68,15 +64,15 @@ module avalon_master
|
|||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (m_avalon.read & ~m_avalon.waitrequest)
|
||||
data_out <= m_avalon.readdata;
|
||||
ls.data_out <= m_avalon.readdata;
|
||||
else
|
||||
data_out <= 0;
|
||||
ls.data_out <= 0;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
m_avalon.read <= 0;
|
||||
else if (ls.new_request & ls_inputs.load)
|
||||
else if (ls.new_request & ls.re)
|
||||
m_avalon.read <= 1;
|
||||
else if (~m_avalon.waitrequest)
|
||||
m_avalon.read <= 0;
|
||||
|
@ -85,7 +81,7 @@ module avalon_master
|
|||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
m_avalon.write <= 0;
|
||||
else if (ls.new_request & ls_inputs.store)
|
||||
else if (ls.new_request & ls.we)
|
||||
m_avalon.write <= 1;
|
||||
else if (~m_avalon.waitrequest)
|
||||
m_avalon.write <= 0;
|
||||
|
|
|
@ -32,10 +32,7 @@ module axi_master
|
|||
|
||||
axi_interface.master m_axi,
|
||||
input logic [2:0] size,
|
||||
output logic[31:0] data_out,
|
||||
|
||||
input data_access_shared_inputs_t ls_inputs,
|
||||
ls_sub_unit_interface.sub_unit ls
|
||||
memory_sub_unit_interface.responder ls
|
||||
|
||||
);
|
||||
logic ready;
|
||||
|
@ -48,12 +45,12 @@ module axi_master
|
|||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (ls.new_request) begin
|
||||
m_axi.araddr <= ls_inputs.addr;
|
||||
m_axi.araddr <= ls.addr;
|
||||
m_axi.arsize <= size;
|
||||
m_axi.awsize <= size;
|
||||
m_axi.awaddr <= ls_inputs.addr;
|
||||
m_axi.wdata <= ls_inputs.data_in;
|
||||
m_axi.wstrb <= ls_inputs.be;
|
||||
m_axi.awaddr <= ls.addr;
|
||||
m_axi.wdata <= ls.data_in;
|
||||
m_axi.wstrb <= ls.be;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -80,27 +77,27 @@ module axi_master
|
|||
//read channel
|
||||
set_clr_reg_with_rst #(.SET_OVER_CLR(1), .WIDTH(1), .RST_VALUE(0)) arvalid_m (
|
||||
.clk, .rst,
|
||||
.set(ls.new_request & ls_inputs.load),
|
||||
.set(ls.new_request & ls.re),
|
||||
.clr(m_axi.arready),
|
||||
.result(m_axi.arvalid)
|
||||
);
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (m_axi.rvalid)
|
||||
data_out <= m_axi.rdata;
|
||||
ls.data_out <= m_axi.rdata;
|
||||
end
|
||||
|
||||
//write channel
|
||||
set_clr_reg_with_rst #(.SET_OVER_CLR(1), .WIDTH(1), .RST_VALUE(0)) awvalid_m (
|
||||
.clk, .rst,
|
||||
.set(ls.new_request & ls_inputs.store),
|
||||
.set(ls.new_request & ls.we),
|
||||
.clr(m_axi.awready),
|
||||
.result(m_axi.awvalid)
|
||||
);
|
||||
|
||||
set_clr_reg_with_rst #(.SET_OVER_CLR(1), .WIDTH(1), .RST_VALUE(0)) wvalid_m (
|
||||
.clk, .rst,
|
||||
.set(ls.new_request & ls_inputs.store),
|
||||
.set(ls.new_request & ls.we),
|
||||
.clr(m_axi.wready),
|
||||
.result(m_axi.wvalid)
|
||||
);
|
||||
|
|
|
@ -39,12 +39,8 @@ module dcache
|
|||
input logic sc_complete,
|
||||
input logic sc_success,
|
||||
input logic clear_reservation,
|
||||
|
||||
input data_access_shared_inputs_t ls_inputs,
|
||||
output logic[31:0] data_out,
|
||||
|
||||
input amo_details_t amo,
|
||||
ls_sub_unit_interface.sub_unit ls
|
||||
memory_sub_unit_interface.responder ls
|
||||
);
|
||||
|
||||
localparam DCACHE_SIZE_IN_WORDS = CONFIG.DCACHE.LINES*CONFIG.DCACHE.LINE_W*CONFIG.DCACHE.WAYS;
|
||||
|
@ -76,7 +72,6 @@ module dcache
|
|||
logic stage2_load;
|
||||
logic stage2_store;
|
||||
logic [3:0] stage2_be;
|
||||
logic [2:0] stage2_fn3;
|
||||
logic [31:0] stage2_data;
|
||||
|
||||
amo_details_t stage2_amo;
|
||||
|
@ -115,12 +110,11 @@ module dcache
|
|||
//2nd Cycle Control Signals
|
||||
always_ff @ (posedge clk) begin
|
||||
if (ls.new_request) begin
|
||||
stage2_addr <= ls_inputs.addr;
|
||||
stage2_be <= ls_inputs.be;
|
||||
stage2_load <= ls_inputs.load;
|
||||
stage2_store <= ls_inputs.store;
|
||||
stage2_fn3 <= ls_inputs.fn3;
|
||||
stage2_data <= ls_inputs.data_in;
|
||||
stage2_addr <= ls.addr;
|
||||
stage2_be <= ls.be;
|
||||
stage2_load <= ls.re;
|
||||
stage2_store <= ls.we;
|
||||
stage2_data <= ls.data_in;
|
||||
stage2_amo <= amo;
|
||||
end
|
||||
end
|
||||
|
@ -130,7 +124,7 @@ module dcache
|
|||
//LR and AMO ops are forced misses (if there is a tag hit they will reuse the same way)
|
||||
//Signal is valid for a single cycle, RAM enables are used to hold outputs in case of pipeline stalls
|
||||
always_ff @ (posedge clk) begin
|
||||
read_hit_allowed <= ls.new_request & ls_inputs.load & dcache_on & ~(amo.is_lr | amo.is_amo);
|
||||
read_hit_allowed <= ls.new_request & ls.re & dcache_on & ~(amo.is_lr | amo.is_amo);
|
||||
read_hit_data_valid <= read_hit_allowed;
|
||||
second_cycle <= ls.new_request;
|
||||
tag_update <= second_cycle & dcache_on & stage2_load & ~tag_hit;//Cache enabled, read miss
|
||||
|
@ -214,7 +208,7 @@ module dcache
|
|||
dcache_tag_banks (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.stage1_addr (ls_inputs.addr),
|
||||
.stage1_addr (ls.addr),
|
||||
.stage2_addr (stage2_addr),
|
||||
.inv_addr ({l1_response.inv_addr, 2'b00}),
|
||||
.update_way (tag_update_way),
|
||||
|
@ -287,7 +281,7 @@ module dcache
|
|||
miss_data <= {31'b0, sc_success};
|
||||
end
|
||||
|
||||
assign data_out = read_hit_data_valid ? dbank_data_out : miss_data;
|
||||
assign ls.data_out = read_hit_data_valid ? dbank_data_out : miss_data;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Pipeline Advancement
|
||||
|
|
|
@ -68,14 +68,15 @@ module fetch
|
|||
localparam NUM_SUB_UNITS = int'(CONFIG.INCLUDE_ILOCAL_MEM) + int'(CONFIG.INCLUDE_ICACHE);
|
||||
localparam NUM_SUB_UNITS_W = (NUM_SUB_UNITS == 1) ? 1 : $clog2(NUM_SUB_UNITS);
|
||||
|
||||
localparam BRAM_ID = 0;
|
||||
localparam LOCAL_MEM_ID = 0;
|
||||
localparam ICACHE_ID = int'(CONFIG.INCLUDE_ILOCAL_MEM);
|
||||
|
||||
localparam NEXT_ID_DEPTH = CONFIG.INCLUDE_ICACHE ? 2 : 1;
|
||||
|
||||
//Subunit signals
|
||||
fetch_sub_unit_interface #(.BASE_ADDR(CONFIG.ILOCAL_MEM_ADDR.L), .UPPER_BOUND(CONFIG.ILOCAL_MEM_ADDR.H)) bram();
|
||||
fetch_sub_unit_interface #(.BASE_ADDR(CONFIG.ICACHE_ADDR.L), .UPPER_BOUND(CONFIG.ICACHE_ADDR.H)) cache();
|
||||
addr_utils_interface #(CONFIG.ILOCAL_MEM_ADDR.L, CONFIG.ILOCAL_MEM_ADDR.H) ilocal_mem_addr_utils ();
|
||||
addr_utils_interface #(CONFIG.ICACHE_ADDR.L, CONFIG.ICACHE_ADDR.H) icache_addr_utils ();
|
||||
memory_sub_unit_interface sub_unit[NUM_SUB_UNITS-1:0]();
|
||||
|
||||
logic [NUM_SUB_UNITS-1:0] sub_unit_address_match;
|
||||
logic [NUM_SUB_UNITS-1:0] unit_ready;
|
||||
|
@ -110,9 +111,6 @@ module fetch
|
|||
|
||||
logic [31:0] translated_address;
|
||||
|
||||
//Cache related
|
||||
logic [31:0] stage2_phys_address;
|
||||
|
||||
genvar i;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
@ -168,11 +166,6 @@ module fetch
|
|||
assign tlb.new_request = tlb.ready & (CONFIG.INCLUDE_S_MODE & tlb_on);
|
||||
assign translated_address = (CONFIG.INCLUDE_S_MODE & tlb_on) ? tlb.physical_address : pc;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (new_mem_request)
|
||||
stage2_phys_address <= translated_address;
|
||||
end
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//Issue Control Signals
|
||||
assign flush_or_rst = (rst | gc.fetch_flush | early_branch_flush);
|
||||
|
@ -211,41 +204,42 @@ module fetch
|
|||
//In the case of a gc.fetch_flush, a request may already be in progress
|
||||
//for any sub unit. That request can either be completed or aborted.
|
||||
//In either case, data_valid must NOT be asserted.
|
||||
generate if (CONFIG.INCLUDE_ILOCAL_MEM) begin : gen_fetch_local_mem
|
||||
assign sub_unit_address_match[BRAM_ID] = bram.address_range_check(translated_address);
|
||||
assign unit_ready[BRAM_ID] = bram.ready;
|
||||
assign unit_data_valid[BRAM_ID] = bram.data_valid;
|
||||
assign bram.new_request = new_mem_request & sub_unit_address_match[BRAM_ID];
|
||||
assign bram.stage1_addr = translated_address;
|
||||
assign bram.stage2_addr = stage2_phys_address;
|
||||
assign bram.flush = gc.fetch_flush;
|
||||
assign unit_data_array[BRAM_ID] = bram.data_out;
|
||||
generate for (i=0; i < NUM_SUB_UNITS; i++) begin : gen_fetch_sources
|
||||
assign sub_unit[i].new_request = new_mem_request & sub_unit_address_match[i] & ~gc.fetch_flush;
|
||||
assign sub_unit[i].addr = translated_address;
|
||||
assign sub_unit[i].re = 1;
|
||||
assign sub_unit[i].we = 0;
|
||||
assign sub_unit[i].be = '0;
|
||||
assign sub_unit[i].data_in = '0;
|
||||
|
||||
ibram i_bram (
|
||||
assign unit_ready[i] = sub_unit[i].ready;
|
||||
assign unit_data_valid[i] = sub_unit[i].data_valid;
|
||||
assign unit_data_array[i] = sub_unit[i].data_out;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate if (CONFIG.INCLUDE_ILOCAL_MEM) begin : gen_fetch_local_mem
|
||||
assign sub_unit_address_match[LOCAL_MEM_ID] = ilocal_mem_addr_utils.address_range_check(translated_address);
|
||||
local_mem_sub_unit i_local_mem (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.fetch_sub (bram),
|
||||
.instruction_bram (instruction_bram)
|
||||
.unit (sub_unit[LOCAL_MEM_ID]),
|
||||
.local_mem (instruction_bram)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate if (CONFIG.INCLUDE_ICACHE) begin : gen_fetch_icache
|
||||
assign sub_unit_address_match[ICACHE_ID] = cache.address_range_check(translated_address);
|
||||
assign unit_ready[ICACHE_ID] = cache.ready;
|
||||
assign unit_data_valid[ICACHE_ID] = cache.data_valid;
|
||||
assign cache.new_request = new_mem_request & sub_unit_address_match[ICACHE_ID];
|
||||
assign cache.stage1_addr = translated_address;
|
||||
assign cache.stage2_addr = stage2_phys_address;
|
||||
assign cache.flush = gc.fetch_flush;
|
||||
assign unit_data_array[ICACHE_ID] = cache.data_out;
|
||||
assign sub_unit_address_match[ICACHE_ID] = icache_addr_utils.address_range_check(translated_address);
|
||||
icache #(.CONFIG(CONFIG))
|
||||
i_cache (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc (gc),
|
||||
.icache_on (icache_on),
|
||||
.l1_request (l1_request),
|
||||
.l1_response (l1_response),
|
||||
.fetch_sub (cache)
|
||||
.fetch_sub (sub_unit[ICACHE_ID])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2017 Eric Matthews, Lesley Shannon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Initial code developed under the supervision of Dr. Lesley Shannon,
|
||||
* Reconfigurable Computing Lab, Simon Fraser University.
|
||||
*
|
||||
* Author(s):
|
||||
* Eric Matthews <ematthew@sfu.ca>
|
||||
*/
|
||||
|
||||
module ibram
|
||||
|
||||
import cva5_config::*;
|
||||
import cva5_types::*;
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
fetch_sub_unit_interface.sub_unit fetch_sub,
|
||||
local_memory_interface.master instruction_bram
|
||||
);
|
||||
|
||||
assign fetch_sub.ready = 1;
|
||||
|
||||
assign instruction_bram.addr = fetch_sub.stage1_addr[31:2];
|
||||
assign instruction_bram.en = fetch_sub.new_request;
|
||||
assign instruction_bram.be = '0;
|
||||
assign instruction_bram.data_in = '0;
|
||||
assign fetch_sub.data_out = instruction_bram.data_out;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst | fetch_sub.flush)
|
||||
fetch_sub.data_valid <= 0;
|
||||
else
|
||||
fetch_sub.data_valid <= fetch_sub.new_request;
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -33,11 +33,12 @@ module icache
|
|||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
input gc_outputs_t gc,
|
||||
input logic icache_on,
|
||||
l1_arbiter_request_interface.master l1_request,
|
||||
l1_arbiter_return_interface.master l1_response,
|
||||
|
||||
fetch_sub_unit_interface.sub_unit fetch_sub
|
||||
memory_sub_unit_interface.responder fetch_sub
|
||||
);
|
||||
|
||||
localparam derived_cache_config_t SCONFIG = get_derived_cache_params(CONFIG, CONFIG.ICACHE, CONFIG.ICACHE_ADDR);
|
||||
|
@ -61,6 +62,7 @@ module icache
|
|||
|
||||
logic miss_data_valid;
|
||||
logic second_cycle;
|
||||
logic [31:0] second_cycle_addr;
|
||||
|
||||
logic idle;
|
||||
logic memory_complete;
|
||||
|
@ -86,7 +88,12 @@ module icache
|
|||
if (rst)
|
||||
second_cycle <= 0;
|
||||
else
|
||||
second_cycle <= fetch_sub.new_request & ~fetch_sub.flush;
|
||||
second_cycle <= fetch_sub.new_request & ~gc.fetch_flush;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (fetch_sub.new_request)
|
||||
second_cycle_addr <= fetch_sub.addr;
|
||||
end
|
||||
|
||||
//As request can be aborted on any cycle, only update tags if memory request is in progress
|
||||
|
@ -114,7 +121,7 @@ module icache
|
|||
logic initiate_l1_request;
|
||||
logic request_r;
|
||||
|
||||
assign l1_request.addr = fetch_sub.stage2_addr;
|
||||
assign l1_request.addr = second_cycle_addr;
|
||||
assign l1_request.data = 0;
|
||||
assign l1_request.rnw = 1;
|
||||
assign l1_request.be = 0;
|
||||
|
@ -124,12 +131,12 @@ module icache
|
|||
|
||||
assign initiate_l1_request = second_cycle & (~tag_hit | ~icache_on);
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst | fetch_sub.flush)
|
||||
if (rst | gc.fetch_flush)
|
||||
request_r <= 0;
|
||||
else
|
||||
request_r <= (initiate_l1_request | request_r) & ~l1_request.ack;
|
||||
end
|
||||
assign l1_request.request = request_r & ~fetch_sub.flush;
|
||||
assign l1_request.request = request_r & ~gc.fetch_flush;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Miss state tracking
|
||||
|
@ -144,7 +151,7 @@ module icache
|
|||
if (rst)
|
||||
miss_aborted_by_flush <= 0;
|
||||
else
|
||||
miss_aborted_by_flush <= (~line_complete) & ((miss_in_progress & fetch_sub.flush) | miss_aborted_by_flush);
|
||||
miss_aborted_by_flush <= (~line_complete) & ((miss_in_progress & gc.fetch_flush) | miss_aborted_by_flush);
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -152,9 +159,9 @@ module icache
|
|||
itag_banks #(.CONFIG(CONFIG), .SCONFIG(SCONFIG))
|
||||
icache_tag_banks (
|
||||
.clk(clk),
|
||||
.rst(rst | fetch_sub.flush), //clears the read_hit_allowed flag
|
||||
.stage1_addr(fetch_sub.stage1_addr),
|
||||
.stage2_addr(fetch_sub.stage2_addr),
|
||||
.rst(rst | gc.fetch_flush), //clears the read_hit_allowed flag
|
||||
.stage1_addr(fetch_sub.addr),
|
||||
.stage2_addr(second_cycle_addr),
|
||||
.update_way(tag_update_way),
|
||||
.update(tag_update),
|
||||
.stage1_adv(fetch_sub.new_request & icache_on),
|
||||
|
@ -168,8 +175,8 @@ module icache
|
|||
generate for (i=0; i < CONFIG.ICACHE.WAYS; i++) begin : idata_bank_gen
|
||||
byte_en_BRAM #(CONFIG.ICACHE.LINES*CONFIG.ICACHE.LINE_W) idata_bank (
|
||||
.clk(clk),
|
||||
.addr_a(fetch_sub.stage1_addr[2 +: SCONFIG.LINE_ADDR_W+SCONFIG.SUB_LINE_ADDR_W]),
|
||||
.addr_b({fetch_sub.stage2_addr[(2+SCONFIG.SUB_LINE_ADDR_W) +: SCONFIG.LINE_ADDR_W], word_count}),
|
||||
.addr_a(fetch_sub.addr[2 +: SCONFIG.LINE_ADDR_W+SCONFIG.SUB_LINE_ADDR_W]),
|
||||
.addr_b({second_cycle_addr[(2+SCONFIG.SUB_LINE_ADDR_W) +: SCONFIG.LINE_ADDR_W], word_count}),
|
||||
.en_a(fetch_sub.new_request),
|
||||
.en_b(tag_update_way[i] & l1_response.data_valid),
|
||||
.be_a('0),
|
||||
|
@ -190,7 +197,7 @@ module icache
|
|||
word_count <= word_count + 1;
|
||||
end
|
||||
|
||||
assign is_target_word = (fetch_sub.stage2_addr[2 +: SCONFIG.SUB_LINE_ADDR_W] == word_count);
|
||||
assign is_target_word = (second_cycle_addr[2 +: SCONFIG.SUB_LINE_ADDR_W] == word_count);
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (l1_response.data_valid & is_target_word)
|
||||
|
@ -200,7 +207,7 @@ module icache
|
|||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst | fetch_sub.flush)
|
||||
if (rst | gc.fetch_flush)
|
||||
miss_data_valid <= 0;
|
||||
else
|
||||
miss_data_valid <= (miss_in_progress & ~miss_aborted_by_flush) & l1_response.data_valid & is_target_word;
|
||||
|
@ -230,9 +237,9 @@ module icache
|
|||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
idle <= 1;
|
||||
else if (fetch_sub.new_request & ~fetch_sub.flush)
|
||||
else if (fetch_sub.new_request & ~gc.fetch_flush)
|
||||
idle <= 0;
|
||||
else if (memory_complete | tag_hit | (second_cycle & fetch_sub.flush) | (~miss_in_progress & fetch_sub.flush)) //read miss OR write through complete
|
||||
else if (memory_complete | tag_hit | (second_cycle & gc.fetch_flush) | (~miss_in_progress & gc.fetch_flush)) //read miss OR write through complete
|
||||
idle <= 1;
|
||||
end
|
||||
|
||||
|
|
|
@ -271,38 +271,46 @@ interface ls_sub_unit_interface #(parameter bit [31:0] BASE_ADDR = 32'h00000000,
|
|||
|
||||
endinterface
|
||||
|
||||
interface addr_utils_interface #(parameter bit [31:0] BASE_ADDR = 32'h00000000, parameter bit [31:0] UPPER_BOUND = 32'hFFFFFFFF);
|
||||
//Based on the lower and upper address ranges,
|
||||
//find the number of bits needed to uniquely identify this memory range.
|
||||
//Assumption: address range is aligned to its size
|
||||
function automatic int unsigned bit_range ();
|
||||
int unsigned i;
|
||||
for(i=0; i < 32; i++) begin
|
||||
if (BASE_ADDR[i] == UPPER_BOUND[i])
|
||||
break;
|
||||
end
|
||||
return (32 - i);
|
||||
endfunction
|
||||
|
||||
interface fetch_sub_unit_interface #(parameter bit [31:0] BASE_ADDR = 32'h00000000, parameter bit [31:0] UPPER_BOUND = 32'hFFFFFFFF);
|
||||
logic [31:0] stage1_addr;
|
||||
logic [31:0] stage2_addr;
|
||||
localparam int unsigned BIT_RANGE = bit_range();
|
||||
|
||||
function address_range_check (input logic[31:0] addr);
|
||||
return (addr[31:32-BIT_RANGE] == BASE_ADDR[31:32-BIT_RANGE]);
|
||||
endfunction
|
||||
endinterface
|
||||
|
||||
interface memory_sub_unit_interface;
|
||||
logic new_request;
|
||||
logic [31:0] addr;
|
||||
logic re;
|
||||
logic we;
|
||||
logic [3:0] be;
|
||||
logic [31:0] data_in;
|
||||
|
||||
logic [31:0] data_out;
|
||||
logic data_valid;
|
||||
logic ready;
|
||||
logic new_request;
|
||||
logic flush;
|
||||
|
||||
//Based on the lower and upper address ranges,
|
||||
//find the number of bits needed to uniquely identify this memory range.
|
||||
//Assumption: address range is aligned to its size
|
||||
function automatic int unsigned bit_range ();
|
||||
int unsigned i;
|
||||
for(i=0; i < 32; i++) begin
|
||||
if (BASE_ADDR[i] == UPPER_BOUND[i])
|
||||
break;
|
||||
end
|
||||
return (32 - i);
|
||||
endfunction
|
||||
|
||||
localparam int unsigned BIT_RANGE = bit_range();
|
||||
|
||||
function address_range_check (input logic[31:0] addr);
|
||||
return (addr[31:32-BIT_RANGE] == BASE_ADDR[31:32-BIT_RANGE]);
|
||||
endfunction
|
||||
|
||||
modport sub_unit (input stage1_addr, stage2_addr, new_request, flush, output data_out, data_valid, ready);
|
||||
modport fetch (output stage1_addr, stage2_addr, new_request, flush, input data_out, data_valid, ready);
|
||||
|
||||
modport responder (
|
||||
input addr, re, we, be, data_in, new_request,
|
||||
output data_out, data_valid, ready
|
||||
);
|
||||
modport controller (
|
||||
input data_out, data_valid, ready,
|
||||
output addr, re, we, be, data_in, new_request
|
||||
);
|
||||
endinterface
|
||||
|
||||
//start and done are cycle cycle pulses
|
||||
|
|
|
@ -73,17 +73,25 @@ module load_store_unit
|
|||
localparam NUM_SUB_UNITS = int'(CONFIG.INCLUDE_DLOCAL_MEM) + int'(CONFIG.INCLUDE_PERIPHERAL_BUS) + int'(CONFIG.INCLUDE_DCACHE);
|
||||
localparam NUM_SUB_UNITS_W = (NUM_SUB_UNITS == 1) ? 1 : $clog2(NUM_SUB_UNITS);
|
||||
|
||||
localparam BRAM_ID = 0;
|
||||
localparam LOCAL_MEM_ID = 0;
|
||||
localparam BUS_ID = int'(CONFIG.INCLUDE_DLOCAL_MEM);
|
||||
localparam DCACHE_ID = int'(CONFIG.INCLUDE_DLOCAL_MEM) + int'(CONFIG.INCLUDE_PERIPHERAL_BUS);
|
||||
|
||||
//Should be equal to pipeline depth of longest load/store subunit
|
||||
localparam ATTRIBUTES_DEPTH = CONFIG.INCLUDE_DCACHE ? 2 : 1;
|
||||
|
||||
//Subunit signals
|
||||
addr_utils_interface #(CONFIG.DLOCAL_MEM_ADDR.L, CONFIG.DLOCAL_MEM_ADDR.H) dlocal_mem_addr_utils ();
|
||||
addr_utils_interface #(CONFIG.PERIPHERAL_BUS_ADDR.L, CONFIG.PERIPHERAL_BUS_ADDR.H) dpbus_addr_utils ();
|
||||
addr_utils_interface #(CONFIG.DCACHE_ADDR.L, CONFIG.DCACHE_ADDR.H) dcache_addr_utils ();
|
||||
memory_sub_unit_interface sub_unit[NUM_SUB_UNITS-1:0]();
|
||||
|
||||
data_access_shared_inputs_t shared_inputs;
|
||||
ls_sub_unit_interface #(.BASE_ADDR(CONFIG.DLOCAL_MEM_ADDR.L), .UPPER_BOUND(CONFIG.DLOCAL_MEM_ADDR.H)) bram();
|
||||
ls_sub_unit_interface #(.BASE_ADDR(CONFIG.PERIPHERAL_BUS_ADDR.L), .UPPER_BOUND(CONFIG.PERIPHERAL_BUS_ADDR.H)) bus();
|
||||
ls_sub_unit_interface #(.BASE_ADDR(CONFIG.DCACHE_ADDR.L), .UPPER_BOUND(CONFIG.DCACHE_ADDR.H)) cache();
|
||||
logic [31:0] unit_data_array [NUM_SUB_UNITS-1:0];
|
||||
logic [NUM_SUB_UNITS-1:0] unit_ready;
|
||||
logic [NUM_SUB_UNITS-1:0] unit_data_valid;
|
||||
logic [NUM_SUB_UNITS-1:0] last_unit;
|
||||
logic [NUM_SUB_UNITS-1:0] current_unit;
|
||||
|
||||
logic units_ready;
|
||||
logic unit_switch_stall;
|
||||
|
@ -97,11 +105,6 @@ module load_store_unit
|
|||
logic [31:0] aligned_load_data;
|
||||
logic [31:0] final_load_data;
|
||||
|
||||
logic [31:0] unit_data_array [NUM_SUB_UNITS-1:0];
|
||||
logic [NUM_SUB_UNITS-1:0] unit_ready;
|
||||
logic [NUM_SUB_UNITS-1:0] unit_data_valid;
|
||||
logic [NUM_SUB_UNITS-1:0] last_unit;
|
||||
logic [NUM_SUB_UNITS-1:0] current_unit;
|
||||
|
||||
logic unaligned_addr;
|
||||
logic load_exception_complete;
|
||||
|
@ -227,7 +230,7 @@ endgenerate
|
|||
//Unit tracking
|
||||
assign current_unit = sub_unit_address_match;
|
||||
|
||||
initial last_unit = BRAM_ID;
|
||||
initial last_unit = LOCAL_MEM_ID;
|
||||
always_ff @ (posedge clk) begin
|
||||
if (load_attributes.push)
|
||||
last_unit <= sub_unit_address_match;
|
||||
|
@ -296,85 +299,73 @@ endgenerate
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Unit Instantiation
|
||||
generate for (genvar i=0; i < NUM_SUB_UNITS; i++) begin : gen_load_store_sources
|
||||
assign sub_unit[i].new_request = issue_request & sub_unit_address_match[i];
|
||||
assign sub_unit[i].addr = shared_inputs.addr;
|
||||
assign sub_unit[i].re = shared_inputs.load;
|
||||
assign sub_unit[i].we = shared_inputs.store;
|
||||
assign sub_unit[i].be = shared_inputs.be;
|
||||
assign sub_unit[i].data_in = shared_inputs.data_in;
|
||||
|
||||
assign unit_ready[i] = sub_unit[i].ready;
|
||||
assign unit_data_valid[i] = sub_unit[i].data_valid;
|
||||
assign unit_data_array[i] = sub_unit[i].data_out;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate if (CONFIG.INCLUDE_DLOCAL_MEM) begin : gen_ls_local_mem
|
||||
assign sub_unit_address_match[BRAM_ID] = bram.address_range_check(shared_inputs.addr);
|
||||
assign bram.new_request = sub_unit_address_match[BRAM_ID] & issue_request;
|
||||
|
||||
assign unit_ready[BRAM_ID] = bram.ready;
|
||||
assign unit_data_valid[BRAM_ID] = bram.data_valid;
|
||||
|
||||
dbram d_bram (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.ls_inputs (shared_inputs),
|
||||
.ls (bram),
|
||||
.data_out (unit_data_array[BRAM_ID]),
|
||||
.data_bram (data_bram)
|
||||
);
|
||||
assign sub_unit_address_match[LOCAL_MEM_ID] = dlocal_mem_addr_utils.address_range_check(shared_inputs.addr);
|
||||
local_mem_sub_unit d_local_mem (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.unit (sub_unit[LOCAL_MEM_ID]),
|
||||
.local_mem (data_bram)
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate if (CONFIG.INCLUDE_PERIPHERAL_BUS) begin : gen_ls_pbus
|
||||
assign sub_unit_address_match[BUS_ID] = bus.address_range_check(shared_inputs.addr);
|
||||
assign bus.new_request = sub_unit_address_match[BUS_ID] & issue_request;
|
||||
|
||||
assign unit_ready[BUS_ID] = bus.ready;
|
||||
assign unit_data_valid[BUS_ID] = bus.data_valid;
|
||||
|
||||
assign sub_unit_address_match[BUS_ID] = dpbus_addr_utils.address_range_check(shared_inputs.addr);
|
||||
if(CONFIG.PERIPHERAL_BUS_TYPE == AXI_BUS)
|
||||
axi_master axi_bus (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.m_axi (m_axi),
|
||||
.size ({1'b0,shared_inputs.fn3[1:0]}),
|
||||
.data_out (unit_data_array[BUS_ID]),
|
||||
.ls_inputs (shared_inputs),
|
||||
.ls (bus)
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.m_axi (m_axi),
|
||||
.size ({1'b0,shared_inputs.fn3[1:0]}),
|
||||
.ls (sub_unit[BUS_ID])
|
||||
); //Lower two bits of fn3 match AXI specification for request size (byte/halfword/word)
|
||||
|
||||
else if (CONFIG.PERIPHERAL_BUS_TYPE == WISHBONE_BUS)
|
||||
wishbone_master wishbone_bus (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.m_wishbone (m_wishbone),
|
||||
.data_out (unit_data_array[BUS_ID]),
|
||||
.ls_inputs (shared_inputs),
|
||||
.ls (bus)
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.m_wishbone (m_wishbone),
|
||||
.ls (sub_unit[BUS_ID])
|
||||
);
|
||||
else if (CONFIG.PERIPHERAL_BUS_TYPE == AVALON_BUS) begin
|
||||
avalon_master avalon_bus (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.ls_inputs (shared_inputs),
|
||||
.m_avalon (m_avalon),
|
||||
.ls (bus),
|
||||
.data_out (unit_data_array[BUS_ID])
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.m_avalon (m_avalon),
|
||||
.ls (sub_unit[BUS_ID])
|
||||
);
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
generate if (CONFIG.INCLUDE_DCACHE) begin : gen_ls_dcache
|
||||
assign sub_unit_address_match[DCACHE_ID] = cache.address_range_check(shared_inputs.addr);
|
||||
assign cache.new_request = sub_unit_address_match[DCACHE_ID] & issue_request;
|
||||
|
||||
assign unit_ready[DCACHE_ID] = cache.ready;
|
||||
assign unit_data_valid[DCACHE_ID] = cache.data_valid;
|
||||
|
||||
assign sub_unit_address_match[DCACHE_ID] = dcache_addr_utils.address_range_check(shared_inputs.addr);
|
||||
dcache # (.CONFIG(CONFIG))
|
||||
data_cache (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.dcache_on (dcache_on),
|
||||
.l1_request (l1_request),
|
||||
.l1_response (l1_response),
|
||||
.sc_complete (sc_complete),
|
||||
.sc_success (sc_success),
|
||||
.clear_reservation (clear_reservation),
|
||||
.ls_inputs (shared_inputs),
|
||||
.data_out (unit_data_array[DCACHE_ID]),
|
||||
.amo (ls_inputs.amo),
|
||||
.ls (cache)
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.dcache_on (dcache_on),
|
||||
.l1_request (l1_request),
|
||||
.l1_response (l1_response),
|
||||
.sc_complete (sc_complete),
|
||||
.sc_success (sc_success),
|
||||
.clear_reservation (clear_reservation),
|
||||
.amo (ls_inputs.amo),
|
||||
.ls (sub_unit[DCACHE_ID])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
|
|
@ -20,36 +20,33 @@
|
|||
* Eric Matthews <ematthew@sfu.ca>
|
||||
*/
|
||||
|
||||
module dbram
|
||||
module local_mem_sub_unit
|
||||
|
||||
import cva5_config::*;
|
||||
import riscv_types::*;
|
||||
import cva5_types::*;
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
input data_access_shared_inputs_t ls_inputs,
|
||||
ls_sub_unit_interface.sub_unit ls,
|
||||
output logic[31:0] data_out,
|
||||
|
||||
local_memory_interface.master data_bram
|
||||
memory_sub_unit_interface.responder unit,
|
||||
local_memory_interface.master local_mem
|
||||
);
|
||||
|
||||
assign ls.ready = 1;
|
||||
assign unit.ready = 1;
|
||||
|
||||
assign data_bram.addr = ls_inputs.addr[31:2];
|
||||
assign data_bram.en = ls.new_request;
|
||||
assign data_bram.be = ls_inputs.be;
|
||||
assign data_bram.data_in = ls_inputs.data_in;
|
||||
assign data_out = data_bram.data_out;
|
||||
assign local_mem.addr = unit.addr[31:2];
|
||||
assign local_mem.en = unit.new_request;
|
||||
assign local_mem.be = unit.be;
|
||||
assign local_mem.data_in = unit.data_in;
|
||||
assign unit.data_out = local_mem.data_out;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
ls.data_valid <= 0;
|
||||
unit.data_valid <= 0;
|
||||
else
|
||||
ls.data_valid <= ls.new_request & ls_inputs.load;
|
||||
unit.data_valid <= unit.new_request & unit.re;
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
|
@ -31,21 +31,17 @@ module wishbone_master
|
|||
input logic rst,
|
||||
|
||||
wishbone_interface.master m_wishbone,
|
||||
output logic[31:0] data_out,
|
||||
|
||||
input data_access_shared_inputs_t ls_inputs,
|
||||
ls_sub_unit_interface.sub_unit ls
|
||||
|
||||
memory_sub_unit_interface.responder ls
|
||||
);
|
||||
//implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (ls.new_request) begin
|
||||
m_wishbone.addr <= ls_inputs.addr;
|
||||
m_wishbone.we <= ls_inputs.store;
|
||||
m_wishbone.sel <= ls_inputs.be;
|
||||
m_wishbone.writedata <= ls_inputs.data_in;
|
||||
m_wishbone.addr <= ls.addr;
|
||||
m_wishbone.we <= ls.we;
|
||||
m_wishbone.sel <= ls.be;
|
||||
m_wishbone.writedata <= ls.data_in;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -67,9 +63,9 @@ module wishbone_master
|
|||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (m_wishbone.ack)
|
||||
data_out <= m_wishbone.readdata;
|
||||
ls.data_out <= m_wishbone.readdata;
|
||||
else
|
||||
data_out <= 0;
|
||||
ls.data_out <= 0;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
|
|
|
@ -14,7 +14,22 @@ core/external_interfaces.sv
|
|||
core/lutrams/lutram_1w_1r.sv
|
||||
core/lutrams/lutram_1w_mr.sv
|
||||
|
||||
core/set_clr_reg_with_rst.sv
|
||||
core/one_hot_occupancy.sv
|
||||
core/binary_occupancy.sv
|
||||
core/one_hot_to_integer.sv
|
||||
core/cycler.sv
|
||||
core/lfsr.sv
|
||||
core/cva5_fifo.sv
|
||||
core/shift_counter.sv
|
||||
core/priority_encoder.sv
|
||||
|
||||
core/toggle_memory.sv
|
||||
core/toggle_memory_set.sv
|
||||
|
||||
core/intel/intel_byte_enable_ram.sv
|
||||
core/xilinx/xilinx_byte_enable_ram.sv
|
||||
core/byte_en_BRAM.sv
|
||||
|
||||
core/csr_unit.sv
|
||||
core/gc_unit.sv
|
||||
|
@ -25,30 +40,13 @@ core/branch_unit.sv
|
|||
core/barrel_shifter.sv
|
||||
core/alu_unit.sv
|
||||
|
||||
core/local_mem_sub_unit.sv
|
||||
core/axi_master.sv
|
||||
core/avalon_master.sv
|
||||
core/wishbone_master.sv
|
||||
|
||||
core/axi_to_arb.sv
|
||||
|
||||
core/one_hot_occupancy.sv
|
||||
core/binary_occupancy.sv
|
||||
core/cva5_fifo.sv
|
||||
core/shift_counter.sv
|
||||
core/priority_encoder.sv
|
||||
|
||||
core/set_clr_reg_with_rst.sv
|
||||
|
||||
core/intel/intel_byte_enable_ram.sv
|
||||
core/xilinx/xilinx_byte_enable_ram.sv
|
||||
core/byte_en_BRAM.sv
|
||||
|
||||
core/one_hot_to_integer.sv
|
||||
|
||||
core/cycler.sv
|
||||
|
||||
core/tag_bank.sv
|
||||
core/dbram.sv
|
||||
core/ddata_bank.sv
|
||||
core/dtag_banks.sv
|
||||
core/amo_alu.sv
|
||||
|
@ -59,17 +57,9 @@ core/store_queue.sv
|
|||
core/load_store_queue.sv
|
||||
core/load_store_unit.sv
|
||||
|
||||
|
||||
core/ibram.sv
|
||||
core/itag_banks.sv
|
||||
core/icache.sv
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
core/clz.sv
|
||||
core/div_core.sv
|
||||
core/div_unit.sv
|
||||
|
@ -79,10 +69,6 @@ core/mmu.sv
|
|||
|
||||
core/mul_unit.sv
|
||||
|
||||
|
||||
|
||||
|
||||
core/l1_arbiter.sv
|
||||
core/ras.sv
|
||||
core/branch_predictor_ram.sv
|
||||
core/branch_predictor.sv
|
||||
|
@ -97,16 +83,15 @@ core/register_bank.sv
|
|||
core/register_file.sv
|
||||
core/writeback.sv
|
||||
|
||||
core/placer_randomizer.sv
|
||||
|
||||
l2_arbiter/l2_fifo.sv
|
||||
l2_arbiter/l2_reservation_logic.sv
|
||||
l2_arbiter/l2_round_robin.sv
|
||||
l2_arbiter/l2_arbiter.sv
|
||||
core/axi_to_arb.sv
|
||||
|
||||
core/toggle_memory.sv
|
||||
core/toggle_memory_set.sv
|
||||
core/instruction_metadata_and_id_management.sv
|
||||
|
||||
core/l1_arbiter.sv
|
||||
|
||||
core/cva5.sv
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue