Mercurial > pygar
comparison modules/bluespec/Pygar/lab4/InstCacheBlocking.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 import Connectable::*; | |
24 import GetPut::*; | |
25 import ClientServer::*; | |
26 import RegFile::*; | |
27 import FIFO::*; | |
28 import FIFOF::*; | |
29 import RWire::*; | |
30 | |
31 // Local includes | |
32 `include "asim/provides/low_level_platform_interface.bsh" | |
33 `include "asim/provides/soft_connections.bsh" | |
34 `include "asim/provides/processor_library.bsh" | |
35 `include "asim/provides/fpga_components.bsh" | |
36 `include "asim/provides/common_services.bsh" | |
37 `include "asim/dict/STATS_INST_CACHE.bsh" | |
38 | |
39 interface ICache#( type req_t, type resp_t ); | |
40 | |
41 // Interface from processor to cache | |
42 interface Server#(req_t,resp_t) proc_server; | |
43 | |
44 // Interface from cache to main memory | |
45 interface Client#(MainMemReq,MainMemResp) mmem_client; | |
46 | |
47 // Interface for enabling/disabling statistics | |
48 interface Put#(Bool) statsEn_put; | |
49 | |
50 endinterface | |
51 | |
52 //---------------------------------------------------------------------- | |
53 // Cache Types | |
54 //---------------------------------------------------------------------- | |
55 | |
56 typedef 10 CacheLineIndexSz; | |
57 typedef 20 CacheLineTagSz; | |
58 typedef 32 CacheLineSz; | |
59 | |
60 typedef Bit#(CacheLineIndexSz) CacheLineIndex; | |
61 typedef Bit#(CacheLineTagSz) CacheLineTag; | |
62 typedef Bit#(CacheLineSz) CacheLine; | |
63 | |
64 typedef enum | |
65 { | |
66 Init, | |
67 Access, | |
68 Evict, | |
69 RefillReq, | |
70 RefillResp | |
71 } | |
72 CacheStage | |
73 deriving (Eq,Bits); | |
74 | |
75 //---------------------------------------------------------------------- | |
76 // Helper functions | |
77 //---------------------------------------------------------------------- | |
78 | |
79 function Bit#(AddrSz) getAddr( InstReq req ); | |
80 | |
81 Bit#(AddrSz) addr = ?; | |
82 case ( req ) matches | |
83 tagged LoadReq .ld : addr = ld.addr; | |
84 tagged StoreReq .st : addr = st.addr; | |
85 endcase | |
86 | |
87 return addr; | |
88 | |
89 endfunction | |
90 | |
91 function CacheLineIndex getCacheLineIndex( InstReq req ); | |
92 Bit#(AddrSz) addr = getAddr(req); | |
93 Bit#(CacheLineIndexSz) index = truncate( addr >> 2 ); | |
94 return index; | |
95 endfunction | |
96 | |
97 function CacheLineTag getCacheLineTag( InstReq req ); | |
98 Bit#(AddrSz) addr = getAddr(req); | |
99 Bit#(CacheLineTagSz) tag = truncate( addr >> fromInteger(valueOf(CacheLineIndexSz)) >> 2 ); | |
100 return tag; | |
101 endfunction | |
102 | |
103 function Bit#(AddrSz) getCacheLineAddr( InstReq req ); | |
104 Bit#(AddrSz) addr = getAddr(req); | |
105 return ((addr >> 2) << 2); | |
106 endfunction | |
107 | |
108 //---------------------------------------------------------------------- | |
109 // Main module | |
110 //---------------------------------------------------------------------- | |
111 | |
112 module [CONNECTED_MODULE] mkInstCache( ICache#(InstReq,InstResp) ); | |
113 | |
114 //----------------------------------------------------------- | |
115 // State | |
116 | |
117 Reg#(CacheStage) stage <- mkReg(Init); | |
118 | |
119 LUTRAM#(CacheLineIndex,Maybe#(CacheLineTag)) cacheTagRam <- mkLUTRAMU_RegFile(); | |
120 LUTRAM#(CacheLineIndex,CacheLine) cacheDataRam <- mkLUTRAMU_RegFile(); | |
121 | |
122 FIFO#(InstReq) reqQ <- mkFIFO(); | |
123 FIFOF#(InstResp) respQ <- mkBFIFOF1(); | |
124 | |
125 FIFO#(MainMemReq) mainMemReqQ <- mkBFIFO1(); | |
126 FIFO#(MainMemResp) mainMemRespQ <- mkFIFO(); | |
127 | |
128 Reg#(CacheLineIndex) initCounter <- mkReg(1); | |
129 | |
130 // Statistics state | |
131 | |
132 Reg#(Bool) statsEn <- mkReg(False); | |
133 | |
134 STAT num_accesses <- mkStatCounter(`STATS_INST_CACHE_NUM_ACCESSES); | |
135 STAT num_misses <- mkStatCounter(`STATS_INST_CACHE_NUM_MISSES); | |
136 STAT num_evictions <- mkStatCounter(`STATS_INST_CACHE_NUM_EVICTIONS); | |
137 | |
138 //----------------------------------------------------------- | |
139 // Name some wires | |
140 | |
141 let req = reqQ.first(); | |
142 let reqIndex = getCacheLineIndex(req); | |
143 let reqTag = getCacheLineTag(req); | |
144 let reqCacheLineAddr = getCacheLineAddr(req); | |
145 let refill = mainMemRespQ.first(); | |
146 | |
147 //----------------------------------------------------------- | |
148 // Initialize | |
149 | |
150 rule init ( stage == Init ); | |
151 traceTiny("mkInstCacheBlocking", "stage","i"); | |
152 initCounter <= initCounter + 1; | |
153 cacheTagRam.upd(initCounter,Invalid); | |
154 if ( initCounter == 0 ) | |
155 stage <= Access; | |
156 endrule | |
157 | |
158 //----------------------------------------------------------- | |
159 // Cache access rule | |
160 | |
161 rule access ( (stage == Access) && respQ.notFull() ); | |
162 | |
163 // Statistics | |
164 | |
165 if ( statsEn ) | |
166 num_accesses.incr(); | |
167 | |
168 // Check tag and valid bit to see if this is a hit or a miss | |
169 | |
170 Maybe#(CacheLineTag) cacheLineTag = cacheTagRam.sub(reqIndex); | |
171 | |
172 // Handle cache hits ... | |
173 | |
174 if ( isValid(cacheLineTag) && ( unJust(cacheLineTag) == reqTag ) ) | |
175 begin | |
176 traceTiny("mkInstCacheBlocking", "hitMiss","h"); | |
177 reqQ.deq(); | |
178 | |
179 case ( req ) matches | |
180 | |
181 tagged LoadReq .ld : | |
182 respQ.enq( LoadResp { tag : ld.tag, data : cacheDataRam.sub(reqIndex) } ); | |
183 | |
184 tagged StoreReq .st : | |
185 $display( " RTL-ERROR : %m : Stores are not allowed on the inst port!" ); | |
186 | |
187 endcase | |
188 | |
189 end | |
190 | |
191 // Handle cache misses - since lines in instruction cache are | |
192 // never dirty we can always immediately issue a refill request | |
193 | |
194 else | |
195 begin | |
196 traceTiny("mkInstCacheBlocking", "hitMiss","m"); | |
197 if ( statsEn ) | |
198 num_misses.incr(); | |
199 if ( statsEn ) | |
200 if ( isJust(cacheLineTag) ) | |
201 num_evictions.incr(); | |
202 | |
203 MainMemReq rfReq | |
204 = LoadReq { tag : 0, | |
205 addr : reqCacheLineAddr }; | |
206 | |
207 mainMemReqQ.enq(rfReq); | |
208 stage <= RefillResp; | |
209 end | |
210 | |
211 endrule | |
212 | |
213 //----------------------------------------------------------- | |
214 // Refill response rule | |
215 | |
216 rule refillResp ( stage == RefillResp ); | |
217 traceTiny("mkInstCacheBlocking", "stage","R"); | |
218 traceTiny("mkInstCacheBlocking", "refill",refill); | |
219 | |
220 // Write the new data into the cache and update the tag | |
221 | |
222 mainMemRespQ.deq(); | |
223 case ( mainMemRespQ.first() ) matches | |
224 | |
225 tagged LoadResp .ld : | |
226 begin | |
227 cacheTagRam.upd(reqIndex,Valid(reqTag)); | |
228 cacheDataRam.upd(reqIndex,ld.data); | |
229 end | |
230 | |
231 tagged StoreResp .st : | |
232 noAction; | |
233 | |
234 endcase | |
235 | |
236 stage <= Access; | |
237 endrule | |
238 | |
239 //----------------------------------------------------------- | |
240 // Methods | |
241 | |
242 interface Client mmem_client; | |
243 interface Get request = fifoToGet(mainMemReqQ); | |
244 interface Put response = fifoToPut(mainMemRespQ); | |
245 endinterface | |
246 | |
247 interface Server proc_server; | |
248 interface Put request = tracePut("mkInstCacheBlocking", "reqTiny",fifoToPut(reqQ)); | |
249 interface Get response = traceGet("mkInstCacheBlocking", "respTiny",fifofToGet(respQ)); | |
250 endinterface | |
251 | |
252 interface Put statsEn_put = regToPut(statsEn); | |
253 | |
254 endmodule | |
255 |