MCPcopy Create free account
hub / github.com/CMU-SAFARI/ramulator2

github.com/CMU-SAFARI/ramulator2 @v2.1.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v2.1.0 ↗ · + Follow
1,450 symbols 4,242 edges 310 files 177 documented · 12% updated 7d ago★ 5892 open issues

Browse by type

Functions 1,090 Types & classes 358 Endpoints 2
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Ramulator 2.1 User Guide

1. Overview

1.1 Introduction

Ramulator 2.1 is a modern, modular, and extensible cycle-level DRAM simulator. It is the successor of Ramulator 1.0 [Kim+, CAL'16] and a major overhaul of Ramulator 2.0 [Luo+, CAL'23]. The goal of Ramulator 2.1 is to enable rapid and agile implementation and evaluation of design changes in the memory controller and DRAM to meet the increasing research effort in improving the performance, security, and reliability of memory systems. Ramulator 2.1 features a clean and modular C++ codebase with automatically generated Python wrappers that enables easy and scriptable configurations and extensions. Users can focus just on the C++ code that implements modeling and simulation logic without having to worry about manually maintaining boilerplate code.

Ramulator 2.1 can either be used as a standalone simulator that takes memory traces, or be easily integrated into other simulators as a DRAM and memory controller simulation library. We currently provide gem5 wrappers that works as a drop-in component for both SE and FS mode (tested with gem5 v25.1, FS mode tested with a post-boot checkpoint).

This Github repository contains the public version of Ramulator 2.1. From time to time, we will synchronize improvements of the code framework, additional functionalities, bug fixes, etc. from our internal version. Ramulator 2.1 welcomes your contribution as well as new ideas and implementations in the memory system.

Currently, Ramulator 2.1 provides the DRAM device and memory controller models for the following standards: - DDR3, DDR4, DDR5 - GDDR6 - LPDDR5 (with WCK2CK sync and expiry tracking and tAAD deadline aware scheduling for separate ACT1 and ACT2) - HBM1, HBM2, HBM3, HBM4 (Row and column command dual-issue and pseudochannels)

What has changed from Ramulator 2.0: - Aggregated bug fixes - More comprehensive support for newer DRAM & controller features - More comprehensive sets of test and validation workflows - Significantly improved the ease of use, configuration, and extension - Overall code quality improvements

1.2 Repository Layout

  • src/ C++ code for main simulator implementation.
  • python/ Python wrappers for easy and scriptable configuration of Ramulator.
  • examples/ Ready-to-run example configurations and traces.
  • tests/ Tests and validation workflows.
  • resources/gem5_wrappers/ Reference wrapper code for gem5 integration.
  • visualizer/ Browser-based trace visualizer (Nuxt/WebGL). See Section 10.

2. Using Ramulator 2.1

We highly recommend to use our container (Dockerfile available at .devcontainer/Dockerfile) to avoid any dependency issues. The repository is also configured to be able to be one-click opened as a Dev Container with all the dependencies already installed. The easiest way to start using and developing Ramulator 2.1 is to directly create a Codespace on the GitHub page of the Ramulator 2.1 repository. If you are using Visual Studio Code, it should automatically prompt you to reopen the repository in a Dev Container after you clone and open the repo for the first time.

If you want to set up the container locally, you can do the following steps:

docker compose up -d --build
docker compose exec ramulator2 bash

Doing so creates a container with all the dependencies, mounts the Ramulator 2.1 repository at /workspace, and automatically activates ramulator2-venv in the container bash.

If you need to configure your own environment, please refer to Section 2.3 for detailed instructions.

2.2 Getting Started

From the repository root:

mkdir -p build
cd build
cmake ..
make -j
cd ..

This default build does three useful things:

  • Builds libramulator.so in the repository root
  • Builds the Python extension module under python/ramulator/
  • Runs the code generator so all the automatically generated code are in sync with the source code

Then run Ramulator 2.1 in standalone mode with an example configuration:

python3 examples/example_config.py

You should see some example statistics being printed. You can head to Section 3 directly for detailed explanations and instructions on how to use and configure Ramulator 2.1 if you do not need to build Ramulator 2.1 in your custom environment.

2.3 Build Requirements

Required:

  • A C++20 compiler, such as g++-12 or clang++-15
  • CMake 3.14 or newer
  • Python 3.10 or newer if you want the Python bindings, the CLI, or the tests

Auto-fetched by CMake (no manual install):

  • yaml-cpp — YAML configuration parsing
  • fmt — C++ print formatting
  • nanobind — Python-C++ bindings (only when RAMULATOR_PYTHON_BINDINGS=ON)
  • argparse — command-line argument parsing (vendored in ext/)

