CMU-SAFARI / ramulator2

Ramulator 2.0 is a modern, modular, extensible, and fast cycle-accurate DRAM simulator. It provides support for agile implementation and evaluation of new memory system designs (e.g., new DRAM standards, emerging RowHammer mitigation techniques). Described in our paper https://people.inf.ethz.ch/omutlu/pub/Ramulator2_arxiv23.pdf
https://arxiv.org/abs/2308.11030
MIT License
251 stars 62 forks source link

GenericDRAMController seems does not support write transaction #30

Open cyyself opened 1 year ago

cyyself commented 1 year ago

I tried to use ramulator2 to test DDR write performance. A simple code is shown above:

#include <memory_system/memory_system.h>
#include <frontend/frontend.h>
#include <base/config.h>
#include <dram/dram.h>
#include <cstdio>

Ramulator::IFrontEnd* ramulator2_frontend;
Ramulator::IMemorySystem* ramulator2_memorysystem;

long long call_back_count = 0;
long long enq_count = 0;

int main(int argc, char *argv[]) {
    assert(argc >= 3);
    int offset = atoi(argv[1]);
    int type = atoi(argv[2]);
    printf("offset=%d\n", offset);
    YAML::Node config = Ramulator::Config::parse_config_file("./config.yaml", {});
    ramulator2_frontend = Ramulator::Factory::create_frontend(config);
    ramulator2_memorysystem = Ramulator::Factory::create_memory_system(config);

    ramulator2_frontend->connect_memory_system(ramulator2_memorysystem);
    ramulator2_memorysystem->connect_frontend(ramulator2_frontend);

    unsigned long addr = 0;

    for (int i=0;i<1000000;i++) { // 1M cycles
        if (i + 1000 < 1000000) {
            bool ok = ramulator2_frontend->receive_external_requests(type, addr, 0, [](Ramulator::Request& req) {
                call_back_count ++;
            });
            if (ok) {
                enq_count ++;
                addr += offset;
            }
        }
        ramulator2_frontend->tick();
        ramulator2_memorysystem->tick();
    }

    printf("%lld %lld\n", enq_count, call_back_count);
    return 0;
}

A simple YAML file is shown above:

Frontend:
  impl: GEM5
  clock_ratio: 1

MemorySystem:
  impl: GenericDRAM
  clock_ratio: 1

  DRAM:
    impl: DDR4
    org:
      preset: DDR4_8Gb_x8
      channel: 1
      rank: 2
    timing:
      preset: DDR4_3200AA
  Controller:
    impl: Generic
    Scheduler:
      impl: FRFCFS
    RefreshManager:
      impl: AllBank
    plugins:

  AddrMapper:
    impl: MOP4CLXOR

If I specify the type to 1, the request type is Ramulator::Request::Type::Write. I will never get a request callback.

My running result:

➜  ramulator-test ./a.out 64 0 # Read
offset=64
235030 235030
➜  ramulator-test ./a.out 64 1 # Write
offset=64
235275 0

After investigating the code, I found that the GenericDRAMController does not support write transactions and leaves the TODO in the code generic_dram_controller.cpp#L123.

if (req_it->type_id == Request::Type::Read) {
  req_it->depart = m_clk + m_dram->m_read_latency;
  pending.push_back(*req_it);
} else if (req_it->type_id == Request::Type::Write) {
  // TODO: Add code to update statistics
}

If I copy the two lines of code from the read transaction processing to the write transaction processing and then recompile the ramultor2, I will get the callback from the write transaction but use the read latency for write transactions.

Is it my fault for misusing the ramulator2, or is the write transaction not supported now?

RichardLuo79 commented 9 months ago

Hi,

Thanks for spotting this. Ramulator 2.0 does support writes in the DRAM model. The reason for this is that the SimpleO3 processor frontend that comes with Ramulator 2.0 does not block on writes, thus no write callback is needed.

This will cause issues if the user is using another frontend (e.g., in your case, your own frontend) that do needs write callbacks. We will modify the controller code to account for this,