24.22.4.2.2. TimingSimpleCPU analysis #1
Backtrace:
EventManager::schedule DRAMCtrl::Rank::startup DRAMCtrl::startup
Snippets:
void
DRAMCtrl::startup()
{
// remember the memory system mode of operation
isTimingMode = system()->isTimingMode();
if (isTimingMode) {
// timestamp offset should be in clock cycles for DRAMPower
timeStampOffset = divCeil(curTick(), tCK);
// update the start tick for the precharge accounting to the
// current tick
for (auto r : ranks) {
r->startup(curTick() + tREFI - tRP);
}
// shift the bus busy time sufficiently far ahead that we never
// have to worry about negative values when computing the time for
// the next request, this will add an insignificant bubble at the
// start of simulation
nextBurstAt = curTick() + tRP + tRCD;
}
}
which then calls:
void
DRAMCtrl::Rank::startup(Tick ref_tick)
{
assert(ref_tick > curTick());
pwrStateTick = curTick();
// kick off the refresh, and give ourselves enough time to
// precharge
schedule(refreshEvent, ref_tick);
}
DRAMCtrl::startup is itself a SimObject method exposed to Python and called from simulate in src/python/m5/simulate.py:
def simulate(*args, **kwargs):
global need_startup
if need_startup:
root = objects.Root.getInstance()
for obj in root.descendants(): obj.startup()
where simulate happens after m5.instantiate, and both are called directly from the toplevel scripts, e.g. for se.py in configs/common/Simulation.py:
def run(options, root, testsys, cpu_class):
...
exit_event = m5.simulate()
By looking up some variable definitions in the source, we now we see some memory parameters clearly:
-
ranks:
std::vector<DRAMCtrl::Rank*>with 2 elements. TODO why do we have 2? What does it represent? Likely linked toconfig.iniatsystem.mem_ctrls.ranks_per_channel=2: https://en.wikipedia.org/wiki/Memory_rank -
tCK=1250,tREFI=7800000,tRP=13750,tRCD=13750: all defined in a single code location with a comment:/** * Basic memory timing parameters initialized based on parameter * values. */Their values can be seen under
config.iniand they are documented insrc/mem/DRAMCtrl.pye.g.:# the base clock period of the DRAM tCK = Param.Latency("Clock period") # minimum time between a precharge and subsequent activate tRP = Param.Latency("Row precharge time") # the amount of time in nanoseconds from issuing an activate command # to the data being available in the row buffer for a read/write tRCD = Param.Latency("RAS to CAS delay") # refresh command interval, how often a "ref" command needs # to be sent. It is 7.8 us for a 64ms refresh requirement tREFI = Param.Latency("Refresh command interval")
So we realize that we are going into deep DRAM modelling, more detail that a mere mortal should ever need to know.
curTick() + tREFI - tRP = 0 + 7800000 - 13750 = 7786250 which is when that refreshEvent was scheduled. Our simulation ends way before that point however, so we will never know what it did thank God.