Python dev dependencies (install with pip install -r requirements-dev.txt):

  • pytest — test framework
  • matplotlib — latency-throughput plotting
  • ruff — Python linter and formatter

setuptools >= 64 is required as the build backend and is pulled in automatically by pip install -e ..

Optional: clang-format.

To build Ramulator 2.1 in standalone mode:

mkdir -p build
cd build
cmake ..
make -j
cd ..

If you only want the pure C++ library without Python bindings for your own simulator:

mkdir -p build
cd build
cmake .. -DRAMULATOR_PYTHON_BINDINGS=OFF
make -j
cd ..

2.4 Installing the Python Package

After building, install the Python package in editable mode so that python -m ramulator and import ramulator work from any directory:

pip install -e .

Then run examples directly:

python3 examples/example_config.py

If you prefer not to install the python package, you can also set PYTHONPATH=python as a one-off alternative:

PYTHONPATH=python python3 examples/example_config.py

3. Your First Run

3.1 Understanding Ramulator 2.1 Configurations

examples/example_config.py looks like the following:

"""Example Ramulator2 configuration and simulation script"""

import ramulator

# Configure the simulation frontend that sends memory requests
frontend = ramulator.frontend.SimpleO3(
    clock_ratio=8,
    traces=["./examples/traces/example_inst.trace"],
    num_expected_insts=500000,
    translation=ramulator.translation.NoTranslation(max_addr=2147483648),
)

# Create DRAM configuration
ddr4 = ramulator.dram.DDR4(org_preset="DDR4_8Gb_x8", timing_preset="DDR4_2400R", rank=1)
# Instantiate the memory controller with the DRAM configuration
ctrl = ramulator.controller.GenericDDR(
    dram=ddr4,
    scheduler=ramulator.scheduler.FRFCFS(),
    refresh_manager=ramulator.refresh_manager.AllBank(),
    row_policy=ramulator.row_policy.Open(),
    addr_mapper=ramulator.addr_mapper.RoBaRaCoCh(),
)
# Create a memory system with the controller
mem = ramulator.memory_system.GenericDRAM(
    clock_ratio=3,
    controllers=[ctrl],
    channel_mapper=ramulator.channel_mapper.CacheLineInterleave(),
)

# Run the simulation
sim = ramulator.Simulation(frontend, mem)
sim.run()

# sim.stats returns a nested Python dict of all simulation statistics
stats = sim.stats

# Guard here for `ramulator export`, which captures the configuration without
# running the simulation.
if stats:
    # Controller stats are under memory_system → controller
    ctrl_stats = stats["memory_system"]["controller"]

    print(f"Controller cycles:     {ctrl_stats['cycles']}")
    print(f"Avg read latency:      {ctrl_stats['avg_read_latency']:.1f} cycles")
    print(f"Read requests:         {ctrl_stats['num_read_reqs']}")
    print(f"Write requests:        {ctrl_stats['num_write_reqs']}")
    print(f"Row hits:              {ctrl_stats['row_hits']}")
    print(f"Row misses:            {ctrl_stats['row_misses']}")
    print(f"Row conflicts:         {ctrl_stats['row_conflicts']}")

There are two top-level components in Ramulator 2.1:

  • frontend generates memory traffic. In this example it is a simple out-of-order core model driven by a memory instruction trace.
  • memory_system encapsulates one or more memory controllers (channel). Each controller owns a DRAM device model.

Any Ramulator 2.1 simulation must contain these two components. They are used to create the main simulation object (ramulator.Simulation(frontend, mem)) used as the entry point of the simulation.

3.2 What Each Part Does

Frontend

frontend = ramulator.frontend.SimpleO3(
    clock_ratio=8,
    traces=["./examples/traces/example_inst.trace"],
    num_expected_insts=500000,
    translation=ramulator.translation.NoTranslation(max_addr=2147483648),
)

The frontend generates memory requests and sends them to the memory system. In this example, SimpleO3 models a simple Out-of-Order processor with an LLC. It reads one or more instruction trace files, each corresponds to a processor core. The simulation will run until the number of retired instructions has reached 500000. The configured fontend will not apply address translation to the memory addresses in the trace (i.e., ramulator.translation.NoTranslation). clock_ratio=8 means that for every x memory ticks (i.e., memory system side clock_ratio=x), the frontend will be ticked 8 times.

DRAM device

ddr4 = ramulator.dram.DDR4(
    org_preset="DDR4_8Gb_x8",
    timing_preset="DDR4_2400R",
    rank=2,
)

This includes:

  • An organization preset, such as die density, DQ width, number of banks, etc.
  • A timing constraints preset, such as tRCD, tRAS, tRP, etc.
  • Optional overrides to both presets. In this example, we set rank=2. You can append as many overrides as you want.

