Mercurial > pygar
diff modules/bluespec/Pygar/core/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 |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/modules/bluespec/Pygar/core/DataCacheBlocking.bsv Fri Apr 23 02:32:05 2010 -0400 1.3 @@ -0,0 +1,295 @@ 1.4 +// The MIT License 1.5 + 1.6 +// Copyright (c) 2009 Massachusetts Institute of Technology 1.7 + 1.8 +// Permission is hereby granted, free of charge, to any person obtaining a copy 1.9 +// of this software and associated documentation files (the "Software"), to deal 1.10 +// in the Software without restriction, including without limitation the rights 1.11 +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1.12 +// copies of the Software, and to permit persons to whom the Software is 1.13 +// furnished to do so, subject to the following conditions: 1.14 + 1.15 +// The above copyright notice and this permission notice shall be included in 1.16 +// all copies or substantial portions of the Software. 1.17 + 1.18 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1.19 +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1.20 +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1.21 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1.22 +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1.23 +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 1.24 +// THE SOFTWARE. 1.25 + 1.26 +import Connectable::*; 1.27 +import GetPut::*; 1.28 +import ClientServer::*; 1.29 +import RegFile::*; 1.30 +import FIFO::*; 1.31 +import FIFOF::*; 1.32 + 1.33 +import BFIFO::*; 1.34 +import MemTypes::*; 1.35 +import ProcTypes::*; 1.36 +import Trace::*; 1.37 + 1.38 +interface DCacheStats; 1.39 + interface Get#(Stat) num_accesses; 1.40 + interface Get#(Stat) num_misses; 1.41 + interface Get#(Stat) num_writebacks; 1.42 +endinterface 1.43 + 1.44 +interface DCache#( type req_t, type resp_t ); 1.45 + 1.46 + // Interface from processor to cache 1.47 + interface Server#(req_t,resp_t) proc_server; 1.48 + 1.49 + // Interface from cache to main memory 1.50 + interface Client#(MainMemReq,MainMemResp) mmem_client; 1.51 + 1.52 + // Interface for enabling/disabling statistics 1.53 + interface Put#(Bool) statsEn_put; 1.54 + 1.55 + // Interface for collecting statistics 1.56 + interface DCacheStats stats; 1.57 + 1.58 +endinterface 1.59 + 1.60 + 1.61 +//---------------------------------------------------------------------- 1.62 +// Cache Types 1.63 +//---------------------------------------------------------------------- 1.64 + 1.65 +typedef 10 CacheLineIndexSz; 1.66 +typedef 20 CacheLineTagSz; 1.67 +typedef 32 CacheLineSz; 1.68 + 1.69 +typedef Bit#(CacheLineIndexSz) CacheLineIndex; 1.70 +typedef Bit#(CacheLineTagSz) CacheLineTag; 1.71 +typedef Bit#(CacheLineSz) CacheLine; 1.72 + 1.73 +typedef enum 1.74 +{ 1.75 + Init, 1.76 + Access, 1.77 + RefillReq, 1.78 + RefillResp 1.79 +} 1.80 +CacheStage 1.81 +deriving (Eq,Bits); 1.82 + 1.83 +//---------------------------------------------------------------------- 1.84 +// Helper functions 1.85 +//---------------------------------------------------------------------- 1.86 + 1.87 +function Bit#(AddrSz) getAddr( DataReq req ); 1.88 + 1.89 + Bit#(AddrSz) addr = ?; 1.90 + case ( req ) matches 1.91 + tagged LoadReq .ld : addr = ld.addr; 1.92 + tagged StoreReq .st : addr = st.addr; 1.93 + endcase 1.94 + 1.95 + return addr; 1.96 + 1.97 +endfunction 1.98 + 1.99 +function CacheLineIndex getCacheLineIndex( DataReq req ); 1.100 + Bit#(AddrSz) addr = getAddr(req); 1.101 + Bit#(CacheLineIndexSz) index = truncate( addr >> 2 ); 1.102 + return index; 1.103 +endfunction 1.104 + 1.105 +function CacheLineTag getCacheLineTag( DataReq req ); 1.106 + Bit#(AddrSz) addr = getAddr(req); 1.107 + Bit#(CacheLineTagSz) tag = truncate( addr >> fromInteger(valueOf(CacheLineIndexSz)) >> 2 ); 1.108 + return tag; 1.109 +endfunction 1.110 + 1.111 +function Bit#(AddrSz) getCacheLineAddr( DataReq req ); 1.112 + Bit#(AddrSz) addr = getAddr(req); 1.113 + return ((addr >> 2) << 2); 1.114 +endfunction 1.115 + 1.116 +//---------------------------------------------------------------------- 1.117 +// Main module 1.118 +//---------------------------------------------------------------------- 1.119 + 1.120 +(* doc = "synthesis attribute ram_style mkDataCache distributed;" *) 1.121 +(* synthesize *) 1.122 +module mkDataCache( DCache#(DataReq,DataResp) ); 1.123 + 1.124 + //----------------------------------------------------------- 1.125 + // State 1.126 + 1.127 + Reg#(CacheStage) stage <- mkReg(Init); 1.128 + 1.129 + RegFile#(CacheLineIndex,Maybe#(CacheLineTag)) cacheTagRam <- mkRegFileFull(); 1.130 + RegFile#(CacheLineIndex,CacheLine) cacheDataRam <- mkRegFileFull(); 1.131 + 1.132 + FIFO#(DataReq) reqQ <- mkFIFO(); 1.133 + FIFOF#(DataResp) respQ <- mkBFIFOF1(); 1.134 + 1.135 + FIFO#(MainMemReq) mainMemReqQ <- mkBFIFO1(); 1.136 + FIFO#(MainMemResp) mainMemRespQ <- mkFIFO(); 1.137 + 1.138 + Reg#(CacheLineIndex) initCounter <- mkReg(1); 1.139 + 1.140 + // Statistics state 1.141 + 1.142 + Reg#(Bool) statsEn <- mkReg(False); 1.143 + 1.144 + Reg#(Stat) num_accesses <- mkReg(0); 1.145 + Reg#(Stat) num_misses <- mkReg(0); 1.146 + Reg#(Stat) num_writebacks <- mkReg(0); 1.147 + 1.148 + //----------------------------------------------------------- 1.149 + // Name some wires 1.150 + 1.151 + let req = reqQ.first(); 1.152 + let reqIndex = getCacheLineIndex(req); 1.153 + let reqTag = getCacheLineTag(req); 1.154 + let reqCacheLineAddr = getCacheLineAddr(req); 1.155 + 1.156 + //----------------------------------------------------------- 1.157 + // Initialize 1.158 + 1.159 + rule init ( stage == Init ); 1.160 + traceTiny("mkDataCacheBlocking", "stage","i"); 1.161 + initCounter <= initCounter + 1; 1.162 + cacheTagRam.upd(initCounter,Invalid); 1.163 + if ( initCounter == 0 ) 1.164 + stage <= Access; 1.165 + endrule 1.166 + 1.167 + //----------------------------------------------------------- 1.168 + // Access cache rule 1.169 + 1.170 + rule access ( (stage == Access) && respQ.notFull() ); 1.171 + 1.172 + // Statistics 1.173 + 1.174 + if ( statsEn ) 1.175 + num_accesses <= num_accesses + 1; 1.176 + 1.177 + 1.178 + // Get the corresponding tag from the rams 1.179 + 1.180 + Maybe#(CacheLineTag) cacheLineTag = cacheTagRam.sub(reqIndex); 1.181 + 1.182 + // Handle cache hits ... 1.183 + 1.184 + if ( isValid(cacheLineTag) && ( unJust(cacheLineTag) == reqTag ) ) 1.185 + begin 1.186 + traceTiny("mkDataCacheBlocking", "hitMiss","h"); 1.187 + reqQ.deq(); 1.188 + 1.189 + case ( req ) matches 1.190 + 1.191 + tagged LoadReq .ld : 1.192 + respQ.enq( LoadResp { tag: ld.tag, data: cacheDataRam.sub(reqIndex) } ); 1.193 + 1.194 + tagged StoreReq .st : 1.195 + begin 1.196 + respQ.enq( StoreResp { tag : st.tag } ); 1.197 + cacheDataRam.upd(reqIndex,st.data); 1.198 + end 1.199 + 1.200 + endcase 1.201 + 1.202 + end 1.203 + 1.204 + // Handle cache misses ... 1.205 + 1.206 + else 1.207 + begin 1.208 + traceTiny("mkDataCacheBlocking", "hitMiss","m"); 1.209 + if ( statsEn ) 1.210 + num_misses <= num_misses + 1; 1.211 + 1.212 + // Currently we don't use dirty bits so we always writeback the data if it is valid 1.213 + 1.214 + if ( isValid(cacheLineTag) ) 1.215 + begin 1.216 + 1.217 + if ( statsEn ) 1.218 + num_writebacks <= num_writebacks + 1; 1.219 + 1.220 + MainMemReq wbReq 1.221 + = StoreReq { tag : 0, 1.222 + addr : { unJust(cacheLineTag), reqIndex, 2'b0 }, 1.223 + data : cacheDataRam.sub(reqIndex) }; 1.224 + 1.225 + mainMemReqQ.enq(wbReq); 1.226 + stage <= RefillReq; 1.227 + end 1.228 + 1.229 + // Otherwise we can issue the refill request now 1.230 + 1.231 + else 1.232 + begin 1.233 + mainMemReqQ.enq( LoadReq { tag: 0, addr: reqCacheLineAddr } ); 1.234 + stage <= RefillResp; 1.235 + end 1.236 + 1.237 + end 1.238 + 1.239 + endrule 1.240 + 1.241 + //----------------------------------------------------------- 1.242 + // Refill request rule 1.243 + 1.244 + rule refillReq ( stage == RefillReq ); 1.245 + traceTiny("mkDataCacheBlocking", "stage","r"); 1.246 + mainMemReqQ.enq( LoadReq { tag: 0, addr: reqCacheLineAddr } ); 1.247 + stage <= RefillResp; 1.248 + endrule 1.249 + 1.250 + //----------------------------------------------------------- 1.251 + // Refill response rule 1.252 + 1.253 + rule refillResp ( stage == RefillResp ); 1.254 + traceTiny("mkDataCacheBlocking", "stage","R"); 1.255 + traceTiny("mkDataCacheBlocking", "refill",mainMemRespQ.first()); 1.256 + 1.257 + // Write the new data into the cache and update the tag 1.258 + 1.259 + mainMemRespQ.deq(); 1.260 + case ( mainMemRespQ.first() ) matches 1.261 + 1.262 + tagged LoadResp .ld : 1.263 + begin 1.264 + cacheTagRam.upd(reqIndex,Valid(reqTag)); 1.265 + cacheDataRam.upd(reqIndex,ld.data); 1.266 + end 1.267 + 1.268 + tagged StoreResp .st : 1.269 + noAction; 1.270 + 1.271 + endcase 1.272 + 1.273 + stage <= Access; 1.274 + endrule 1.275 + 1.276 + //----------------------------------------------------------- 1.277 + // Methods 1.278 + 1.279 + interface Client mmem_client; 1.280 + interface Get request = toGet(mainMemReqQ); 1.281 + interface Put response = toPut(mainMemRespQ); 1.282 + endinterface 1.283 + 1.284 + interface Server proc_server; 1.285 + interface Put request = tracePut("mkDataCacheBlocking", "reqTiny",toPut(reqQ)); 1.286 + interface Get response = traceGet("mkDataCacheBlocking", "respTiny",toGet(respQ)); 1.287 + endinterface 1.288 + 1.289 + interface Put statsEn_put = toPut(asReg(statsEn)); 1.290 + 1.291 + interface DCacheStats stats; 1.292 + interface Get num_accesses = toGet(asReg(num_accesses)); 1.293 + interface Get num_misses = toGet(asReg(num_misses)); 1.294 + interface Get num_writebacks = toGet(asReg(num_writebacks)); 1.295 + endinterface 1.296 + 1.297 +endmodule 1.298 +