diff --git a/rtl/core/pipeline/fetch.sv b/rtl/core/pipeline/fetch.sv index 9e95768d..743a82a1 100644 --- a/rtl/core/pipeline/fetch.sv +++ b/rtl/core/pipeline/fetch.sv @@ -71,6 +71,11 @@ logic [`XLEN-1:0] instr_word; logic if_stall; logic pc_misaligned; +//////////////////////////////////////////////////////////////// +logic [`XLEN-1:0] pc_new_jal; +logic [`XLEN-1:0] jal_imm; +logic is_jal; + assign icache2if = icache2if_i; assign mmu2if = mmu2if_i; @@ -119,11 +124,6 @@ always_comb begin endcase end -//////////////////////////////////////////////////////////////// -logic [`XLEN-1:0] pc_new_jal; -logic [`XLEN-1:0] jal_imm; -logic is_jal; - assign jal_imm = {{12{instr_word[31]}}, instr_word[19:12], instr_word[20], instr_word[30:21], 1'b0}; //assign pc_new_jal = pc_ff + jal_imm; diff --git a/rtl/defines/cache_defs.svh b/rtl/defines/cache_defs.svh index 145aa13a..be37afc7 100644 --- a/rtl/defines/cache_defs.svh +++ b/rtl/defines/cache_defs.svh @@ -90,22 +90,6 @@ typedef enum logic [2:0] { DCACHE_FLUSH_DONE } type_dcache_states_e; -// Bus interface from LSU to dcache -typedef struct packed { - logic [DCACHE_ADDR_WIDTH-1:0] addr; - logic [DCACHE_DATA_WIDTH-1:0] w_data; - logic [3:0] sel_byte; - logic w_en; - logic req; -} type_lsummu2dcache_s; - -// Bus interface from Icache to IF -typedef struct packed { - logic [DCACHE_DATA_WIDTH-1:0] r_data; - logic ack; -} type_dcache2lsummu_s; - - typedef struct packed { logic [DCACHE_ADDR_WIDTH-1:0] addr; logic [DCACHE_LINE_WIDTH-1:0] w_data; diff --git a/rtl/defines/store_buffer_defs.svh b/rtl/defines/store_buffer_defs.svh new file mode 100644 index 00000000..9373ef92 --- /dev/null +++ b/rtl/defines/store_buffer_defs.svh @@ -0,0 +1,48 @@ +// Copyright 2023 University of Engineering and Technology Lahore. +// Licensed under the Apache License, Version 2.0, see LICENSE file for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Description: +// +// Author: Fazail Ali Butt, UET Lahore +// Date: 30.11.2024 + +`ifndef STORE_BUFFER_DEFS +`define STORE_BUFFER_DEFS + +`include "pcore_interface_defs.svh" +`include "mmu_defs.svh" +`include "cache_defs.svh" + +//=========================== Store Buffer related definitions ===========================// +parameter STORE_BUFFER_WIDTH = 4; +parameter BLEN = STORE_BUFFER_WIDTH; + +typedef struct packed { + logic [DCACHE_ADDR_WIDTH-1:0] addr; + logic [DCACHE_DATA_WIDTH-1:0] w_data; + logic [3:0] sel_byte; + logic w_en; + logic req; +} type_stb2dcache_s; + +typedef struct packed { + logic [DCACHE_DATA_WIDTH-1:0] r_data; + logic ack; +} type_dcache2stb_s; + +// Bus interface from LSU to STB +typedef struct packed { + logic [DCACHE_ADDR_WIDTH-1:0] addr; + logic [DCACHE_DATA_WIDTH-1:0] w_data; + logic [3:0] sel_byte; + logic w_en; + logic req; +} type_lsummu2stb_s; + +typedef struct packed { + logic ack; + logic [DCACHE_DATA_WIDTH-1:0] r_data; +} type_stb2lsummu_s; + +`endif diff --git a/rtl/memory/main_mem.sv b/rtl/memory/main_mem.sv index f94c1d4b..1dbdfbfe 100644 --- a/rtl/memory/main_mem.sv +++ b/rtl/memory/main_mem.sv @@ -56,7 +56,8 @@ end initial begin // Reading the contents of example imem.txt file to memory variable - $readmemh("imem.txt", dualport_memory); + $readmemh("imem.txt", dualport_memory); + //$readmemh("sdk/example-uart/build/pcore.hex", dualport_memory); end //`endif `else diff --git a/rtl/memory/mem_top.sv b/rtl/memory/mem_top.sv index 63d346a9..52316d72 100644 --- a/rtl/memory/mem_top.sv +++ b/rtl/memory/mem_top.sv @@ -13,10 +13,12 @@ `include "../defines/mmu_defs.svh" `include "../defines/cache_defs.svh" `include "../defines/ddr_defs.svh" +`include "../defines/store_buffer_defs.svh" `else `include "mmu_defs.svh" `include "cache_defs.svh" `include "ddr_defs.svh" +`include "store_buffer_defs.svh" `endif module mem_top ( @@ -65,8 +67,8 @@ type_dbus2peri_s dbus2peri; type_peri2dbus_s dcache2dbus; // Signals from data memory type_peri2dbus_s bmem2dbus; -type_lsummu2dcache_s lsummu2dcache; -type_dcache2lsummu_s dcache2lsummu; +//type_lsummu2dcache_s lsummu2dcache; +//type_dcache2lsummu_s dcache2lsummu; type_mem2dcache_s mem2dcache; type_dcache2mem_s dcache2mem; @@ -88,6 +90,21 @@ logic dcache2mem_kill; logic timeout_flag; logic [5:0] timeout_next, timeout_ff; +// Store Buffer related signals +type_stb2dcache_s stb2dcache; +type_dcache2stb_s dcache2stb; + +type_lsummu2stb_s lsummu2stb; +type_stb2lsummu_s stb2lsummu; +logic stb_dmem_sel_o; +logic stb2dcache_empty; + +logic mmu2stb_sel, dbus2stb_sel, dbus_sel; +logic stb2dbus_sel, stb2mmu_sel; +logic mmu_sel; + +assign mmu_sel = ~dmem_sel & mmu2dcache.r_req & ~mmu2dcache.flush_req; + // Signal assignments assign mmu2dcache = mmu2dcache_i; assign dmem_sel = dmem_sel_i; @@ -140,8 +157,8 @@ always_ff @(posedge clk) begin end end -always_comb begin -lsummu2dcache = '0; +/*always_comb begin +lsummu2stb = '0; dcache2dbus = '0; dcache2mmu = '0; cache_arbiter_state_next = cache_arbiter_state_ff; @@ -151,34 +168,35 @@ dcache_kill_req = '0; DCACHE_ARBITER_IDLE: begin if (dmem_sel) begin - lsummu2dcache.addr = dbus2peri.addr; - lsummu2dcache.w_data = dbus2peri.w_data; - lsummu2dcache.sel_byte = dbus2peri.sel_byte; - lsummu2dcache.w_en = dbus2peri.w_en; - lsummu2dcache.req = dbus2peri.req; + lsummu2stb.addr = dbus2peri.addr; + lsummu2stb.w_data = dbus2peri.w_data; + lsummu2stb.sel_byte = dbus2peri.sel_byte; + lsummu2stb.w_en = dbus2peri.w_en; + lsummu2stb.req = dbus2peri.req; + cache_arbiter_state_next = DCACHE_ARBITER_LSU; end else if (~dmem_sel & mmu2dcache.r_req & ~mmu2dcache.flush_req) begin - lsummu2dcache.addr = mmu2dcache.paddr; - lsummu2dcache.w_data = '0; - lsummu2dcache.sel_byte = '0; - lsummu2dcache.w_en = '0; - lsummu2dcache.req = 1'b1; + lsummu2stb.addr = mmu2dcache.paddr; + lsummu2stb.w_data = '0; + lsummu2stb.sel_byte = '0; + lsummu2stb.w_en = '0; + lsummu2stb.req = 1'b1; cache_arbiter_state_next = DCACHE_ARBITER_MMU; end end DCACHE_ARBITER_LSU: begin - if (dcache2lsummu.ack) begin - dcache2dbus.r_data = dcache2lsummu.r_data; + if (stb2lsummu.ack) begin + dcache2dbus.r_data = stb2lsummu.r_data; dcache2dbus.ack = 1'b1; cache_arbiter_state_next = DCACHE_ARBITER_IDLE; end else begin cache_arbiter_state_next = DCACHE_ARBITER_LSU; - lsummu2dcache.addr = dbus2peri.addr; - lsummu2dcache.w_data = dbus2peri.w_data; - lsummu2dcache.sel_byte = dbus2peri.sel_byte; - lsummu2dcache.w_en = dbus2peri.w_en; - lsummu2dcache.req = dbus2peri.req; + lsummu2stb.addr = dbus2peri.addr; + lsummu2stb.w_data = dbus2peri.w_data; + lsummu2stb.sel_byte = dbus2peri.sel_byte; + lsummu2stb.w_en = dbus2peri.w_en; + lsummu2stb.req = dbus2peri.req; end end @@ -187,41 +205,150 @@ dcache_kill_req = '0; if (mmu2dcache.flush_req) begin cache_arbiter_state_next = DCACHE_ARBITER_IDLE; dcache_kill_req = 1'b1; - end else if (dcache2lsummu.ack) begin - dcache2mmu.r_data = dcache2lsummu.r_data; + end else if (stb2lsummu.ack) begin + dcache2mmu.r_data = stb2lsummu.r_data; dcache2mmu.r_valid = 1'b1; cache_arbiter_state_next = DCACHE_ARBITER_IDLE; end else begin cache_arbiter_state_next = DCACHE_ARBITER_MMU; - lsummu2dcache.addr = mmu2dcache.paddr; - lsummu2dcache.w_data = '0; - lsummu2dcache.sel_byte = '0; - lsummu2dcache.w_en = '0; - lsummu2dcache.req = 1'b1; + lsummu2stb.addr = mmu2dcache.paddr; + lsummu2stb.w_data = '0; + lsummu2stb.sel_byte = '0; + lsummu2stb.w_en = '0; + lsummu2stb.req = 1'b1; end end default: begin end endcase +end*/ + +always_comb begin +mmu2stb_sel = '0; +dbus2stb_sel = '0; +dbus_sel = '0; +stb2dbus_sel = '0; +stb2mmu_sel = '0; + case (cache_arbiter_state_ff) + + DCACHE_ARBITER_IDLE: begin + if (dmem_sel) begin + dbus2stb_sel = 1'b1; + dbus_sel = 1'b1; + cache_arbiter_state_next = DCACHE_ARBITER_LSU; + end else if (mmu_sel) begin + mmu2stb_sel = 1'b1; + cache_arbiter_state_next = DCACHE_ARBITER_MMU; + end + end + + DCACHE_ARBITER_LSU: begin + if (stb2lsummu.ack) begin + stb2dbus_sel = 1'b1; + cache_arbiter_state_next = DCACHE_ARBITER_IDLE; + end else begin + cache_arbiter_state_next = DCACHE_ARBITER_LSU; + dbus2stb_sel = 1'b1; + dbus_sel = 1'b1; + end + + end + + DCACHE_ARBITER_MMU: begin + if (mmu2dcache.flush_req) begin + cache_arbiter_state_next = DCACHE_ARBITER_IDLE; + dcache_kill_req = 1'b1; + end else if (stb2lsummu.ack) begin + stb2mmu_sel = 1'b1; + cache_arbiter_state_next = DCACHE_ARBITER_IDLE; + end else begin + cache_arbiter_state_next = DCACHE_ARBITER_MMU; + mmu2stb_sel = 1'b1; + end + end + + default: begin + cache_arbiter_state_next = DCACHE_ARBITER_IDLE; + end + endcase end +always_comb begin // lsummu2stb + lsummu2stb = '0; + if (dbus_sel & dbus2stb_sel) begin + lsummu2stb.addr = dbus2peri.addr; + lsummu2stb.w_data = dbus2peri.w_data; + lsummu2stb.sel_byte = dbus2peri.sel_byte; + lsummu2stb.w_en = dbus2peri.w_en; + lsummu2stb.req = dbus2peri.req; + end else if (mmu2stb_sel) begin + lsummu2stb.addr = mmu2dcache.paddr; + lsummu2stb.w_data = '0; + lsummu2stb.sel_byte = '0; + lsummu2stb.w_en = '0; + lsummu2stb.req = 1'b1; + end +end // lsummu2stb + +always_comb begin // stb2dbus + dcache2dbus.ack = '0; + if (stb2dbus_sel) begin + dcache2dbus.r_data = stb2lsummu.r_data; + dcache2dbus.ack = 1'b1; + end +end // stb2dbus + +always_comb begin // stb2mmu + dcache2mmu = '0; + if (stb2mmu_sel) begin + dcache2mmu.r_data = stb2lsummu.r_data; + dcache2mmu.r_valid = 1'b1; + end +end // stb2mmu + +//========================== Store Buffer top module ===========================// +store_buffer_top store_buffer_top_module ( + .clk (clk), + .rst_n (rst_n), + +// LSU/MMU --> store_buffer_top + .lsummu2stb_i (lsummu2stb), + .dmem_sel_i (dmem_sel), + +// store_buffer_top --> LSU/MMU + .stb2lsummu_o (stb2lsummu), + +// store_buffer_top --> dcache + .stb2dcache_o (stb2dcache), + .stb2dcache_empty (stb2dcache_empty), + .dmem_sel_o (stb_dmem_sel_o), + +// dcache --> store_buffer_top + .dcache2stb_i (dcache2stb) +); + //========================== Data cache top module ===========================// wb_dcache_top wb_dcache_top_module( .clk (clk), .rst_n (rst_n), // LSU/MMU to data cache interface - .lsummu2dcache_i (lsummu2dcache), // lsummu2dmem - .dcache2lsummu_o (dcache2lsummu), // dmem2lsummu + .stb2dcache_i (stb2dcache), // stb2dcache + + .dcache2stb_o (dcache2stb), // dcache2stb + + .stb2dcache_empty (stb2dcache_empty), + .dcache_kill_i (dcache_kill_req), .dcache2mem_kill_o (dcache2mem_kill), // Data cache to main memory interface .mem2dcache_i (mem2dcache), .dcache2mem_o (dcache2mem), + .dcache_flush_i (dcache_flush_i), - .dmem_sel_i (dmem_sel | mmu2dcache.r_req) + .dmem_sel_i (stb_dmem_sel_o | mmu2dcache.r_req) ); //============================= Main memory and its memory interface =============================// @@ -362,3 +489,4 @@ assign dcache2dbus_o = dcache2dbus; assign dcache2mmu_o = dcache2mmu; endmodule : mem_top + diff --git a/rtl/memory/store-buffer/lsu_stb_controller.sv b/rtl/memory/store-buffer/lsu_stb_controller.sv new file mode 100644 index 00000000..9b83e71f --- /dev/null +++ b/rtl/memory/store-buffer/lsu_stb_controller.sv @@ -0,0 +1,110 @@ +// Copyright 2023 University of Engineering and Technology Lahore. +// Licensed under the Apache License, Version 2.0, see LICENSE file for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Description: The Store Buffer module. +// +// Author: Fazail Ali Butt, UET Lahore +// Date: 15.11.2024 + +module lsu_stb_controller ( + input logic clk, + input logic rst_n, + + // LSU --> lsu_stb_controller + input logic st_req, // store request from lsu + input logic dmem_sel_i, // Input from LSU (data memory select) + + // store_buffer_datapath --> lsu_stb_controller + input logic stb_full, // Store buffer stb_full flag + + // lsu_stb_controller --> LSU + output logic stb_ack, // stb_acknowledgement signal + + // lsu_stb_controller --> store_buffer_datapath + output logic wr_en // Store buffer write enable +); + + typedef enum logic [1:0] { + SB_IDLE = 2'b00, + SB_WRITE = 2'b01, + SB_FULL = 2'b10 + } state_t; + + state_t current_state, next_state; + + //State transition logic (sequential) + always_ff @(posedge clk or negedge rst_n) begin + if (!rst_n) begin + current_state <= SB_IDLE; + end else begin + current_state <= next_state; + end + end + + // Next state logic (combinational) + always_comb begin + // Default values + wr_en = 1'b0; + stb_ack = 1'b0; + + case (current_state) + SB_IDLE: begin + stb_ack = 1'b0; + if (st_req) begin + if (stb_full) begin + wr_en = 1'b0; + next_state = SB_FULL; + end else begin + wr_en = 1'b1; + next_state = SB_WRITE; + end + end else begin + wr_en = 1'b0; + next_state = SB_IDLE; + end + end + + SB_WRITE: begin + stb_ack = 1'b1; + if (st_req) begin + if (stb_full) begin + wr_en = 1'b0; + next_state = SB_FULL; + end else begin + wr_en = 1'b1; + next_state = SB_WRITE; + end + end else begin + wr_en = 1'b0; + next_state = SB_IDLE; + end + end + + SB_FULL: begin + stb_ack = 1'b0; + if (st_req) begin + if (stb_full) begin + wr_en = 1'b0; + next_state = SB_FULL; + end else begin + wr_en = 1'b1; + next_state = SB_WRITE; + end + end else begin + wr_en = 1'b0; + next_state = SB_IDLE; + end + end + default: begin + next_state = SB_IDLE; + end + endcase + + if (~dmem_sel_i) begin + next_state = SB_IDLE; + end + + end + +endmodule diff --git a/rtl/memory/store-buffer/stb_cache_controller.sv b/rtl/memory/store-buffer/stb_cache_controller.sv new file mode 100644 index 00000000..fd840903 --- /dev/null +++ b/rtl/memory/store-buffer/stb_cache_controller.sv @@ -0,0 +1,115 @@ +// Copyright 2023 University of Engineering and Technology Lahore. +// Licensed under the Apache License, Version 2.0, see LICENSE file for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Description: The Store Buffer module. +// +// Author: Fazail Ali Butt, UET Lahore +// Date: 15.11.2024 + +module stb_cache_controller ( + input logic clk, + input logic rst_n, + + // store_buffer_datapath --> stb_cache_controller + input logic stb_empty, // Store buffer empty flag + + // dcache --> stb_cache_controller + input logic dcache2stb_ack, // Acknowledgement from cache + + // stb_cache_controller --> store_buffer_datapath + output logic rd_en, // enable for read counter + output logic rd_sel, // Store buffer mux read selection + + // stb_cache_controller --> dcache + output logic stb_req, // Store buffer request signal + output logic stb_w_en, // Last word enable (for last write to cache) + output logic dm_sel +); + + typedef enum logic { + IDLE = 1'b0, + SB_CACHE_WRITE = 1'b1 + } state_t; + + state_t current_state, next_state; + + // State transition logic (sequential) + always_ff @(posedge clk or negedge rst_n) begin + if (!rst_n) begin + current_state <= IDLE; + end else begin + current_state <= next_state; + end + end + + // Next state logic (combinational) + always_comb + begin + // Default values + rd_sel = 1'b0; + stb_req = 1'b0; + stb_w_en = 1'b0; + rd_en = 1'b0; + dm_sel = 1'b0; + + case (current_state) + IDLE: begin + if (!stb_empty) begin + stb_req = 1'b1; + rd_sel = 1'b1; + stb_w_en = 1'b1; + dm_sel = 1'b1; + rd_en = 1'b0; + next_state = SB_CACHE_WRITE; + end + else begin + rd_sel = 1'b0; + stb_req = 1'b0; + stb_w_en = 1'b0; + rd_en = 1'b0; + dm_sel = 1'b0; + next_state = IDLE; + end + end + + SB_CACHE_WRITE: begin + if (!dcache2stb_ack && !stb_empty) begin + stb_req = 1'b1; + rd_sel = 1'b1; + stb_w_en = 1'b1; + dm_sel = 1'b1; + rd_en = 1'b0; + next_state = SB_CACHE_WRITE; // Stay SB_CACHE_WRITE state till store buffer contain data + + end + else if (dcache2stb_ack && !stb_empty) begin + stb_req = 1'b0; + rd_sel = 1'b0; + stb_w_en = 1'b0; + dm_sel = 1'b1; + rd_en = 1'b1; + next_state = SB_CACHE_WRITE; // Stay SB_CACHE_WRITE state till all data written to cache then cache acknowledges set + end + else if (dcache2stb_ack && stb_empty) begin + stb_req = 1'b0; + rd_sel = 1'b0; + stb_w_en = 1'b0; + dm_sel = 1'b1; + rd_en = 1'b1; + next_state = IDLE; + end + else if (stb_empty) begin + stb_req = 1'b0; + rd_sel = 1'b0; + stb_w_en = 1'b0; + dm_sel = 1'b0; + rd_en = 1'b0; + next_state = IDLE; + end + end + + default: next_state = IDLE; + endcase + end +endmodule diff --git a/rtl/memory/store-buffer/store_buffer_datapath.sv b/rtl/memory/store-buffer/store_buffer_datapath.sv new file mode 100644 index 00000000..1607feb0 --- /dev/null +++ b/rtl/memory/store-buffer/store_buffer_datapath.sv @@ -0,0 +1,110 @@ +// Copyright 2023 University of Engineering and Technology Lahore. +// Licensed under the Apache License, Version 2.0, see LICENSE file for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Description: The Store Buffer module. +// +// Author: Fazail Ali Butt, UET Lahore +// Date: 15.11.2024 + +`ifndef VERILATOR +`include "../../defines/store_buffer_defs.svh" +`else +`include "store_buffer_defs.svh" +`endif + +module store_buffer_datapath ( + input logic clk, + input logic rst_n, + +// LSU --> store_buffer_datapath + input logic [DCACHE_ADDR_WIDTH-1:0] lsummu2stb_addr, // Address input from LSU/MMU + input logic [DCACHE_DATA_WIDTH-1:0] lsummu2stb_wdata, // Data input from LSU/MMU + input logic [3:0] lsummu2stb_sel_byte, // Byte selection input from LSU/MMU + +// lsu_stb_controller --> store_buffer_datapath + input logic wr_en, // Write enable signal + +// stb_cache_controller --> store_buffer_datapath + input logic rd_en, // Read enable signal + input logic rd_sel, // Read Selection signal + +// store_buffer_datapath --> dcache + output logic [DCACHE_ADDR_WIDTH-1:0] stb_addr, // Address output to Cache + output logic [DCACHE_DATA_WIDTH-1:0] stb_wdata, // Data output to Cache + output logic [3:0] stb_sel_byte, // Byte selection output to Cache + +// store_buffer_datapath --> store buffer controllers + output logic stb_full, // Full signal + output logic stb_empty // Empty signal +); + + // Buffer Registers (arrays to hold multiple entries) + logic [DCACHE_ADDR_WIDTH-1:0] addr_buf [BLEN-1:0]; + logic [DCACHE_DATA_WIDTH-1:0] data_buf [BLEN-1:0]; + logic [3:0] sel_byte_buf [BLEN-1:0]; + + // Buffer Counter (to track read and write index) + logic [$clog2(BLEN)-1:0] rd_index; + logic [$clog2(BLEN)-1:0] wr_index, wr_index_comp; + + // counter for write operaitons + always_ff @(posedge clk or negedge rst_n) begin + if (!rst_n) begin + wr_index <= 0; + end + else if (wr_en) begin + wr_index <= (wr_index + 1); + end else begin + wr_index <= wr_index; + end + end + + // counter for read operaitons + always_ff @(posedge clk or negedge rst_n) begin + if (!rst_n) begin + rd_index <= 0; + end + else if (rd_en) begin + rd_index <= (rd_index + 1); + end + else begin + rd_index <= rd_index; + end + end + + // Write/Read logic + always_ff @(posedge clk or negedge rst_n) begin + if (!rst_n) begin + addr_buf [wr_index] <= addr_buf [wr_index]; + data_buf [wr_index] <= data_buf [wr_index]; + sel_byte_buf [wr_index] <= sel_byte_buf [wr_index]; + end else begin + if (wr_en) begin + // Write new values to buffer at wr_index + addr_buf [wr_index] <= lsummu2stb_addr; + data_buf [wr_index] <= lsummu2stb_wdata; + sel_byte_buf [wr_index] <= lsummu2stb_sel_byte; + end + end + end + + always_comb begin + if (rd_sel) begin + stb_addr = addr_buf [rd_index]; + stb_wdata = data_buf [rd_index]; + stb_sel_byte = sel_byte_buf [rd_index]; + end else begin + stb_addr = '0; + stb_wdata = '0; + stb_sel_byte = '0; + end + end + + assign wr_index_comp = (wr_index == BLEN-1) ? '0: wr_index + 1; + + assign stb_full = (wr_index_comp == rd_index) ? 1'b1 : 1'b0; + assign stb_empty = (wr_index == rd_index) ? 1'b1 : 1'b0; + +endmodule + diff --git a/rtl/memory/store-buffer/store_buffer_top.sv b/rtl/memory/store-buffer/store_buffer_top.sv new file mode 100644 index 00000000..01449a4a --- /dev/null +++ b/rtl/memory/store-buffer/store_buffer_top.sv @@ -0,0 +1,170 @@ +// Copyright 2023 University of Engineering and Technology Lahore. +// Licensed under the Apache License, Version 2.0, see LICENSE file for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Description: The Store Buffer module. +// +// Author: Fazail Ali Butt, UET Lahore +// Date: 15.11.2024 + +`ifndef VERILATOR +`include "../../defines/store_buffer_defs.svh" +`else +`include "store_buffer_defs.svh" +`endif + +module store_buffer_top ( + input logic clk, // Clock + input logic rst_n, // Reset, active low + + // LSU --> store_buffer_top + input wire type_lsummu2stb_s lsummu2stb_i, + input logic dmem_sel_i, // Data memory select from LSU + + // store_buffer_top --> LSU + output type_stb2lsummu_s stb2lsummu_o, + + // store_buffer_top --> dcache + output type_stb2dcache_s stb2dcache_o, + + output logic stb2dcache_empty, // store buffer empty signal to dcache + output logic dmem_sel_o, // Data memory select from Store Buffer + + // dCache --> store_buffer_top + input wire type_dcache2stb_s dcache2stb_i +); + +// Local Signals + logic wr_en; // Store Buffer Write Enable (from LSU controller) + logic rd_en; // Store Buffer Read Enable (from Cache controller) + logic stb_full; // Store Buffer full signal + logic stb_empty, empty_ff; // Store Buffer empty signal + logic rd_sel; // selection for read mux + logic stb_bypass; // Buffer Bypass signal + + logic stb_ack; // store buffer acknowledgement signal for lsu + + logic [DCACHE_ADDR_WIDTH-1:0] stb_addr; // store buffer addr to dcache + logic [DCACHE_DATA_WIDTH-1:0] stb_wdata; // store buffer wdata to dcache + logic [3:0] stb_sel_byte; // store buffer sel_byte to dcache + logic stb_req; // store buffer request to dcache + logic stb_w_en; // store buffer write enable to dcache + logic dm_sel; // store buffer dmem selection to dcache + + logic st_req; // store request + + assign st_req = lsummu2stb_i.req & lsummu2stb_i.w_en; + +/* =========================================== Bypassing Store buffer for Load Instructions ====================== */ + // Store Buffer bypass for load instructions + logic wr_ff; + always_ff @(posedge clk or negedge rst_n ) begin + if (!rst_n)begin + empty_ff <= '0; + wr_ff <= '0; + end else begin + empty_ff <= stb_empty; + wr_ff <= lsummu2stb_i.w_en; + end + end + + assign stb_bypass = ((lsummu2stb_i.req & !wr_ff) | (!lsummu2stb_i.req & !wr_ff)) & empty_ff; + +/* =========================================== Store Buffer Datapath ============================================= */ + store_buffer_datapath u_store_buffer ( + .clk (clk), + .rst_n (rst_n), + + // LSU --> store_buffer_datapath + .lsummu2stb_addr (lsummu2stb_i.addr), + .lsummu2stb_wdata (lsummu2stb_i.w_data), + .lsummu2stb_sel_byte (lsummu2stb_i.sel_byte), + + // lsu_stb_controller --> store_buffer_datapath + .wr_en (wr_en), + + // stb_cache_controller --> store_buffer_datapath + .rd_en (rd_en), + .rd_sel (rd_sel), + + // store_buffer_datapath --> dcache + .stb_addr (stb_addr), + .stb_wdata (stb_wdata), + .stb_sel_byte (stb_sel_byte), + + // store_buffer --> store_buffer_controllers + .stb_full (stb_full), + .stb_empty (stb_empty) + ); + +/* =========================================== LSU to Store Buffer Controller ==================================== */ + lsu_stb_controller u_lsu_stb_controller ( + .clk (clk), + .rst_n (rst_n), + + // LSU --> lsu_stb_controller + .dmem_sel_i (dmem_sel_i), + + // store buffer top --> lsu_stb_controller + .st_req (st_req), + + // store_buffer_datapath --> lsu_stb_controller + .stb_full (stb_full), + + // lsu_stb_controller --> LSU + .stb_ack (stb_ack), + + // lsu_stb_controller --> store_buffer_datapath + .wr_en (wr_en) + ); + +/* =========================================== Store Buffer to Cache Controller ================================== */ + stb_cache_controller u_stb_cache_controller ( + .clk (clk), + .rst_n (rst_n), + + // store_buffer_datapath --> stb_cache_controller + .stb_empty (stb_empty), + + // dcache --> stb_cache_controller + .dcache2stb_ack (dcache2stb_i.ack), + + // stb_cache_controller --> store_buffer_datapath + .rd_en (rd_en), + .rd_sel (rd_sel), + + // stb_cache_controller --> dcache + .stb_req (stb_req), + .stb_w_en (stb_w_en), + .dm_sel (dm_sel) + ); + +/* =========================================== Output signals ==================================================== */ + assign stb2dcache_empty = stb_empty; + + always_comb begin + stb2lsummu_o.ack = stb_ack; + stb2lsummu_o.r_data = '0; + + stb2dcache_o.addr = stb_addr; + stb2dcache_o.w_data = stb_wdata; + stb2dcache_o.sel_byte = stb_sel_byte; + stb2dcache_o.req = stb_req; + stb2dcache_o.w_en = stb_w_en; + + dmem_sel_o = dm_sel; + if (stb_bypass) begin + stb2lsummu_o.ack = dcache2stb_i.ack; + stb2lsummu_o.r_data = dcache2stb_i.r_data; + + stb2dcache_o.addr = lsummu2stb_i.addr; + stb2dcache_o.w_data = lsummu2stb_i.w_data; + stb2dcache_o.sel_byte = lsummu2stb_i.sel_byte; + stb2dcache_o.req = lsummu2stb_i.req; + stb2dcache_o.w_en = lsummu2stb_i.w_en; + + dmem_sel_o = dmem_sel_i; + end + end + +endmodule diff --git a/rtl/memory/wb_dcache/wb_dcache_controller.sv b/rtl/memory/wb_dcache/wb_dcache_controller.sv index 9dcd24d1..d775a42e 100644 --- a/rtl/memory/wb_dcache/wb_dcache_controller.sv +++ b/rtl/memory/wb_dcache/wb_dcache_controller.sv @@ -30,9 +30,9 @@ module wb_dcache_controller ( output logic [DCACHE_IDX_BITS-1:0] evict_index_o, // LSU/MMU to data cache interface - input wire lsummu2dcache_req_i, - input wire lsummu2dcache_wr_i, - output logic dcache2lsummu_ack_o, + input wire stb2dcache_req_i, + input wire stb2dcache_wr_i, + output logic dcache2stb_ack_o, input wire dcache_kill_i, // Data memory to data cache interface @@ -47,8 +47,8 @@ module wb_dcache_controller ( type_dcache_states_e dcache_state_ff, dcache_state_next; logic [DCACHE_IDX_BITS-1:0] evict_index_next, evict_index_ff; -logic lsummu2dcache_wr_ff; -logic dcache2lsummu_ack; +logic stb2dcache_wr_ff; +logic dcache2stb_ack; logic dcache_hit; logic dcache_miss; logic dcache_evict; @@ -60,22 +60,22 @@ logic cache_wr; logic cache_line_wr; logic cache_line_clean; logic dcache2mem_kill; -logic lsummu2dcache_req_ff, dmem_sel_ff; +logic stb2dcache_req_ff, dmem_sel_ff; -assign dcache_hit = lsummu2dcache_req_ff & dmem_sel_ff & cache_hit_i; -assign dcache_miss = lsummu2dcache_req_ff & dmem_sel_ff & ~cache_hit_i ; +assign dcache_hit = stb2dcache_req_ff & dmem_sel_ff & cache_hit_i; +assign dcache_miss = stb2dcache_req_ff & dmem_sel_ff & ~cache_hit_i ; assign dcache_evict = cache_evict_req_i; always_ff@(posedge clk) begin if(!rst_n) begin - lsummu2dcache_req_ff <= '0; + stb2dcache_req_ff <= '0; dmem_sel_ff <= '0; - lsummu2dcache_wr_ff <= '0; + stb2dcache_wr_ff <= '0; end else begin - lsummu2dcache_req_ff <= lsummu2dcache_req_i; + stb2dcache_req_ff <= stb2dcache_req_i; dmem_sel_ff <= dmem_sel_i; - lsummu2dcache_wr_ff <= lsummu2dcache_wr_i; + stb2dcache_wr_ff <= stb2dcache_wr_i; end end @@ -94,7 +94,7 @@ end always_comb begin dcache_state_next = dcache_state_ff; evict_index_next = evict_index_ff; - dcache2lsummu_ack = 1'b0; + dcache2stb_ack = 1'b0; dcache2mem_req = 1'b0; dcache2mem_wr = 1'b0; cache_wrb_req = 1'b0; @@ -108,7 +108,7 @@ always_comb begin // In case of flush, go to FLUSH State if (dcache_flush_i) begin dcache_state_next = DCACHE_FLUSH; - end else if (lsummu2dcache_req_i) begin + end else if (stb2dcache_req_i) begin dcache_state_next = DCACHE_PROCESS_REQ; end else begin dcache_state_next = DCACHE_IDLE; @@ -121,12 +121,12 @@ always_comb begin if (dcache_hit) begin // In case of hit, perform the cache read/write operation - if (lsummu2dcache_wr_ff) begin + if (stb2dcache_wr_ff) begin cache_wr = 1'b1; dcache_state_next = DCACHE_IDLE; - dcache2lsummu_ack = 1'b1; + dcache2stb_ack = 1'b1; end else begin - dcache2lsummu_ack = 1'b1; + dcache2stb_ack = 1'b1; dcache_state_next = DCACHE_IDLE; end @@ -144,7 +144,7 @@ always_comb begin end DCACHE_WRITE: begin dcache_state_next = DCACHE_IDLE; - dcache2lsummu_ack = 1'b1; + dcache2stb_ack = 1'b1; end DCACHE_ALLOCATE: begin @@ -192,7 +192,7 @@ always_comb begin end else begin if (&evict_index_ff) begin // evict_index_ff == DCACHE_MAX_IDX dcache_state_next = DCACHE_FLUSH_DONE; - // dcache2lsummu_ack = 1'b1; + // dcache2stb_ack = 1'b1; evict_index_next = '0; end else begin evict_index_next = evict_index_ff + 1; @@ -202,7 +202,7 @@ always_comb begin end DCACHE_FLUSH_DONE: begin - dcache2lsummu_ack = 1'b1; + dcache2stb_ack = 1'b1; dcache_state_next = DCACHE_IDLE; end default: begin @@ -232,6 +232,6 @@ assign dcache2mem_wr_o = dcache2mem_wr; assign dcache2mem_req_o = dcache2mem_req; assign dcache2mem_kill_o = dcache2mem_kill; -assign dcache2lsummu_ack_o = dcache2lsummu_ack; +assign dcache2stb_ack_o = dcache2stb_ack; endmodule diff --git a/rtl/memory/wb_dcache/wb_dcache_datapath.sv b/rtl/memory/wb_dcache/wb_dcache_datapath.sv index d9209a29..394fccf1 100644 --- a/rtl/memory/wb_dcache/wb_dcache_datapath.sv +++ b/rtl/memory/wb_dcache/wb_dcache_datapath.sv @@ -29,11 +29,11 @@ module wb_dcache_datapath( // LSU/MMU to data cache interface input wire dcache_flush_i, - input wire lsummu2dcache_req_i, - input wire [DCACHE_ADDR_WIDTH-1:0] lsummu2dcache_addr_i, - input wire [DCACHE_DATA_WIDTH-1:0] lsummu2dcache_wdata_i, + input wire stb2dcache_req_i, + input wire [DCACHE_ADDR_WIDTH-1:0] stb2dcache_addr_i, + input wire [DCACHE_DATA_WIDTH-1:0] stb2dcache_wdata_i, input wire [3:0] sel_byte_i, - output logic [DCACHE_DATA_WIDTH-1:0] dcache2lsummu_data_o, + output logic [DCACHE_DATA_WIDTH-1:0] dcache2stb_data_o, // Data cache to data memory interface input wire [DCACHE_LINE_WIDTH-1:0] mem2dcache_data_i, @@ -47,13 +47,13 @@ type_dcache_data_s cache_line_read, cache_line_write, cache_wd type_dcache_tag_s cache_tag_read, cache_tag_write; logic [DCACHE_DATA_WIDTH-1:0] cache_word_read, cache_word_write; -logic [DCACHE_DATA_WIDTH-1:0] lsummu2dcache_wdata; +logic [DCACHE_DATA_WIDTH-1:0] stb2dcache_wdata; logic [DCACHE_ADDR_WIDTH-1:0] dcache2mem_addr; logic [15:0] cache_line_sel_byte, cache_data_wr_sel; logic [3:0] sel_byte; logic [3:0] cache_tag_wr_sel; -logic [DCACHE_DATA_WIDTH-1:0] dcache2lsummu_data_ff, dcache2lsummu_data_next; +logic [DCACHE_DATA_WIDTH-1:0] dcache2stb_data_ff, dcache2stb_data_next; logic [DCACHE_TAG_BITS-1:0] addr_tag, addr_tag_ff; logic [1:0] addr_offset, addr_offset_ff; logic [DCACHE_IDX_BITS-1:0] addr_index, addr_index_ff; @@ -63,20 +63,20 @@ logic dcache_flush; assign dcache_flush = dcache_flush_i; assign evict_index = evict_index_i; //assign sel_byte = sel_byte_i; -//assign lsummu2dcache_wdata = lsummu2dcache_wdata_i; +//assign stb2dcache_wdata = stb2dcache_wdata_i; -assign addr_tag = lsummu2dcache_addr_i[DCACHE_ADDR_WIDTH-1:DCACHE_TAG_LSB]; -assign addr_offset = lsummu2dcache_addr_i[DCACHE_OFFSET_BITS-1:2]; +assign addr_tag = stb2dcache_addr_i[DCACHE_ADDR_WIDTH-1:DCACHE_TAG_LSB]; +assign addr_offset = stb2dcache_addr_i[DCACHE_OFFSET_BITS-1:2]; assign addr_index = dcache_flush ? evict_index : cache_wr_i ? addr_index_ff : - lsummu2dcache_addr_i[DCACHE_TAG_LSB-1:DCACHE_OFFSET_BITS]; + stb2dcache_addr_i[DCACHE_TAG_LSB-1:DCACHE_OFFSET_BITS]; always_ff@(posedge clk) begin if(!rst_n) begin - lsummu2dcache_wdata <= '0; + stb2dcache_wdata <= '0; sel_byte <= '0; end else begin - lsummu2dcache_wdata <= lsummu2dcache_wdata_i; // MT + stb2dcache_wdata <= stb2dcache_wdata_i; // MT sel_byte <= sel_byte_i; end end @@ -103,10 +103,10 @@ end always_comb begin cache_word_write = '0; // MT cache_word_read - if (sel_byte[0]) cache_word_write[7:0] = lsummu2dcache_wdata[7:0]; - if (sel_byte[1]) cache_word_write[15:8] = lsummu2dcache_wdata[15:8]; - if (sel_byte[2]) cache_word_write[23:16] = lsummu2dcache_wdata[23:16]; - if (sel_byte[3]) cache_word_write[31:24] = lsummu2dcache_wdata[31:24]; + if (sel_byte[0]) cache_word_write[7:0] = stb2dcache_wdata[7:0]; + if (sel_byte[1]) cache_word_write[15:8] = stb2dcache_wdata[15:8]; + if (sel_byte[2]) cache_word_write[23:16] = stb2dcache_wdata[23:16]; + if (sel_byte[3]) cache_word_write[31:24] = stb2dcache_wdata[31:24]; end always_comb begin @@ -130,7 +130,7 @@ always_comb begin cache_line_write[127:96] = cache_word_write; cache_line_sel_byte[15:12] = sel_byte; end - // default: dcache2lsummu_data_next = '0; + // default: dcache2stb_data_next = '0; endcase end @@ -157,7 +157,7 @@ always_comb begin if (cache_wrb_req_i) begin dcache2mem_addr = {cache_tag_read.tag[DCACHE_TAG_BITS-1:0], addr_index, {{DCACHE_OFFSET_BITS}{1'b0}}}; end else begin - dcache2mem_addr = lsummu2dcache_addr_i; + dcache2mem_addr = stb2dcache_addr_i; end end @@ -167,9 +167,9 @@ assign cache_data_wr_sel = cache_line_wr_i ? 16'hFFFF : cache_wr_i ? cache_line_ always_ff@(posedge clk) begin if(!rst_n) begin - dcache2lsummu_data_ff <= '0; + dcache2stb_data_ff <= '0; end else begin - dcache2lsummu_data_ff <= dcache2lsummu_data_next; + dcache2stb_data_ff <= dcache2stb_data_next; end end @@ -179,7 +179,7 @@ always_ff@(posedge clk) begin addr_index_ff <= '0; end else begin addr_tag_ff <= addr_tag; - addr_index_ff <= lsummu2dcache_addr_i[DCACHE_TAG_LSB-1:DCACHE_OFFSET_BITS]; + addr_index_ff <= stb2dcache_addr_i[DCACHE_TAG_LSB-1:DCACHE_OFFSET_BITS]; end end @@ -187,7 +187,7 @@ dcache_data_ram dcache_data_ram_module ( .clk (clk), .rst_n (rst_n), - .req (lsummu2dcache_req_i), + .req (stb2dcache_req_i), .wr_en (cache_data_wr_sel), .addr (addr_index), .wdata (cache_wdata), @@ -199,7 +199,7 @@ dcache_tag_ram dcache_tag_ram_module ( .clk (clk), .rst_n (rst_n), - .req (lsummu2dcache_req_i), + .req (stb2dcache_req_i), .wr_en (cache_tag_wr_sel), .addr (addr_index), .wdata (cache_tag_write), @@ -208,12 +208,12 @@ dcache_tag_ram dcache_tag_ram_module ( // Output signals update -assign dcache2lsummu_data_next = cache_word_read; // Read data from cache to LSU/MMU +assign dcache2stb_data_next = cache_word_read; // Read data from cache to LSU/MMU assign cache_hit_o = (addr_tag_ff == cache_tag_read.tag[DCACHE_TAG_BITS-1:0]) && cache_tag_read.valid; assign cache_evict_req_o = cache_tag_read.dirty[0]; // & cache_tag_read.valid; assign dcache2mem_addr_o = dcache2mem_addr; assign dcache2mem_data_o = cache_line_read; -assign dcache2lsummu_data_o = dcache2lsummu_data_next; +assign dcache2stb_data_o = dcache2stb_data_next; endmodule diff --git a/rtl/memory/wb_dcache/wb_dcache_top.sv b/rtl/memory/wb_dcache/wb_dcache_top.sv index 54693e05..53d93f99 100644 --- a/rtl/memory/wb_dcache/wb_dcache_top.sv +++ b/rtl/memory/wb_dcache/wb_dcache_top.sv @@ -21,10 +21,11 @@ module wb_dcache_top ( input wire dmem_sel_i, input wire dcache_flush_i, input wire dcache_kill_i, + input wire stb2dcache_empty, // LSU/MMU to data cache interface - input wire type_lsummu2dcache_s lsummu2dcache_i, - output type_dcache2lsummu_s dcache2lsummu_o, + input wire type_stb2dcache_s stb2dcache_i, + output type_dcache2stb_s dcache2stb_o, // Data cache to data memory interface input wire type_mem2dcache_s mem2dcache_i, @@ -40,15 +41,18 @@ logic cache_line_clean; logic cache_wrb_req; logic [DCACHE_IDX_BITS-1:0] evict_index; -type_lsummu2dcache_s lsummu2dcache; -type_dcache2lsummu_s dcache2lsummu; +type_stb2dcache_s stb2dcache; +type_dcache2stb_s dcache2stb; type_mem2dcache_s mem2dcache; type_dcache2mem_s dcache2mem; -assign lsummu2dcache = lsummu2dcache_i; +logic top_dcache_flush; + +assign stb2dcache = stb2dcache_i; assign mem2dcache = mem2dcache_i; +assign top_dcache_flush = stb2dcache_empty && dcache_flush_i; wb_dcache_controller wb_dcache_controller_module( .clk (clk), @@ -64,12 +68,12 @@ wb_dcache_controller wb_dcache_controller_module( .cache_wrb_req_o (cache_wrb_req), // LSU/MMU <---> data cache signals - .lsummu2dcache_req_i (lsummu2dcache.req), - .lsummu2dcache_wr_i (lsummu2dcache.w_en), - .dcache2lsummu_ack_o (dcache2lsummu.ack), - .dcache_flush_i (dcache_flush_i), + .stb2dcache_req_i (stb2dcache.req), + .stb2dcache_wr_i (stb2dcache.w_en), + .dcache2stb_ack_o (dcache2stb.ack), + .dcache_flush_i (top_dcache_flush), .dcache_kill_i (dcache_kill_i), -// .dcache_flush_ack_o (dcache2lsummu.flush_ack), +// .dcache_flush_ack_o (dcache2stb.flush_ack), // Data memory <---> data cache signals .mem2dcache_ack_i (mem2dcache.ack), @@ -93,12 +97,12 @@ wb_dcache_datapath wb_dcache_datapath_module( .cache_evict_req_o (cache_evict_req), // LSU/MMU <---> data cache signals - .dcache_flush_i (dcache_flush_i), - .lsummu2dcache_req_i (lsummu2dcache.req), - .lsummu2dcache_addr_i (lsummu2dcache.addr), - .lsummu2dcache_wdata_i (lsummu2dcache.w_data), - .sel_byte_i (lsummu2dcache.sel_byte), - .dcache2lsummu_data_o (dcache2lsummu.r_data), + .dcache_flush_i (top_dcache_flush), + .stb2dcache_req_i (stb2dcache.req), + .stb2dcache_addr_i (stb2dcache.addr), + .stb2dcache_wdata_i (stb2dcache.w_data), + .sel_byte_i (stb2dcache.sel_byte), + .dcache2stb_data_o (dcache2stb.r_data), // Data memory <---> data cache signals .mem2dcache_data_i (mem2dcache.r_data), @@ -107,7 +111,7 @@ wb_dcache_datapath wb_dcache_datapath_module( ); -assign dcache2lsummu_o = dcache2lsummu; +assign dcache2stb_o = dcache2stb; assign dcache2mem_o = dcache2mem;