blob: 66fee0e67faa7844d16eeb25da959339c4e715d1 [file] [log] [blame]
Rodrigo Huerta46bbb382021-10-29 19:59:13 +02001/*
2*
3* This file is part of the Elpis processor project.
4*
5* Copyright © 2020-present. All rights reserved.
6* Authors: Aurora Tomas and Rodrigo Huerta.
7*
8* This file is licensed under both the BSD-3 license for individual/non-commercial
9* use. Full text of both licenses can be found in LICENSE file.
10*/
11
12`default_nettype none
13
14`ifdef TESTS
15 `include "elpis/definitions.v"
16`else
17 `include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
18`endif
19
20module storebuffer(
21 input clk,
22 input reset,
23 input[31:0] addr_in,
24 input[31:0] data_in,
25 input is_byte,
26 input sb_we, // Add a new entry into SB
27 input sb_re, // Read request (bypass) from an entry of SB
28 input stall_dcache,
29 input hit_dtlb,
30 output reg sb_hit,
31 output full_out,
32 output empty_out,
33 output reg[31:0] addr_out,
34 output reg[31:0] data_out,
35 output reg is_byte_out,
36 output reg drain_out,
37 output reg is_data_to_cache
38);
39 reg useless_bit, hold_value_to_cache;
40 reg[31:0] sb_addr[0:`SB_NUM_ENTRIES-1];
41 reg[31:0] sb_data[0:`SB_NUM_ENTRIES-1];
42 reg sb_size[0:`SB_NUM_ENTRIES-1]; // 0 - word, 1 - byte
43 reg sb_valid[0:`SB_NUM_ENTRIES-1];
44
45 reg[$clog2(`SB_NUM_ENTRIES)-1:0] head;
46 reg[$clog2(`SB_NUM_ENTRIES)-1:0] tail;
47 reg[$clog2(`SB_NUM_ENTRIES)-1:0] tail_last;
48 reg[$clog2(`SB_NUM_ENTRIES):0] entry_count;
49
50 wire[31:0] ld_first_byte, ld_last_byte;
51 wire[1:0] offset;
52
53 assign ld_first_byte = addr_in;
54 assign ld_last_byte = (is_byte) ? addr_in : (addr_in+3);
55 assign offset = addr_in[1:0];
56
57 assign empty_out = (entry_count == 0);
58 assign full_out = (entry_count == `SB_NUM_ENTRIES);
59
60 reg[1:0] hit_pos;
61 integer i;
62 always@(*) begin
63 sb_hit = 1'b0;
Rodrigo Huertaad8a7432021-11-02 21:34:04 +010064 hit_pos = 2'b0;
Rodrigo Huerta46bbb382021-10-29 19:59:13 +020065 for (i = 0; (i < `SB_NUM_ENTRIES); i=i+1) begin
66 if (sb_valid[i] && (sb_addr[i] <= ld_first_byte) && ( (sb_addr[i] + (sb_size[i] ? 0 : 3'b11) ) >= ld_last_byte) ) begin
67 sb_hit = 1'b1;
68 hit_pos = i[1:0];
69 end
70 end
Rodrigo Huerta46bbb382021-10-29 19:59:13 +020071 end
72
73 always@(posedge clk) begin
74 if (reset) begin
75 head <= 2'b0;
76 tail <= 2'b0;
77 entry_count <= 3'b0;
78 for(i = 0; i < `SB_NUM_ENTRIES; i=i+1) begin
79 sb_valid[i] <= 1'b0;
80 end
81 end else begin
82 if (sb_re && sb_hit) begin
83 data_out <= (is_byte && sb_size[hit_pos]) ? {24'b0, sb_data[hit_pos][offset*'d8]} : sb_data[hit_pos];
84 end
85
86 if(sb_we && sb_hit) begin
87 if (is_byte && !sb_size[hit_pos]) begin
88 // We have a word and want to write a byte
89 sb_data[hit_pos][offset*8+:8] <= data_in[7:0];
90 end else if (is_byte && sb_size[hit_pos]) begin
91 // We have a byte and want to write a byte
92 sb_data[hit_pos] <= {24'b0, data_in[7:0]};
93 end else begin
94 // We have (byte or word) and we want to write a word
95 sb_data[hit_pos] <= data_in;
96 sb_size[hit_pos] <= 1'b0;
97 end
98 end
99
100 if ((full_out && !stall_dcache) || (!sb_we && !sb_re && !empty_out && !stall_dcache)) begin
101 drain_out <= 1'b1;
102 tail_last <= tail;
103 is_data_to_cache <= 1'b1;
104 addr_out <= sb_addr[tail];
105 data_out <= sb_data[tail];
106 is_byte_out <= sb_size[tail];
107 entry_count <= entry_count - 1'b1;
108 sb_valid[tail] <= 1'b0;
109 {useless_bit, tail} <= (tail+1'b1)%`SB_NUM_ENTRIES;
110 hold_value_to_cache <= 1'b1;
111 end else if(stall_dcache && hold_value_to_cache) begin
112 drain_out <= 1'b1;
113 is_data_to_cache <= 1'b1;
114 addr_out <= sb_addr[tail_last];
115 data_out <= sb_data[tail_last];
116 is_byte_out <= sb_size[tail_last];
117 hold_value_to_cache <= 1'b1;
118 end else begin
119 drain_out <= 1'b0;
120 is_data_to_cache <= 1'b0;
121 hold_value_to_cache <= 1'b0;
122 tail_last <= 'b0;
123 end
124
125 if (sb_we && !full_out && !sb_hit && hit_dtlb) begin
126 sb_addr[head] <= addr_in;
127 sb_data[head] <= data_in;
128 sb_size[head] <= is_byte;
129 sb_valid[head] <= 1'b1;
130 entry_count <= entry_count + 1'b1;
131 {useless_bit, head} <= (head + 1'b1)%`SB_NUM_ENTRIES;
132 end
133 end
134 end
135
136endmodule