If you want to understand what this object turns into at runtime, section 9.3 walks through the full DRAM device model and the hierarchical state machine behind it.

Controller

ctrl = ramulator.controller.GenericDDR(
    dram=ddr4,
    scheduler=ramulator.scheduler.FRFCFS(),
    refresh_manager=ramulator.refresh_manager.AllBank(),
    row_policy=ramulator.row_policy.Open(),
    addr_mapper=ramulator.addr_mapper.RoBaRaCoCh(),
)

This configures a GenericDDR memory controller for our just configured ddr4 DRAM. It has an FRFCFS (First-Ready First-Come-First-Served) scheduler, an all-bank refresh, an Open row policy, and a RoBaRaCoCh address mapper.

Memory system

mem = ramulator.memory_system.GenericDRAM(
    clock_ratio=3,
    controllers=[ctrl],
    channel_mapper=ramulator.channel_mapper.CacheLineInterleave(),
)

GenericDRAM is a thin top-level wrapper around one or more controllers. It contains a clock_ratio that sets the memory-side tick rate, a list of controllers (controllers=[...]), and a channel mapper (channel_mapper=...) that decides which memory requests goes to which controller. clock_ratio=3 means that for every y frontend ticks (i.e., front side clock_ratio=y), the memory system will be ticked 3 times. Currently, GenericDRAM requires all its memory controllers to have the same frequency.

3.4 What You Should Expect to See

The example prints a few key numbers from sim.stats after the simulation finishes:

Controller cycles:     81302
Avg read latency:      45.2 cycles
Read requests:         6
Write requests:        0
Row hits:              3
Row misses:            3
Row conflicts:         0

The exact numbers depend on the workload and configuration.

sim.stats is a nested Python dict with two top-level keys: "frontend" and "memory_system". The most useful counters live under stats["memory_system"]["controller"]:

Stat Meaning
cycles Controller cycles
avg_read_latency Average read latency in controller cycles
num_read_reqs Read requests accepted
num_write_reqs Write requests accepted
row_hits Total row hits
row_misses Total row misses
row_conflicts Total row conflicts
read_queue_len_avg Average read queue occupancy
write_queue_len_avg Average write queue occupancy
total_num_read_requests Total reads accepted by the memory system (one level up, under stats["memory_system"])
total_num_write_requests Total writes accepted by the memory system

With a single channel, stats["memory_system"]["controller"] is a dict. With multiple channels it becomes a list of dicts (one per channel), each with an "id" field (e.g., "Channel 0").

4. Writing Configurations

4.1 The Main Components

The Ramulator Python package exposes the major components as a set of namespaces:

  • ramulator.frontend
  • ramulator.dram
  • ramulator.controller
  • ramulator.scheduler
  • ramulator.refresh_manager
  • ramulator.row_policy
  • ramulator.addr_mapper
  • ramulator.channel_mapper
  • ramulator.translation
  • ramulator.controller_plugin
  • ramulator.memory_system

4.2 Common First Changes

Switch to another DRAM standard

You can swap DDR4 for another standard by replacing the DRAM object and, when needed, the controller class.

Examples:

dram = ramulator.dram.DDR5(org_preset="DDR5_8Gb_x8", timing_preset="DDR5_4800AN")
ctrl = ramulator.controller.GenericDDR(dram=dram, ...)
dram = ramulator.dram.LPDDR5(org_preset="LPDDR5_8Gb_x16", timing_preset="LPDDR5_5500")
ctrl = ramulator.controller.LPDDR5(dram=dram,...)

```python dram = ramulator.dram.HBM2(org_p

Extension points exported contracts — how you extend this code

Core symbols most depended-on inside this repo

Shape

Method 686
Function 404
Class 320
Interface 30
Enum 8
Route 2

Languages

C++58%
Python32%
TypeScript10%

Modules by API surface

visualizer/app/composables/useRenderer.ts57 symbols
tests/utils/test_harness.cpp46 symbols
src/ramulator/controller/impl/blockhammer_controller.cpp28 symbols
src/ramulator/controller/impl/lpddr_controller_base.cpp24 symbols
tests/controller_scheduling/test_gddr7.py23 symbols
src/ramulator/base/config_node.h23 symbols
src/ramulator/controller/controller_base.cpp22 symbols
src/ramulator/base/base.h22 symbols
tests/controller_scheduling/HBMController/test_hbm34_controller.py20 symbols
tests/controller_scheduling/harness.py18 symbols
src/ramulator/dram/dram_spec.h18 symbols
tests/device_timings/test_gddr7.py17 symbols

For agents

$ claude mcp add ramulator2 \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page