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 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
16 /*========= package imports========== */
18 import SpecialFIFOs::*;
19 import Connectable::*;
21 /*==================================== */
22 /* ======== project imports ========= */
25 import defined_types::*;
28 import branchpredictor::*;
30 `include "core_parameters.bsv"
31 `ifdef MMU import iTLB::*; `endif
32 /* ================================== */
35 /*======= Mandatory Interface to the core ================ */
36 interface Put#(Tuple5#(Bit#(2),Bit#(`VADDR),Bit#(`VADDR),Bool,Bit#(3))) request_from_core;
37 method Maybe#(Tuple7#(Bit#(`VADDR),Bit#(2),Bit#(`VADDR),Bit#(32), Trap_type, Bit#(`PERFMONITORS), Bit#(3))) instruction_response_to_core;
38 method Action flush(Flush_type _flush);
39 method Bit#(`PERFMONITORS) imem_perfmon;
40 // method Bool init_complete;
41 method Action stall_fetch(Bool stall);
42 /*=============================================== */
43 /*====== Madatory Interface to the external Bus ======= */
44 method Action response_from_memory(From_Memory#(`DCACHE_WORD_SIZE) mem_data);
45 method ActionValue#(To_Memory#(`PADDR)) request_to_memory;
46 /*============================================ */
48 interface Get#(Tuple4#(Bit#(3),Bit#(`VADDR),Bit#(`VADDR),Bit#(2))) prediction_response;
49 method Action training (Maybe#(Training_data#(`VADDR)) training_data);
50 interface Put#(Tuple2#(Bit#(3),Bit#(`VADDR))) send_prediction_request;
53 method Action translation_protection_frm_csr(bit tlb_disable, Chmod per_bits, Bit#(TAdd#(4,`ASID)) asid);
54 interface Get#(Request_PPN_PTW#(`VADDR,`OFFSET)) to_PTW;
55 interface Put#(Tuple2#(Bool,To_TLB#(`PADDR,`OFFSET,`ASID))) refill_TLB;
56 method Action fence_itlb(Fence_VMA_type#(`VADDR) rsdata);
59 method Action prefetch();
63 (*mutually_exclusive="request_from_core.put,send_cache_request_to_memory"*)
64 //(*mutually_exclusive="request_from_core.put,send_translated_vaddress"*)
65 module mkimem(Ifc_imem);
66 Ifc_icache icache <- mkicache;
67 Reg#(Bool) io_access_started<-mkReg(False);
69 Wire#(Bit#(`VADDR)) wr_address_from_core <-mkWire();
70 Wire#(Bool) wr_flush <-mkDWire(False);
73 Ifc_branchpredictor bpu<-mkbranchpredictor();
77 Wire#(Maybe#(Tuple7#(Bit#(`VADDR),Bit#(2),Bit#(`VADDR), Bit#(32), Trap_type, Bit#(`PERFMONITORS),Bit#(3)))) wr_response_to_cpu<-mkDWire(tagged Invalid);
78 FIFOF#(To_Memory#(`PADDR)) ff_request_to_memory <-mkSizedBypassFIFOF(1);
79 Reg#(Trap_type) rg_exception <- mkReg(tagged None);
80 Reg#(Bit#(3)) epochs <-mkReg(0);
81 Reg#(Bit#(`VADDR)) pc<-mkReg(0);
82 Reg#(Bit#(`VADDR)) npc<-mkReg(0);
83 Reg#(Bit#(2)) prediction <-mkReg(0);
86 Ifc_iTLB itlb <- mkiTLB;
87 rule send_translated_paddress(rg_exception matches tagged None);
88 let x <- itlb.send_ppn;
89 //if(x.exception matches tagged None) begin
90 icache.physical_address(truncate(x.address),x.exception); //TODO vaddr
94 rule send_cache_request_to_memory;
95 let x<-icache.request_to_memory;
96 ff_request_to_memory.enq(x);
98 /*======= collect responses from the cache and store them in the FIFOs============ */
100 // This rule collects the prediction information from the branchpredictor and stores in them
101 // FIFO. The request to the predictor is provided as part of the request to the cache itself.
102 // This the branchpredictor will not work for io accesses.
103 // This rule collects the instructions provided by the cache. The cache can provide a one or two instructions. If there is a hit
104 // in the cache then a single instruction is provided. On a miss in the cache the instruction are supplied as part of the cache-line-fill
105 // which is 2 instructions at a time. Whethere to enque one or two or no instructions into the core pipe is indicated by the variable
106 // singledual. A value of 00 indicates that none of the instructions provided by the memory (as part of the line) need to be enqued
107 // into the cache. A value of 01 means the lower instruction should be enqued, 'b10 means the upper instruction only needs to be enqued
108 // and 'b11 means both the instructions need to be enqueud.
109 rule collect_first_instruction_from_icache;
110 let x=icache.response_to_core;
111 if(x matches tagged Valid .resp)begin
112 let {instr,trap,perf}=resp;
113 wr_response_to_cpu<=tagged Valid tuple7(pc,prediction,npc,instr,trap,perf,epochs);
116 /*======================================================================================= */
119 /*==== prefetch should start as soon as the cache is idle and a previous line was a miss=== */
121 rule perform_prefetch;
122 let x<-icache.prefetch;
123 `ifdef MMU itlb.get_vaddr(signExtend(x)); `endif
126 /*===================================================================== */
129 /*===================== Interface to the Core ======== */
130 interface request_from_core = interface Put
131 method Action put(Tuple5#(Bit#(2),Bit#(`VADDR),Bit#(`VADDR),Bool,Bit#(3)) request);
132 let {pred,nextpc,instr_addr,fence,epoch_req}=request;
137 `ifdef verbose $display($time,"\tIMEM: Sending request to cache for address: %h prediction: %b",instr_addr,prediction); `endif
139 itlb.get_vaddr(signExtend(instr_addr));
141 icache.virtual_address(instr_addr,fence);
144 method Maybe#(Tuple7#(Bit#(`VADDR), Bit#(2),Bit#(`VADDR),Bit#(32), Trap_type, Bit#(`PERFMONITORS),Bit#(3))) instruction_response_to_core=wr_response_to_cpu;
145 /*==================================================== */
148 method Action training (Maybe#(Training_data#(`VADDR)) training_data)=bpu.training(training_data);
149 interface send_prediction_request=bpu.send_prediction_request;
150 interface prediction_response=bpu.prediction_response;
153 method Action flush(Flush_type _flush);
157 method Bit#(`PERFMONITORS) imem_perfmon=icache.icache_perfmon;
158 method Action stall_fetch(Bool stall) = icache.stall_fetch(stall);
159 /*===================================================== */
161 /*======= Interface to the external Memory =========== */
162 method Action response_from_memory(From_Memory#(`DCACHE_WORD_SIZE) mem_data)=icache.response_from_memory(mem_data);
163 method ActionValue#(To_Memory#(`PADDR)) request_to_memory;
164 ff_request_to_memory.deq;
165 return ff_request_to_memory.first;
167 /*===================================================== */
169 method Action translation_protection_frm_csr(bit tlb_disable, Chmod per_bits, Bit#(TAdd#(4,`ASID)) asid);
170 itlb.translation_protection_frm_csr(tlb_disable, per_bits, asid);
172 interface to_PTW = itlb.to_PTW;
173 interface refill_TLB = itlb.refill_TLB;
174 method Action fence_itlb(Fence_VMA_type#(`VADDR) rsdata);
175 itlb.fence_TLB(rsdata);