Mercurial > pygar
diff modules/bluespec/Pygar/core/InstCacheBlocking.d @ 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/InstCacheBlocking.d Fri Apr 23 02:32:05 2010 -0400 1.3 @@ -0,0 +1,269 @@ 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 +import RWire::*; 1.33 + 1.34 +import BFIFO::*; 1.35 +import MemTypes::*; 1.36 +import ProcTypes::*; 1.37 +import Trace::*; 1.38 + 1.39 +interface ICacheStats; 1.40 + interface Get#(Stat) num_accesses; 1.41 + interface Get#(Stat) num_misses; 1.42 + interface Get#(Stat) num_evictions; 1.43 +endinterface 1.44 + 1.45 +interface ICache#( type req_t, type resp_t ); 1.46 + 1.47 + // Interface from processor to cache 1.48 + interface Server#(req_t,resp_t) proc_server; 1.49 + 1.50 + // Interface from cache to main memory 1.51 + interface Client#(MainMemReq,MainMemResp) mmem_client; 1.52 + 1.53 + // Interface for enabling/disabling statistics 1.54 + interface Put#(Bool) statsEn_put; 1.55 + 1.56 + // Interface for collecting statistics 1.57 + interface ICacheStats stats; 1.58 + 1.59 +endinterface 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 + Evict, 1.78 + RefillReq, 1.79 + RefillResp 1.80 +} 1.81 +CacheStage 1.82 +deriving (Eq,Bits); 1.83 + 1.84 +//---------------------------------------------------------------------- 1.85 +// Helper functions 1.86 +//---------------------------------------------------------------------- 1.87 + 1.88 +function Bit#(AddrSz) getAddr( InstReq req ); 1.89 + 1.90 + Bit#(AddrSz) addr = ?; 1.91 + case ( req ) matches 1.92 + tagged LoadReq .ld : addr = ld.addr; 1.93 + tagged StoreReq .st : addr = st.addr; 1.94 + endcase 1.95 + 1.96 + return addr; 1.97 + 1.98 +endfunction 1.99 + 1.100 +function CacheLineIndex getCacheLineIndex( InstReq req ); 1.101 + Bit#(AddrSz) addr = getAddr(req); 1.102 + Bit#(CacheLineIndexSz) index = truncate( addr >> 2 ); 1.103 + return index; 1.104 +endfunction 1.105 + 1.106 +function CacheLineTag getCacheLineTag( InstReq req ); 1.107 + Bit#(AddrSz) addr = getAddr(req); 1.108 + Bit#(CacheLineTagSz) tag = truncate( addr >> fromInteger(valueOf(CacheLineIndexSz)) >> 2 ); 1.109 + return tag; 1.110 +endfunction 1.111 + 1.112 +function Bit#(AddrSz) getCacheLineAddr( InstReq req ); 1.113 + Bit#(AddrSz) addr = getAddr(req); 1.114 + return ((addr >> 2) << 2); 1.115 +endfunction 1.116 + 1.117 +//---------------------------------------------------------------------- 1.118 +// Main module 1.119 +//---------------------------------------------------------------------- 1.120 + 1.121 +(* doc = "synthesis attribute ram_style mkInstCache distributed;" *) 1.122 +(* synthesize *) 1.123 +module mkInstCache( ICache#(InstReq,InstResp) ); 1.124 + 1.125 + //----------------------------------------------------------- 1.126 + // State 1.127 + 1.128 + Reg#(CacheStage) stage <- mkReg(Init); 1.129 + 1.130 + RegFile#(CacheLineIndex,Maybe#(CacheLineTag)) cacheTagRam <- mkRegFileFull(); 1.131 + RegFile#(CacheLineIndex,CacheLine) cacheDataRam <- mkRegFileFull(); 1.132 + 1.133 + FIFO#(InstReq) reqQ <- mkFIFO(); 1.134 + FIFOF#(InstResp) respQ <- mkBFIFOF1(); 1.135 + 1.136 + FIFO#(MainMemReq) mainMemReqQ <- mkBFIFO1(); 1.137 + FIFO#(MainMemResp) mainMemRespQ <- mkFIFO(); 1.138 + 1.139 + Reg#(CacheLineIndex) initCounter <- mkReg(1); 1.140 + 1.141 + // Statistics state 1.142 + 1.143 + Reg#(Bool) statsEn <- mkReg(False); 1.144 + 1.145 + Reg#(Stat) numAccesses <- mkReg(0); 1.146 + Reg#(Stat) numMisses <- mkReg(0); 1.147 + Reg#(Stat) numEvictions <- mkReg(0); 1.148 + 1.149 + //----------------------------------------------------------- 1.150 + // Name some wires 1.151 + 1.152 + let req = reqQ.first(); 1.153 + let reqIndex = getCacheLineIndex(req); 1.154 + let reqTag = getCacheLineTag(req); 1.155 + let reqCacheLineAddr = getCacheLineAddr(req); 1.156 + let refill = mainMemRespQ.first(); 1.157 + 1.158 + //----------------------------------------------------------- 1.159 + // Initialize 1.160 + 1.161 + rule init ( stage == Init ); 1.162 + traceTiny("mkInstCacheBlocking", "stage","i"); 1.163 + initCounter <= initCounter + 1; 1.164 + cacheTagRam.upd(initCounter,Invalid); 1.165 + if ( initCounter == 0 ) 1.166 + stage <= Access; 1.167 + endrule 1.168 + 1.169 + //----------------------------------------------------------- 1.170 + // Cache access rule 1.171 + 1.172 + rule access ( (stage == Access) && respQ.notFull() ); 1.173 + 1.174 + // Statistics 1.175 + 1.176 + if ( statsEn ) 1.177 + numAccesses <= numAccesses + 1; 1.178 + 1.179 + // Check tag and valid bit to see if this is a hit or a miss 1.180 + 1.181 + Maybe#(CacheLineTag) cacheLineTag = cacheTagRam.sub(reqIndex); 1.182 + 1.183 + // Handle cache hits ... 1.184 + 1.185 + if ( isValid(cacheLineTag) && ( unJust(cacheLineTag) == reqTag ) ) 1.186 + begin 1.187 + traceTiny("mkInstCacheBlocking", "hitMiss","h"); 1.188 + reqQ.deq(); 1.189 + 1.190 + case ( req ) matches 1.191 + 1.192 + tagged LoadReq .ld : 1.193 + respQ.enq( LoadResp { tag : ld.tag, data : cacheDataRam.sub(reqIndex) } ); 1.194 + 1.195 + tagged StoreReq .st : 1.196 + $display( " RTL-ERROR : %m : Stores are not allowed on the inst port!" ); 1.197 + 1.198 + endcase 1.199 + 1.200 + end 1.201 + 1.202 + // Handle cache misses - since lines in instruction cache are 1.203 + // never dirty we can always immediately issue a refill request 1.204 + 1.205 + else 1.206 + begin 1.207 + traceTiny("mkInstCacheBlocking", "hitMiss","m"); 1.208 + if ( statsEn ) 1.209 + numMisses <= numMisses + 1; 1.210 + if ( statsEn ) 1.211 + if ( isJust(cacheLineTag) ) 1.212 + numEvictions <= numEvictions + 1; 1.213 + 1.214 + MainMemReq rfReq 1.215 + = LoadReq { tag : 0, 1.216 + addr : reqCacheLineAddr }; 1.217 + 1.218 + mainMemReqQ.enq(rfReq); 1.219 + stage <= RefillResp; 1.220 + end 1.221 + 1.222 + endrule 1.223 + 1.224 + //----------------------------------------------------------- 1.225 + // Refill response rule 1.226 + 1.227 + rule refillResp ( stage == RefillResp ); 1.228 + traceTiny("mkInstCacheBlocking", "stage","R"); 1.229 + traceTiny("mkInstCacheBlocking", "refill",refill); 1.230 + 1.231 + // Write the new data into the cache and update the tag 1.232 + 1.233 + mainMemRespQ.deq(); 1.234 + case ( mainMemRespQ.first() ) matches 1.235 + 1.236 + tagged LoadResp .ld : 1.237 + begin 1.238 + cacheTagRam.upd(reqIndex,Valid(reqTag)); 1.239 + cacheDataRam.upd(reqIndex,ld.data); 1.240 + end 1.241 + 1.242 + tagged StoreResp .st : 1.243 + noAction; 1.244 + 1.245 + endcase 1.246 + 1.247 + stage <= Access; 1.248 + endrule 1.249 + 1.250 + //----------------------------------------------------------- 1.251 + // Methods 1.252 + 1.253 + interface Client mmem_client; 1.254 + interface Get request = fifoToGet(mainMemReqQ); 1.255 + interface Put response = fifoToPut(mainMemRespQ); 1.256 + endinterface 1.257 + 1.258 + interface Server proc_server; 1.259 + interface Put request = tracePut("mkInstCacheBlocking", "reqTiny",toPut(reqQ)); 1.260 + interface Get response = traceGet("mkInstCacheBlocking", "respTiny",toGet(respQ)); 1.261 + endinterface 1.262 + 1.263 + interface Put statsEn_put = toPut(asReg(statsEn)); 1.264 + 1.265 + interface ICacheStats stats; 1.266 + interface Get num_accesses = toGet(asReg(numAccesses)); 1.267 + interface Get num_misses = toGet(asReg(numMisses)); 1.268 + interface Get num_evictions = toGet(asReg(numEvictions)); 1.269 + endinterface 1.270 + 1.271 +endmodule 1.272 +