diff options
49 files changed, 324 insertions, 882 deletions
diff --git a/configs/ruby/AMD_Base_Constructor.py b/configs/ruby/AMD_Base_Constructor.py index a8a0e0dde..6ba5547f9 100644 --- a/configs/ruby/AMD_Base_Constructor.py +++ b/configs/ruby/AMD_Base_Constructor.py @@ -52,7 +52,7 @@ class L1Cache(RubyCache): def create(self, size, assoc, options): self.size = MemorySize(size) self.assoc = assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() # # Note: the L2 Cache latency is not currently used @@ -63,7 +63,7 @@ class L2Cache(RubyCache): def create(self, size, assoc, options): self.size = MemorySize(size) self.assoc = assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class CPCntrl(AMD_Base_Controller, CntrlBase): def create(self, options, ruby_system, system): diff --git a/configs/ruby/GPU_RfO.py b/configs/ruby/GPU_RfO.py index 1f4df38ea..3e0002f04 100644 --- a/configs/ruby/GPU_RfO.py +++ b/configs/ruby/GPU_RfO.py @@ -76,28 +76,28 @@ class TccDirCache(RubyCache): options.tcc_dir_factor) / long(options.num_tccs) self.start_index_bit = math.log(options.cacheline_size, 2) + \ math.log(options.num_tccs, 2) - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class L1DCache(RubyCache): resourceStalls = False def create(self, options): self.size = MemorySize(options.l1d_size) self.assoc = options.l1d_assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class L1ICache(RubyCache): resourceStalls = False def create(self, options): self.size = MemorySize(options.l1i_size) self.assoc = options.l1i_assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class L2Cache(RubyCache): resourceStalls = False def create(self, options): self.size = MemorySize(options.l2_size) self.assoc = options.l2_assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class CPCntrl(CorePair_Controller, CntrlBase): @@ -149,7 +149,7 @@ class TCPCache(RubyCache): tagAccessLatency = 1 def create(self, options): self.size = MemorySize(options.tcp_size) - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class TCPCntrl(TCP_Controller, CntrlBase): @@ -222,7 +222,7 @@ class SQCCache(RubyCache): dataAccessLatency = 4 tagAccessLatency = 1 def create(self, options): - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class SQCCntrl(SQC_Controller, CntrlBase): @@ -282,7 +282,7 @@ class TCC(RubyCache): self.size.value = long(128 * self.assoc) self.start_index_bit = math.log(options.cacheline_size, 2) + \ math.log(options.num_tccs, 2) - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class TCCCntrl(TCC_Controller, CntrlBase): def create(self, options, ruby_system, system): @@ -347,7 +347,7 @@ class L3Cache(RubyCache): self.dataAccessLatency = options.l3_data_latency self.tagAccessLatency = options.l3_tag_latency self.resourceStalls = options.no_resource_stalls - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class L3Cntrl(L3Cache_Controller, CntrlBase): def create(self, options, ruby_system, system): diff --git a/configs/ruby/GPU_VIPER.py b/configs/ruby/GPU_VIPER.py index 52b6c28ab..535c7f921 100644 --- a/configs/ruby/GPU_VIPER.py +++ b/configs/ruby/GPU_VIPER.py @@ -74,7 +74,7 @@ class L1Cache(RubyCache): def create(self, size, assoc, options): self.size = MemorySize(size) self.assoc = assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class L2Cache(RubyCache): resourceStalls = False @@ -84,7 +84,7 @@ class L2Cache(RubyCache): def create(self, size, assoc, options): self.size = MemorySize(size) self.assoc = assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class CPCntrl(CorePair_Controller, CntrlBase): @@ -135,7 +135,7 @@ class TCPCache(RubyCache): self.size = MemorySize(options.tcp_size) self.assoc = options.tcp_assoc self.resourceStalls = options.no_tcc_resource_stalls - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class TCPCntrl(TCP_Controller, CntrlBase): @@ -210,7 +210,7 @@ class SQCCache(RubyCache): def create(self, options): self.size = MemorySize(options.sqc_size) self.assoc = options.sqc_assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class SQCCntrl(SQC_Controller, CntrlBase): @@ -259,7 +259,7 @@ class TCC(RubyCache): self.size.value = long(128 * self.assoc) self.start_index_bit = math.log(options.cacheline_size, 2) + \ math.log(options.num_tccs, 2) - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class TCCCntrl(TCC_Controller, CntrlBase): @@ -289,7 +289,7 @@ class L3Cache(RubyCache): self.dataAccessLatency = options.l3_data_latency self.tagAccessLatency = options.l3_tag_latency self.resourceStalls = False - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class L3Cntrl(L3Cache_Controller, CntrlBase): def create(self, options, ruby_system, system): diff --git a/configs/ruby/GPU_VIPER_Baseline.py b/configs/ruby/GPU_VIPER_Baseline.py index 5c713ce2d..a33a99a2e 100644 --- a/configs/ruby/GPU_VIPER_Baseline.py +++ b/configs/ruby/GPU_VIPER_Baseline.py @@ -74,7 +74,7 @@ class L1Cache(RubyCache): def create(self, size, assoc, options): self.size = MemorySize(size) self.assoc = assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class L2Cache(RubyCache): resourceStalls = False @@ -84,7 +84,7 @@ class L2Cache(RubyCache): def create(self, size, assoc, options): self.size = MemorySize(size) self.assoc = assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class CPCntrl(CorePair_Controller, CntrlBase): @@ -138,7 +138,7 @@ class TCPCache(RubyCache): self.dataAccessLatency = 4 self.tagAccessLatency = 1 self.resourceStalls = options.no_tcc_resource_stalls - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class TCPCntrl(TCP_Controller, CntrlBase): @@ -178,7 +178,7 @@ class SQCCache(RubyCache): def create(self, options): self.size = MemorySize(options.sqc_size) self.assoc = options.sqc_assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class SQCCntrl(SQC_Controller, CntrlBase): @@ -222,7 +222,7 @@ class TCC(RubyCache): self.size.value = long(128 * self.assoc) self.start_index_bit = math.log(options.cacheline_size, 2) + \ math.log(options.num_tccs, 2) - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class TCCCntrl(TCC_Controller, CntrlBase): def create(self, options, ruby_system, system): @@ -250,7 +250,7 @@ class L3Cache(RubyCache): self.dataAccessLatency = options.l3_data_latency self.tagAccessLatency = options.l3_tag_latency self.resourceStalls = False - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class ProbeFilter(RubyCache): size = "4MB" @@ -268,7 +268,7 @@ class ProbeFilter(RubyCache): self.dataAccessLatency = 1 self.resourceStalls = options.no_resource_stalls self.start_index_bit = 6 + int(math.log(options.blocks_per_region, 2)) - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class L3Cntrl(L3Cache_Controller, CntrlBase): def create(self, options, ruby_system, system): diff --git a/configs/ruby/GPU_VIPER_Region.py b/configs/ruby/GPU_VIPER_Region.py index 8b317fbaf..e3f717634 100644 --- a/configs/ruby/GPU_VIPER_Region.py +++ b/configs/ruby/GPU_VIPER_Region.py @@ -75,7 +75,7 @@ class L1Cache(RubyCache): def create(self, size, assoc, options): self.size = MemorySize(size) self.assoc = assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class L2Cache(RubyCache): resourceStalls = False @@ -85,7 +85,7 @@ class L2Cache(RubyCache): def create(self, size, assoc, options): self.size = MemorySize(size) self.assoc = assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class CPCntrl(CorePair_Controller, CntrlBase): @@ -139,7 +139,7 @@ class TCPCache(RubyCache): self.dataAccessLatency = 4 self.tagAccessLatency = 1 self.resourceStalls = options.no_tcc_resource_stalls - self.replacement_policy = PseudoLRUReplacementPolicy(assoc = self.assoc) + self.replacement_policy = TreePLRURP(num_leaves = self.assoc) class TCPCntrl(TCP_Controller, CntrlBase): @@ -179,7 +179,7 @@ class SQCCache(RubyCache): def create(self, options): self.size = MemorySize(options.sqc_size) self.assoc = options.sqc_assoc - self.replacement_policy = PseudoLRUReplacementPolicy(assoc = self.assoc) + self.replacement_policy = TreePLRURP(num_leaves = self.assoc) class SQCCntrl(SQC_Controller, CntrlBase): @@ -223,7 +223,7 @@ class TCC(RubyCache): self.size.value = long(128 * self.assoc) self.start_index_bit = math.log(options.cacheline_size, 2) + \ math.log(options.num_tccs, 2) - self.replacement_policy = PseudoLRUReplacementPolicy(assoc = self.assoc) + self.replacement_policy = TreePLRURP(num_leaves = self.assoc) class TCCCntrl(TCC_Controller, CntrlBase): def create(self, options, ruby_system, system): @@ -249,7 +249,7 @@ class L3Cache(RubyCache): self.dataAccessLatency = options.l3_data_latency self.tagAccessLatency = options.l3_tag_latency self.resourceStalls = False - self.replacement_policy = PseudoLRUReplacementPolicy(assoc = self.assoc) + self.replacement_policy = TreePLRURP(num_leaves = self.assoc) class L3Cntrl(L3Cache_Controller, CntrlBase): def create(self, options, ruby_system, system): @@ -328,7 +328,7 @@ class RegionDir(RubyCache): self.dataAccessLatency = 1 self.resourceStalls = options.no_resource_stalls self.start_index_bit = 6 + int(math.log(options.blocks_per_region, 2)) - self.replacement_policy = PseudoLRUReplacementPolicy(assoc = self.assoc) + self.replacement_policy = TreePLRURP(num_leaves = self.assoc) # Region directory controller : Contains region directory and associated state # machine for dealing with region coherence requests. class RegionCntrl(RegionDir_Controller, CntrlBase): @@ -386,7 +386,7 @@ class RBCntrl(RegionBuffer_Controller, CntrlBase): if options.recycle_latency: self.recycle_latency = options.recycle_latency self.cacheMemory.replacement_policy = \ - PseudoLRUReplacementPolicy(assoc = self.cacheMemory.assoc) + TreePLRURP(num_leaves = self.cacheMemory.assoc) def define_options(parser): parser.add_option("--num-subcaches", type="int", default=4) diff --git a/configs/ruby/MESI_Three_Level.py b/configs/ruby/MESI_Three_Level.py index 20f48db32..22b02fa35 100644 --- a/configs/ruby/MESI_Three_Level.py +++ b/configs/ruby/MESI_Three_Level.py @@ -91,11 +91,11 @@ def create_system(options, full_system, system, dma_ports, bootmem, # l0i_cache = L0Cache(size = '4096B', assoc = 1, is_icache = True, start_index_bit = block_size_bits, - replacement_policy = LRUReplacementPolicy()) + replacement_policy = LRURP()) l0d_cache = L0Cache(size = '4096B', assoc = 1, is_icache = False, start_index_bit = block_size_bits, - replacement_policy = LRUReplacementPolicy()) + replacement_policy = LRURP()) # the ruby random tester reuses num_cpus to specify the # number of cpu ports connected to the tester object, which diff --git a/configs/ruby/MOESI_AMD_Base.py b/configs/ruby/MOESI_AMD_Base.py index 0475dcb0c..2757f3d60 100644 --- a/configs/ruby/MOESI_AMD_Base.py +++ b/configs/ruby/MOESI_AMD_Base.py @@ -71,21 +71,21 @@ class L1DCache(RubyCache): def create(self, options): self.size = MemorySize(options.l1d_size) self.assoc = options.l1d_assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class L1ICache(RubyCache): resourceStalls = False def create(self, options): self.size = MemorySize(options.l1i_size) self.assoc = options.l1i_assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class L2Cache(RubyCache): resourceStalls = False def create(self, options): self.size = MemorySize(options.l2_size) self.assoc = options.l2_assoc - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class CPCntrl(CorePair_Controller, CntrlBase): @@ -143,7 +143,7 @@ class L3Cache(RubyCache): self.dataAccessLatency = options.l3_data_latency self.tagAccessLatency = options.l3_tag_latency self.resourceStalls = options.no_resource_stalls - self.replacement_policy = PseudoLRUReplacementPolicy() + self.replacement_policy = TreePLRURP() class L3Cntrl(L3Cache_Controller, CntrlBase): def create(self, options, ruby_system, system): diff --git a/src/learning_gem5/part3/MSI-dir.sm b/src/learning_gem5/part3/MSI-dir.sm index 7bd7aae83..f00df37ef 100644 --- a/src/learning_gem5/part3/MSI-dir.sm +++ b/src/learning_gem5/part3/MSI-dir.sm @@ -125,7 +125,7 @@ machine(MachineType:Directory, "Directory protocol") // NOTE: We use a netdest for the sharers and the owner so we can simply // copy the structure into the message we send as a response. - structure(Entry, desc="...", interface="AbstractEntry") { + structure(Entry, desc="...", interface="AbstractCacheEntry", main="false") { State DirState, desc="Directory state"; NetDest Sharers, desc="Sharers for this block"; NetDest Owner, desc="Owner of this block"; diff --git a/src/mem/cache/replacement_policies/replaceable_entry.hh b/src/mem/cache/replacement_policies/replaceable_entry.hh index c558beea1..2b08749e4 100644 --- a/src/mem/cache/replacement_policies/replaceable_entry.hh +++ b/src/mem/cache/replacement_policies/replaceable_entry.hh @@ -52,7 +52,7 @@ struct ReplacementData {}; */ class ReplaceableEntry { - private: + protected: /** * Set to which this entry belongs. */ diff --git a/src/mem/ruby/SConscript b/src/mem/ruby/SConscript index 450a4bfca..abba91b89 100644 --- a/src/mem/ruby/SConscript +++ b/src/mem/ruby/SConscript @@ -111,7 +111,6 @@ def MakeInclude(source): include_action = MakeAction(MakeIncludeAction, Transform("MAKE INC", 1)) env.Command(target, source, include_action) -MakeInclude('slicc_interface/AbstractEntry.hh') MakeInclude('slicc_interface/AbstractCacheEntry.hh') MakeInclude('slicc_interface/Message.hh') MakeInclude('slicc_interface/RubyRequest.hh') diff --git a/src/mem/ruby/protocol/Garnet_standalone-dir.sm b/src/mem/ruby/protocol/Garnet_standalone-dir.sm index 3a4327972..663ba1703 100644 --- a/src/mem/ruby/protocol/Garnet_standalone-dir.sm +++ b/src/mem/ruby/protocol/Garnet_standalone-dir.sm @@ -55,7 +55,7 @@ machine(MachineType:Directory, "Garnet_standalone Directory") // TYPES // DirectoryEntry - structure(Entry, desc="...", interface="AbstractEntry") { + structure(Entry, desc="...", interface="AbstractCacheEntry", main="false") { State DirectoryState, desc="Directory state"; DataBlock DataBlk, desc="data for the block"; } diff --git a/src/mem/ruby/protocol/MESI_Two_Level-dir.sm b/src/mem/ruby/protocol/MESI_Two_Level-dir.sm index 991de5a2c..2e935de66 100644 --- a/src/mem/ruby/protocol/MESI_Two_Level-dir.sm +++ b/src/mem/ruby/protocol/MESI_Two_Level-dir.sm @@ -72,7 +72,7 @@ machine(MachineType:Directory, "MESI Two Level directory protocol") // TYPES // DirectoryEntry - structure(Entry, desc="...", interface="AbstractEntry") { + structure(Entry, desc="...", interface="AbstractCacheEntry", main="false") { State DirectoryState, desc="Directory state"; MachineID Owner; } diff --git a/src/mem/ruby/protocol/MI_example-dir.sm b/src/mem/ruby/protocol/MI_example-dir.sm index e9f652152..471608de0 100644 --- a/src/mem/ruby/protocol/MI_example-dir.sm +++ b/src/mem/ruby/protocol/MI_example-dir.sm @@ -27,7 +27,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -machine(MachineType:Directory, "Directory protocol") +machine(MachineType:Directory, "Directory protocol") : DirectoryMemory * directory; Cycles directory_latency := 12; Cycles to_memory_controller_latency := 1; @@ -54,7 +54,7 @@ machine(MachineType:Directory, "Directory protocol") M_DRD, AccessPermission:Busy, desc="Blocked on an invalidation for a DMA read"; M_DWR, AccessPermission:Busy, desc="Blocked on an invalidation for a DMA write"; - M_DWRI, AccessPermission:Busy, desc="Intermediate state M_DWR-->I"; + M_DWRI, AccessPermission:Busy, desc="Intermediate state M_DWR-->I"; M_DRDI, AccessPermission:Busy, desc="Intermediate state M_DRD-->I"; IM, AccessPermission:Busy, desc="Intermediate state I-->M"; @@ -83,7 +83,7 @@ machine(MachineType:Directory, "Directory protocol") // TYPES // DirectoryEntry - structure(Entry, desc="...", interface="AbstractEntry") { + structure(Entry, desc="...", interface="AbstractCacheEntry", main="false") { State DirectoryState, desc="Directory state"; NetDest Sharers, desc="Sharers for this block"; NetDest Owner, desc="Owner of this block"; @@ -125,7 +125,7 @@ machine(MachineType:Directory, "Directory protocol") directory.allocate(addr, new Entry)); return dir_entry; } - + State getState(TBE tbe, Addr addr) { if (is_valid(tbe)) { return tbe.TBEState; @@ -150,7 +150,7 @@ machine(MachineType:Directory, "Directory protocol") } getDirectoryEntry(addr).DirectoryState := state; - + if (state == State:I) { assert(getDirectoryEntry(addr).Owner.count() == 0); assert(getDirectoryEntry(addr).Sharers.count() == 0); @@ -354,7 +354,7 @@ machine(MachineType:Directory, "Directory protocol") out_msg.PhysicalAddress := address; out_msg.LineAddress := address; out_msg.Type := DMAResponseType:ACK; - out_msg.Destination.add(tbe.DmaRequestor); + out_msg.Destination.add(tbe.DmaRequestor); out_msg.MessageSize := MessageSizeType:Writeback_Control; } } @@ -401,7 +401,7 @@ machine(MachineType:Directory, "Directory protocol") action(p_popIncomingDMARequestQueue, "p", desc="Pop incoming DMA queue") { dmaRequestQueue_in.dequeue(clockEdge()); } - + action(v_allocateTBE, "v", desc="Allocate TBE") { peek(dmaRequestQueue_in, DMARequestMsg) { TBEs.allocate(address); @@ -490,7 +490,7 @@ machine(MachineType:Directory, "Directory protocol") transition({IM, MI, ID, ID_W}, {GETX, GETS, PUTX, PUTX_NotOwner} ) { z_recycleRequestQueue; } - + transition({IM, MI, ID, ID_W}, {DMA_READ, DMA_WRITE} ) { y_recycleDMARequestQueue; } @@ -546,7 +546,7 @@ machine(MachineType:Directory, "Directory protocol") p_popIncomingDMARequestQueue; } - transition(M_DRD, PUTX, M_DRDI) { + transition(M_DRD, PUTX, M_DRDI) { drp_sendDMAData; c_clearOwner; l_queueMemoryWBRequest; @@ -555,7 +555,7 @@ machine(MachineType:Directory, "Directory protocol") transition(M_DRDI, Memory_Ack, I) { l_sendWriteBackAck; - w_deallocateTBE; + w_deallocateTBE; l_popMemQueue; } diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm index cc5ceb0b5..152d8b50a 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-Region-dir.sm @@ -159,7 +159,7 @@ machine(MachineType:Directory, "AMD_Base-like protocol") // TYPES // DirectoryEntry - structure(Entry, desc="...", interface="AbstractEntry") { + structure(Entry, desc="...", interface="AbstractCacheEntry", main="false") { State DirectoryState, desc="Directory state"; DataBlock DataBlk, desc="data for the block"; NetDest VicDirtyIgnore, desc="VicDirty coming from whom to ignore"; diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm index 4cde5ad03..971b84634 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-dir.sm @@ -119,7 +119,7 @@ machine(MachineType:Directory, "AMD Baseline protocol") // TYPES // DirectoryEntry - structure(Entry, desc="...", interface="AbstractEntry") { + structure(Entry, desc="...", interface="AbstractCacheEntry", main="false") { State DirectoryState, desc="Directory state"; DataBlock DataBlk, desc="data for the block"; NetDest VicDirtyIgnore, desc="VicDirty coming from whom to ignore"; diff --git a/src/mem/ruby/protocol/MOESI_AMD_Base-probeFilter.sm b/src/mem/ruby/protocol/MOESI_AMD_Base-probeFilter.sm index d23094a2e..51efb1015 100644 --- a/src/mem/ruby/protocol/MOESI_AMD_Base-probeFilter.sm +++ b/src/mem/ruby/protocol/MOESI_AMD_Base-probeFilter.sm @@ -148,7 +148,7 @@ machine(MachineType:Directory, "AMD Baseline protocol") } // DirectoryEntry - structure(Entry, desc="...", interface="AbstractEntry") { + structure(Entry, desc="...", interface="AbstractCacheEntry", main="false") { State DirectoryState, desc="Directory state"; DataBlock DataBlk, desc="data for the block"; NetDest VicDirtyIgnore, desc="VicDirty coming from whom to ignore"; diff --git a/src/mem/ruby/protocol/MOESI_CMP_directory-L2cache.sm b/src/mem/ruby/protocol/MOESI_CMP_directory-L2cache.sm index f20085fd5..18e3b891e 100644 --- a/src/mem/ruby/protocol/MOESI_CMP_directory-L2cache.sm +++ b/src/mem/ruby/protocol/MOESI_CMP_directory-L2cache.sm @@ -193,7 +193,7 @@ machine(MachineType:L2Cache, "Token protocol") } - structure(DirEntry, desc="...", interface="AbstractEntry") { + structure(DirEntry, desc="...", interface="AbstractCacheEntry", main="false") { NetDest Sharers, desc="Set of the internal processors that want the block in shared state"; MachineID Owner, desc="ID of the L1 cache to forward the block to once we get a response"; bool OwnerValid, default="false", desc="true if Owner means something"; diff --git a/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm b/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm index f12d16658..29f862e2e 100644 --- a/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm +++ b/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm @@ -106,7 +106,7 @@ machine(MachineType:Directory, "Directory protocol") // TYPES // DirectoryEntry - structure(Entry, desc="...", interface='AbstractEntry') { + structure(Entry, desc="...", interface='AbstractCacheEntry', main="false") { State DirectoryState, desc="Directory state"; NetDest Sharers, desc="Sharers for this block"; NetDest Owner, desc="Owner of this block"; diff --git a/src/mem/ruby/protocol/MOESI_CMP_token-L2cache.sm b/src/mem/ruby/protocol/MOESI_CMP_token-L2cache.sm index 948a2d95f..119508aa8 100644 --- a/src/mem/ruby/protocol/MOESI_CMP_token-L2cache.sm +++ b/src/mem/ruby/protocol/MOESI_CMP_token-L2cache.sm @@ -35,7 +35,7 @@ machine(MachineType:L2Cache, "Token protocol") // L2 BANK QUEUES // From local bank of L2 cache TO the network - + // this L2 bank -> a local L1 || mod-directory MessageBuffer * responseFromL2Cache, network="To", virtual_network="4", vnet_type="response"; @@ -45,10 +45,10 @@ machine(MachineType:L2Cache, "Token protocol") // this L2 bank -> a local L1 MessageBuffer * L1RequestFromL2Cache, network="To", virtual_network="1", vnet_type="request"; - - + + // FROM the network to this local bank of L2 cache - + // a local L1 || mod-directory -> this L2 bank MessageBuffer * responseToL2Cache, network="From", virtual_network="4", vnet_type="response"; @@ -123,7 +123,7 @@ machine(MachineType:L2Cache, "Token protocol") DataBlock DataBlk, desc="data for the block"; } - structure(DirEntry, desc="...", interface="AbstractEntry") { + structure(DirEntry, desc="...", interface="AbstractCacheEntry", main="false") { Set Sharers, desc="Set of the internal processors that want the block in shared state"; bool exclusive, default="false", desc="if local exclusive is likely"; } diff --git a/src/mem/ruby/protocol/MOESI_CMP_token-dir.sm b/src/mem/ruby/protocol/MOESI_CMP_token-dir.sm index b9b65b585..2e3f12024 100644 --- a/src/mem/ruby/protocol/MOESI_CMP_token-dir.sm +++ b/src/mem/ruby/protocol/MOESI_CMP_token-dir.sm @@ -47,17 +47,17 @@ machine(MachineType:Directory, "Token protocol") MessageBuffer * requestFromDir, network="To", virtual_network="1", vnet_type="request"; - + // Message Queues to dir from other controllers / network MessageBuffer * responseToDir, network="From", virtual_network="4", vnet_type="response"; MessageBuffer * persistentToDir, network="From", virtual_network="3", vnet_type="persistent"; - + MessageBuffer * requestToDir, network="From", virtual_network="2", vnet_type="request"; - + MessageBuffer * dmaRequestToDir, network="From", virtual_network="0", vnet_type="request"; @@ -120,7 +120,7 @@ machine(MachineType:Directory, "Token protocol") // TYPES // DirectoryEntry - structure(Entry, desc="...", interface="AbstractEntry") { + structure(Entry, desc="...", interface="AbstractCacheEntry", main="false") { State DirectoryState, desc="Directory state"; int Tokens, default="max_tokens()", desc="Number of tokens for the line we're holding"; diff --git a/src/mem/ruby/protocol/MOESI_hammer-dir.sm b/src/mem/ruby/protocol/MOESI_hammer-dir.sm index 3b0016868..3c457b171 100644 --- a/src/mem/ruby/protocol/MOESI_hammer-dir.sm +++ b/src/mem/ruby/protocol/MOESI_hammer-dir.sm @@ -148,7 +148,7 @@ machine(MachineType:Directory, "AMD Hammer-like protocol") // TYPES // DirectoryEntry - structure(Entry, desc="...", interface="AbstractEntry") { + structure(Entry, desc="...", interface="AbstractCacheEntry", main="false") { State DirectoryState, desc="Directory state"; } diff --git a/src/mem/ruby/protocol/RubySlicc_Types.sm b/src/mem/ruby/protocol/RubySlicc_Types.sm index 2d4c250da..fd7628965 100644 --- a/src/mem/ruby/protocol/RubySlicc_Types.sm +++ b/src/mem/ruby/protocol/RubySlicc_Types.sm @@ -174,22 +174,18 @@ structure(RubyRequest, desc="...", interface="Message", external="yes") { PacketPtr pkt, desc="Packet associated with this request"; } -structure(AbstractEntry, primitive="yes", external = "yes") { +structure(AbstractCacheEntry, primitive="yes", external = "yes") { void changePermission(AccessPermission); } structure (DirectoryMemory, external = "yes") { - AbstractEntry allocate(Addr, AbstractEntry); - AbstractEntry lookup(Addr); + AbstractCacheEntry allocate(Addr, AbstractCacheEntry); + AbstractCacheEntry lookup(Addr); bool isPresent(Addr); void invalidateBlock(Addr); void recordRequestType(DirectoryRequestType); } -structure(AbstractCacheEntry, primitive="yes", external = "yes") { - void changePermission(AccessPermission); -} - structure (CacheMemory, external = "yes") { bool cacheAvail(Addr); Addr cacheProbe(Addr); diff --git a/src/mem/ruby/slicc_interface/AbstractCacheEntry.cc b/src/mem/ruby/slicc_interface/AbstractCacheEntry.cc index 00dfc6c64..b98425d7e 100644 --- a/src/mem/ruby/slicc_interface/AbstractCacheEntry.cc +++ b/src/mem/ruby/slicc_interface/AbstractCacheEntry.cc @@ -31,21 +31,29 @@ #include "base/trace.hh" #include "debug/RubyCache.hh" -AbstractCacheEntry::AbstractCacheEntry() +AbstractCacheEntry::AbstractCacheEntry() : ReplaceableEntry() { m_Permission = AccessPermission_NotPresent; m_Address = 0; m_locked = -1; + m_last_touch_tick = 0; } AbstractCacheEntry::~AbstractCacheEntry() { } +// Get cache permission +AccessPermission +AbstractCacheEntry::getPermission() const +{ + return m_Permission; +} + void AbstractCacheEntry::changePermission(AccessPermission new_perm) { - AbstractEntry::changePermission(new_perm); + m_Permission = new_perm; if ((new_perm == AccessPermission_Invalid) || (new_perm == AccessPermission_NotPresent)) { m_locked = -1; diff --git a/src/mem/ruby/slicc_interface/AbstractCacheEntry.hh b/src/mem/ruby/slicc_interface/AbstractCacheEntry.hh index c943c75d0..0519b3f7d 100644 --- a/src/mem/ruby/slicc_interface/AbstractCacheEntry.hh +++ b/src/mem/ruby/slicc_interface/AbstractCacheEntry.hh @@ -36,21 +36,28 @@ #include <iostream> #include "base/logging.hh" +#include "mem/cache/replacement_policies/replaceable_entry.hh" #include "mem/ruby/common/Address.hh" #include "mem/ruby/protocol/AccessPermission.hh" -#include "mem/ruby/slicc_interface/AbstractEntry.hh" class DataBlock; -class AbstractCacheEntry : public AbstractEntry +class AbstractCacheEntry : public ReplaceableEntry { + private: + // The last access tick for the cache entry. + Tick m_last_touch_tick; + public: AbstractCacheEntry(); virtual ~AbstractCacheEntry() = 0; // Get/Set permission of the entry + AccessPermission getPermission() const; void changePermission(AccessPermission new_perm); + virtual void print(std::ostream& out) const = 0; + // The methods below are those called by ruby runtime, add when it // is absolutely necessary and should all be virtual function. virtual DataBlock& getDataBlk() @@ -68,22 +75,20 @@ class AbstractCacheEntry : public AbstractEntry void clearLocked(); bool isLocked(int context) const; - void setSetIndex(uint32_t s) { m_set_index = s; } - uint32_t getSetIndex() const { return m_set_index; } - - void setWayIndex(uint32_t s) { m_way_index = s; } - uint32_t getWayIndex() const { return m_way_index; } - // Address of this block, required by CacheMemory Addr m_Address; // Holds info whether the address is locked. // Required for implementing LL/SC operations. int m_locked; - private: - // Set and way coordinates of the entry within the cache memory object. - uint32_t m_set_index; - uint32_t m_way_index; + AccessPermission m_Permission; // Access permission for this + // block, required by CacheMemory + + // Get the last access Tick. + Tick getLastAccess() { return m_last_touch_tick; } + + // Set the last access Tick. + void setLastAccess(Tick tick) { m_last_touch_tick = tick; } }; inline std::ostream& diff --git a/src/mem/ruby/slicc_interface/AbstractEntry.cc b/src/mem/ruby/slicc_interface/AbstractEntry.cc deleted file mode 100644 index 51f16df6a..000000000 --- a/src/mem/ruby/slicc_interface/AbstractEntry.cc +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "mem/ruby/slicc_interface/AbstractEntry.hh" - -AbstractEntry::AbstractEntry() -{ - m_Permission = AccessPermission_NotPresent; -} - -AbstractEntry::~AbstractEntry() -{ -} - -AccessPermission -AbstractEntry::getPermission() const -{ - return m_Permission; -} - -void -AbstractEntry::changePermission(AccessPermission new_perm) -{ - m_Permission = new_perm; -} diff --git a/src/mem/ruby/slicc_interface/AbstractEntry.hh b/src/mem/ruby/slicc_interface/AbstractEntry.hh deleted file mode 100644 index a75055f5e..000000000 --- a/src/mem/ruby/slicc_interface/AbstractEntry.hh +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __MEM_RUBY_SLICC_INTERFACE_ABSTRACTENTRY_HH__ -#define __MEM_RUBY_SLICC_INTERFACE_ABSTRACTENTRY_HH__ - -#include <iostream> - -#include "mem/ruby/protocol/AccessPermission.hh" - -class AbstractEntry -{ - public: - AbstractEntry(); - virtual ~AbstractEntry() = 0; - - // Get/Set permission of the entry - AccessPermission getPermission() const; - void changePermission(AccessPermission new_perm); - - virtual void print(std::ostream& out) const = 0; - - AccessPermission m_Permission; // Access permission for this - // block, required by CacheMemory -}; - -inline std::ostream& -operator<<(std::ostream& out, const AbstractEntry& obj) -{ - obj.print(out); - out << std::flush; - return out; -} - -#endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTENTRY_HH__ diff --git a/src/mem/ruby/slicc_interface/SConscript b/src/mem/ruby/slicc_interface/SConscript index 2d00fb7fe..d8d931c63 100644 --- a/src/mem/ruby/slicc_interface/SConscript +++ b/src/mem/ruby/slicc_interface/SConscript @@ -36,6 +36,5 @@ if env['PROTOCOL'] == 'None': SimObject('Controller.py') Source('AbstractController.cc') -Source('AbstractEntry.cc') Source('AbstractCacheEntry.cc') Source('RubyRequest.cc') diff --git a/src/mem/ruby/structures/AbstractReplacementPolicy.cc b/src/mem/ruby/structures/AbstractReplacementPolicy.cc deleted file mode 100644 index 01eb6e517..000000000 --- a/src/mem/ruby/structures/AbstractReplacementPolicy.cc +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2013 Advanced Micro Devices, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Derek Hower - */ - -#include "mem/ruby/structures/AbstractReplacementPolicy.hh" - -#include "base/logging.hh" - -AbstractReplacementPolicy::AbstractReplacementPolicy(const Params * p) - : SimObject(p) -{ - m_num_sets = p->size/p->block_size/p->assoc; - m_assoc = p->assoc; - m_last_ref_ptr = new Tick*[m_num_sets]; - for (unsigned i = 0; i < m_num_sets; i++){ - m_last_ref_ptr[i] = new Tick[m_assoc]; - for (unsigned j = 0; j < m_assoc; j++){ - m_last_ref_ptr[i][j] = 0; - } - } -} - -AbstractReplacementPolicy * -ReplacementPolicyParams::create() -{ - fatal("Cannot create an AbstractReplacementPolicy"); - return NULL; -} - - - -AbstractReplacementPolicy::~AbstractReplacementPolicy() -{ - if (m_last_ref_ptr != NULL){ - for (unsigned i = 0; i < m_num_sets; i++){ - if (m_last_ref_ptr[i] != NULL){ - delete[] m_last_ref_ptr[i]; - } - } - delete[] m_last_ref_ptr; - } -} - -Tick -AbstractReplacementPolicy::getLastAccess(int64_t set, int64_t way) -{ - return m_last_ref_ptr[set][way]; -} diff --git a/src/mem/ruby/structures/AbstractReplacementPolicy.hh b/src/mem/ruby/structures/AbstractReplacementPolicy.hh deleted file mode 100644 index c118f3c11..000000000 --- a/src/mem/ruby/structures/AbstractReplacementPolicy.hh +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2007 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __MEM_RUBY_STRUCTURES_ABSTRACTREPLACEMENTPOLICY_HH__ -#define __MEM_RUBY_STRUCTURES_ABSTRACTREPLACEMENTPOLICY_HH__ - -#include "base/types.hh" -#include "mem/ruby/common/TypeDefines.hh" -#include "params/ReplacementPolicy.hh" -#include "sim/sim_object.hh" - -class CacheMemory; - -class AbstractReplacementPolicy : public SimObject -{ - public: - typedef ReplacementPolicyParams Params; - AbstractReplacementPolicy(const Params * p); - virtual ~AbstractReplacementPolicy(); - - /* touch a block. a.k.a. update timestamp */ - virtual void touch(int64_t set, int64_t way, Tick time) = 0; - - /* returns the way to replace */ - virtual int64_t getVictim(int64_t set) const = 0; - - /* get the time of the last access */ - Tick getLastAccess(int64_t set, int64_t way); - - virtual bool useOccupancy() const { return false; } - - void setCache(CacheMemory * pCache) {m_cache = pCache;} - CacheMemory * m_cache; - - protected: - unsigned m_num_sets; /** total number of sets */ - unsigned m_assoc; /** set associativity */ - Tick **m_last_ref_ptr; /** timestamp of last reference */ -}; - -#endif // __MEM_RUBY_STRUCTURES_ABSTRACTREPLACEMENTPOLICY_HH__ diff --git a/src/mem/ruby/structures/CacheMemory.cc b/src/mem/ruby/structures/CacheMemory.cc index 5dc346388..a7aa6370b 100644 --- a/src/mem/ruby/structures/CacheMemory.cc +++ b/src/mem/ruby/structures/CacheMemory.cc @@ -65,11 +65,12 @@ CacheMemory::CacheMemory(const Params *p) m_cache_size = p->size; m_cache_assoc = p->assoc; m_replacementPolicy_ptr = p->replacement_policy; - m_replacementPolicy_ptr->setCache(this); m_start_index_bit = p->start_index_bit; m_is_instruction_only_cache = p->is_icache; m_resource_stalls = p->resourceStalls; m_block_size = p->block_size; // may be 0 at this point. Updated in init() + m_use_occupancy = dynamic_cast<WeightedLRUPolicy*>( + m_replacementPolicy_ptr) ? true : false; } void @@ -85,6 +86,15 @@ CacheMemory::init() m_cache.resize(m_cache_num_sets, std::vector<AbstractCacheEntry*>(m_cache_assoc, nullptr)); + replacement_data.resize(m_cache_num_sets, + std::vector<ReplData>(m_cache_assoc, nullptr)); + // instantiate all the replacement_data here + for (int i = 0; i < m_cache_num_sets; i++) { + for ( int j = 0; j < m_cache_assoc; j++) { + replacement_data[i][j] = + m_replacementPolicy_ptr->instantiateEntry(); + } + } } CacheMemory::~CacheMemory() @@ -170,7 +180,8 @@ CacheMemory::tryCacheAccess(Addr address, RubyRequestType type, if (loc != -1) { // Do we even have a tag match? AbstractCacheEntry* entry = m_cache[cacheSet][loc]; - m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); + m_replacementPolicy_ptr->touch(replacement_data[cacheSet][loc]); + m_cache[cacheSet][loc]->setLastAccess(curTick()); data_ptr = &(entry->getDataBlk()); if (entry->m_Permission == AccessPermission_Read_Write) { @@ -198,7 +209,8 @@ CacheMemory::testCacheAccess(Addr address, RubyRequestType type, if (loc != -1) { // Do we even have a tag match? AbstractCacheEntry* entry = m_cache[cacheSet][loc]; - m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); + m_replacementPolicy_ptr->touch(replacement_data[cacheSet][loc]); + m_cache[cacheSet][loc]->setLastAccess(curTick()); data_ptr = &(entry->getDataBlk()); return m_cache[cacheSet][loc]->m_Permission != @@ -252,7 +264,7 @@ CacheMemory::cacheAvail(Addr address) const } AbstractCacheEntry* -CacheMemory::allocate(Addr address, AbstractCacheEntry *entry, bool touch) +CacheMemory::allocate(Addr address, AbstractCacheEntry *entry) { assert(address == makeLineAddress(address)); assert(!isTagPresent(address)); @@ -278,13 +290,11 @@ CacheMemory::allocate(Addr address, AbstractCacheEntry *entry, bool touch) address); set[i]->m_locked = -1; m_tag_index[address] = i; - entry->setSetIndex(cacheSet); - entry->setWayIndex(i); - - if (touch) { - m_replacementPolicy_ptr->touch(cacheSet, i, curTick()); - } - + set[i]->setPosition(cacheSet, i); + // Call reset function here to set initial value for different + // replacement policies. + m_replacementPolicy_ptr->reset(replacement_data[cacheSet][i]); + set[i]->setLastAccess(curTick()); return entry; } } @@ -300,6 +310,7 @@ CacheMemory::deallocate(Addr address) int64_t cacheSet = addressToCacheSet(address); int loc = findTagInSet(cacheSet, address); if (loc != -1) { + m_replacementPolicy_ptr->invalidate(replacement_data[cacheSet][loc]); delete m_cache[cacheSet][loc]; m_cache[cacheSet][loc] = NULL; m_tag_index.erase(address); @@ -314,8 +325,16 @@ CacheMemory::cacheProbe(Addr address) const assert(!cacheAvail(address)); int64_t cacheSet = addressToCacheSet(address); - return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]-> - m_Address; + std::vector<ReplaceableEntry*> candidates; + for (int i = 0; i < m_cache_assoc; i++) { + // Pass the value of replacement_data to the cache entry so that we + // can use it in the getVictim() function. + m_cache[cacheSet][i]->replacementData = replacement_data[cacheSet][i]; + candidates.push_back(static_cast<ReplaceableEntry*>( + m_cache[cacheSet][i])); + } + return m_cache[cacheSet][m_replacementPolicy_ptr-> + getVictim(candidates)->getWay()]->m_Address; } // looks an address up in the cache @@ -347,16 +366,19 @@ CacheMemory::setMRU(Addr address) int64_t cacheSet = addressToCacheSet(address); int loc = findTagInSet(cacheSet, address); - if (loc != -1) - m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); + if (loc != -1) { + m_replacementPolicy_ptr->touch(replacement_data[cacheSet][loc]); + m_cache[cacheSet][loc]->setLastAccess(curTick()); + } } void CacheMemory::setMRU(const AbstractCacheEntry *e) { - uint32_t cacheSet = e->getSetIndex(); - uint32_t loc = e->getWayIndex(); - m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); + uint32_t cacheSet = e->getSet(); + uint32_t loc = e->getWay(); + m_replacementPolicy_ptr->touch(replacement_data[cacheSet][loc]); + m_cache[cacheSet][loc]->setLastAccess(curTick()); } void @@ -366,13 +388,17 @@ CacheMemory::setMRU(Addr address, int occupancy) int loc = findTagInSet(cacheSet, address); if (loc != -1) { - if (m_replacementPolicy_ptr->useOccupancy()) { - (static_cast<WeightedLRUPolicy*>(m_replacementPolicy_ptr))-> - touch(cacheSet, loc, curTick(), occupancy); + // m_use_occupancy can decide whether we are using WeightedLRU + // replacement policy. Depending on different replacement policies, + // use different touch() function. + if (m_use_occupancy) { + static_cast<WeightedLRUPolicy*>(m_replacementPolicy_ptr)->touch( + replacement_data[cacheSet][loc], occupancy); } else { m_replacementPolicy_ptr-> - touch(cacheSet, loc, curTick()); + touch(replacement_data[cacheSet][loc]); } + m_cache[cacheSet][loc]->setLastAccess(curTick()); } } @@ -413,9 +439,10 @@ CacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const } if (request_type != RubyRequestType_NULL) { + Tick lastAccessTick; + lastAccessTick = m_cache[i][j]->getLastAccess(); tr->addRecord(cntrl, m_cache[i][j]->m_Address, - 0, request_type, - m_replacementPolicy_ptr->getLastAccess(i, j), + 0, request_type, lastAccessTick, m_cache[i][j]->getDataBlk()); warmedUpBlocks++; } diff --git a/src/mem/ruby/structures/CacheMemory.hh b/src/mem/ruby/structures/CacheMemory.hh index 16339ee55..ce5d81d04 100644 --- a/src/mem/ruby/structures/CacheMemory.hh +++ b/src/mem/ruby/structures/CacheMemory.hh @@ -35,13 +35,14 @@ #include <vector> #include "base/statistics.hh" +#include "mem/cache/replacement_policies/base.hh" +#include "mem/cache/replacement_policies/replaceable_entry.hh" #include "mem/ruby/common/DataBlock.hh" #include "mem/ruby/protocol/CacheRequestType.hh" #include "mem/ruby/protocol/CacheResourceType.hh" #include "mem/ruby/protocol/RubyRequest.hh" #include "mem/ruby/slicc_interface/AbstractCacheEntry.hh" #include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" -#include "mem/ruby/structures/AbstractReplacementPolicy.hh" #include "mem/ruby/structures/BankedArray.hh" #include "mem/ruby/system/CacheRecorder.hh" #include "params/RubyCache.hh" @@ -51,6 +52,7 @@ class CacheMemory : public SimObject { public: typedef RubyCacheParams Params; + typedef std::shared_ptr<ReplacementData> ReplData; CacheMemory(const Params *p); ~CacheMemory(); @@ -74,15 +76,10 @@ class CacheMemory : public SimObject bool cacheAvail(Addr address) const; // find an unused entry and sets the tag appropriate for the address - AbstractCacheEntry* allocate(Addr address, - AbstractCacheEntry* new_entry, bool touch); - AbstractCacheEntry* allocate(Addr address, AbstractCacheEntry* new_entry) - { - return allocate(address, new_entry, true); - } + AbstractCacheEntry* allocate(Addr address, AbstractCacheEntry* new_entry); void allocateVoid(Addr address, AbstractCacheEntry* new_entry) { - allocate(address, new_entry, true); + allocate(address, new_entry); } // Explicitly free up this address @@ -173,7 +170,11 @@ class CacheMemory : public SimObject std::unordered_map<Addr, int> m_tag_index; std::vector<std::vector<AbstractCacheEntry*> > m_cache; - AbstractReplacementPolicy *m_replacementPolicy_ptr; + /** + * We use BaseReplacementPolicy from Classic system here, hence we can use + * different replacement policies from Classic system in Ruby system. + */ + BaseReplacementPolicy *m_replacementPolicy_ptr; BankedArray dataArray; BankedArray tagArray; @@ -185,6 +186,22 @@ class CacheMemory : public SimObject int m_start_index_bit; bool m_resource_stalls; int m_block_size; + + /** + * We store all the ReplacementData in a 2-dimensional array. By doing + * this, we can use all replacement policies from Classic system. Ruby + * cache will deallocate cache entry every time we evict the cache block + * so we cannot store the ReplacementData inside the cache entry. + * Instantiate ReplacementData for multiple times will break replacement + * policy like TreePLRU. + */ + std::vector<std::vector<ReplData> > replacement_data; + + /** + * Set to true when using WeightedLRU replacement policy, otherwise, set to + * false. + */ + bool m_use_occupancy; }; std::ostream& operator<<(std::ostream& out, const CacheMemory& obj); diff --git a/src/mem/ruby/structures/DirectoryMemory.cc b/src/mem/ruby/structures/DirectoryMemory.cc index 551e3f57f..d9da05861 100644 --- a/src/mem/ruby/structures/DirectoryMemory.cc +++ b/src/mem/ruby/structures/DirectoryMemory.cc @@ -68,7 +68,7 @@ void DirectoryMemory::init() { m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes(); - m_entries = new AbstractEntry*[m_num_entries]; + m_entries = new AbstractCacheEntry*[m_num_entries]; for (int i = 0; i < m_num_entries; i++) m_entries[i] = NULL; } @@ -109,7 +109,7 @@ DirectoryMemory::mapAddressToLocalIdx(Addr address) return ret >> RubySystem::getBlockSizeBits(); } -AbstractEntry* +AbstractCacheEntry* DirectoryMemory::lookup(Addr address) { assert(isPresent(address)); @@ -120,8 +120,8 @@ DirectoryMemory::lookup(Addr address) return m_entries[idx]; } -AbstractEntry* -DirectoryMemory::allocate(Addr address, AbstractEntry *entry) +AbstractCacheEntry* +DirectoryMemory::allocate(Addr address, AbstractCacheEntry *entry) { assert(isPresent(address)); uint64_t idx; diff --git a/src/mem/ruby/structures/DirectoryMemory.hh b/src/mem/ruby/structures/DirectoryMemory.hh index bbed4f975..f879b294f 100644 --- a/src/mem/ruby/structures/DirectoryMemory.hh +++ b/src/mem/ruby/structures/DirectoryMemory.hh @@ -47,7 +47,7 @@ #include "base/addr_range.hh" #include "mem/ruby/common/Address.hh" #include "mem/ruby/protocol/DirectoryRequestType.hh" -#include "mem/ruby/slicc_interface/AbstractEntry.hh" +#include "mem/ruby/slicc_interface/AbstractCacheEntry.hh" #include "params/RubyDirectoryMemory.hh" #include "sim/sim_object.hh" @@ -76,8 +76,8 @@ class DirectoryMemory : public SimObject uint64_t getSize() { return m_size_bytes; } bool isPresent(Addr address); - AbstractEntry *lookup(Addr address); - AbstractEntry *allocate(Addr address, AbstractEntry* new_entry); + AbstractCacheEntry *lookup(Addr address); + AbstractCacheEntry *allocate(Addr address, AbstractCacheEntry* new_entry); void print(std::ostream& out) const; void recordRequestType(DirectoryRequestType requestType); @@ -89,7 +89,7 @@ class DirectoryMemory : public SimObject private: const std::string m_name; - AbstractEntry **m_entries; + AbstractCacheEntry **m_entries; // int m_size; // # of memory module blocks this directory is // responsible for uint64_t m_size_bytes; diff --git a/src/mem/ruby/structures/LRUPolicy.cc b/src/mem/ruby/structures/LRUPolicy.cc deleted file mode 100644 index 3b6d91754..000000000 --- a/src/mem/ruby/structures/LRUPolicy.cc +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2013 Advanced Micro Devices, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Derek Hower - */ - -#include "mem/ruby/structures/LRUPolicy.hh" - -LRUPolicy::LRUPolicy(const Params * p) - : AbstractReplacementPolicy(p) -{ -} - - -LRUPolicy::~LRUPolicy() -{ -} - -LRUPolicy * -LRUReplacementPolicyParams::create() -{ - return new LRUPolicy(this); -} - - -void -LRUPolicy::touch(int64_t set, int64_t index, Tick time) -{ - assert(index >= 0 && index < m_assoc); - assert(set >= 0 && set < m_num_sets); - - m_last_ref_ptr[set][index] = time; -} - -int64_t -LRUPolicy::getVictim(int64_t set) const -{ - Tick time, smallest_time; - int64_t smallest_index = 0; - smallest_time = m_last_ref_ptr[set][0]; - - for (unsigned i = 0; i < m_assoc; i++) { - time = m_last_ref_ptr[set][i]; - - if (time < smallest_time) { - smallest_index = i; - smallest_time = time; - } - } - - return smallest_index; -} diff --git a/src/mem/ruby/structures/LRUPolicy.hh b/src/mem/ruby/structures/LRUPolicy.hh deleted file mode 100644 index 388718319..000000000 --- a/src/mem/ruby/structures/LRUPolicy.hh +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2007 Mark D. Hill and David A. Wood - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __MEM_RUBY_STRUCTURES_LRUPOLICY_HH__ -#define __MEM_RUBY_STRUCTURES_LRUPOLICY_HH__ - -#include "mem/ruby/structures/AbstractReplacementPolicy.hh" -#include "params/LRUReplacementPolicy.hh" - -/* Simple true LRU replacement policy */ - -class LRUPolicy : public AbstractReplacementPolicy -{ - public: - typedef LRUReplacementPolicyParams Params; - LRUPolicy(const Params * p); - ~LRUPolicy(); - - void touch(int64_t set, int64_t way, Tick time); - int64_t getVictim(int64_t set) const; -}; - -#endif // __MEM_RUBY_STRUCTURES_LRUPOLICY_HH__ diff --git a/src/mem/ruby/structures/LRUReplacementPolicy.py b/src/mem/ruby/structures/LRUReplacementPolicy.py deleted file mode 100644 index 9c36b5f51..000000000 --- a/src/mem/ruby/structures/LRUReplacementPolicy.py +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright (c) 2013 Advanced Micro Devices, Inc -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Author: Derek Hower - - - -from m5.params import * -from m5.SimObject import SimObject -from m5.objects.ReplacementPolicy import ReplacementPolicy - -class LRUReplacementPolicy(ReplacementPolicy): - type = 'LRUReplacementPolicy' - cxx_class = 'LRUPolicy' - cxx_header = 'mem/ruby/structures/LRUPolicy.hh' - - diff --git a/src/mem/ruby/structures/PseudoLRUPolicy.cc b/src/mem/ruby/structures/PseudoLRUPolicy.cc deleted file mode 100644 index e423bb58d..000000000 --- a/src/mem/ruby/structures/PseudoLRUPolicy.cc +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2013 Advanced Micro Devices, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Derek Hower - */ - -#include "mem/ruby/structures/PseudoLRUPolicy.hh" - -PseudoLRUPolicy::PseudoLRUPolicy(const Params * p) - : AbstractReplacementPolicy(p) -{ - // associativity cannot exceed capacity of tree representation - assert(m_num_sets > 0 && - m_assoc > 1 && - m_assoc <= (int64_t) sizeof(uint64_t)*4); - - m_trees = NULL; - m_num_levels = 0; - - m_effective_assoc = 1; - while (m_effective_assoc < m_assoc) { - // effective associativity is ceiling power of 2 - m_effective_assoc <<= 1; - } - int tmp_assoc = m_effective_assoc; - while (true) { - tmp_assoc /= 2; - if (!tmp_assoc) break; - m_num_levels++; - } - assert(m_num_levels < sizeof(unsigned int)*4); - m_trees = new uint64_t[m_num_sets]; - for (unsigned i = 0; i < m_num_sets; i++) { - m_trees[i] = 0; - } -} - -PseudoLRUPolicy * -PseudoLRUReplacementPolicyParams::create() -{ - return new PseudoLRUPolicy(this); -} - - -PseudoLRUPolicy::~PseudoLRUPolicy() -{ - if (m_trees != NULL) - delete[] m_trees; -} - -void -PseudoLRUPolicy::touch(int64_t set, int64_t index, Tick time) -{ - assert(index >= 0 && index < m_assoc); - assert(set >= 0 && set < m_num_sets); - - int tree_index = 0; - int node_val; - for (int i = m_num_levels - 1; i >= 0; i--) { - node_val = (index >> i)&1; - if (node_val) - m_trees[set] |= node_val << tree_index; - else - m_trees[set] &= ~(1 << tree_index); - tree_index = node_val ? (tree_index*2)+2 : (tree_index*2)+1; - } - m_last_ref_ptr[set][index] = time; -} - -int64_t -PseudoLRUPolicy::getVictim(int64_t set) const -{ - int64_t index = 0; - - int tree_index = 0; - int node_val; - for (unsigned i = 0; i < m_num_levels; i++){ - node_val = (m_trees[set] >> tree_index) & 1; - index += node_val ? 0 : (m_effective_assoc >> (i + 1)); - tree_index = node_val ? (tree_index * 2) + 1 : (tree_index * 2) + 2; - } - assert(index >= 0 && index < m_effective_assoc); - - /* return either the found index or the max possible index */ - /* NOTE: this is not a fair replacement when assoc is not a power of 2 */ - return (index > (m_assoc - 1)) ? m_assoc - 1 : index; -} diff --git a/src/mem/ruby/structures/PseudoLRUPolicy.hh b/src/mem/ruby/structures/PseudoLRUPolicy.hh deleted file mode 100644 index a96c802b2..000000000 --- a/src/mem/ruby/structures/PseudoLRUPolicy.hh +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2007 Mark D. Hill and David A. Wood - * Copyright (c) 2013 Advanced Micro Devices, Inc - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __MEM_RUBY_STRUCTURES_PSEUDOLRUPOLICY_HH__ -#define __MEM_RUBY_STRUCTURES_PSEUDOLRUPOLICY_HH__ - -#include "mem/ruby/structures/AbstractReplacementPolicy.hh" -#include "params/PseudoLRUReplacementPolicy.hh" - -/** - * Implementation of tree-based pseudo-LRU replacement - * - * Works for any associativity between 1 and 128. - * - * Also implements associativities that are not a power of 2 by - * ignoring paths that lead to a larger index (i.e. truncating the - * tree). Note that when this occurs, the algorithm becomes less - * fair, as it will favor indicies in the larger (by index) half of - * the associative set. This is most unfair when the nearest power of - * 2 is one below the associativy, and most fair when it is one above. - */ - -class PseudoLRUPolicy : public AbstractReplacementPolicy -{ - public: - typedef PseudoLRUReplacementPolicyParams Params; - PseudoLRUPolicy(const Params * p); - ~PseudoLRUPolicy(); - - void touch(int64_t set, int64_t way, Tick time); - int64_t getVictim(int64_t set) const; - - private: - unsigned int m_effective_assoc; /** nearest (to ceiling) power of 2 */ - unsigned int m_num_levels; /** number of levels in the tree */ - uint64_t* m_trees; /** bit representation of the - * trees, one for each set */ -}; - -#endif // __MEM_RUBY_STRUCTURES_PSEUDOLRUPOLICY_HH__ diff --git a/src/mem/ruby/structures/PseudoLRUReplacementPolicy.py b/src/mem/ruby/structures/PseudoLRUReplacementPolicy.py deleted file mode 100644 index 2b892d47a..000000000 --- a/src/mem/ruby/structures/PseudoLRUReplacementPolicy.py +++ /dev/null @@ -1,35 +0,0 @@ -# -# Copyright (c) 2013 Advanced Micro Devices, Inc -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Author: Derek Hower - -from m5.objects.ReplacementPolicy import ReplacementPolicy - -class PseudoLRUReplacementPolicy(ReplacementPolicy): - type = 'PseudoLRUReplacementPolicy' - cxx_class = 'PseudoLRUPolicy' - cxx_header = 'mem/ruby/structures/PseudoLRUPolicy.hh' diff --git a/src/mem/ruby/structures/ReplacementPolicy.py b/src/mem/ruby/structures/ReplacementPolicy.py deleted file mode 100644 index 4570cc9df..000000000 --- a/src/mem/ruby/structures/ReplacementPolicy.py +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright (c) 2013 Advanced Micro Devices, Inc -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer; -# redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution; -# neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Author: Derek Hower - -from m5.params import * -from m5.proxy import * -from m5.SimObject import SimObject - -class ReplacementPolicy(SimObject): - type = 'ReplacementPolicy' - cxx_class = 'AbstractReplacementPolicy' - cxx_header = 'mem/ruby/structures/AbstractReplacementPolicy.hh' - - block_size = Param.Int(Parent.cache_line_size, "block size in bytes") - - size = Param.MemorySize(Parent.size, "capacity in bytes") - - assoc = Param.Int(Parent.assoc, "associativity") diff --git a/src/mem/ruby/structures/RubyCache.py b/src/mem/ruby/structures/RubyCache.py index cf8410c6d..49c20ff4c 100644 --- a/src/mem/ruby/structures/RubyCache.py +++ b/src/mem/ruby/structures/RubyCache.py @@ -29,7 +29,7 @@ from m5.params import * from m5.proxy import * -from m5.objects.PseudoLRUReplacementPolicy import PseudoLRUReplacementPolicy +from m5.objects.ReplacementPolicies import * from m5.SimObject import SimObject class RubyCache(SimObject): @@ -38,8 +38,7 @@ class RubyCache(SimObject): cxx_header = "mem/ruby/structures/CacheMemory.hh" size = Param.MemorySize("capacity in bytes"); assoc = Param.Int(""); - replacement_policy = Param.ReplacementPolicy(PseudoLRUReplacementPolicy(), - "") + replacement_policy = Param.BaseReplacementPolicy(TreePLRURP(), "") start_index_bit = Param.Int(6, "index start, default 6 for 64-byte line"); is_icache = Param.Bool(False, "is instruction only cache"); block_size = Param.MemorySize("0B", "block size in bytes. 0 means default RubyBlockSize") diff --git a/src/mem/ruby/structures/SConscript b/src/mem/ruby/structures/SConscript index c39cd0e51..fdd9289f3 100644 --- a/src/mem/ruby/structures/SConscript +++ b/src/mem/ruby/structures/SConscript @@ -35,17 +35,11 @@ if env['PROTOCOL'] == 'None': SimObject('RubyCache.py') SimObject('DirectoryMemory.py') -SimObject('LRUReplacementPolicy.py') -SimObject('PseudoLRUReplacementPolicy.py') -SimObject('ReplacementPolicy.py') SimObject('RubyPrefetcher.py') SimObject('WireBuffer.py') -Source('AbstractReplacementPolicy.cc') Source('DirectoryMemory.cc') Source('CacheMemory.cc') -Source('LRUPolicy.cc') -Source('PseudoLRUPolicy.cc') Source('WireBuffer.cc') Source('PersistentTable.cc') Source('Prefetcher.cc') diff --git a/src/mem/ruby/system/WeightedLRUPolicy.cc b/src/mem/ruby/system/WeightedLRUPolicy.cc index 2899f73a7..8f330d917 100644 --- a/src/mem/ruby/system/WeightedLRUPolicy.cc +++ b/src/mem/ruby/system/WeightedLRUPolicy.cc @@ -35,16 +35,12 @@ #include "mem/ruby/system/WeightedLRUPolicy.hh" +#include <cassert> +#include <memory> + WeightedLRUPolicy::WeightedLRUPolicy(const Params* p) - : AbstractReplacementPolicy(p), m_cache(p->cache) + : BaseReplacementPolicy(p) { - m_last_occ_ptr = new int*[m_num_sets]; - for (unsigned i = 0; i < m_num_sets; i++){ - m_last_occ_ptr[i] = new int[m_assoc]; - for (unsigned j = 0; j < m_assoc; j++){ - m_last_occ_ptr[i][j] = 0; - } - } } WeightedLRUPolicy * @@ -53,61 +49,78 @@ WeightedLRUReplacementPolicyParams::create() return new WeightedLRUPolicy(this); } -WeightedLRUPolicy::~WeightedLRUPolicy() -{ - if (m_last_occ_ptr != NULL){ - for (unsigned i = 0; i < m_num_sets; i++){ - if (m_last_occ_ptr[i] != NULL){ - delete[] m_last_occ_ptr[i]; - } - } - delete[] m_last_occ_ptr; - } -} - void -WeightedLRUPolicy::touch(int64_t set, int64_t index, Tick time) +WeightedLRUPolicy::touch(const std::shared_ptr<ReplacementData>& + replacement_data) const { - assert(index >= 0 && index < m_assoc); - assert(set >= 0 && set < m_num_sets); - - m_last_ref_ptr[set][index] = time; + std::static_pointer_cast<WeightedLRUReplData>(replacement_data)-> + last_touch_tick = curTick(); } void -WeightedLRUPolicy::touch(int64_t set, int64_t index, Tick time, int occupancy) +WeightedLRUPolicy::touch(const std::shared_ptr<ReplacementData>& + replacement_data, int occupancy) const { - assert(index >= 0 && index < m_assoc); - assert(set >= 0 && set < m_num_sets); - - m_last_ref_ptr[set][index] = time; - m_last_occ_ptr[set][index] = occupancy; + std::static_pointer_cast<WeightedLRUReplData>(replacement_data)-> + last_touch_tick = curTick(); + std::static_pointer_cast<WeightedLRUReplData>(replacement_data)-> + last_occ_ptr = occupancy; } -int64_t -WeightedLRUPolicy::getVictim(int64_t set) const +ReplaceableEntry* +WeightedLRUPolicy::getVictim(const ReplacementCandidates& candidates) const { - Tick time, smallest_time; - int64_t smallest_index; - - smallest_index = 0; - smallest_time = m_last_ref_ptr[set][0]; - int smallest_weight = m_last_occ_ptr[set][0]; + assert(candidates.size() > 0); - for (unsigned i = 1; i < m_assoc; i++) { + ReplaceableEntry* victim = candidates[0]; + // Use weight (last_occ_ptr) to find victim. + // Evict the block that has the smallest weight. + // If two blocks have the same weight, evict the oldest one. + for (const auto& candidate : candidates) { + // candidate's replacement_data + std::shared_ptr<WeightedLRUReplData> candidate_replacement_data = + std::static_pointer_cast<WeightedLRUReplData>( + candidate->replacementData); + // victim's replacement_data + std::shared_ptr<WeightedLRUReplData> victim_replacement_data = + std::static_pointer_cast<WeightedLRUReplData>( + victim->replacementData); - int weight = m_last_occ_ptr[set][i]; - if (weight < smallest_weight) { - smallest_weight = weight; - smallest_index = i; - smallest_time = m_last_ref_ptr[set][i]; - } else if (weight == smallest_weight) { - time = m_last_ref_ptr[set][i]; - if (time < smallest_time) { - smallest_index = i; - smallest_time = time; + if (candidate_replacement_data->last_occ_ptr < + victim_replacement_data->last_occ_ptr) { + victim = candidate; + } else if (candidate_replacement_data->last_occ_ptr == + victim_replacement_data->last_occ_ptr) { + // Evict the block with a smaller tick. + Tick time = candidate_replacement_data->last_touch_tick; + if (time < victim_replacement_data->last_touch_tick) { + victim = candidate; } } } - return smallest_index; + return victim; +} + +std::shared_ptr<ReplacementData> +WeightedLRUPolicy::instantiateEntry() +{ + return std::shared_ptr<ReplacementData>(new WeightedLRUReplData); +} + +void +WeightedLRUPolicy::reset(const std::shared_ptr<ReplacementData>& + replacement_data) const +{ + // Set last touch timestamp + std::static_pointer_cast<WeightedLRUReplData>( + replacement_data)->last_touch_tick = curTick(); +} + +void +WeightedLRUPolicy::invalidate(const std::shared_ptr<ReplacementData>& + replacement_data) const +{ + // Reset last touch timestamp + std::static_pointer_cast<WeightedLRUReplData>( + replacement_data)->last_touch_tick = Tick(0); } diff --git a/src/mem/ruby/system/WeightedLRUPolicy.hh b/src/mem/ruby/system/WeightedLRUPolicy.hh index 47fcec4a6..a11784584 100644 --- a/src/mem/ruby/system/WeightedLRUPolicy.hh +++ b/src/mem/ruby/system/WeightedLRUPolicy.hh @@ -36,27 +36,78 @@ #ifndef __MEM_RUBY_SYSTEM_WEIGHTEDLRUPOLICY_HH__ #define __MEM_RUBY_SYSTEM_WEIGHTEDLRUPOLICY_HH__ -#include "mem/ruby/structures/AbstractReplacementPolicy.hh" +#include "mem/cache/replacement_policies/base.hh" #include "mem/ruby/structures/CacheMemory.hh" #include "params/WeightedLRUReplacementPolicy.hh" /* Simple true LRU replacement policy */ -class WeightedLRUPolicy : public AbstractReplacementPolicy +class WeightedLRUPolicy : public BaseReplacementPolicy { + protected: + /** Weighted LRU implementation of replacement data. */ + struct WeightedLRUReplData : ReplacementData + { + /** pointer for last occupancy */ + int last_occ_ptr; + + /** Tick on which the entry was last touched. */ + Tick last_touch_tick; + + /** + * Default constructor. Invalidate data. + */ + WeightedLRUReplData() : ReplacementData(), + last_occ_ptr(0), last_touch_tick(0) {} + }; public: typedef WeightedLRUReplacementPolicyParams Params; WeightedLRUPolicy(const Params* p); - ~WeightedLRUPolicy(); + ~WeightedLRUPolicy() {} + + /** + * Invalidate replacement data to set it as the next probable victim. + * Sets its last touch tick as the starting tick. + * + * @param replacement_data Replacement data to be invalidated. + */ + void invalidate(const std::shared_ptr<ReplacementData>& replacement_data) + const override; + /** + * Touch an entry to update its replacement data. + * Sets its last touch tick as the current tick. + * + * @param replacement_data Replacement data to be touched. + */ + void touch(const std::shared_ptr<ReplacementData>& + replacement_data) const override; + void touch(const std::shared_ptr<ReplacementData>& replacement_data, + int occupancy) const; - void touch(int64_t set, int64_t way, Tick time) override; - void touch(int64_t set, int64_t way, Tick time, int occupancy); - int64_t getVictim(int64_t set) const override; + /** + * Reset replacement data. Used when an entry is inserted. + * Sets its last touch tick as the current tick. + * + * @param replacement_data Replacement data to be reset. + */ + void reset(const std::shared_ptr<ReplacementData>& replacement_data) const + override; - bool useOccupancy() const override { return true; } + /** + * Instantiate a replacement data entry. + * + * @return A shared pointer to the new replacement data. + */ + std::shared_ptr<ReplacementData> instantiateEntry() override; - CacheMemory * m_cache; - int **m_last_occ_ptr; + /** + * Find replacement victim using weight. + * + * @param candidates Replacement candidates, selected by indexing policy. + * @return Replacement entry to be replaced. + */ + ReplaceableEntry* getVictim(const ReplacementCandidates& + candidates) const override; }; #endif // __MEM_RUBY_SYSTEM_WeightedLRUPolicy_HH__ diff --git a/src/mem/ruby/system/WeightedLRUReplacementPolicy.py b/src/mem/ruby/system/WeightedLRUReplacementPolicy.py index fa50c95dc..48143e5d9 100644 --- a/src/mem/ruby/system/WeightedLRUReplacementPolicy.py +++ b/src/mem/ruby/system/WeightedLRUReplacementPolicy.py @@ -33,10 +33,9 @@ from m5.params import * from m5.proxy import * -from m5.objects.ReplacementPolicy import ReplacementPolicy +from m5.objects.ReplacementPolicies import BaseReplacementPolicy -class WeightedLRUReplacementPolicy(ReplacementPolicy): +class WeightedLRUReplacementPolicy(BaseReplacementPolicy): type = "WeightedLRUReplacementPolicy" cxx_class = "WeightedLRUPolicy" cxx_header = "mem/ruby/system/WeightedLRUPolicy.hh" - cache = Param.RubyCache("") diff --git a/src/mem/slicc/ast/FormalParamAST.py b/src/mem/slicc/ast/FormalParamAST.py index ce73304f1..778b5c1aa 100644 --- a/src/mem/slicc/ast/FormalParamAST.py +++ b/src/mem/slicc/ast/FormalParamAST.py @@ -53,9 +53,10 @@ class FormalParamAST(AST): self.symtab.newSymbol(v) if self.pointer or str(type) == "TBE" or ( + # Check whether type is entry by checking the interface since + # in protocol files, entries use AbstractCacheEntry as interfaces. "interface" in type and ( - type["interface"] == "AbstractCacheEntry" or - type["interface"] == "AbstractEntry")): + type["interface"] == "AbstractCacheEntry")): return type, "%s* %s" % (type.c_ident, param) else: return type, "const %s& %s" % (type.c_ident, param) diff --git a/src/mem/slicc/ast/LocalVariableAST.py b/src/mem/slicc/ast/LocalVariableAST.py index 5c6bfe80a..c1a5fdbd9 100644 --- a/src/mem/slicc/ast/LocalVariableAST.py +++ b/src/mem/slicc/ast/LocalVariableAST.py @@ -61,9 +61,10 @@ class LocalVariableAST(StatementAST): self.pairs) self.symtab.newSymbol(v) if self.pointer or str(type) == "TBE" or ( + # Check whether type is Entry by checking interface since + # entries in protocol files use AbstractCacheEntry as interfaces. "interface" in type and ( - type["interface"] == "AbstractCacheEntry" or - type["interface"] == "AbstractEntry")): + type["interface"] == "AbstractCacheEntry")): code += "%s* %s" % (type.c_ident, ident) else: code += "%s %s" % (type.c_ident, ident) diff --git a/src/mem/slicc/ast/MemberExprAST.py b/src/mem/slicc/ast/MemberExprAST.py index 320146065..50151bd0a 100644 --- a/src/mem/slicc/ast/MemberExprAST.py +++ b/src/mem/slicc/ast/MemberExprAST.py @@ -41,10 +41,13 @@ class MemberExprAST(ExprAST): return_type, gcode = self.expr_ast.inline(True) fix = code.nofix() + + # Check whether return_type is Entry by checking + # interfaces since entries in protocol files use + # AbstractCacheEntry as interfaces. if str(return_type) == "TBE" \ or ("interface" in return_type and - (return_type["interface"] == "AbstractCacheEntry" or - return_type["interface"] == "AbstractEntry")): + (return_type["interface"] == "AbstractCacheEntry")): code("(*$gcode).m_${{self.field}}") else: code("($gcode).m_${{self.field}}") diff --git a/src/mem/slicc/ast/MethodCallExprAST.py b/src/mem/slicc/ast/MethodCallExprAST.py index 104d6f8df..102ab6e4c 100644 --- a/src/mem/slicc/ast/MethodCallExprAST.py +++ b/src/mem/slicc/ast/MethodCallExprAST.py @@ -143,18 +143,18 @@ class MemberMethodCallExprAST(MethodCallExprAST): methodId = implementedMethodId return_type = obj_type.methods[methodId].return_type + # Check object type or interface of entries by checking + # AbstractCacheEntry since AbstractCacheEntry is used in + # protocol files. if str(obj_type) == "AbstractCacheEntry" or \ - str(obj_type) == "AbstractEntry" or \ ("interface" in obj_type and ( - obj_type["interface"] == "AbstractCacheEntry" or - obj_type["interface"] == "AbstractEntry")): + obj_type["interface"] == "AbstractCacheEntry")): prefix = "%s((*(%s))." % (prefix, code) else: prefix = "%s((%s)." % (prefix, code) return obj_type, methodId, prefix - class ClassMethodCallExprAST(MethodCallExprAST): def __init__(self, slicc, type_ast, proc_name, expr_ast_vec): s = super(ClassMethodCallExprAST, self) |