CacheMemory.hh revision 10974
16145Snate@binkert.org/*
26145Snate@binkert.org * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood
36145Snate@binkert.org * Copyright (c) 2013 Advanced Micro Devices, Inc.
46145Snate@binkert.org * All rights reserved.
56145Snate@binkert.org *
66145Snate@binkert.org * Redistribution and use in source and binary forms, with or without
76145Snate@binkert.org * modification, are permitted provided that the following conditions are
86145Snate@binkert.org * met: redistributions of source code must retain the above copyright
96145Snate@binkert.org * notice, this list of conditions and the following disclaimer;
106145Snate@binkert.org * redistributions in binary form must reproduce the above copyright
116145Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
126145Snate@binkert.org * documentation and/or other materials provided with the distribution;
136145Snate@binkert.org * neither the name of the copyright holders nor the names of its
146145Snate@binkert.org * contributors may be used to endorse or promote products derived from
156145Snate@binkert.org * this software without specific prior written permission.
166145Snate@binkert.org *
176145Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
186145Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
196145Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
206145Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
216145Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
226145Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
236145Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
246145Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
256145Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
266145Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
276145Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
286145Snate@binkert.org */
296145Snate@binkert.org
307039Snate@binkert.org#ifndef __MEM_RUBY_STRUCTURES_CACHEMEMORY_HH__
317039Snate@binkert.org#define __MEM_RUBY_STRUCTURES_CACHEMEMORY_HH__
327039Snate@binkert.org
336145Snate@binkert.org#include <string>
346145Snate@binkert.org#include <vector>
357039Snate@binkert.org
367039Snate@binkert.org#include "base/hashmap.hh"
376145Snate@binkert.org#include "base/statistics.hh"
387002Snate@binkert.org#include "mem/protocol/CacheRequestType.hh"
397021Stushar@csail.mit.edu#include "mem/protocol/CacheResourceType.hh"
407002Snate@binkert.org#include "mem/protocol/RubyRequest.hh"
419171Snilay@cs.wisc.edu#include "mem/ruby/common/DataBlock.hh"
429465Snilay@cs.wisc.edu#include "mem/ruby/slicc_interface/AbstractCacheEntry.hh"
436145Snate@binkert.org#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
447039Snate@binkert.org#include "mem/ruby/structures/AbstractReplacementPolicy.hh"
457039Snate@binkert.org#include "mem/ruby/structures/BankedArray.hh"
467039Snate@binkert.org#include "mem/ruby/system/CacheRecorder.hh"
479465Snilay@cs.wisc.edu#include "params/RubyCache.hh"
489230Snilay@cs.wisc.edu#include "sim/sim_object.hh"
497039Snate@binkert.org
507039Snate@binkert.orgclass CacheMemory : public SimObject
516145Snate@binkert.org{
527039Snate@binkert.org  public:
537039Snate@binkert.org    typedef RubyCacheParams Params;
547039Snate@binkert.org    CacheMemory(const Params *p);
556145Snate@binkert.org    ~CacheMemory();
567039Snate@binkert.org
577039Snate@binkert.org    void init();
587973Snilay@cs.wisc.edu
596145Snate@binkert.org    // Public Methods
609171Snilay@cs.wisc.edu    // perform a cache access and see if we hit or not.  Return true on a hit.
617039Snate@binkert.org    bool tryCacheAccess(const Address& address, RubyRequestType type,
627039Snate@binkert.org                        DataBlock*& data_ptr);
637039Snate@binkert.org
647039Snate@binkert.org    // similar to above, but doesn't require full access check
657039Snate@binkert.org    bool testCacheAccess(const Address& address, RubyRequestType type,
667039Snate@binkert.org                         DataBlock*& data_ptr);
679171Snilay@cs.wisc.edu
687039Snate@binkert.org    // tests to see if an address is present in the cache
697039Snate@binkert.org    bool isTagPresent(const Address& address) const;
707039Snate@binkert.org
717039Snate@binkert.org    // Returns true if there is:
727039Snate@binkert.org    //   a) a tag match on this address or there is
739171Snilay@cs.wisc.edu    //   b) an unused line in the same cache "way"
747039Snate@binkert.org    bool cacheAvail(const Address& address) const;
757039Snate@binkert.org
767039Snate@binkert.org    // find an unused entry and sets the tag appropriate for the address
777039Snate@binkert.org    AbstractCacheEntry* allocate(const Address& address,
787039Snate@binkert.org                                 AbstractCacheEntry* new_entry, bool touch);
799171Snilay@cs.wisc.edu    AbstractCacheEntry* allocate(const Address& address,
807039Snate@binkert.org                                 AbstractCacheEntry* new_entry)
817039Snate@binkert.org    {
827039Snate@binkert.org        return allocate(address, new_entry, true);
837039Snate@binkert.org    }
847039Snate@binkert.org    void allocateVoid(const Address& address, AbstractCacheEntry* new_entry)
859171Snilay@cs.wisc.edu    {
867039Snate@binkert.org        allocate(address, new_entry, true);
877039Snate@binkert.org    }
887039Snate@binkert.org
897039Snate@binkert.org    // Explicitly free up this address
907039Snate@binkert.org    void deallocate(const Address& address);
919171Snilay@cs.wisc.edu
929171Snilay@cs.wisc.edu    // Returns with the physical address of the conflicting cache line
939171Snilay@cs.wisc.edu    Address cacheProbe(const Address& address) const;
947039Snate@binkert.org
959171Snilay@cs.wisc.edu    // looks an address up in the cache
969171Snilay@cs.wisc.edu    AbstractCacheEntry* lookup(const Address& address);
979171Snilay@cs.wisc.edu    const AbstractCacheEntry* lookup(const Address& address) const;
989465Snilay@cs.wisc.edu
999171Snilay@cs.wisc.edu    Cycles getLatency() const { return m_latency; }
1009171Snilay@cs.wisc.edu    Cycles getTagLatency() const { return tagArray.getLatency(); }
1019171Snilay@cs.wisc.edu    Cycles getDataLatency() const { return dataArray.getLatency(); }
1029171Snilay@cs.wisc.edu
1039171Snilay@cs.wisc.edu
1049171Snilay@cs.wisc.edu    // Hook for checkpointing the contents of the cache
1059171Snilay@cs.wisc.edu    void recordCacheContents(int cntrl, CacheRecorder* tr) const;
1069171Snilay@cs.wisc.edu
1079171Snilay@cs.wisc.edu    // Set this address to most recently used
1089171Snilay@cs.wisc.edu    void setMRU(const Address& address);
1099171Snilay@cs.wisc.edu
1109171Snilay@cs.wisc.edu    void setLocked (const Address& addr, int context);
1119171Snilay@cs.wisc.edu    void clearLocked (const Address& addr);
1129171Snilay@cs.wisc.edu    bool isLocked (const Address& addr, int context);
1139171Snilay@cs.wisc.edu
1149171Snilay@cs.wisc.edu    // Print cache contents
1159171Snilay@cs.wisc.edu    void print(std::ostream& out) const;
1169171Snilay@cs.wisc.edu    void printData(std::ostream& out) const;
1176145Snate@binkert.org
1186145Snate@binkert.org    void regStats();
1197039Snate@binkert.org    bool checkResourceAvailable(CacheResourceType res, Address addr);
1207039Snate@binkert.org    void recordRequestType(CacheRequestType requestType);
1216145Snate@binkert.org
1227039Snate@binkert.org  public:
1237039Snate@binkert.org    Stats::Scalar m_demand_hits;
1247039Snate@binkert.org    Stats::Scalar m_demand_misses;
1256145Snate@binkert.org    Stats::Formula m_demand_accesses;
1266145Snate@binkert.org
1277039Snate@binkert.org    Stats::Scalar m_sw_prefetches;
128    Stats::Scalar m_hw_prefetches;
129    Stats::Formula m_prefetches;
130
131    Stats::Vector m_accessModeType;
132
133    Stats::Scalar numDataArrayReads;
134    Stats::Scalar numDataArrayWrites;
135    Stats::Scalar numTagArrayReads;
136    Stats::Scalar numTagArrayWrites;
137
138    Stats::Scalar numTagArrayStalls;
139    Stats::Scalar numDataArrayStalls;
140
141    int getCacheSize() const { return m_cache_size; }
142    int getNumBlocks() const { return m_cache_num_sets * m_cache_assoc; }
143    Address getAddressAtIdx(int idx) const;
144
145  private:
146    // convert a Address to its location in the cache
147    int64 addressToCacheSet(const Address& address) const;
148
149    // Given a cache tag: returns the index of the tag in a set.
150    // returns -1 if the tag is not found.
151    int findTagInSet(int64 line, const Address& tag) const;
152    int findTagInSetIgnorePermissions(int64 cacheSet,
153                                      const Address& tag) const;
154
155    // Private copy constructor and assignment operator
156    CacheMemory(const CacheMemory& obj);
157    CacheMemory& operator=(const CacheMemory& obj);
158
159  private:
160    Cycles m_latency;
161
162    // Data Members (m_prefix)
163    bool m_is_instruction_only_cache;
164
165    // The first index is the # of cache lines.
166    // The second index is the the amount associativity.
167    m5::hash_map<Address, int> m_tag_index;
168    std::vector<std::vector<AbstractCacheEntry*> > m_cache;
169
170    AbstractReplacementPolicy *m_replacementPolicy_ptr;
171
172    BankedArray dataArray;
173    BankedArray tagArray;
174
175    int m_cache_size;
176    int m_cache_num_sets;
177    int m_cache_num_set_bits;
178    int m_cache_assoc;
179    int m_start_index_bit;
180    bool m_resource_stalls;
181};
182
183std::ostream& operator<<(std::ostream& out, const CacheMemory& obj);
184
185#endif // __MEM_RUBY_STRUCTURES_CACHEMEMORY_HH__
186