SDRAM uses SDR0MemBase now
[shakti-core.git] / src / core / icache.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;
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 import mem_config1::*;
26 /*===== project imports==== */
27 import QuadMem::*;
28 import Assert::*;
29 import defined_types::*;
30 `include "core_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 `ifdef MMU
42 method Action physical_address(Bit#(`PADDR) paddr, Trap_type ex);
43 `endif
44
45 method Bit#(`PERFMONITORS) icache_perfmon;
46 `ifdef prefetch
47 method ActionValue#(Bit#(`VADDR)) prefetch();
48 `endif
49 endinterface
50
51 typedef enum {Idle,KeepPolling,Stall,ReadingCache,Fence,IOReadResp} IcacheState deriving (Bits,Eq,FShow);
52
53 (*synthesize*)
54 (*preempts="read_from_lbdata_into_hold_reg,keep_polling_on_stall"*)
55 (*preempts="virtual_address,read_from_lbdata_into_hold_reg"*)
56 (*preempts="read_data_fromcache,read_from_lbdata_into_hold_reg"*)
57 module mkicache(Ifc_icache);
58 /* VAddr = [tag_bits|set_bits|word_bits|byte_bits] */
59 let byte_bits=valueOf(TLog#(`ICACHE_WORD_SIZE)); // number of bits to select a byte within a word. = 2
60 let word_bits=valueOf(TLog#(`ICACHE_BLOCK_SIZE)); // number of bits to select a word within a block. = 4
61 let set_bits=valueOf(TLog#(`ICACHE_SETS)); // number of bits to select a set from the cache. =
62
63 Ifc_dcache_data data [`ICACHE_WAYS];
64 Ifc_dcache_tag tag [`ICACHE_WAYS];
65 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin
66 tag[i] <- mkdcache_tag;
67 data[i] <-mkdcache_data;
68 end
69
70 LFSR#(Bit#(2)) random_line<-mkRCounter(3); // for random line replacement
71 Reg#(Bit#(`VADDR)) rg_vaddress<-mkReg(0);
72 Reg#(Bit#(`PADDR)) rg_paddress<-mkReg(0);
73 Reg#(Trap_type) rg_tlb_exception[2]<-mkCReg(2,tagged None);
74 Reg#(Bool) rg_trnslte_done[2] <- mkCReg(2, `ifdef MMU False `else True `endif );
75 Reg#(Bool) rg_stall_fetch <- mkReg(False);
76
77 Reg#(Bit#(`PERFMONITORS)) rg_perf_monitor<-mkReg(0);
78 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
79 Reg#(Bit#(TAdd#(1,TLog#(`ICACHE_SETS)))) rg_index <-mkReg(0);
80 Reg#(Bit#(TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE))) rg_we<-mkReg(0);
81 Reg#(Bit#(TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE))) line_bytes_written<-mkReg(0);
82 Reg#(Bool) increment_counters <-mkReg(True);
83 Reg#(Bool) capture_counters <-mkDReg(False);
84
85 Wire#(Maybe#(Bit#(`VADDR))) wr_memoperation_address <-mkDWire(tagged Invalid);
86
87 Reg#(Bool) ignore_memory_response<-mkReg(False);
88 `ifdef prefetch
89 Reg#(Bool) prefetchmode<-mkReg(False);
90 Reg#(Maybe#(Bit#(`VADDR))) rg_prefetchpc<-mkReg(tagged Invalid);
91 `endif
92
93 Ifc_QuadMem lbdata <-mkQuadMem;
94 Wire#(Maybe#(Tuple3#(Bit#(32), Trap_type,Bit#(`PERFMONITORS)))) wr_response_to_cpu<-mkDWire(tagged Invalid);
95 FIFOF#(To_Memory#(`PADDR)) ff_request_to_memory <-mkSizedBypassFIFOF(1);
96 FIFOF#(From_Memory#(`DCACHE_WORD_SIZE)) ff_response_from_memory <-mkSizedBypassFIFOF(1);
97 FIFOF#(Tuple4#(Bit#(`PADDR),Bit#(`VADDR),Bit#(TLog#(`ICACHE_WAYS)),Bit#(TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE)))) memoperation <-mkUGSizedFIFOF(2);
98
99 Wire#(Maybe#(Bit#(TLog#(`ICACHE_SETS)))) wr_tag_read_index <- mkDWire(tagged Invalid);
100 Reg#(Maybe#(Bit#(TLog#(`ICACHE_SETS)))) wr_tag_write_index <- mkDReg(tagged Invalid);
101
102 Wire#(Maybe#(Bit#(TLog#(`ICACHE_SETS)))) wr_data_read_index <- mkDWire(tagged Invalid);
103 Reg#(Maybe#(Bit#(TLog#(`ICACHE_SETS)))) wr_data_write_index <- mkDReg(tagged Invalid);
104
105
106 rule display_state;
107 `ifdef verbose $display($time,"\tICACHE: State: ",fshow(rg_state[2])); `endif
108 `ifdef verbose $display($time,"\tICACHE: translation done %h tlbexception: ", rg_trnslte_done[1], fshow(rg_tlb_exception[1])); `endif
109 endrule
110
111 /*====== Invalidate all the entries in the cache on startup or during Fence ==== */
112 rule fencing_the_cache(rg_state[0]==Fence && !memoperation.notEmpty);
113 rg_we<=0;
114 `ifdef verbose $display($time,"\tFencing icache of index %d", rg_index); `endif
115 if(rg_index==fromInteger(`ICACHE_SETS)) begin
116 if(!rg_stall_fetch) begin
117 `ifdef verbose $display($time,"\tFencing icache of is over"); `endif
118 rg_state[0]<=Idle;
119 rg_index<=0;
120 random_line.seed('d3);
121 end
122 end
123 else begin
124 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin
125 tag[i].write_request(True,truncate(rg_index),0);
126 end
127 rg_index<=rg_index+1;
128 end
129 endrule
130 /*=============================================================================== */
131 rule read_data_fromcache(rg_state[0]==ReadingCache && memoperation.notFull);
132 /*========== Check for hit or miss =================== */
133 Bit#(TLog#(`ICACHE_WAYS)) linenum=0;
134 Bit#(`PERFMONITORS) perf_monitor=rg_perf_monitor;
135 Bit#(TMul#(TMul#(`ICACHE_BLOCK_SIZE,`ICACHE_WORD_SIZE),8)) dataline=0;
136 Bit#(TMul#(TMul#(`ICACHE_BLOCK_SIZE,`ICACHE_WORD_SIZE),8)) dataline_lb=0;
137 increment_counters<=True;
138 Bool hit=False;
139 Bool lbhit=False;
140 Bit#(`ICACHE_WAYS) valid_values=0; // hold the valid and dirty bits
141 Bit#(TLog#(`ICACHE_BLOCK_SIZE)) byteoffset=rg_vaddress[word_bits+byte_bits-1:byte_bits];
142 Bit#(TLog#(`ICACHE_SETS)) setindex=rg_vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
143 `ifdef MMU
144 Bit#(`ICACHE_TAG_BITS) cpu_tag=rg_paddress[`PADDR-1:`PADDR-`ICACHE_TAG_BITS];
145 `else
146 Bit#(`ICACHE_TAG_BITS) cpu_tag=rg_vaddress[`PADDR-1:`PADDR-`ICACHE_TAG_BITS];
147 `endif
148 if(rg_trnslte_done[0]) begin
149 `ifdef MMU
150 if(rg_tlb_exception[0] matches tagged None)begin
151 if(!is_IO_Addr(rg_paddress))begin
152 `else
153 if(!is_IO_Addr(truncate(rg_vaddress)))begin
154 `endif
155 `ifdef prefetch
156 if(!prefetchmode && increment_counters)
157 perf_monitor[`ICACHE_CACHEABLE]=1; // cacheable access increment
158 `else
159 perf_monitor[`ICACHE_CACHEABLE]=1; // cacheable access increment
160 `endif
161 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin
162 let stored_tag=tag[i].read_response[19:0];
163 let stored_valid=tag[i].read_response[20];
164 valid_values[i]=tag[i].read_response[20];
165
166 if(stored_valid==1 && stored_tag==cpu_tag)begin // if a tag matches capture the tag and data
167 hit=True;
168 linenum=fromInteger(i);
169 dataline=data[i].read_response;
170 `ifdef verbose $display($time,"ICACHE: DATALINE: %h",dataline); `endif
171 end
172 end
173 //wr_tag_read_index <= tagged Valid setindex;
174 //wr_data_read_index <= tagged Valid setindex;
175 Bit#(32) data_value=(dataline>>{5'd0,byteoffset}*32)[31:0];
176
177 let linebuffer=lbdata.response_portA;
178 let {lb_paddress,lb_vaddress,lbreplaceblock,lbwriteenable}=memoperation.first;
179 Bit#(`ICACHE_TAG_BITS) lbtag=lb_paddress[`PADDR-1:`PADDR-`ICACHE_TAG_BITS];
180 Bit#(TLog#(`ICACHE_SETS)) lbset=lb_vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
181 if(memoperation.notEmpty && lbset==setindex && lbtag==cpu_tag)begin
182 dataline_lb=linebuffer;
183 `ifdef verbose $display($time,"\tICACHE: LB BUFFER HIT: data %h",dataline_lb); `endif
184 lbhit=True;
185 hit=False;
186 end
187 Bit#(32) data_value_lb=(dataline_lb>>{5'd0,byteoffset}*32)[31:0];
188
189 Bit#(TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE)) requested_word=('hF<<({2'd0,byteoffset}*4));
190 Bool polling_required= (line_bytes_written & requested_word) != requested_word;
191 `ifdef verbose $display($time,"\tICACHE: DATAVALUE: %h DATAVALUELB: %h requested_word: %h line_bytes_written: %h",data_value,data_value_lb,requested_word, line_bytes_written); `endif
192 /*====================================================== */
193 /*=========== Respond to Core ============================ */
194 if(rg_vaddress[1:0]!=0)begin // miss-aligned error.
195 perf_monitor[`ICACHE_MISALIGNED]=1; // cache mis-aligned error.
196 wr_response_to_cpu<=tagged Valid (tuple3(0,tagged Exception Inst_addr_misaligned,perf_monitor));
197 rg_perf_monitor<=0;
198 rg_state[0]<=Idle;
199 `ifdef prefetch prefetchmode<=False; `endif
200 `ifdef MMU rg_trnslte_done[0] <= False; `endif
201 end
202 else if(hit || (lbhit&&!polling_required))begin // if there has been a hit.
203 if(lbhit )
204 data_value = data_value_lb;
205 `ifdef verbose $display($time,"\tICACHE: Hit for address : %h data: %h offset: %h line: %d hit: %b lbhit: %b, polling_required: %b",rg_vaddress,data_value,byteoffset,linenum,hit,lbhit, polling_required); `endif
206 `ifdef prefetch
207 rg_prefetchpc<=tagged Invalid;
208 if(!prefetchmode)begin
209 wr_response_to_cpu<=tagged Valid (tuple3(data_value,tagged None,perf_monitor));
210 rg_perf_monitor<=0;
211 `ifdef MMU rg_trnslte_done[0] <= False; `endif
212 end
213 else
214 prefetchmode<=False;
215 `else
216 wr_response_to_cpu<=tagged Valid (tuple3(data_value,tagged None,perf_monitor));
217 rg_perf_monitor<=0;
218 `ifdef MMU rg_trnslte_done[0] <= False; `endif
219 `endif
220 rg_state[0]<=Idle;
221 end
222 else if(lbhit && polling_required)begin
223 rg_state[0]<=KeepPolling;
224 end
225 /*====================================================== */
226 /*==== Request to memory =============================== */
227 else begin // miss
228 `ifdef prefetch
229 if(!prefetchmode) begin
230 if(rg_vaddress[11:5]!='1)begin // check that prefetch does not cross physical page boundary
231 Bit#(`VADDR) mask='1<<(byte_bits+word_bits);
232 rg_prefetchpc<=tagged Valid ((rg_vaddress&mask)+('d1<<(word_bits+byte_bits)));
233 perf_monitor[`ICACHE_MISS]=1; // cache miss increment.
234 end
235 rg_state[0]<=KeepPolling;
236 end
237 else // in prefetch mode send memory request and leave
238 rg_state[0]<=Idle;
239 `else
240 perf_monitor[`ICACHE_MISS]=1; // cache miss increment.
241 rg_state[0]<=KeepPolling;
242 `endif
243 Bit#(TLog#(`ICACHE_WAYS)) replaceblock;
244 if(valid_values=='1)begin // if all the lines are valid and no match then replace line
245 perf_monitor[`ICACHE_LINEREPLACE]=1; // cache line replacement increment.
246 replaceblock=truncate(random_line.value);
247 random_line.next;
248 `ifdef prefetch
249 if(prefetchmode)begin
250 `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
251 perf_monitor[`ICACHE_PREFETCHMISS]=1;
252 end
253 `endif
254 `ifdef verbose else
255 $display($time,"\tICACHE: Miss of address: %h Replacing line: %d valid: %b",rg_vaddress,random_line.value[1:0],valid_values); `endif
256 end
257 else begin // find the line which is not valid and fill it
258 let x=countZerosLSB(valid_values)-1;
259 replaceblock=pack(truncate(x));
260 `ifdef prefetch
261 if(prefetchmode)begin
262 `ifdef verbose $display($time,"\tICACHE: Prefetch Miss of address: %h Filling line: %d",rg_vaddress,x); `endif
263 perf_monitor[`ICACHE_PREFETCHMISS]=1;
264 end
265 `endif
266 `ifdef verbose else
267 $display($time,"\tICACHE: Miss of address: %h Filling line: %d",rg_vaddress,x); `endif
268 end
269 `ifdef MMU
270 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});
271 `else
272 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});
273 `endif
274 Bit#(TLog#(`ICACHE_BLOCK_SIZE)) val1=(rg_vaddress&'hfffffff8)[word_bits+byte_bits-1:byte_bits];
275 Bit#(TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE)) writeenable='hFF;
276 writeenable=writeenable<<{3'b0,val1}*4;
277 memoperation.enq(tuple4(rg_paddress,rg_vaddress,replaceblock,writeenable));
278 `ifdef verbose $display($time,"\tICACHE: mask: %h byteoffset: %h perfmonitors: %h",writeenable,val1,perf_monitor); `endif
279 rg_perf_monitor<=perf_monitor;
280 end
281 end
282 else begin
283 `ifdef prefetch
284 if(prefetchmode)begin
285 `ifdef verbose $display($time,"\tICACHE: Do not prefetch in IO space"); `endif
286 rg_state[0]<=Idle;
287 prefetchmode<=False;
288 end
289 else `endif
290 begin
291
292 `ifdef MMU
293 ff_request_to_memory.enq(To_Memory {address:truncate(rg_paddress),burst_length:1,ld_st:Load, transfer_size:2});
294 `else
295 ff_request_to_memory.enq(To_Memory {address:truncate(rg_vaddress),burst_length:1,ld_st:Load, transfer_size:2});
296 `endif
297 rg_state[0]<=IOReadResp;
298 `ifdef verbose $display($time,"\tICACHE: Sending Address for IO ACCESS: %h",rg_paddress); `endif
299 end
300 end
301 end
302 else begin
303 `ifdef prefetch
304 if(prefetchmode)begin
305 `ifdef verbose $display($time,"\tICACHE: do not respond if Prefetch generated a exception"); `endif
306 prefetchmode<=False;
307 end
308 else `endif
309 begin
310 wr_response_to_cpu<=tagged Valid tuple3(0,rg_tlb_exception[0],perf_monitor);
311 `ifdef verbose $display($time,"\tICACHE: TLB Exception "); `endif
312 end
313 rg_state[0]<=Idle;
314 `ifdef MMU rg_trnslte_done[0] <= False; `endif
315 rg_tlb_exception[0]<=tagged None;
316 end
317 /*===================================================================*/
318 end
319 else begin
320 `ifdef verbose $display($time,"\tICACHE: Translated Address not Available"); `endif
321 rg_state[0] <= KeepPolling;
322 end
323 endrule
324 /*======= filling up the cache from the data recieved from the external memory ======= */
325 rule read_IO_response(rg_state[0]==IOReadResp && !memoperation.notEmpty);
326 let memresp=ff_response_from_memory.first;
327 ff_response_from_memory.deq;
328 `ifdef verbose $display($time,"\tICACHE: Got response from IO ADDRESS: %h",memresp.data_line); `endif
329 wr_response_to_cpu<=tagged Valid (tuple3(truncate(memresp.data_line),memresp.bus_error==1?tagged Exception Inst_access_fault:tagged None,1));
330 rg_state[0]<=Idle;
331 endrule
332 rule read_from_lbdata_into_hold_reg(line_bytes_written=='1 && memoperation.notEmpty);
333 let lb_hold_reg=lbdata.response_portB;
334 let {paddress,vaddress,replaceblock,writeenable}=memoperation.first;
335 Bit#(`ICACHE_TAG_BITS) cpu_tag=paddress[`PADDR-1:`PADDR-`ICACHE_TAG_BITS];
336 Bit#(TLog#(`ICACHE_SETS)) setindex=vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
337 Bit#(4) lbreplaceblock=0;
338 case (replaceblock)
339 'd0:lbreplaceblock='b0001;
340 'd1:lbreplaceblock='b0010;
341 'd2:lbreplaceblock='b0100;
342 'd3:lbreplaceblock='b1000;
343 endcase
344 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin
345 tag[i].write_request((unpack(lbreplaceblock[i])&&True),setindex,{2'b1,cpu_tag});
346 data[i].write_request(duplicate(lbreplaceblock[i]),setindex,lb_hold_reg);
347 end
348 line_bytes_written<=0;
349 memoperation.deq;
350 `ifdef verbose $display($time,"\tICACHE: capturing lbdata cpu_tag: %h setindex: %d linenum: %b data: %h",cpu_tag, setindex,lbreplaceblock,lb_hold_reg); `endif
351 if(rg_state[1]==KeepPolling)
352 rg_state[1]<=Stall;
353 endrule
354
355 rule fillcache(memoperation.notEmpty && line_bytes_written!='1);
356 let memresp=ff_response_from_memory.first;
357 ff_response_from_memory.deq;
358 let {paddress,vaddress,replaceblock,writeenable}=memoperation.first;
359 let cpu_tag=paddress[`PADDR-1:`PADDR-`ICACHE_TAG_BITS];
360 Bit#(TLog#(`ICACHE_SETS)) setindex=vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
361 `ifdef verbose $display($time,"\tICACHE: Response from Memory: %h writeenable: %h",memresp.data_line, writeenable); `endif
362 let we=writeenable;
363 if(|line_bytes_written!=0)begin
364 we=rg_we;
365 end
366 Bit#(TMul#(2,TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE))) extended_mask=zeroExtend(we)<<8;
367 lbdata.write_portB(we,duplicate(memresp.data_line));
368 `ifdef verbose $display($time,"\tICACHE: linebytes: %h currently writing into: %h",line_bytes_written,we); `endif
369 if(memresp.last_word)begin // if all the data words have been fetched exit
370 `ifdef verbose $display($time,"\tICACHE: Received Last response from Memory"); `endif
371 end
372 `ifdef prefetch
373 prefetchmode<=False;
374 `endif
375 rg_we<=(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]);
376 line_bytes_written<=line_bytes_written|we;
377 endrule
378 /*===================================================================================== */
379 rule stall_the_next_request_by_one_cycle(rg_state[0]==Stall);
380 Bit#(TLog#(`ICACHE_SETS)) setindex=rg_vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
381 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin // send address to the Block_rams
382 tag[i].read_request(setindex);
383 data[i].read_request(setindex);
384 end
385 rg_state[0]<=ReadingCache;
386 endrule
387 /*===================================================================================== */
388 rule keep_polling_on_stall(rg_state[1]==KeepPolling);
389 Bit#(TLog#(`ICACHE_BLOCK_SIZE)) byteoffset=rg_vaddress[word_bits+byte_bits-1:byte_bits];
390 Bit#(TMul#(`ICACHE_WORD_SIZE,`ICACHE_BLOCK_SIZE)) requested_word=('hF<<({2'd0,byteoffset}*4));
391 Bit#(`PERFMONITORS) perf_monitor=0;
392 if(capture_counters)begin
393 perf_monitor[`ICACHE_CACHEABLE]=1;
394 perf_monitor[`ICACHE_MISS]=1;
395 rg_perf_monitor<=perf_monitor;
396 end
397 let {lb_paddress,lb_vaddress,replaceblock,writeenable}=memoperation.first;
398 Bit#(TLog#(`ICACHE_SETS)) setindex=rg_vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
399 Bit#(20) cpu_tag=rg_paddress[`PADDR-1:`PADDR-20];
400 Bit#(`ICACHE_TAG_BITS) lbtag=lb_paddress[`PADDR-1:`PADDR-`ICACHE_TAG_BITS];
401 Bit#(TLog#(`ICACHE_SETS)) lbset=lb_vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
402 Bool generate_request=True;
403 `ifdef verbose $display($time,"\tICACHE: line_bytes_written: %h requested_word: %h memoperation: %b ",line_bytes_written,requested_word,memoperation.notEmpty); `endif
404 if(lbset==setindex && lbtag==cpu_tag && memoperation.notEmpty)
405 if((line_bytes_written & requested_word) != requested_word)
406 generate_request=False;
407 if(rg_trnslte_done[1] && generate_request)begin
408 if(rg_tlb_exception[1] matches tagged None)begin
409 begin
410 `ifdef verbose $display($time,"\tICACHE: Accessing LB"); `endif
411 rg_state[1]<=ReadingCache;
412 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin // send address to the Block_rams
413 tag[i].read_request(setindex);
414 data[i].read_request(setindex);
415 end
416 end
417 end
418 else begin
419 rg_state[1]<=ReadingCache;
420 end
421 end
422 endrule
423
424 /*============= Prediction in burst mode ================================ */
425 method Action virtual_address(Bit#(`VADDR) vaddress,Bool fence)if(rg_state[1]==Idle);
426 if(fence)begin
427 rg_state[1]<=Fence;
428 end
429 else begin
430 Bit#(TLog#(`ICACHE_SETS)) setindex=vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
431 `ifdef verbose $display($time,"\tICACHE: Request of VAddr: %h set: %d",vaddress, setindex); `endif
432 rg_vaddress<=vaddress;
433 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin // send address to the Block_rams
434 tag[i].read_request(truncate(setindex));
435 data[i].read_request(vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits]);
436 end
437 rg_state[1]<=ReadingCache;
438 end
439 endmethod
440 method Maybe#(Tuple3#(Bit#(32), Trap_type, Bit#(`PERFMONITORS))) response_to_core;
441 return wr_response_to_cpu;
442 endmethod
443 `ifdef MMU
444 method Action physical_address(Bit#(`PADDR) paddr, Trap_type ex);
445 `ifdef verbose $display($time,"\tICACHE: Sending physical address %h to icache ",paddr); `endif
446 rg_paddress<=paddr;
447 rg_tlb_exception[1]<=ex;
448 //rg_state[1]<=ReadingCache;
449 rg_trnslte_done[1] <= True;
450 endmethod
451 `endif
452 method ActionValue#(To_Memory#(`PADDR)) request_to_memory;
453 ff_request_to_memory.deq;
454 return ff_request_to_memory.first;
455 endmethod
456 method Action response_from_memory(From_Memory#(`DCACHE_WORD_SIZE) resp);
457 if(!ignore_memory_response)
458 ff_response_from_memory.enq(resp);
459 else if(resp.last_word)
460 ignore_memory_response<=False;
461 endmethod
462 method Bit#(`PERFMONITORS) icache_perfmon;
463 return rg_perf_monitor;
464 endmethod
465 method Action stall_fetch(Bool stall);
466 rg_stall_fetch <= stall;
467 endmethod
468 `ifdef prefetch
469 method ActionValue#(Bit#(`VADDR)) prefetch() if(rg_state[1]==Idle &&& rg_prefetchpc matches tagged Valid .vaddress &&& !memoperation.notEmpty);
470 Bit#(TLog#(`ICACHE_SETS)) setindex=vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits];
471 `ifdef verbose $display($time,"\tICACHE: Prefetch Request of VAddr: %h set: %d",vaddress, setindex); `endif
472 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin // send address to the Block_rams
473 tag[i].read_request(truncate(setindex));
474 data[i].read_request(vaddress[set_bits+word_bits+byte_bits-1:word_bits+byte_bits]);
475 end
476 rg_state[1]<=ReadingCache;
477 rg_vaddress<=vaddress;
478 prefetchmode<=True;
479 rg_prefetchpc<=tagged Invalid;
480 return vaddress;
481 endmethod
482 `endif
483 endmodule
484 endpackage