NMRU tutorial
Overview
Here we will discuss how to add a new replacement policy,
which is encapsulated in a SimObject.
Our basic strategy will be to copy one of the existing
policies in: /src/mem/cache/replacement_policies/
Step 1: Copy an existing policy.
Copy any of the existing replacement policies to use as a starting point for NMRU.
cp lru_rp.cc nmru_rp.cc
cp lru_rp.hh nmru_rp.hh
Within each file, rename any LRU specific prefixes to NMRU.
Step 2
Each SimObject has a Python class which is associated with it. This Python class describes the parameters of your SimObject that can be controlled from the Python configuration files. For our NMRU replacement policy, we are just going to inherit all of the parameters from the BaseReplacementPolicy. Thus, we simply need to declare a new class for our SimObject and set it’s name and the C++ header that will define the C++ class for the SimObject.
We edit the file, ReplacementPolicies.py
, in /src/mem/cache/replacement_policies
class NMRURP(BaseReplacementPolicy):
type = 'NMRURP'
cxx_class = 'gem5::replacement_policy::NMRU'
cxx_header = "mem/cache/replacement_policies/nmru_rp.hh"
Step 3: Register the C++ file
Each SimObject must be registered with SCons so that its Params object and
Python wrapper is created. Additionally, we also have to tell SCons which C++
files to compile. To do this, modify the SConscipt file in the directory that
your SimObject is in. For each SimObject, add a call to SimObject and for each
source file add a call to Source. In this example, you need to add the
following to src/mem/cache/replacement_policies/SConscript
:
Source('nmru_rp.cc')
Also add NMRURP
to the SimObject array in src/mem/cache/replacement_policies/SConscript
.
At this point, you should be able to compile the code.
Step 4: Modify the source code to implement NMRU
Implement the functionality of NMRU – i.e. replace any line that’s not
the most recently used line. The key function is getVictim
in nmru_rp.cc
.
Also, looking at the random replacement policy may help.
Step 5: Make it configurable in se.py
Supposing you would like to use se.py
, you should add an addtional paramter to the cache-of-interest.
In particular, you would add: dcache_class(size= ... , replacement_policy=NMRURP())
.
If you want to get fancier, you can make the replacement policy easy to change as a paramter.
To do that, first add this line to configs/common/ObjectList
after cpu_list is defined:
repl_list = ObjectList(getattr(m5.objects, 'BaseReplacementPolicy', None))
Then, add some new options in configs/common/Options.py
:
parser.add_option("--l1d_repl", type="choice", default="LRURP",
choices=ObjectList.repl_list.get_names(),
help = "replacement policy for l1")
parser.add_option("--l2_repl", type="choice", default="LRURP",
choices=ObjectList.repl_list.get_names(),
help = "replacement policy for l2")
Finally, connect these options up to the dcache, in configs/common/CacheConfig.py
dcache = dcache_class(size=options.l1d_size,
assoc=options.l1d_assoc,
replacement_policy=ObjectList.repl_list.get(options.l1d_repl)())
The same will work for l2 cache:
system.l2 = l2_cache_class(clk_domain=system.cpu_clk_domain,
size=options.l2_size,
assoc=options.l2_assoc,
replacement_policy=ObjectList.repl_list.get(options.l2_repl)())