From 11b03190f2c84c9fbfa3d4611b6b3a60ee83ae8d Mon Sep 17 00:00:00 2001 From: Florian Zaruba Date: Fri, 8 Dec 2017 17:01:25 +0100 Subject: [PATCH] Make appropriate AXI size requests --- include/ariane_pkg.sv | 16 +++++++++++++++- include/nbdcache_pkg.sv | 3 ++- src/cache_ctrl.sv | 14 +++++++++++--- src/load_unit.sv | 2 ++ src/lsu.sv | 6 ++++++ src/miss_handler.sv | 36 +++++++++++++++++++++++------------- src/mmu.sv | 1 + src/nbdcache.sv | 2 ++ src/ptw.sv | 2 ++ src/store_buffer.sv | 11 ++++++++--- src/store_unit.sv | 27 +++++++++++++++++---------- 11 files changed, 89 insertions(+), 31 deletions(-) diff --git a/include/ariane_pkg.sv b/include/ariane_pkg.sv index 02ce9e864..630237033 100644 --- a/include/ariane_pkg.sv +++ b/include/ariane_pkg.sv @@ -104,6 +104,20 @@ package ariane_pkg; DIV, DIVU, DIVW, DIVUW, REM, REMU, REMW, REMUW } fu_op; + // ---------------------- + // Extract Bytes from Op + // ---------------------- + // TODO: Add atomics + function automatic logic [1:0] extract_transfer_size (fu_op op); + case (op) + LD, SD: return 2'b11; + LW, LWU, SW: return 2'b10; + LH, LHU, SH: return 2'b01; + LB, SB, LBU: return 2'b00; + default: return 2'b11; + endcase + endfunction + typedef struct packed { logic valid; logic [63:0] vaddr; @@ -393,7 +407,7 @@ package ariane_pkg; // ---------------------- // Arithmetic Functions - // ----------------------s + // ---------------------- function automatic logic [63:0] sext32 (logic [31:0] operand); return {{32{operand[31]}}, operand[31:0]}; endfunction diff --git a/include/nbdcache_pkg.sv b/include/nbdcache_pkg.sv index 6b9c0b263..8f0fa8230 100644 --- a/include/nbdcache_pkg.sv +++ b/include/nbdcache_pkg.sv @@ -38,11 +38,12 @@ package nbdcache_pkg; typedef struct packed { logic valid; - logic bypass; logic [63:0] addr; logic [7:0] be; + logic [1:0] size; logic we; logic [63:0] wdata; + logic bypass; } miss_req_t; typedef struct packed { diff --git a/src/cache_ctrl.sv b/src/cache_ctrl.sv index e59cad365..61d631bf7 100644 --- a/src/cache_ctrl.sv +++ b/src/cache_ctrl.sv @@ -28,6 +28,7 @@ module cache_ctrl #( input logic data_req_i, input logic data_we_i, input logic [7:0] data_be_i, + input logic [1:0] data_size_i, input logic kill_req_i, input logic tag_valid_i, output logic data_gnt_o, @@ -67,6 +68,7 @@ module cache_ctrl #( logic [INDEX_WIDTH-1:0] index; logic [TAG_WIDTH-1:0] tag; logic [7:0] be; + logic [1:0] size; logic we; logic [63:0] wdata; logic bypass; @@ -118,6 +120,7 @@ module cache_ctrl #( mem_req_d.index = address_index_i; mem_req_d.tag = address_tag_i; mem_req_d.be = data_be_i; + mem_req_d.size = data_size_i; mem_req_d.we = data_we_i; mem_req_d.wdata = data_wdata_i; // TODO: Check for non-cache able accesses @@ -164,6 +167,7 @@ module cache_ctrl #( state_d = WAIT_TAG; // switch back to WAIT_TAG mem_req_d.index = address_index_i; mem_req_d.be = data_be_i; + mem_req_d.size = data_size_i; mem_req_d.we = data_we_i; mem_req_d.wdata = data_wdata_i; mem_req_d.tag = address_tag_i; @@ -290,13 +294,16 @@ module cache_ctrl #( miss_req_o.bypass = mem_req_q.bypass; miss_req_o.addr = {mem_req_q.tag, mem_req_q.index}; miss_req_o.be = mem_req_q.be; + miss_req_o.size = mem_req_q.size; miss_req_o.we = mem_req_q.we; miss_req_o.wdata = mem_req_q.wdata; // got a grant so go to valid if (bypass_gnt_i) begin state_d = WAIT_REFILL_VALID; - data_gnt_o = 1'b1; + // if this was a write we still need to give a grant to the store unit + if (mem_req_q.we) + data_gnt_o = 1'b1; end if (miss_gnt_i && !mem_req_q.we) @@ -317,8 +324,9 @@ module cache_ctrl #( if (data_req_i) begin // save index, be and we mem_req_d.index = address_index_i; - mem_req_d.be = data_be_i; - mem_req_d.we = data_we_i; + mem_req_d.be = data_be_i; + mem_req_d.size = data_size_i; + mem_req_d.we = data_we_i; mem_req_d.wdata = data_wdata_i; mem_req_d.tag = address_tag_i; diff --git a/src/load_unit.sv b/src/load_unit.sv index 2b51cb8cb..7d7988639 100644 --- a/src/load_unit.sv +++ b/src/load_unit.sv @@ -48,6 +48,7 @@ module load_unit ( output logic data_req_o, output logic data_we_o, output logic [7:0] data_be_o, + output logic [1:0] data_size_o, output logic kill_req_o, output logic tag_valid_o, input logic data_gnt_i, @@ -92,6 +93,7 @@ module load_unit ( kill_req_o = 1'b0; tag_valid_o = 1'b0; data_be_o = lsu_ctrl_i.be; + data_size_o = extract_transfer_size(lsu_ctrl_i.operator); pop_ld_o = 1'b0; case (CS) diff --git a/src/lsu.sv b/src/lsu.sv index 27765d552..77fdd3417 100644 --- a/src/lsu.sv +++ b/src/lsu.sv @@ -133,6 +133,8 @@ module lsu #( logic [2:0][63:0] data_wdata_i; logic [2:0] data_req_i; logic [2:0] data_we_i; + logic [2:0][1:0] data_size_i; + logic [2:0] kill_req_i; logic [2:0] tag_valid_i; logic [2:0][7:0] data_be_i; @@ -163,6 +165,7 @@ module lsu #( .data_req_i ( data_req_i ), .data_we_i ( data_we_i ), .data_be_i ( data_be_i ), + .data_size_i ( data_size_i ), .kill_req_i ( kill_req_i ), .tag_valid_i ( tag_valid_i ), .data_gnt_o ( data_gnt_o ), @@ -202,6 +205,7 @@ module lsu #( .data_req_o ( data_req_i [0] ), .data_we_o ( data_we_i [0] ), .data_be_o ( data_be_i [0] ), + .data_size_o ( data_size_i [0] ), .kill_req_o ( kill_req_i [0] ), .tag_valid_o ( tag_valid_i [0] ), .data_gnt_i ( data_gnt_o [0] ), @@ -237,6 +241,7 @@ module lsu #( .data_req_o ( data_req_i [2] ), .data_we_o ( data_we_i [2] ), .data_be_o ( data_be_i [2] ), + .data_size_o ( data_size_i [2] ), .kill_req_o ( kill_req_i [2] ), .tag_valid_o ( tag_valid_i [2] ), .data_gnt_i ( data_gnt_o [2] ), @@ -273,6 +278,7 @@ module lsu #( .data_req_o ( data_req_i [1] ), .data_we_o ( data_we_i [1] ), .data_be_o ( data_be_i [1] ), + .data_size_o ( data_size_i [1] ), .kill_req_o ( kill_req_i [1] ), .tag_valid_o ( tag_valid_i [1] ), .data_gnt_i ( data_gnt_o [1] ), diff --git a/src/miss_handler.sv b/src/miss_handler.sv index 61db284a9..19a4fb550 100644 --- a/src/miss_handler.sv +++ b/src/miss_handler.sv @@ -57,6 +57,7 @@ module miss_handler #( logic [NR_PORTS-1:0][63:0] miss_req_wdata; logic [NR_PORTS-1:0] miss_req_we; logic [NR_PORTS-1:0][7:0] miss_req_be; + logic [NR_PORTS-1:0][1:0] miss_req_size; // Cache Line Refill <-> AXI logic req_fsm_miss_valid; @@ -340,17 +341,17 @@ module miss_handler #( // Bypass Arbiter // ---------------------- // Connection Arbiter <-> AXI - logic req_fsm_bypass_valid; - logic [63:0] req_fsm_bypass_addr; - logic [63:0] req_fsm_bypass_wdata; - logic req_fsm_bypass_we; - logic [7:0] req_fsm_bypass_be; - - logic gnt_bypass_fsm; - logic valid_bypass_fsm; - logic [63:0] data_bypass_fsm; - logic [$clog2(NR_PORTS)-1:0] id_fsm_bypass; - logic [AXI_ID_WIDTH-1:0] id_bypass_fsm; + logic req_fsm_bypass_valid; + logic [63:0] req_fsm_bypass_addr; + logic [63:0] req_fsm_bypass_wdata; + logic req_fsm_bypass_we; + logic [7:0] req_fsm_bypass_be; + logic [1:0] req_fsm_bypass_size; + logic gnt_bypass_fsm; + logic valid_bypass_fsm; + logic [63:0] data_bypass_fsm; + logic [$clog2(NR_PORTS)-1:0] id_fsm_bypass; + logic [AXI_ID_WIDTH-1:0] id_bypass_fsm; arbiter #( .NR_PORTS ( NR_PORTS ), @@ -362,6 +363,7 @@ module miss_handler #( .data_wdata_i ( miss_req_wdata ), .data_we_i ( miss_req_we ), .data_be_i ( miss_req_be ), + .data_size_i ( miss_req_size ), .data_gnt_o ( bypass_gnt_o ), .data_rvalid_o ( bypass_valid_o ), .data_rdata_o ( bypass_data_o ), @@ -373,6 +375,7 @@ module miss_handler #( .data_req_o ( req_fsm_bypass_valid ), .data_we_o ( req_fsm_bypass_we ), .data_be_o ( req_fsm_bypass_be ), + .data_size_o ( req_fsm_bypass_size ), .data_gnt_i ( gnt_bypass_fsm ), .data_rvalid_i ( valid_bypass_fsm ), .data_rdata_i ( data_bypass_fsm ), @@ -389,6 +392,7 @@ module miss_handler #( .we_i ( req_fsm_bypass_we ), .wdata_i ( req_fsm_bypass_wdata ), .be_i ( req_fsm_bypass_be ), + .size_i ( req_fsm_bypass_size ), .id_i ( {{{AXI_ID_WIDTH-$clog2(NR_PORTS)}{1'b0}}, id_fsm_bypass} ), .valid_o ( valid_bypass_fsm ), .rdata_o ( data_bypass_fsm ), @@ -412,6 +416,7 @@ module miss_handler #( .we_i ( req_fsm_miss_we ), .wdata_i ( req_fsm_miss_wdata ), .be_i ( req_fsm_miss_be ), + .size_i ( 2'b11 ), .id_i ( '0 ), .valid_o ( valid_miss_fsm ), .rdata_o ( data_miss_fsm ), @@ -445,6 +450,7 @@ module miss_handler #( miss_req_wdata [i] = miss_req.wdata; miss_req_we [i] = miss_req.we; miss_req_be [i] = miss_req.be; + miss_req_size [i] = miss_req.size; end end @@ -474,6 +480,7 @@ module arbiter #( input logic [NR_PORTS-1:0][DATA_WIDTH-1:0] data_wdata_i, input logic [NR_PORTS-1:0] data_we_i, input logic [NR_PORTS-1:0][DATA_WIDTH/8-1:0] data_be_i, + input logic [NR_PORTS-1:0][1:0] data_size_i, output logic [NR_PORTS-1:0] data_gnt_o, output logic [NR_PORTS-1:0] data_rvalid_o, output logic [NR_PORTS-1:0][DATA_WIDTH-1:0] data_rdata_o, @@ -485,6 +492,7 @@ module arbiter #( output logic [DATA_WIDTH-1:0] data_wdata_o, output logic data_we_o, output logic [DATA_WIDTH/8-1:0] data_be_o, + output logic [1:0] data_size_o, input logic data_gnt_i, input logic data_rvalid_i, input logic [DATA_WIDTH-1:0] data_rdata_i @@ -511,6 +519,7 @@ module arbiter #( address_o = address_i[request_index]; data_wdata_o = data_wdata_i[request_index]; data_be_o = data_be_i[request_index]; + data_size_o = data_size_i[request_index]; data_we_o = data_we_i[request_index]; data_gnt_o[request_index] = data_gnt_i; id_o = request_index; @@ -569,6 +578,7 @@ module axi_adapter #( input logic we_i, input logic [(DATA_WIDTH/64)-1:0][63:0] wdata_i, input logic [(DATA_WIDTH/64)-1:0][7:0] be_i, + input logic [1:0] size_i, input logic [AXI_ID_WIDTH-1:0] id_i, // read port output logic valid_o, @@ -603,7 +613,7 @@ module axi_adapter #( axi.aw_prot = 3'b0; axi.aw_region = 4'b0; axi.aw_len = 8'b0; - axi.aw_size = 3'b011; // 8 bytes + axi.aw_size = {1'b0, size_i}; axi.aw_burst = (req_i == SINGLE_REQ) ? 2'b00 : 2'b01; // fixed size for single request and incremental transfer for everything else axi.aw_lock = 1'b0; axi.aw_cache = 4'b0; @@ -618,7 +628,7 @@ module axi_adapter #( axi.ar_prot = 3'b0; axi.ar_region = 4'b0; axi.ar_len = 8'b0; - axi.ar_size = 3'b011; // 8 bytes + axi.ar_size = {1'b0, size_i}; // 8 bytes axi.ar_burst = (req_i == SINGLE_REQ) ? 2'b00 : (CRITICAL_WORD_FIRST ? 2'b10 : 2'b01); // wrapping transfer in case of a critical word first strategy axi.ar_lock = 1'b0; axi.ar_cache = 4'b0; diff --git a/src/mmu.sv b/src/mmu.sv index 72c34acaf..0c6dcd550 100644 --- a/src/mmu.sv +++ b/src/mmu.sv @@ -81,6 +81,7 @@ module mmu #( output logic data_req_o, output logic data_we_o, output logic [7:0] data_be_o, + output logic [1:0] data_size_o, output logic kill_req_o, output logic tag_valid_o, input logic data_gnt_i, diff --git a/src/nbdcache.sv b/src/nbdcache.sv index 6c2731d9a..b1c42d0a3 100644 --- a/src/nbdcache.sv +++ b/src/nbdcache.sv @@ -42,6 +42,7 @@ module nbdcache ( input logic [2:0] data_req_i, input logic [2:0] data_we_i, input logic [2:0][7:0] data_be_i, + input logic [2:0][1:0] data_size_i, input logic [2:0] kill_req_i, input logic [2:0] tag_valid_i, output logic [2:0] data_gnt_o, @@ -111,6 +112,7 @@ module nbdcache ( .data_req_i ( data_req_i [i] ), .data_we_i ( data_we_i [i] ), .data_be_i ( data_be_i [i] ), + .data_size_i ( data_size_i [i] ), .kill_req_i ( kill_req_i [i] ), .tag_valid_i ( tag_valid_i [i] ), .data_gnt_o ( data_gnt_o [i] ), diff --git a/src/ptw.sv b/src/ptw.sv index ac8e82018..068668293 100644 --- a/src/ptw.sv +++ b/src/ptw.sv @@ -44,6 +44,7 @@ module ptw #( output logic data_req_o, output logic data_we_o, output logic [7:0] data_be_o, + output logic [1:0] data_size_o, output logic kill_req_o, output logic tag_valid_o, input logic data_gnt_i, @@ -154,6 +155,7 @@ module ptw #( tag_valid_n = 1'b0; data_req_o = 1'b0; data_be_o = 8'hFF; + data_size_o = 2'b11; data_we_o = 1'b0; ptw_error_o = 1'b0; itlb_update_o = 1'b0; diff --git a/src/store_buffer.sv b/src/store_buffer.sv index 36dca1929..35fd8a291 100644 --- a/src/store_buffer.sv +++ b/src/store_buffer.sv @@ -37,6 +37,7 @@ module store_buffer ( input logic [63:0] paddr_i, // physical address of store which needs to be placed in the queue input logic [63:0] data_i, // data which is placed in the queue input logic [7:0] be_i, // byte enable in + input logic [1:0] data_size_i, // type of request we are making (e.g.: bytes to write) // D$ interface output logic [11:0] address_index_o, @@ -45,6 +46,7 @@ module store_buffer ( output logic data_req_o, output logic data_we_o, output logic [7:0] data_be_o, + output logic [1:0] data_size_o, output logic kill_req_o, output logic tag_valid_o, input logic data_gnt_i, @@ -63,6 +65,7 @@ module store_buffer ( logic [63:0] address; logic [63:0] data; logic [7:0] be; + logic [1:0] data_size; logic valid; // this entry is valid, we need this for checking if the address offset matches } speculative_queue_n [DEPTH_SPEC-1:0], speculative_queue_q [DEPTH_SPEC-1:0], commit_queue_n [DEPTH_COMMIT-1:0], commit_queue_q [DEPTH_COMMIT-1:0]; @@ -94,9 +97,10 @@ module store_buffer ( // LSU interface // we are ready to accept a new entry and the input data is valid if (valid_i) begin - speculative_queue_n[speculative_write_pointer_q].address = paddr_i; - speculative_queue_n[speculative_write_pointer_q].data = data_i; - speculative_queue_n[speculative_write_pointer_q].be = be_i; + speculative_queue_n[speculative_write_pointer_q].address = paddr_i; + speculative_queue_n[speculative_write_pointer_q].data = data_i; + speculative_queue_n[speculative_write_pointer_q].be = be_i; + speculative_queue_n[speculative_write_pointer_q].data_size = data_size_i; speculative_queue_n[speculative_write_pointer_q].valid = 1'b1; // advance the write pointer speculative_write_pointer_n = speculative_write_pointer_q + 1'b1; @@ -137,6 +141,7 @@ module store_buffer ( assign tag_valid_o = 1'b0; assign data_wdata_o = commit_queue_q[commit_read_pointer_q].data; assign data_be_o = commit_queue_q[commit_read_pointer_q].be; + assign data_size_o = commit_queue_q[commit_read_pointer_q].data_size; // we will never kill a request in the store buffer since we already know that the translation is valid // e.g.: a kill request will only be necessary if we are not sure if the requested memory address will result in a TLB fault assign kill_req_o = 1'b0; diff --git a/src/store_unit.sv b/src/store_unit.sv index 5e8f258f0..766ce7885 100644 --- a/src/store_unit.sv +++ b/src/store_unit.sv @@ -51,6 +51,7 @@ module store_unit ( output logic data_req_o, output logic data_we_o, output logic [7:0] data_be_o, + output logic [1:0] data_size_o, output logic kill_req_o, output logic tag_valid_o, input logic data_gnt_i, @@ -67,6 +68,7 @@ module store_unit ( // keep the data and the byte enable for the second cycle (after address translation) logic [63:0] st_data_n, st_data_q; logic [7:0] st_be_n, st_be_q; + logic [1:0] st_data_size_n, st_data_size_q; logic [TRANS_ID_BITS-1:0] trans_id_n, trans_id_q; // output assignments @@ -175,8 +177,10 @@ module store_unit ( // ----------- // re-align the write data to comply with the address offset always_comb begin - st_be_n = lsu_ctrl_i.be; - st_data_n = lsu_ctrl_i.data; + st_be_n = lsu_ctrl_i.be; + st_data_n = lsu_ctrl_i.data; + st_data_size_n = extract_transfer_size(lsu_ctrl_i.operator); + case (lsu_ctrl_i.vaddr[2:0]) 3'b000: st_data_n = lsu_ctrl_i.data; 3'b001: st_data_n = {lsu_ctrl_i.data[55:0], lsu_ctrl_i.data[63:56]}; @@ -196,6 +200,7 @@ module store_unit ( .valid_i ( st_valid ), .data_i ( st_data_q ), .be_i ( st_be_q ), + .data_size_i ( st_data_size_q ), // store buffer out .ready_o ( st_ready ), .* @@ -205,15 +210,17 @@ module store_unit ( // --------------- always_ff @(posedge clk_i or negedge rst_ni) begin if(~rst_ni) begin - CS <= IDLE; - st_be_q <= '0; - st_data_q <= '0; - trans_id_q <= '0; + CS <= IDLE; + st_be_q <= '0; + st_data_q <= '0; + st_data_size_q <= '0; + trans_id_q <= '0; end else begin - CS <= NS; - st_be_q <= st_be_n; - st_data_q <= st_data_n; - trans_id_q <= trans_id_n; + CS <= NS; + st_be_q <= st_be_n; + st_data_q <= st_data_n; + trans_id_q <= trans_id_n; + st_data_size_q <= st_data_size_n; end end