Mercurial > pygar
comparison modules/bluespec/Pygar/lab4/DataCacheBlocking.bsv @ 8:74716e9a81cc pygar svn.9
[svn r9] Pygar now has the proper directory structure to play nicely with awb. Also, the apm file for audio-core willcompile successfully.
author | rlm |
---|---|
date | Fri, 23 Apr 2010 02:32:05 -0400 |
parents | |
children | 3958de09a7c1 |
comparison
equal
deleted
inserted
replaced
7:7393cd19371e | 8:74716e9a81cc |
---|---|
1 // The MIT License | |
2 | |
3 // Copyright (c) 2009 Massachusetts Institute of Technology | |
4 | |
5 // Permission is hereby granted, free of charge, to any person obtaining a copy | |
6 // of this software and associated documentation files (the "Software"), to deal | |
7 // in the Software without restriction, including without limitation the rights | |
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
9 // copies of the Software, and to permit persons to whom the Software is | |
10 // furnished to do so, subject to the following conditions: | |
11 | |
12 // The above copyright notice and this permission notice shall be included in | |
13 // all copies or substantial portions of the Software. | |
14 | |
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
21 // THE SOFTWARE. | |
22 | |
23 // Local includes | |
24 `include "asim/provides/low_level_platform_interface.bsh" | |
25 `include "asim/provides/soft_connections.bsh" | |
26 `include "asim/provides/processor_library.bsh" | |
27 `include "asim/provides/fpga_components.bsh" | |
28 `include "asim/provides/common_services.bsh" | |
29 `include "asim/dict/STATS_DATA_CACHE.bsh" | |
30 | |
31 import Connectable::*; | |
32 import GetPut::*; | |
33 import ClientServer::*; | |
34 import RegFile::*; | |
35 import FIFO::*; | |
36 import FIFOF::*; | |
37 | |
38 | |
39 | |
40 | |
41 interface DCache#( type req_t, type resp_t ); | |
42 | |
43 // Interface from processor to cache | |
44 interface Server#(req_t,resp_t) proc_server; | |
45 | |
46 // Interface from cache to main memory | |
47 interface Client#(MainMemReq,MainMemResp) mmem_client; | |
48 | |
49 // Interface for enabling/disabling statistics | |
50 interface Put#(Bool) statsEn_put; | |
51 | |
52 endinterface | |
53 | |
54 | |
55 //---------------------------------------------------------------------- | |
56 // Cache Types | |
57 //---------------------------------------------------------------------- | |
58 | |
59 typedef 10 CacheLineIndexSz; | |
60 typedef 20 CacheLineTagSz; | |
61 typedef 32 CacheLineSz; | |
62 | |
63 typedef Bit#(CacheLineIndexSz) CacheLineIndex; | |
64 typedef Bit#(CacheLineTagSz) CacheLineTag; | |
65 typedef Bit#(CacheLineSz) CacheLine; | |
66 | |
67 typedef enum | |
68 { | |
69 Init, | |
70 Access, | |
71 RefillReq, | |
72 RefillResp | |
73 } | |
74 CacheStage | |
75 deriving (Eq,Bits); | |
76 | |
77 //---------------------------------------------------------------------- | |
78 // Helper functions | |
79 //---------------------------------------------------------------------- | |
80 | |
81 function Bit#(AddrSz) getAddr( DataReq req ); | |
82 | |
83 Bit#(AddrSz) addr = ?; | |
84 case ( req ) matches | |
85 tagged LoadReq .ld : addr = ld.addr; | |
86 tagged StoreReq .st : addr = st.addr; | |
87 endcase | |
88 | |
89 return addr; | |
90 | |
91 endfunction | |
92 | |
93 function CacheLineIndex getCacheLineIndex( DataReq req ); | |
94 Bit#(AddrSz) addr = getAddr(req); | |
95 Bit#(CacheLineIndexSz) index = truncate( addr >> 2 ); | |
96 return index; | |
97 endfunction | |
98 | |
99 function CacheLineTag getCacheLineTag( DataReq req ); | |
100 Bit#(AddrSz) addr = getAddr(req); | |
101 Bit#(CacheLineTagSz) tag = truncate( addr >> fromInteger(valueOf(CacheLineIndexSz)) >> 2 ); | |
102 return tag; | |
103 endfunction | |
104 | |
105 function Bit#(AddrSz) getCacheLineAddr( DataReq req ); | |
106 Bit#(AddrSz) addr = getAddr(req); | |
107 return ((addr >> 2) << 2); | |
108 endfunction | |
109 | |
110 //---------------------------------------------------------------------- | |
111 // Main module | |
112 //---------------------------------------------------------------------- | |
113 | |
114 module [CONNECTED_MODULE] mkDataCache( DCache#(DataReq,DataResp) ); | |
115 | |
116 //----------------------------------------------------------- | |
117 // State | |
118 | |
119 Reg#(CacheStage) stage <- mkReg(Init); | |
120 | |
121 LUTRAM#(CacheLineIndex,Maybe#(CacheLineTag)) cacheTagRam <- mkLUTRAMU_RegFile(); | |
122 LUTRAM#(CacheLineIndex,CacheLine) cacheDataRam <- mkLUTRAMU_RegFile(); | |
123 | |
124 FIFO#(DataReq) reqQ <- mkFIFO(); | |
125 FIFOF#(DataResp) respQ <- mkBFIFOF1(); | |
126 | |
127 FIFO#(MainMemReq) mainMemReqQ <- mkBFIFO1(); | |
128 FIFO#(MainMemResp) mainMemRespQ <- mkFIFO(); | |
129 | |
130 Reg#(CacheLineIndex) initCounter <- mkReg(1); | |
131 | |
132 // Statistics state | |
133 | |
134 Reg#(Bool) statsEn <- mkReg(False); | |
135 | |
136 STAT num_accesses <- mkStatCounter(`STATS_DATA_CACHE_NUM_ACCESSES); | |
137 STAT num_misses <- mkStatCounter(`STATS_DATA_CACHE_NUM_MISSES); | |
138 STAT num_writebacks <- mkStatCounter(`STATS_DATA_CACHE_NUM_WRITEBACKS); | |
139 | |
140 //----------------------------------------------------------- | |
141 // Name some wires | |
142 | |
143 let req = reqQ.first(); | |
144 let reqIndex = getCacheLineIndex(req); | |
145 let reqTag = getCacheLineTag(req); | |
146 let reqCacheLineAddr = getCacheLineAddr(req); | |
147 | |
148 //----------------------------------------------------------- | |
149 // Initialize | |
150 | |
151 rule init ( stage == Init ); | |
152 traceTiny("mkDataCacheBlocking", "stage","i"); | |
153 initCounter <= initCounter + 1; | |
154 cacheTagRam.upd(initCounter,Invalid); | |
155 if ( initCounter == 0 ) | |
156 stage <= Access; | |
157 endrule | |
158 | |
159 //----------------------------------------------------------- | |
160 // Access cache rule | |
161 | |
162 rule access ( (stage == Access) && respQ.notFull() ); | |
163 | |
164 // Statistics | |
165 | |
166 if ( statsEn ) | |
167 num_accesses.incr(); | |
168 | |
169 | |
170 // Get the corresponding tag from the rams | |
171 | |
172 Maybe#(CacheLineTag) cacheLineTag = cacheTagRam.sub(reqIndex); | |
173 | |
174 // Handle cache hits ... | |
175 | |
176 if ( isValid(cacheLineTag) && ( unJust(cacheLineTag) == reqTag ) ) | |
177 begin | |
178 traceTiny("mkDataCacheBlocking", "hitMiss","h"); | |
179 reqQ.deq(); | |
180 | |
181 case ( req ) matches | |
182 | |
183 tagged LoadReq .ld : | |
184 respQ.enq( LoadResp { tag: ld.tag, data: cacheDataRam.sub(reqIndex) } ); | |
185 | |
186 tagged StoreReq .st : | |
187 begin | |
188 respQ.enq( StoreResp { tag : st.tag } ); | |
189 cacheDataRam.upd(reqIndex,st.data); | |
190 end | |
191 | |
192 endcase | |
193 | |
194 end | |
195 | |
196 // Handle cache misses ... | |
197 | |
198 else | |
199 begin | |
200 traceTiny("mkDataCacheBlocking", "hitMiss","m"); | |
201 if ( statsEn ) | |
202 num_misses.incr(); | |
203 | |
204 // Currently we don't use dirty bits so we always writeback the data if it is valid | |
205 | |
206 if ( isValid(cacheLineTag) ) | |
207 begin | |
208 | |
209 if ( statsEn ) | |
210 num_writebacks.incr(); | |
211 | |
212 MainMemReq wbReq | |
213 = StoreReq { tag : 0, | |
214 addr : { unJust(cacheLineTag), reqIndex, 2'b0 }, | |
215 data : cacheDataRam.sub(reqIndex) }; | |
216 | |
217 mainMemReqQ.enq(wbReq); | |
218 stage <= RefillReq; | |
219 end | |
220 | |
221 // Otherwise we can issue the refill request now | |
222 | |
223 else | |
224 begin | |
225 mainMemReqQ.enq( LoadReq { tag: 0, addr: reqCacheLineAddr } ); | |
226 stage <= RefillResp; | |
227 end | |
228 | |
229 end | |
230 | |
231 endrule | |
232 | |
233 //----------------------------------------------------------- | |
234 // Refill request rule | |
235 | |
236 rule refillReq ( stage == RefillReq ); | |
237 traceTiny("mkDataCacheBlocking", "stage","r"); | |
238 mainMemReqQ.enq( LoadReq { tag: 0, addr: reqCacheLineAddr } ); | |
239 stage <= RefillResp; | |
240 endrule | |
241 | |
242 //----------------------------------------------------------- | |
243 // Refill response rule | |
244 | |
245 rule refillResp ( stage == RefillResp ); | |
246 traceTiny("mkDataCacheBlocking", "stage","R"); | |
247 traceTiny("mkDataCacheBlocking", "refill",mainMemRespQ.first()); | |
248 | |
249 // Write the new data into the cache and update the tag | |
250 | |
251 mainMemRespQ.deq(); | |
252 case ( mainMemRespQ.first() ) matches | |
253 | |
254 tagged LoadResp .ld : | |
255 begin | |
256 cacheTagRam.upd(reqIndex,Valid(reqTag)); | |
257 cacheDataRam.upd(reqIndex,ld.data); | |
258 end | |
259 | |
260 tagged StoreResp .st : | |
261 noAction; | |
262 | |
263 endcase | |
264 | |
265 stage <= Access; | |
266 endrule | |
267 | |
268 //----------------------------------------------------------- | |
269 // Methods | |
270 | |
271 interface Client mmem_client; | |
272 interface Get request = fifoToGet(mainMemReqQ); | |
273 interface Put response = fifoToPut(mainMemRespQ); | |
274 endinterface | |
275 | |
276 interface Server proc_server; | |
277 interface Put request = tracePut("mkDataCacheBlocking", "reqTiny",fifoToPut(reqQ)); | |
278 interface Get response = traceGet("mkDataCacheBlocking", "respTiny",fifofToGet(respQ)); | |
279 endinterface | |
280 | |
281 interface Put statsEn_put = regToPut(statsEn); | |
282 | |
283 endmodule |