0134d5267ce7afadcb028261d9a1363152c9e2f4
[shakti-core.git] / src / core / icache_asic.bsv
1 /*
2 Copyright (c) 2013, IIT Madras
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
7 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 * Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
13 */
14 package icache_asic;
15 /*===== Pacakge imports ===== */
16 import BRAMCore::*;
17 import FIFO::*;
18 import FIFOF::*;
19 import SpecialFIFOs::*;
20 import LFSR::*;
21 import ConfigReg::*;
22 import DReg::*;
23 import BUtils::*;
24 import MemoryMap::*;
25 /*===== project imports==== */
26 import defined_types::*;
27 `ifdef bpu
28 import branchpredictor::*;
29 `endif
30 `include "defined_parameters.bsv"
31 /*========================= */
32
33
34 interface Ifc_icache;
35 method Action virtual_address(Bit#(`VADDR) vaddress,Bool fence);
36 method Maybe#(Tuple3#(Bit#(32), Trap_type, Bit#(`PERFMONITORS))) response_to_core;
37 method Action response_from_memory(From_Memory#(`DCACHE_WORD_SIZE) resp);
38 method ActionValue#(To_Memory#(`PADDR)) request_to_memory;
39 method Action stall_fetch(Bool stall);
40
41 // method Bool init_complete;
42 `ifdef bpu
43 method Maybe#(Tuple2#(Bit#(`VADDR),Bit#(2))) prediction_response;
44 method Action training (Maybe#(Training_data#(`VADDR)) training_data);
45 `endif
46 `ifdef MMU
47 method Action physical_address(Bit#(`PADDR) paddr, Trap_type ex);
48 `endif
49
50 method Bit#(`PERFMONITORS) icache_perfmon;
51 `ifdef prefetch
52 method ActionValue#(Bit#(`VADDR)) prefetch();
53 `endif
54 endinterface
55
56 typedef enum {Idle,Stall,ReadingCache,Fence,IOReadResp} IcacheState deriving (Bits,Eq,FShow);
57
58 (*synthesize*)
59 (*preempts="fillcache,fencing_the_cache"*)
60 module mkicache(Ifc_icache);
61 /* VAddr = [tag_bits|set_bits|word_bits|byte_bits] */
62 let byte_bits=valueOf(TLog#(`ICACHE_WORD_SIZE)); // number of bits to select a byte within a word. = 2
63 let word_bits=valueOf(TLog#(`ICACHE_BLOCK_SIZE)); // number of bits to select a word within a block. = 4
64 let set_bits=valueOf(TLog#(`ICACHE_SETS)); // number of bits to select a set from the cache. =
65 `ifdef bpu
66 Ifc_branchpredictor bpu <-mkbranchpredictor;
67 Wire#(Maybe#(Tuple2#(Bit#(`VADDR),Bit#(2)))) wr_prediction_to_cpu <-mkDWire(tagged Invalid);
68 `endif
69
70 BRAM_DUAL_PORT#(Bit#(TLog#(`ICACHE_SETS)),Bit#(TAdd#(`ICACHE_TAG_BITS,2))) tag [`ICACHE_WAYS];
71 BRAM_DUAL_PORT_BE#(Bit#(TLog#(`ICACHE_SETS)),Bit#(TMul#(TMul#(8,`ICACHE_WORD_SIZE),`ICACHE_BLOCK_SIZE)),64) data [`ICACHE_WAYS];
72 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin
73 tag[i] <- mkBRAMCore2(`ICACHE_SETS,False);
74 data[i] <-mkBRAMCore2BE(`ICACHE_SETS,False);
75 end
76
77 LFSR#(Bit#(2)) random_line<-mkRCounter(3); // for random line replacement
78 Reg#(Bit#(`VADDR)) rg_vaddress<-mkReg(0);
79 Reg#(Bit#(`PADDR)) rg_paddress<-mkReg(0);
80 Reg#(Trap_type) rg_tlb_exception[2]<-mkCReg(2,tagged None);
81 Reg#(Bool) rg_trnslte_done[2] <- mkCReg(2, `ifdef MMU False `else True `endif );
82 Reg#(Bool) rg_stall_fetch <- mkReg(False);
83
84 Reg#(Bit#(`PERFMONITORS)) rg_perf_monitor<-mkReg(0);
85 Reg#(IcacheState) rg_state[3]<-mkCReg(3,Fence); // this needs to be a CReg so that request can fire in the same cycle as response
86 Reg#(Bit#(TAdd#(1,TLog#(`ICACHE_SETS)))) rg_index <-mkReg(0);
87 Reg#(Maybe#(Bit#(TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE)))) rg_we<-mkReg(tagged Invalid);
88 Reg#(Bit#(TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE))) line_bytes_written<-mkReg(0);
89 Reg#(Bool) increment_counters <-mkReg(True);
90 Reg#(Bool) capture_counters <-mkDReg(False);
91
92 Wire#(Maybe#(Bit#(`VADDR))) wr_memoperation_address <-mkDWire(tagged Invalid);
93
94 Reg#(Bool) ignore_memory_response<-mkReg(False);
95 `ifdef prefetch
96 Reg#(Bool) prefetchmode<-mkReg(False);
97 Reg#(Maybe#(Bit#(`VADDR))) rg_prefetchpc<-mkReg(tagged Invalid);
98 `endif
99
100 Wire#(Maybe#(Tuple3#(Bit#(32), Trap_type,Bit#(`PERFMONITORS)))) wr_response_to_cpu<-mkDWire(tagged Invalid);
101 FIFOF#(To_Memory#(`PADDR)) ff_request_to_memory <-mkSizedBypassFIFOF(1);
102 FIFOF#(From_Memory#(`DCACHE_WORD_SIZE)) ff_response_from_memory <-mkSizedBypassFIFOF(1);
103 FIFOF#(Tuple4#(Bit#(`PADDR),Bit#(`VADDR),Bit#(TLog#(`ICACHE_WAYS)),Bit#(TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE)))) memoperation <-mkUGSizedFIFOF(2);
104 rule display_state;
105 `ifdef verbose $display($time,"\tICACHE: State: ",fshow(rg_state[2])," wr_flush ",fshow(wr_flush)," rg_flush ",fshow(rg_flush)); `endif
106 `ifdef verbose $display($time,"\tICACHE: translation done %h tlbexception: ", rg_trnslte_done[1], fshow(rg_tlb_exception[1])); `endif
107 endrule
108
109 /*====== Invalidate all the entries in the cache on startup or during Fence ==== */
110 rule fencing_the_cache(rg_state[0]==Fence);
111 rg_we<=tagged Invalid;
112 memoperation.clear;
113 `ifdef verbose $display($time,"\tFencing icache of index %d", rg_index); `endif
114 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin
115 tag[i].b.put(True,truncate(rg_index),0);
116 end
117 if(rg_index==fromInteger(`ICACHE_SETS)) begin
118 if(!rg_stall_fetch) begin
119 `ifdef verbose $display($time,"\tFencing icache of is over"); `endif
120 rg_state[0]<=Idle;
121 rg_index<=0;
122 random_line.seed('d3);
123 end
124 end
125 else
126 rg_index<=rg_index+1;
127 endrule
128 rule discard_memory_responses_during_fence;
129 ff_response_from_memory.deq;
130 endrule
131 /*=============================================================================== */
132 rule read_data_fromcache(rg_state[0]==ReadingCache && memoperation.notFull);
133 /*========== Check for hit or miss =================== */
134 Bit#(TLog#(`ICACHE_WAYS)) linenum=0;
135 Bit#(`PERFMONITORS) perf_monitor=rg_perf_monitor;
136 Bit#(TMul#(TMul#(`ICACHE_BLOCK_SIZE,`ICACHE_WORD_SIZE),8)) dataline=0;
137 increment_counters<=True;
138 Bool hit=False;
139 Bit#(`ICACHE_WAYS) valid_values; // hold the valid and dirty bits
140 Bit#(TLog#(`ICACHE_BLOCK_SIZE)) byteoffset=rg_vaddress[word_bits+byte_bits-1:byte_bits];
141 Bit#(TLog#(`DCACHE_SETS)) setindex=rg_vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
142 `ifdef MMU
143 Bit#(`ICACHE_TAG_BITS) cpu_tag=rg_paddress[`PADDR-1:`PADDR-`ICACHE_TAG_BITS];
144 `else
145 Bit#(`ICACHE_TAG_BITS) cpu_tag=rg_vaddress[`PADDR-1:`PADDR-`ICACHE_TAG_BITS];
146 `endif
147 if(rg_trnslte_done[0]) begin
148 `ifdef MMU
149 if(rg_tlb_exception[0] matches tagged None)begin
150 if(!is_IO_Addr(rg_paddress))begin
151 `else
152 if(!is_IO_Addr(truncate(rg_vaddress)))begin
153 `endif
154 `ifdef prefetch
155 if(!prefetchmode && increment_counters)
156 perf_monitor[`ICACHE_CACHEABLE]=1; // cacheable access increment
157 `else
158 perf_monitor[`ICACHE_CACHEABLE]=1; // cacheable access increment
159 `endif
160 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin
161 let stored_tag=tag[i].a.read[19:0];
162 let stored_valid=tag[i].a.read[20];
163 valid_values[i]=tag[i].a.read[20];
164 if(stored_valid==1 && stored_tag==cpu_tag)begin // if a tag matches capture the tag and data
165 hit=True;
166 linenum=fromInteger(i);
167 dataline=data[i].a.read;
168 `ifdef verbose $display($time,"ICACHE: DATALINE: %h",dataline); `endif
169 end
170 end
171 Bit#(32) data_value=(dataline>>{5'd0,byteoffset}*32)[31:0];
172
173 /*====================================================== */
174 /*=========== Respond to Core ============================ */
175 if(rg_vaddress[1:0]!=0)begin // miss-aligned error.
176 perf_monitor[`ICACHE_MISALIGNED]=1; // cache mis-aligned error.
177 wr_response_to_cpu<=tagged Valid (tuple3(0,tagged Exception Inst_addr_misaligned,perf_monitor));
178 rg_perf_monitor<=0;
179 rg_state[0]<=Idle;
180 `ifdef prefetch prefetchmode<=False; `endif
181 let x<-bpu.prediction_response;
182 wr_prediction_to_cpu<=tagged Valid x;
183 `ifdef MMU rg_trnslte_done[0] <= False; `endif
184 end
185 else if(hit)begin // if there has been a hit.
186 `ifdef verbose $display($time,"\tICACHE: Hit for address : %h data: %h offset: %h line: %d",rg_vaddress,data_value,byteoffset,linenum); `endif
187 rg_prefetchpc<=tagged Invalid;
188 `ifdef prefetch
189 if(!prefetchmode)begin
190 wr_response_to_cpu<=tagged Valid (tuple3(data_value,tagged None,perf_monitor));
191 rg_perf_monitor<=0;
192 `ifdef MMU rg_trnslte_done[0] <= False; `endif
193 end
194 else
195 prefetchmode<=False;
196 `else
197 wr_response_to_cpu<=tagged Valid (tuple3(data_value,tagged None,perf_monitor));
198 rg_perf_monitor<=0;
199 `ifdef MMU rg_trnslte_done[0] <= False; `endif
200 `endif
201 rg_state[0]<=Idle;
202 let x<-bpu.prediction_response;
203 wr_prediction_to_cpu<=tagged Valid x;
204 end
205 /*====================================================== */
206 /*==== Request to memory =============================== */
207 else begin // miss
208 `ifdef prefetch
209 if(!prefetchmode) begin
210 if(rg_vaddress[11:5]!='1)begin // check that prefetch does not cross physical page boundary
211 Bit#(`VADDR) mask='1<<(byte_bits+word_bits);
212 rg_prefetchpc<=tagged Valid ((rg_vaddress&mask)+('d1<<(word_bits+byte_bits)));
213 perf_monitor[`ICACHE_MISS]=1; // cache miss increment.
214 end
215 rg_state[0]<=Stall;
216 end
217 else // in prefetch mode send memory request and leave
218 rg_state[0]<=Idle;
219 `else
220 perf_monitor[`ICACHE_MISS]=1; // cache miss increment.
221 rg_state[0]<=Stall;
222 `endif
223 Bit#(TLog#(`ICACHE_WAYS)) replaceblock;
224 if(valid_values=='1)begin // if all the lines are valid and no match then replace line
225 perf_monitor[`ICACHE_LINEREPLACE]=1; // cache line replacement increment.
226 replaceblock=truncate(random_line.value);
227 random_line.next;
228 if(prefetchmode)begin
229 `ifdef verbose $display($time,"\tICACHE: Prefetch Miss of address: %h Replacing line: %d valid: %b",rg_vaddress,random_line.value[1:0],valid_values); `endif
230 perf_monitor[`ICACHE_PREFETCHMISS]=1;
231 end
232 `ifdef verbose else
233 $display($time,"\tICACHE: Miss of address: %h Replacing line: %d valid: %b",rg_vaddress,random_line.value[1:0],valid_values); `endif
234 end
235 else begin // find the line which is not valid and fill it
236 let x=countZerosLSB(valid_values)-1;
237 replaceblock=pack(truncate(x));
238 if(prefetchmode)begin
239 `ifdef verbose $display($time,"\tICACHE: Prefetch Miss of address: %h Filling line: %d",rg_vaddress,x); `endif
240 perf_monitor[`ICACHE_PREFETCHMISS]=1;
241 end
242 `ifdef verbose else
243 $display($time,"\tICACHE: Miss of address: %h Filling line: %d",rg_vaddress,x); `endif
244 end
245 `ifdef MMU
246 ff_request_to_memory.enq(To_Memory {address:truncate(rg_paddress&'hfffffff8),burst_length:fromInteger(`ICACHE_BLOCK_SIZE/2),ld_st:Load, transfer_size:3});
247 `else
248 ff_request_to_memory.enq(To_Memory {address:truncate(rg_vaddress&'hfffffff8),burst_length:fromInteger(`ICACHE_BLOCK_SIZE/2),ld_st:Load, transfer_size:3});
249 `endif
250 Bit#(TLog#(`ICACHE_BLOCK_SIZE)) val1=(rg_vaddress&'hfffffff8)[word_bits+byte_bits-1:byte_bits];
251 Bit#(TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE)) writeenable='hFF;
252 writeenable=writeenable<<{3'b0,val1}*4;
253 memoperation.enq(tuple4(rg_paddress,rg_vaddress,replaceblock,writeenable));
254 `ifdef verbose $display($time,"\tICACHE: mask: %h byteoffset: %h perfmonitors: %h",writeenable,val1,perf_monitor); `endif
255 rg_perf_monitor<=perf_monitor;
256 end
257 end
258 else begin
259 if(!prefetchmode)begin
260 `ifdef MMU
261 ff_request_to_memory.enq(To_Memory {address:truncate(rg_paddress),burst_length:1,ld_st:Load, transfer_size:2});
262 `else
263 ff_request_to_memory.enq(To_Memory {address:truncate(rg_vaddress),burst_length:1,ld_st:Load, transfer_size:2});
264 `endif
265 rg_state[0]<=IOReadResp;
266 `ifdef verbose $display($time,"\tICACHE: Sending Address for IO ACCESS: %h",rg_paddress); `endif
267 end
268 else begin
269 $display($time,"\tICACHE: Do not prefetch in IO space");
270 rg_state[0]<=Idle;
271 prefetchmode<=False;
272 end
273 end
274 end
275 else begin
276 if(!prefetchmode)begin
277 wr_response_to_cpu<=tagged Valid tuple3(0,rg_tlb_exception[0],perf_monitor);
278 let x<-bpu.prediction_response;
279 wr_prediction_to_cpu<=tagged Valid x;
280 end
281 else begin
282 $display($time,"\tICACHE: do not respond if Prefetch generated a exception");
283 prefetchmode<=False;
284 end
285 rg_state[0]<=Idle;
286 `ifdef MMU rg_trnslte_done[0] <= False; `endif
287 rg_tlb_exception[0]<=tagged None;
288 end
289 /*===================================================================*/
290 end
291 else begin
292 `ifdef verbose $display($time,"\tICACHE: Translated Address not Available"); `endif
293 rg_state[0] <= Stall;
294 end
295 endrule
296 /*======= filling up the cache from the data recieved from the external memory ======= */
297 rule read_IO_response(rg_state[0]==IOReadResp && !memoperation.notEmpty);
298 let memresp=ff_response_from_memory.first;
299 `ifdef verbose $display($time,"\tICACHE: Got response from IO ADDRESS: %h",memresp.data_line); `endif
300 wr_response_to_cpu<=tagged Valid (tuple3(truncate(memresp.data_line),memresp.bus_error==1?tagged Exception Inst_access_fault:tagged None,1));
301 wr_prediction_to_cpu<=tagged Valid (tuple2(0,0));
302 rg_state[0]<=Idle;
303 endrule
304 rule temp(memoperation.notEmpty);
305 let {paddress,vaddress,replaceblock,writeenable}=memoperation.first;
306 wr_memoperation_address<=tagged Valid vaddress;
307 endrule
308 rule fillcache(memoperation.notEmpty);
309 let memresp=ff_response_from_memory.first;
310 let {paddress,vaddress,replaceblock,writeenable}=memoperation.first;
311 `ifdef MMU
312 let cpu_tag=paddress[`PADDR-1:`PADDR-`ICACHE_TAG_BITS];
313 `else
314 let cpu_tag=vaddress[`PADDR-1:`PADDR-`ICACHE_TAG_BITS];
315 `endif
316 let setindex=vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
317 `ifdef verbose $display($time,"\tICACHE: Response from Memory: %h ",memresp.data_line); `endif
318 let we=writeenable;
319 if(rg_we matches tagged Valid .x)begin
320 we=x;
321 end
322 Bit#(TMul#(2,TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE))) extended_mask=zeroExtend(we)<<8;
323 data[replaceblock].b.put(we,setindex,duplicate(memresp.data_line));
324 `ifdef verbose $display($time,"\tICACHE ExtendedMASK: %h RgMASK: %h line_bytes_written: %h",extended_mask,we,line_bytes_written); `endif
325 tag[replaceblock].b.put(True,setindex,{2'b1,cpu_tag}); // update the tag value
326 if(memresp.last_word)begin // if all the data words have been fetched exit
327 `ifdef verbose $display($time,"\tICACHE: Received Last response from Memory"); `endif
328 `ifdef prefetch
329 prefetchmode<=False;
330 `endif
331 rg_we<=tagged Invalid;
332 memoperation.deq;
333 line_bytes_written<=0;
334 end
335 else begin
336 rg_we<=tagged Valid (extended_mask[2*`ICACHE_BLOCK_SIZE*`ICACHE_WORD_SIZE-1:`ICACHE_BLOCK_SIZE*`ICACHE_WORD_SIZE]|extended_mask[`ICACHE_BLOCK_SIZE*`ICACHE_WORD_SIZE-1:0]);
337 line_bytes_written<=line_bytes_written|we;
338 end
339 endrule
340 /*===================================================================================== */
341 /*===================================================================================== */
342 rule keep_polling_on_stall(rg_state[0]==Stall);
343 Bit#(TLog#(`ICACHE_BLOCK_SIZE)) byteoffset=rg_vaddress[word_bits+byte_bits-1:byte_bits];
344 Bit#(TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE)) requested_word=('hF<<({2'd0,byteoffset}*4));
345 Bool generate_request=True;
346 Bit#(`PERFMONITORS) perf_monitor=0;
347 if(capture_counters)begin
348 perf_monitor[`ICACHE_CACHEABLE]=1;
349 perf_monitor[`ICACHE_MISS]=1;
350 rg_perf_monitor<=perf_monitor;
351 end
352
353 if(!memoperation.notFull)
354 generate_request=False;
355 else if(wr_memoperation_address matches tagged Valid .x)begin // some line is being filled from memory
356 Bit#(TSub#(`VADDR,TAdd#(TLog#(`ICACHE_WORD_SIZE),TLog#(`ICACHE_BLOCK_SIZE)))) memline=x[`VADDR-1:word_bits+byte_bits];
357 Bit#(TSub#(`VADDR,TAdd#(TLog#(`ICACHE_WORD_SIZE),TLog#(`ICACHE_BLOCK_SIZE)))) reqline=rg_vaddress[`VADDR-1:word_bits+byte_bits];
358 if(memline==reqline) // they are accessing the same line
359 if((line_bytes_written & requested_word) != requested_word)
360 generate_request=False;
361 end
362 if(generate_request && rg_trnslte_done[1])begin
363 Bit#(TLog#(`ICACHE_SETS)) setindex=rg_vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
364 `ifdef verbose $display($time,"\tICACHE: POLLING ON VAddr: %h set: %d rg_trnslte_done: %b",rg_vaddress, setindex,rg_trnslte_done[1]); `endif
365 increment_counters<=False;
366 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin // send address to the Block_rams
367 tag[i].a.put(False,rg_vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits], ?);
368 data[i].a.put('d0,rg_vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits], ?);
369 end
370 `ifdef bpu
371 bpu.send_prediction_request(rg_vaddress);
372 `endif
373 rg_state[0]<=ReadingCache;
374 end
375 endrule
376
377 /*============= Prediction in burst mode ================================ */
378 method Action virtual_address(Bit#(`VADDR) vaddress,Bool fence)if(rg_state[1]==Idle);
379 if(fence)begin
380 rg_state[1]<=Fence;
381 end
382 else begin
383 Bit#(TLog#(`ICACHE_SETS)) setindex=vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
384 `ifdef verbose $display($time,"\tICACHE: Request of VAddr: %h set: %d",vaddress, setindex); `endif
385 Bit#(TLog#(`ICACHE_BLOCK_SIZE)) byteoffset=vaddress[word_bits+byte_bits-1:byte_bits];
386 Bit#(TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE)) requested_word=('hF<<({2'd0,byteoffset}*4));
387 Bool generate_request=True;
388 if(!memoperation.notFull)
389 generate_request=False;
390 else if(wr_memoperation_address matches tagged Valid .x)begin // some line is being filled from memory
391 Bit#(TSub#(`VADDR,TAdd#(TLog#(`ICACHE_WORD_SIZE),TLog#(`ICACHE_BLOCK_SIZE)))) memline=x[`VADDR-1:word_bits+byte_bits];
392 Bit#(TSub#(`VADDR,TAdd#(TLog#(`ICACHE_WORD_SIZE),TLog#(`ICACHE_BLOCK_SIZE)))) reqline=vaddress[`VADDR-1:word_bits+byte_bits];
393 if(memline==reqline) // they are accessing the same line
394 if((line_bytes_written & requested_word) != requested_word)
395 generate_request=False;
396 end
397 rg_vaddress<=vaddress;
398 if(generate_request)begin
399 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin // send address to the Block_rams
400 tag[i].a.put(False,vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits], ?);
401 data[i].a.put('d0,vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits], ?);
402 end
403 `ifdef bpu
404 bpu.send_prediction_request(vaddress);
405 `endif
406 rg_state[1]<=ReadingCache;
407 end
408 else begin
409 `ifdef verbose $display($time,"\tICACHE: Miss during Cache Fill"); `endif
410 capture_counters<=True;
411 rg_state[1]<=Stall;
412 end
413 end
414 endmethod
415 method Maybe#(Tuple3#(Bit#(32), Trap_type, Bit#(`PERFMONITORS))) response_to_core;
416 return wr_response_to_cpu;
417 endmethod
418 `ifdef MMU
419 method Action physical_address(Bit#(`PADDR) paddr, Trap_type ex);
420 `ifdef verbose $display($time,"\tICACHE: Sending physical address %h to icache ",paddr); `endif
421 rg_paddress<=paddr;
422 rg_tlb_exception[1]<=ex;
423 //rg_state[1]<=ReadingCache;
424 rg_trnslte_done[1] <= True;
425 endmethod
426 `endif
427 method ActionValue#(To_Memory#(`PADDR)) request_to_memory;
428 ff_request_to_memory.deq;
429 return ff_request_to_memory.first;
430 endmethod
431 method Action response_from_memory(From_Memory#(`DCACHE_WORD_SIZE) resp);
432 if(!ignore_memory_response)
433 ff_response_from_memory.enq(resp);
434 else if(resp.last_word)
435 ignore_memory_response<=False;
436 endmethod
437 method Bit#(`PERFMONITORS) icache_perfmon;
438 return rg_perf_monitor;
439 endmethod
440 // method Bool init_complete;
441 // return (rg_state[1]!=Fence `ifdef bpu && bpu.init_complete `endif );
442 // endmethod
443 method Action stall_fetch(Bool stall);
444 rg_stall_fetch <= stall;
445 endmethod
446 `ifdef prefetch
447 method ActionValue#(Bit#(`VADDR)) prefetch() if(rg_state[1]==Idle &&& rg_prefetchpc matches tagged Valid .vaddress &&& !memoperation.notEmpty);
448 Bit#(TLog#(`ICACHE_SETS)) setindex=vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
449 `ifdef verbose $display($time,"\tICACHE: Prefetch Request of VAddr: %h set: %d",vaddress, setindex); `endif
450 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin // send address to the Block_rams
451 tag[i].a.put(False,vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits], ?);
452 data[i].a.put('d0,vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits], ?);
453 end
454 rg_state[1]<=ReadingCache;
455 rg_vaddress<=vaddress;
456 prefetchmode<=True;
457 rg_prefetchpc<=tagged Invalid;
458 return vaddress;
459 endmethod
460 `endif
461 `ifdef bpu
462 method Maybe#(Tuple2#(Bit#(`VADDR),Bit#(2))) prediction_response;
463 return wr_prediction_to_cpu;
464 endmethod
465 method Action training (Maybe#(Training_data#(`VADDR)) training_data)=bpu.training(training_data);
466 `endif
467 endmodule
468 endpackage