Mercurial > pygar
diff 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 |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/modules/bluespec/Pygar/lab4/InstCacheBlocking.bsv Fri Apr 23 02:32:05 2010 -0400 1.3 @@ -0,0 +1,255 @@ 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 +// Local includes 1.35 +`include "asim/provides/low_level_platform_interface.bsh" 1.36 +`include "asim/provides/soft_connections.bsh" 1.37 +`include "asim/provides/processor_library.bsh" 1.38 +`include "asim/provides/fpga_components.bsh" 1.39 +`include "asim/provides/common_services.bsh" 1.40 +`include "asim/dict/STATS_INST_CACHE.bsh" 1.41 + 1.42 +interface ICache#( type req_t, type resp_t ); 1.43 + 1.44 + // Interface from processor to cache 1.45 + interface Server#(req_t,resp_t) proc_server; 1.46 + 1.47 + // Interface from cache to main memory 1.48 + interface Client#(MainMemReq,MainMemResp) mmem_client; 1.49 + 1.50 + // Interface for enabling/disabling statistics 1.51 + interface Put#(Bool) statsEn_put; 1.52 + 1.53 +endinterface 1.54 + 1.55 +//---------------------------------------------------------------------- 1.56 +// Cache Types 1.57 +//---------------------------------------------------------------------- 1.58 + 1.59 +typedef 10 CacheLineIndexSz; 1.60 +typedef 20 CacheLineTagSz; 1.61 +typedef 32 CacheLineSz; 1.62 + 1.63 +typedef Bit#(CacheLineIndexSz) CacheLineIndex; 1.64 +typedef Bit#(CacheLineTagSz) CacheLineTag; 1.65 +typedef Bit#(CacheLineSz) CacheLine; 1.66 + 1.67 +typedef enum 1.68 +{ 1.69 + Init, 1.70 + Access, 1.71 + Evict, 1.72 + RefillReq, 1.73 + RefillResp 1.74 +} 1.75 +CacheStage 1.76 +deriving (Eq,Bits); 1.77 + 1.78 +//---------------------------------------------------------------------- 1.79 +// Helper functions 1.80 +//---------------------------------------------------------------------- 1.81 + 1.82 +function Bit#(AddrSz) getAddr( InstReq req ); 1.83 + 1.84 + Bit#(AddrSz) addr = ?; 1.85 + case ( req ) matches 1.86 + tagged LoadReq .ld : addr = ld.addr; 1.87 + tagged StoreReq .st : addr = st.addr; 1.88 + endcase 1.89 + 1.90 + return addr; 1.91 + 1.92 +endfunction 1.93 + 1.94 +function CacheLineIndex getCacheLineIndex( InstReq req ); 1.95 + Bit#(AddrSz) addr = getAddr(req); 1.96 + Bit#(CacheLineIndexSz) index = truncate( addr >> 2 ); 1.97 + return index; 1.98 +endfunction 1.99 + 1.100 +function CacheLineTag getCacheLineTag( InstReq req ); 1.101 + Bit#(AddrSz) addr = getAddr(req); 1.102 + Bit#(CacheLineTagSz) tag = truncate( addr >> fromInteger(valueOf(CacheLineIndexSz)) >> 2 ); 1.103 + return tag; 1.104 +endfunction 1.105 + 1.106 +function Bit#(AddrSz) getCacheLineAddr( InstReq req ); 1.107 + Bit#(AddrSz) addr = getAddr(req); 1.108 + return ((addr >> 2) << 2); 1.109 +endfunction 1.110 + 1.111 +//---------------------------------------------------------------------- 1.112 +// Main module 1.113 +//---------------------------------------------------------------------- 1.114 + 1.115 +module [CONNECTED_MODULE] mkInstCache( ICache#(InstReq,InstResp) ); 1.116 + 1.117 + //----------------------------------------------------------- 1.118 + // State 1.119 + 1.120 + Reg#(CacheStage) stage <- mkReg(Init); 1.121 + 1.122 + LUTRAM#(CacheLineIndex,Maybe#(CacheLineTag)) cacheTagRam <- mkLUTRAMU_RegFile(); 1.123 + LUTRAM#(CacheLineIndex,CacheLine) cacheDataRam <- mkLUTRAMU_RegFile(); 1.124 + 1.125 + FIFO#(InstReq) reqQ <- mkFIFO(); 1.126 + FIFOF#(InstResp) respQ <- mkBFIFOF1(); 1.127 + 1.128 + FIFO#(MainMemReq) mainMemReqQ <- mkBFIFO1(); 1.129 + FIFO#(MainMemResp) mainMemRespQ <- mkFIFO(); 1.130 + 1.131 + Reg#(CacheLineIndex) initCounter <- mkReg(1); 1.132 + 1.133 + // Statistics state 1.134 + 1.135 + Reg#(Bool) statsEn <- mkReg(False); 1.136 + 1.137 + STAT num_accesses <- mkStatCounter(`STATS_INST_CACHE_NUM_ACCESSES); 1.138 + STAT num_misses <- mkStatCounter(`STATS_INST_CACHE_NUM_MISSES); 1.139 + STAT num_evictions <- mkStatCounter(`STATS_INST_CACHE_NUM_EVICTIONS); 1.140 + 1.141 + //----------------------------------------------------------- 1.142 + // Name some wires 1.143 + 1.144 + let req = reqQ.first(); 1.145 + let reqIndex = getCacheLineIndex(req); 1.146 + let reqTag = getCacheLineTag(req); 1.147 + let reqCacheLineAddr = getCacheLineAddr(req); 1.148 + let refill = mainMemRespQ.first(); 1.149 + 1.150 + //----------------------------------------------------------- 1.151 + // Initialize 1.152 + 1.153 + rule init ( stage == Init ); 1.154 + traceTiny("mkInstCacheBlocking", "stage","i"); 1.155 + initCounter <= initCounter + 1; 1.156 + cacheTagRam.upd(initCounter,Invalid); 1.157 + if ( initCounter == 0 ) 1.158 + stage <= Access; 1.159 + endrule 1.160 + 1.161 + //----------------------------------------------------------- 1.162 + // Cache access rule 1.163 + 1.164 + rule access ( (stage == Access) && respQ.notFull() ); 1.165 + 1.166 + // Statistics 1.167 + 1.168 + if ( statsEn ) 1.169 + num_accesses.incr(); 1.170 + 1.171 + // Check tag and valid bit to see if this is a hit or a miss 1.172 + 1.173 + Maybe#(CacheLineTag) cacheLineTag = cacheTagRam.sub(reqIndex); 1.174 + 1.175 + // Handle cache hits ... 1.176 + 1.177 + if ( isValid(cacheLineTag) && ( unJust(cacheLineTag) == reqTag ) ) 1.178 + begin 1.179 + traceTiny("mkInstCacheBlocking", "hitMiss","h"); 1.180 + reqQ.deq(); 1.181 + 1.182 + case ( req ) matches 1.183 + 1.184 + tagged LoadReq .ld : 1.185 + respQ.enq( LoadResp { tag : ld.tag, data : cacheDataRam.sub(reqIndex) } ); 1.186 + 1.187 + tagged StoreReq .st : 1.188 + $display( " RTL-ERROR : %m : Stores are not allowed on the inst port!" ); 1.189 + 1.190 + endcase 1.191 + 1.192 + end 1.193 + 1.194 + // Handle cache misses - since lines in instruction cache are 1.195 + // never dirty we can always immediately issue a refill request 1.196 + 1.197 + else 1.198 + begin 1.199 + traceTiny("mkInstCacheBlocking", "hitMiss","m"); 1.200 + if ( statsEn ) 1.201 + num_misses.incr(); 1.202 + if ( statsEn ) 1.203 + if ( isJust(cacheLineTag) ) 1.204 + num_evictions.incr(); 1.205 + 1.206 + MainMemReq rfReq 1.207 + = LoadReq { tag : 0, 1.208 + addr : reqCacheLineAddr }; 1.209 + 1.210 + mainMemReqQ.enq(rfReq); 1.211 + stage <= RefillResp; 1.212 + end 1.213 + 1.214 + endrule 1.215 + 1.216 + //----------------------------------------------------------- 1.217 + // Refill response rule 1.218 + 1.219 + rule refillResp ( stage == RefillResp ); 1.220 + traceTiny("mkInstCacheBlocking", "stage","R"); 1.221 + traceTiny("mkInstCacheBlocking", "refill",refill); 1.222 + 1.223 + // Write the new data into the cache and update the tag 1.224 + 1.225 + mainMemRespQ.deq(); 1.226 + case ( mainMemRespQ.first() ) matches 1.227 + 1.228 + tagged LoadResp .ld : 1.229 + begin 1.230 + cacheTagRam.upd(reqIndex,Valid(reqTag)); 1.231 + cacheDataRam.upd(reqIndex,ld.data); 1.232 + end 1.233 + 1.234 + tagged StoreResp .st : 1.235 + noAction; 1.236 + 1.237 + endcase 1.238 + 1.239 + stage <= Access; 1.240 + endrule 1.241 + 1.242 + //----------------------------------------------------------- 1.243 + // Methods 1.244 + 1.245 + interface Client mmem_client; 1.246 + interface Get request = fifoToGet(mainMemReqQ); 1.247 + interface Put response = fifoToPut(mainMemRespQ); 1.248 + endinterface 1.249 + 1.250 + interface Server proc_server; 1.251 + interface Put request = tracePut("mkInstCacheBlocking", "reqTiny",fifoToPut(reqQ)); 1.252 + interface Get response = traceGet("mkInstCacheBlocking", "respTiny",fifofToGet(respQ)); 1.253 + endinterface 1.254 + 1.255 + interface Put statsEn_put = regToPut(statsEn); 1.256 + 1.257 +endmodule 1.258 +