Mercurial > pygar
diff 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 |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/modules/bluespec/Pygar/lab4/DataCacheBlocking.bsv Fri Apr 23 02:32:05 2010 -0400 1.3 @@ -0,0 +1,283 @@ 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 +// Local includes 1.27 +`include "asim/provides/low_level_platform_interface.bsh" 1.28 +`include "asim/provides/soft_connections.bsh" 1.29 +`include "asim/provides/processor_library.bsh" 1.30 +`include "asim/provides/fpga_components.bsh" 1.31 +`include "asim/provides/common_services.bsh" 1.32 +`include "asim/dict/STATS_DATA_CACHE.bsh" 1.33 + 1.34 +import Connectable::*; 1.35 +import GetPut::*; 1.36 +import ClientServer::*; 1.37 +import RegFile::*; 1.38 +import FIFO::*; 1.39 +import FIFOF::*; 1.40 + 1.41 + 1.42 + 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 +endinterface 1.56 + 1.57 + 1.58 +//---------------------------------------------------------------------- 1.59 +// Cache Types 1.60 +//---------------------------------------------------------------------- 1.61 + 1.62 +typedef 10 CacheLineIndexSz; 1.63 +typedef 20 CacheLineTagSz; 1.64 +typedef 32 CacheLineSz; 1.65 + 1.66 +typedef Bit#(CacheLineIndexSz) CacheLineIndex; 1.67 +typedef Bit#(CacheLineTagSz) CacheLineTag; 1.68 +typedef Bit#(CacheLineSz) CacheLine; 1.69 + 1.70 +typedef enum 1.71 +{ 1.72 + Init, 1.73 + Access, 1.74 + RefillReq, 1.75 + RefillResp 1.76 +} 1.77 +CacheStage 1.78 +deriving (Eq,Bits); 1.79 + 1.80 +//---------------------------------------------------------------------- 1.81 +// Helper functions 1.82 +//---------------------------------------------------------------------- 1.83 + 1.84 +function Bit#(AddrSz) getAddr( DataReq req ); 1.85 + 1.86 + Bit#(AddrSz) addr = ?; 1.87 + case ( req ) matches 1.88 + tagged LoadReq .ld : addr = ld.addr; 1.89 + tagged StoreReq .st : addr = st.addr; 1.90 + endcase 1.91 + 1.92 + return addr; 1.93 + 1.94 +endfunction 1.95 + 1.96 +function CacheLineIndex getCacheLineIndex( DataReq req ); 1.97 + Bit#(AddrSz) addr = getAddr(req); 1.98 + Bit#(CacheLineIndexSz) index = truncate( addr >> 2 ); 1.99 + return index; 1.100 +endfunction 1.101 + 1.102 +function CacheLineTag getCacheLineTag( DataReq req ); 1.103 + Bit#(AddrSz) addr = getAddr(req); 1.104 + Bit#(CacheLineTagSz) tag = truncate( addr >> fromInteger(valueOf(CacheLineIndexSz)) >> 2 ); 1.105 + return tag; 1.106 +endfunction 1.107 + 1.108 +function Bit#(AddrSz) getCacheLineAddr( DataReq req ); 1.109 + Bit#(AddrSz) addr = getAddr(req); 1.110 + return ((addr >> 2) << 2); 1.111 +endfunction 1.112 + 1.113 +//---------------------------------------------------------------------- 1.114 +// Main module 1.115 +//---------------------------------------------------------------------- 1.116 + 1.117 +module [CONNECTED_MODULE] mkDataCache( DCache#(DataReq,DataResp) ); 1.118 + 1.119 + //----------------------------------------------------------- 1.120 + // State 1.121 + 1.122 + Reg#(CacheStage) stage <- mkReg(Init); 1.123 + 1.124 + LUTRAM#(CacheLineIndex,Maybe#(CacheLineTag)) cacheTagRam <- mkLUTRAMU_RegFile(); 1.125 + LUTRAM#(CacheLineIndex,CacheLine) cacheDataRam <- mkLUTRAMU_RegFile(); 1.126 + 1.127 + FIFO#(DataReq) reqQ <- mkFIFO(); 1.128 + FIFOF#(DataResp) respQ <- mkBFIFOF1(); 1.129 + 1.130 + FIFO#(MainMemReq) mainMemReqQ <- mkBFIFO1(); 1.131 + FIFO#(MainMemResp) mainMemRespQ <- mkFIFO(); 1.132 + 1.133 + Reg#(CacheLineIndex) initCounter <- mkReg(1); 1.134 + 1.135 + // Statistics state 1.136 + 1.137 + Reg#(Bool) statsEn <- mkReg(False); 1.138 + 1.139 + STAT num_accesses <- mkStatCounter(`STATS_DATA_CACHE_NUM_ACCESSES); 1.140 + STAT num_misses <- mkStatCounter(`STATS_DATA_CACHE_NUM_MISSES); 1.141 + STAT num_writebacks <- mkStatCounter(`STATS_DATA_CACHE_NUM_WRITEBACKS); 1.142 + 1.143 + //----------------------------------------------------------- 1.144 + // Name some wires 1.145 + 1.146 + let req = reqQ.first(); 1.147 + let reqIndex = getCacheLineIndex(req); 1.148 + let reqTag = getCacheLineTag(req); 1.149 + let reqCacheLineAddr = getCacheLineAddr(req); 1.150 + 1.151 + //----------------------------------------------------------- 1.152 + // Initialize 1.153 + 1.154 + rule init ( stage == Init ); 1.155 + traceTiny("mkDataCacheBlocking", "stage","i"); 1.156 + initCounter <= initCounter + 1; 1.157 + cacheTagRam.upd(initCounter,Invalid); 1.158 + if ( initCounter == 0 ) 1.159 + stage <= Access; 1.160 + endrule 1.161 + 1.162 + //----------------------------------------------------------- 1.163 + // Access cache rule 1.164 + 1.165 + rule access ( (stage == Access) && respQ.notFull() ); 1.166 + 1.167 + // Statistics 1.168 + 1.169 + if ( statsEn ) 1.170 + num_accesses.incr(); 1.171 + 1.172 + 1.173 + // Get the corresponding tag from the rams 1.174 + 1.175 + Maybe#(CacheLineTag) cacheLineTag = cacheTagRam.sub(reqIndex); 1.176 + 1.177 + // Handle cache hits ... 1.178 + 1.179 + if ( isValid(cacheLineTag) && ( unJust(cacheLineTag) == reqTag ) ) 1.180 + begin 1.181 + traceTiny("mkDataCacheBlocking", "hitMiss","h"); 1.182 + reqQ.deq(); 1.183 + 1.184 + case ( req ) matches 1.185 + 1.186 + tagged LoadReq .ld : 1.187 + respQ.enq( LoadResp { tag: ld.tag, data: cacheDataRam.sub(reqIndex) } ); 1.188 + 1.189 + tagged StoreReq .st : 1.190 + begin 1.191 + respQ.enq( StoreResp { tag : st.tag } ); 1.192 + cacheDataRam.upd(reqIndex,st.data); 1.193 + end 1.194 + 1.195 + endcase 1.196 + 1.197 + end 1.198 + 1.199 + // Handle cache misses ... 1.200 + 1.201 + else 1.202 + begin 1.203 + traceTiny("mkDataCacheBlocking", "hitMiss","m"); 1.204 + if ( statsEn ) 1.205 + num_misses.incr(); 1.206 + 1.207 + // Currently we don't use dirty bits so we always writeback the data if it is valid 1.208 + 1.209 + if ( isValid(cacheLineTag) ) 1.210 + begin 1.211 + 1.212 + if ( statsEn ) 1.213 + num_writebacks.incr(); 1.214 + 1.215 + MainMemReq wbReq 1.216 + = StoreReq { tag : 0, 1.217 + addr : { unJust(cacheLineTag), reqIndex, 2'b0 }, 1.218 + data : cacheDataRam.sub(reqIndex) }; 1.219 + 1.220 + mainMemReqQ.enq(wbReq); 1.221 + stage <= RefillReq; 1.222 + end 1.223 + 1.224 + // Otherwise we can issue the refill request now 1.225 + 1.226 + else 1.227 + begin 1.228 + mainMemReqQ.enq( LoadReq { tag: 0, addr: reqCacheLineAddr } ); 1.229 + stage <= RefillResp; 1.230 + end 1.231 + 1.232 + end 1.233 + 1.234 + endrule 1.235 + 1.236 + //----------------------------------------------------------- 1.237 + // Refill request rule 1.238 + 1.239 + rule refillReq ( stage == RefillReq ); 1.240 + traceTiny("mkDataCacheBlocking", "stage","r"); 1.241 + mainMemReqQ.enq( LoadReq { tag: 0, addr: reqCacheLineAddr } ); 1.242 + stage <= RefillResp; 1.243 + endrule 1.244 + 1.245 + //----------------------------------------------------------- 1.246 + // Refill response rule 1.247 + 1.248 + rule refillResp ( stage == RefillResp ); 1.249 + traceTiny("mkDataCacheBlocking", "stage","R"); 1.250 + traceTiny("mkDataCacheBlocking", "refill",mainMemRespQ.first()); 1.251 + 1.252 + // Write the new data into the cache and update the tag 1.253 + 1.254 + mainMemRespQ.deq(); 1.255 + case ( mainMemRespQ.first() ) matches 1.256 + 1.257 + tagged LoadResp .ld : 1.258 + begin 1.259 + cacheTagRam.upd(reqIndex,Valid(reqTag)); 1.260 + cacheDataRam.upd(reqIndex,ld.data); 1.261 + end 1.262 + 1.263 + tagged StoreResp .st : 1.264 + noAction; 1.265 + 1.266 + endcase 1.267 + 1.268 + stage <= Access; 1.269 + endrule 1.270 + 1.271 + //----------------------------------------------------------- 1.272 + // Methods 1.273 + 1.274 + interface Client mmem_client; 1.275 + interface Get request = fifoToGet(mainMemReqQ); 1.276 + interface Put response = fifoToPut(mainMemRespQ); 1.277 + endinterface 1.278 + 1.279 + interface Server proc_server; 1.280 + interface Put request = tracePut("mkDataCacheBlocking", "reqTiny",fifoToPut(reqQ)); 1.281 + interface Get response = traceGet("mkDataCacheBlocking", "respTiny",fifofToGet(respQ)); 1.282 + endinterface 1.283 + 1.284 + interface Put statsEn_put = regToPut(statsEn); 1.285 + 1.286 +endmodule