use Num_Fast_Slaves define
[shakti-core.git] / src / core / imem.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 imem;
15
16 /*========= package imports========== */
17 import FIFOF::*;
18 import SpecialFIFOs::*;
19 import Connectable::*;
20 import GetPut::*;
21 /*==================================== */
22 /* ======== project imports ========= */
23 import TxRx ::*;
24 import icache ::*;
25 import defined_types::*;
26 import MemoryMap::*;
27 `ifdef bpu
28 import branchpredictor::*;
29 `endif
30 `include "core_parameters.bsv"
31 `ifdef MMU import iTLB::*; `endif
32 /* ================================== */
33
34 interface Ifc_imem;
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 /*============================================ */
47 `ifdef bpu
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;
51 `endif
52 `ifdef MMU
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);
57 `endif
58 `ifdef prefetch
59 method Action prefetch();
60 `endif
61 endinterface
62 (*synthesize*)
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);
68
69 Wire#(Bit#(`VADDR)) wr_address_from_core <-mkWire();
70 Wire#(Bool) wr_flush <-mkDWire(False);
71
72 `ifdef bpu
73 Ifc_branchpredictor bpu<-mkbranchpredictor();
74 `endif
75
76
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);
84
85 `ifdef MMU
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
91 //end
92 endrule
93 `endif
94 rule send_cache_request_to_memory;
95 let x<-icache.request_to_memory;
96 ff_request_to_memory.enq(x);
97 endrule
98 /*======= collect responses from the cache and store them in the FIFOs============ */
99
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);
114 end
115 endrule
116 /*======================================================================================= */
117
118
119 /*==== prefetch should start as soon as the cache is idle and a previous line was a miss=== */
120 `ifdef prefetch
121 rule perform_prefetch;
122 let x<-icache.prefetch;
123 `ifdef MMU itlb.get_vaddr(signExtend(x)); `endif
124 endrule
125 `endif
126 /*===================================================================== */
127
128
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;
133 epochs<=epoch_req;
134 pc<=instr_addr;
135 prediction<=pred;
136 npc<=nextpc;
137 `ifdef verbose $display($time,"\tIMEM: Sending request to cache for address: %h prediction: %b",instr_addr,prediction); `endif
138 `ifdef MMU
139 itlb.get_vaddr(signExtend(instr_addr));
140 `endif
141 icache.virtual_address(instr_addr,fence);
142 endmethod
143 endinterface;
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 /*==================================================== */
146
147 `ifdef bpu
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;
151 `endif
152
153 method Action flush(Flush_type _flush);
154 `ifdef MMU
155 `endif
156 endmethod
157 method Bit#(`PERFMONITORS) imem_perfmon=icache.icache_perfmon;
158 method Action stall_fetch(Bool stall) = icache.stall_fetch(stall);
159 /*===================================================== */
160
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;
166 endmethod
167 /*===================================================== */
168 `ifdef MMU
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);
171 endmethod
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);
176 endmethod
177 `endif
178 endmodule
179
180 endpackage