Table of contents
  1. File Path Setting
  2. Enviornment
  3. Declaring Simobject
  4. Creating Wrapper
  5. Add option for Ramulator config file

File Path Setting

gem5/
├── configs/ 
│   |
│   └── common/
│       |- MemConfig.py
│       |- Options.py
│       └─ ...
|   
├── src/ 
│   └── mem/
│ 	|- ramulator2.cc ramualator.hh
│ 	|- Ramulator2.py
│ 	|- SConscript
│ 	└─ ...
│
├── ext/  # not guided in this docs
│  └── ramulator2/
│ 	|- SConscript
│ 	└─ ramulator2/  
│ 	    |- src/
│ 	    |- libramulator.so
│ 	    └─ ...
  • Above tree shows overall files which requires modification to integrate gem5 and ramulator2 and its path

This docs mainly guides only modification on gem5 source files. To set-up ramulator2 local file, please refer to ramulator2 documentation.

You can get all complete code at my github.


Enviornment

  • >= Ubuntu22.04 (due to support on c++23)
  • c++-12 (apt-get install c++-12)
  • clang++-15 (apt-get install clang clang++-15)
  • cmake
  • gem5 ver.22.0

Declaring Simobject

# gem5/src/mem/SConscript
if env['HAVE_RAMULATOR2']:
    SimObject("Ramulator2.py", sim_objects=['Ramulator2'])
    Source("ramulator2.cc")
    DebugFlag("Ramulator2")
  • SimObject(“Ramulator2.py”…): Add class “Ramulator2” as a simobject.
  • Source(“ramulator2.cc”): compile the predefined c++ wrapper code.
  • DebugFlag(“Ramulator2”): (optional), add “Ramulator2” as one of gem5 debug flag
# gem5/src/mem/Ramulator2.py
from m5.SimObject import *
from m5.params import *
from m5.objects.AbstractMemory import *

class Ramulator2(AbstractMemory):
    type = "Ramulator2"
    cxx_class = "gem5::memory::Ramulator2"
    cxx_header = "mem/ramulator2.hh"
    port = ResponsePort("The port for receiving memory requests and sending responses")
  • Defines the python class for Ramulator2
  • While compiling, gem5 follows cxx_headers path and reach cxx_class instance

# gem5/common/MemConfig.py config_mem() new code
...
if issubclass(intf, m5.objects.Ramulator2):
    mem_ctrl = dram_intf
else:
    mem_ctrl = dram_intf.controller()
...
  • While the conventional dram class returns dram interface instance by calling function called controller(), Ramulator2 is not
  • Connect it to dram_intf

Creating Wrapper

  • TBD

Add option for Ramulator config file

# gem5/configs/common/Options.py
...
parser.add_argument(
    "--ramulator-config",
    type=str,
    dest="ramulator_config",
    help="inputs ramulator configuration file"
)
...
  • Now, the option --ramulator-config is added
# gem5/configs/common/MemConfig.py create_mem_intf()
...
if issubclass(intf, m5.objects.Ramualator2):
    if not options.ramulator_config:
        print("--mem-type=Ramulator2 requires options --ramulator-config")
        exit(1)
    interface.config_path = options.ramulator_config
...
  • Connect the option to Ramulator2 simobject
  • interface is an instance of python-defined Ramulator2 class
  • options.ramualtor_config comes from previous subsection
# gem5/src/mem/Ramulator2.py
from m5.SimObject import *
from m5.params import *
from m5.objects.AbstractMemory import *

class Ramulator2(AbstractMemory):
    type = "Ramulator2"
    cxx_class = "gem5::memory::Ramulator2"
    cxx_header = "mem/ramulator2.hh"
    port = ResponsePort("The port for receiving memory requests and sending responses")

    #NOTE newly added to accommodate config file
    config_path = Param.String("", "--ramulator-config")
  • Define new varialbe in python class to accommodate the new option
  • Compiling gem5, param/Ramulator2.hh adds new string variable config_path
# gem5/src/mem/ramualtor2.hh
namespace gem5 {
namespace memory {
class Ramulator2 : public AbstractMemory {
...
private:
    std::string config_path;
...
}
}}

# gem5/src/mem/ramualtor2.cc
Ramulator2::Ramulator2(const Params &p){ // Constructor
config_path = p.config_path;
YAML::Node config = parse_config(config_path); // this is pseudo-code
}
  • In wrapper code, you can call the config_path by referencing member variable of Params which comes from param/Ramulator2.hh