1
+ `include " constants.sv"
2
+
3
+ module cache (
4
+ input int log_stream,
5
+ input int cache_stream,
6
+ input wire clk, reset, c_dump,
7
+ input wire [`ADDR1_BUS_SIZE - 1 : 0 ] a1_in,
8
+ inout wire [`DATA1_BUS_SIZE - 1 : 0 ] d1_in,
9
+ inout wire [`CTR1_BUS_SIZE - 1 : 0 ] c1_in,
10
+ output wire [`ADDR2_BUS_SIZE - 1 : 0 ] a2_out,
11
+ inout wire [`DATA2_BUS_BIT_SIZE - 1 : 0 ] d2_in,
12
+ inout wire [`CTR2_BUS_SIZE - 1 : 0 ] c2_in
13
+ );
14
+ reg [`DATA1_BUS_SIZE - 1 : 0 ] d1_reg = 'z ;
15
+ reg [`CTR1_BUS_SIZE - 1 : 0 ] c1_reg = 'z ;
16
+ reg [`ADDR2_BUS_SIZE - 1 : 0 ] a2_reg = 'z ;
17
+ reg [`DATA2_BUS_BIT_SIZE - 1 : 0 ] d2_reg = 'z ;
18
+ reg [`CTR2_BUS_SIZE - 1 : 0 ] c2_reg = NONE ;
19
+ assign d1_in = d1_reg;
20
+ assign c1_in = c1_reg;
21
+ assign d2_in = d2_reg;
22
+ assign a2_out = a2_reg;
23
+ assign c2_in = c2_reg;
24
+
25
+ reg [`LINE_BIT_SIZE - 1 : 0 ] cache_memory[`CACHE_WAY_BLOCKS_NUMBER - 1 : 0 ][`CACHE_WAY - 1 : 0 ];
26
+ reg [`TAG_SIZE - 1 : 0 ] line_tag[`CACHE_WAY_BLOCKS_NUMBER - 1 : 0 ][`CACHE_WAY - 1 : 0 ];
27
+ reg modified[`CACHE_WAY_BLOCKS_NUMBER - 1 : 0 ][`CACHE_WAY - 1 : 0 ];
28
+ reg invalid[`CACHE_WAY_BLOCKS_NUMBER - 1 : 0 ][`CACHE_WAY - 1 : 0 ];
29
+ reg last_used[`CACHE_WAY_BLOCKS_NUMBER - 1 : 0 ];
30
+ reg [`TAG_SIZE - 1 : 0 ] requested_tag;
31
+ reg [`SET_SIZE - 1 : 0 ] requested_set;
32
+ reg [`OFFSET_SIZE - 1 : 0 ] requested_offset;
33
+ reg [`CTR1_BUS_SIZE - 1 : 0 ] requested_operation = NONE ;
34
+ reg [`MAX_WRITE_REQUEST_SIZE - 1 : 0 ] data_to_write;
35
+
36
+ task write_to_memory (
37
+ input reg [`SET_SIZE - 1 : 0 ] set,
38
+ input int ind_in_way_block
39
+ );
40
+ c2_reg = WRITE ;
41
+ a2_reg[`SET_SIZE + : `TAG_SIZE ] = line_tag[set][ind_in_way_block];
42
+ a2_reg[0 + : `SET_SIZE ] = set;
43
+
44
+ $fdisplay (log_stream, " Time: %0t , cache send write request to memory on a2: %b " , $time , a2_out);
45
+
46
+ for (int i = 0 ; i < `MEMORY_INTERACTION_TICK_NUMBER ; i++ ) begin
47
+ d2_reg = (cache_memory[set][ind_in_way_block] >> i * `DATA2_BUS_BIT_SIZE ) & ((1 << `DATA2_BUS_BIT_SIZE ) - 1 );
48
+ `delay (`CLOCK_DELAY , 0 )
49
+ end
50
+
51
+ modified[set][ind_in_way_block] = 0 ;
52
+ c2_reg = 'z ;
53
+
54
+ wait (clk == 1 && c2_in == RESPONSE );
55
+ // Clock = 1
56
+
57
+ $fdisplay (log_stream, " Time: %0t , memory answered to cache on write c2: %b " , $time , c2_in);
58
+ wait (clk == 0 );
59
+ // Clock = 0
60
+
61
+ c2_reg = NONE ;
62
+ $fdisplay (log_stream, " Time: %0t , cache has taken the c2: %b " , $time , c2_in);
63
+ endtask ;
64
+
65
+ task read_from_memory (
66
+ input reg [`TAG_SIZE - 1 : 0 ] tag,
67
+ input reg [`SET_SIZE - 1 : 0 ] set,
68
+ input int ind_in_way_block
69
+ );
70
+ c2_reg = READ ;
71
+ a2_reg[`SET_SIZE + : `TAG_SIZE ] = tag;
72
+ a2_reg[0 + : `SET_SIZE ] = set;
73
+
74
+ $fdisplay (log_stream, " Time: %0t , cache send read request to memory, a2: %b " , $time , a2_out);
75
+
76
+ `delay (`CLOCK_DELAY , 0 )
77
+ c2_reg = 'z ;
78
+ d2_reg = 'z ;
79
+
80
+ wait (clk == 1 && c2_in == RESPONSE );
81
+ // Clock = 1
82
+
83
+ cache_memory[set][ind_in_way_block] = 0 ;
84
+ for (int i = 0 ; i < `MEMORY_INTERACTION_TICK_NUMBER ; i++ ) begin
85
+ cache_memory[set][ind_in_way_block][i * `DATA2_BUS_BIT_SIZE + : `DATA2_BUS_BIT_SIZE ] = d2_in;
86
+ `delay (`CLOCK_DELAY , 1 )
87
+ end ;
88
+
89
+ invalid[set][ind_in_way_block] = 0 ;
90
+ modified[set][ind_in_way_block] = 0 ;
91
+ line_tag[set][ind_in_way_block] = tag;
92
+ $fdisplay (log_stream, " Time: %0t , memory answered to cache on read with data: %b " , $time , cache_memory[set][ind_in_way_block]);
93
+
94
+ wait (clk == 0 );
95
+ // Clock = 0
96
+
97
+ c2_reg = NONE ;
98
+ $fdisplay (log_stream, " Time: %0t , cache has taken the c2: %b " , $time , c2_in);
99
+ endtask ;
100
+
101
+ task reset_cache ;
102
+ $fdisplay (log_stream, " Cache reset" );
103
+ for (int i = 0 ; i < `CACHE_WAY_BLOCKS_NUMBER ; i++ ) begin
104
+ for (int j = 0 ; j < `CACHE_WAY ; j++ ) begin
105
+ cache_memory[i][j] = 0 ;
106
+ invalid[i][j] = 1 ;
107
+ modified[i][j] = 0 ;
108
+ end ;
109
+ last_used[i] = 0 ;
110
+ end
111
+ endtask
112
+
113
+ task dump_cache ;
114
+ for (int i = 0 ; i < `CACHE_WAY_BLOCKS_NUMBER ; i++ ) begin
115
+ for (int j = 0 ; j < `CACHE_WAY ; j++ ) begin
116
+ $fdisplay (cache_stream, " tag: %b , set: %b , ind_in_way_block: %b , cache_line: %b " , line_tag[i][j], i, j, cache_memory[i][j]);
117
+ end
118
+ end
119
+ endtask
120
+
121
+ initial reset_cache ();
122
+
123
+ int ind_in_way_block = - 1 ;
124
+ int requested_bit_offset;
125
+
126
+ always @ (posedge reset)
127
+ reset_cache ();
128
+
129
+ always @ (posedge c_dump)
130
+ dump_cache ();
131
+
132
+ always @ (clk) begin
133
+
134
+ if (clk == 1 && c1_in != NONE_C1 ) begin
135
+ requested_operation = c1_in;
136
+ requested_set = a1_in & ((1 << `SET_SIZE ) - 1 );
137
+ requested_tag = (a1_in >> `SET_SIZE );
138
+ if (c1_in == WRITE8 )
139
+ data_to_write = d1_in & ((1 << 8 ) - 1 );
140
+ else if (c1_in == WRITE16 || c1_in == WRITE32_OR_RESPONSE )
141
+ data_to_write = d1_in;
142
+
143
+ if (c1_in != INVALIDATE ) begin
144
+ `delay (`CLOCK_DELAY , 1 )
145
+
146
+ requested_offset = a1_in & ((1 << `OFFSET_SIZE ) - 1 );
147
+ if (c1_in == WRITE32_OR_RESPONSE )
148
+ data_to_write[`DATA1_BUS_SIZE + : `DATA1_BUS_SIZE ] = d1_in;
149
+ end
150
+
151
+ $fdisplay (log_stream, " Time: %0t , cache got the request: %0d , tag: %b , set: %b , offset: %b " , $time , requested_operation, requested_tag, requested_set, requested_offset);
152
+ if (c1_in == WRITE8 || c1_in == WRITE16 || c1_in == WRITE32_OR_RESPONSE )
153
+ $fdisplay (log_stream, " with data to write: %b " , data_to_write);
154
+ end
155
+
156
+ if (clk == 0 && requested_operation != NONE ) begin
157
+ c1_reg = NONE_C1 ;
158
+ $fdisplay (log_stream, " Time: %0t , cache has taken the c1 bus and started processing request" , $time );
159
+
160
+ if (requested_operation == INVALIDATE ) begin
161
+ for (int j = 0 ; j < `CACHE_WAY ; j++ ) begin
162
+ if (invalid[requested_set][j] == 0 && line_tag[requested_set][j] == requested_tag) begin
163
+ last_used[requested_set] = ! j;
164
+ if (modified[requested_set][j])
165
+ write_to_memory (requested_set, j);
166
+ invalid[requested_set][j] = 1 ;
167
+ end
168
+ end
169
+ c1_reg = WRITE32_OR_RESPONSE ;
170
+ end else begin
171
+ ind_in_way_block = - 1 ;
172
+ for (int j = 0 ; j < `CACHE_WAY ; j++ )
173
+ if (invalid[requested_set][j] == 0 && line_tag[requested_set][j] == requested_tag)
174
+ ind_in_way_block = j;
175
+
176
+ if (ind_in_way_block == - 1 ) begin
177
+ $fdisplay (log_stream, " Time: %0t , cache miss at set: %b at tag: %b " , $time , requested_set, requested_tag);
178
+ test_simulation.cpu_inst.cache_misses++ ;
179
+ `delay (`CACHE_MISS_RESPONSE_TIME - `CACHE_INTERACTION_TICK_NUMBER * `CLOCK_DELAY , 0 )
180
+
181
+ ind_in_way_block = ! last_used[requested_set];
182
+
183
+ if (modified[requested_set][ind_in_way_block] == 1 && invalid[requested_set][ind_in_way_block] == 0 )
184
+ write_to_memory (requested_set, ind_in_way_block);
185
+
186
+ read_from_memory (requested_tag, requested_set, ind_in_way_block);
187
+ end else begin
188
+ $fdisplay (log_stream, " Time: %0t , cache hit at set: %b at tag: %b " , $time , requested_set, requested_tag);
189
+ test_simulation.cpu_inst.cache_hits++ ;
190
+ `delay (`CACHE_HIT_RESPONSE_TIME - `CACHE_INTERACTION_TICK_NUMBER * `CLOCK_DELAY , 0 )
191
+ end
192
+
193
+ c1_reg = WRITE32_OR_RESPONSE ;
194
+ requested_bit_offset = requested_offset * 8 ; // bytes to bits
195
+
196
+ case (requested_operation)
197
+ WRITE8 : begin
198
+ cache_memory[requested_set][ind_in_way_block][requested_bit_offset + : 8 ] = data_to_write;
199
+ modified[requested_set][ind_in_way_block] = 1 ;
200
+ end
201
+
202
+ WRITE16 : begin
203
+ cache_memory[requested_set][ind_in_way_block][requested_bit_offset + : 16 ] = data_to_write;
204
+ modified[requested_set][ind_in_way_block] = 1 ;
205
+ end
206
+
207
+ WRITE32_OR_RESPONSE : begin
208
+ cache_memory[requested_set][ind_in_way_block][requested_bit_offset + : 32 ] = data_to_write;
209
+ modified[requested_set][ind_in_way_block] = 1 ;
210
+ end
211
+
212
+ READ8 : d1_reg = cache_memory[requested_set][ind_in_way_block][requested_bit_offset + : 8 ];
213
+
214
+ READ16 : d1_reg = cache_memory[requested_set][ind_in_way_block][requested_bit_offset + : 16 ];
215
+
216
+ READ32 : begin
217
+ $fdisplay (log_stream, " Time: %0t , cache_memory: %b " , $time , cache_memory[requested_set][ind_in_way_block][requested_bit_offset + : 16 ]);
218
+ d1_reg = cache_memory[requested_set][ind_in_way_block][requested_bit_offset + : 16 ];
219
+ `delay (`CLOCK_DELAY , 0 );
220
+ $fdisplay (log_stream, " Time: %0t , cache_memory: %b " , $time , cache_memory[requested_set][ind_in_way_block][requested_bit_offset + 16 + : 16 ]);
221
+ d1_reg = cache_memory[requested_set][ind_in_way_block][requested_bit_offset + 16 + : 16 ];
222
+ end
223
+ endcase
224
+
225
+ last_used[requested_set] = ind_in_way_block;
226
+ end
227
+
228
+ `delay (`CLOCK_DELAY , 0 )
229
+
230
+ $fdisplay (log_stream, " Time: %0t , cache has given the c1 bus" , $time );
231
+ c1_reg = 'z ;
232
+ d1_reg = 'z ;
233
+ requested_operation = NONE ;
234
+ end
235
+ end ;
236
+ endmodule ;
0 commit comments