2 Copyright (c) 2013, IIT Madras
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
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.
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 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
15 /*===== Pacakge imports ===== */
19 import SpecialFIFOs::*;
25 import mem_config1::*;
26 /*===== project imports==== */
29 import defined_types::*;
30 `include "core_parameters.bsv"
31 /*========================= */
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);
42 method Action physical_address(Bit#(`PADDR) paddr, Trap_type ex);
45 method Bit#(`PERFMONITORS) icache_perfmon;
47 method ActionValue#(Bit#(`VADDR)) prefetch();
51 typedef enum {Idle,KeepPolling,Stall,ReadingCache,Fence,IOReadResp} IcacheState deriving (Bits,Eq,FShow);
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. =
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;
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);
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);
85 Wire#(Maybe#(Bit#(`VADDR))) wr_memoperation_address <-mkDWire(tagged Invalid);
87 Reg#(Bool) ignore_memory_response<-mkReg(False);
89 Reg#(Bool) prefetchmode<-mkReg(False);
90 Reg#(Maybe#(Bit#(`VADDR))) rg_prefetchpc<-mkReg(tagged Invalid);
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);
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);
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);
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
111 /*====== Invalidate all the entries in the cache on startup or during Fence ==== */
112 rule fencing_the_cache(rg_state[0]==Fence && !memoperation.notEmpty);
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
120 random_line.seed('d3);
124 for(Integer i=0;i<`ICACHE_WAYS;i=i+1)begin
125 tag[i].write_request(True,truncate(rg_index),0);
127 rg_index<=rg_index+1;
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;
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];
144 Bit#(`ICACHE_TAG_BITS) cpu_tag=rg_paddress[`PADDR-1:`PADDR-`ICACHE_TAG_BITS];
146 Bit#(`ICACHE_TAG_BITS) cpu_tag=rg_vaddress[`PADDR-1:`PADDR-`ICACHE_TAG_BITS];
148 if(rg_trnslte_done[0]) begin
150 if(rg_tlb_exception[0] matches tagged None)begin
151 if(!is_IO_Addr(rg_paddress))begin
153 if(!is_IO_Addr(truncate(rg_vaddress)))begin
156 if(!prefetchmode && increment_counters)
157 perf_monitor[`ICACHE_CACHEABLE]=1; // cacheable access increment
159 perf_monitor[`ICACHE_CACHEABLE]=1; // cacheable access increment
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];
166 if(stored_valid==1 && stored_tag==cpu_tag)begin // if a tag matches capture the tag and data
168 linenum=fromInteger(i);
169 dataline=data[i].read_response;
170 `ifdef verbose $display($time,"ICACHE: DATALINE: %h",dataline); `endif
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];
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
187 Bit#(32) data_value_lb=(dataline_lb>>{5'd0,byteoffset}*32)[31:0];
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));
199 `ifdef prefetch prefetchmode<=False; `endif
200 `ifdef MMU rg_trnslte_done[0] <= False; `endif
202 else if(hit || (lbhit&&!polling_required))begin // if there has been a hit.
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
207 rg_prefetchpc<=tagged Invalid;
208 if(!prefetchmode)begin
209 wr_response_to_cpu<=tagged Valid (tuple3(data_value,tagged None,perf_monitor));
211 `ifdef MMU rg_trnslte_done[0] <= False; `endif
216 wr_response_to_cpu<=tagged Valid (tuple3(data_value,tagged None,perf_monitor));
218 `ifdef MMU rg_trnslte_done[0] <= False; `endif
222 else if(lbhit && polling_required)begin
223 rg_state[0]<=KeepPolling;
225 /*====================================================== */
226 /*==== Request to memory =============================== */
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.
235 rg_state[0]<=KeepPolling;
237 else // in prefetch mode send memory request and leave
240 perf_monitor[`ICACHE_MISS]=1; // cache miss increment.
241 rg_state[0]<=KeepPolling;
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);
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;
255 $display($time,"\tICACHE: Miss of address: %h Replacing line: %d valid: %b",rg_vaddress,random_line.value[1:0],valid_values); `endif
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));
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;
267 $display($time,"\tICACHE: Miss of address: %h Filling line: %d",rg_vaddress,x); `endif
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});
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});
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;
284 if(prefetchmode)begin
285 `ifdef verbose $display($time,"\tICACHE: Do not prefetch in IO space"); `endif
293 ff_request_to_memory.enq(To_Memory {address:truncate(rg_paddress),burst_length:1,ld_st:Load, transfer_size:2});
295 ff_request_to_memory.enq(To_Memory {address:truncate(rg_vaddress),burst_length:1,ld_st:Load, transfer_size:2});
297 rg_state[0]<=IOReadResp;
298 `ifdef verbose $display($time,"\tICACHE: Sending Address for IO ACCESS: %h",rg_paddress); `endif
304 if(prefetchmode)begin
305 `ifdef verbose $display($time,"\tICACHE: do not respond if Prefetch generated a exception"); `endif
310 wr_response_to_cpu<=tagged Valid tuple3(0,rg_tlb_exception[0],perf_monitor);
311 `ifdef verbose $display($time,"\tICACHE: TLB Exception "); `endif
314 `ifdef MMU rg_trnslte_done[0] <= False; `endif
315 rg_tlb_exception[0]<=tagged None;
317 /*===================================================================*/
320 `ifdef verbose $display($time,"\tICACHE: Translated Address not Available"); `endif
321 rg_state[0] <= KeepPolling;
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));
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;
339 'd0:lbreplaceblock='b0001;
340 'd1:lbreplaceblock='b0010;
341 'd2:lbreplaceblock='b0100;
342 'd3:lbreplaceblock='b1000;
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);
348 line_bytes_written<=0;
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)
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
363 if(|line_bytes_written!=0)begin
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
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;
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);
385 rg_state[0]<=ReadingCache;
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;
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
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);
419 rg_state[1]<=ReadingCache;
424 /*============= Prediction in burst mode ================================ */
425 method Action virtual_address(Bit#(`VADDR) vaddress,Bool fence)if(rg_state[1]==Idle);
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]);
437 rg_state[1]<=ReadingCache;
440 method Maybe#(Tuple3#(Bit#(32), Trap_type, Bit#(`PERFMONITORS))) response_to_core;
441 return wr_response_to_cpu;
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
447 rg_tlb_exception[1]<=ex;
448 //rg_state[1]<=ReadingCache;
449 rg_trnslte_done[1] <= True;
452 method ActionValue#(To_Memory#(`PADDR)) request_to_memory;
453 ff_request_to_memory.deq;
454 return ff_request_to_memory.first;
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;
462 method Bit#(`PERFMONITORS) icache_perfmon;
463 return rg_perf_monitor;
465 method Action stall_fetch(Bool stall);
466 rg_stall_fetch <= stall;
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]);
476 rg_state[1]<=ReadingCache;
477 rg_vaddress<=vaddress;
479 rg_prefetchpc<=tagged Invalid;