From 3dbb089dcb0d38629baa9ce56747786c0cc60e7d Mon Sep 17 00:00:00 2001 From: Derek Christ Date: Wed, 5 Jan 2022 13:48:19 +0100 Subject: [PATCH] Add an idle state to the state machine A state with the field "idleClks" is a state that forces the TrafficGenerator to idle the specified amount of clocks. --- .../src/common/configuration/TraceSetup.cpp | 96 +++++++++++----- .../src/common/configuration/TraceSetup.h | 12 +- .../common/configuration/tests/simpletest.cpp | 36 ++++-- DRAMSys/simulator/TrafficGenerator.cpp | 103 +++++++++++------- DRAMSys/simulator/TrafficGenerator.h | 22 ++-- 5 files changed, 183 insertions(+), 86 deletions(-) diff --git a/DRAMSys/library/src/common/configuration/TraceSetup.cpp b/DRAMSys/library/src/common/configuration/TraceSetup.cpp index e6bc15d4..fd509ee2 100644 --- a/DRAMSys/library/src/common/configuration/TraceSetup.cpp +++ b/DRAMSys/library/src/common/configuration/TraceSetup.cpp @@ -42,6 +42,10 @@ TrafficInitiator::~TrafficInitiator() { } +TraceGeneratorState::~TraceGeneratorState() +{ +} + void to_json(json &j, const TraceSetup &c) { // Create an empty array @@ -66,13 +70,21 @@ void to_json(json &j, const TraceSetup &c) if (generator->states.size() == 1) { const auto &state = generator->states[0]; - initiator_j["numRequests"] = state.numRequests; - initiator_j["rwRatio"] = state.rwRatio; - initiator_j["addressDistribution"] = state.addressDistribution; - initiator_j["addressIncrement"] = state.addressIncrement; - initiator_j["minAddress"] = state.minAddress; - initiator_j["maxAddress"] = state.maxAddress; - initiator_j["clksPerRequest"] = state.clksPerRequest; + + if (const auto trafficState = dynamic_cast(state.get())) + { + initiator_j["numRequests"] = trafficState->numRequests; + initiator_j["rwRatio"] = trafficState->rwRatio; + initiator_j["addressDistribution"] = trafficState->addressDistribution; + initiator_j["addressIncrement"] = trafficState->addressIncrement; + initiator_j["minAddress"] = trafficState->minAddress; + initiator_j["maxAddress"] = trafficState->maxAddress; + initiator_j["clksPerRequest"] = trafficState->clksPerRequest; + } + else if (const auto idleState = dynamic_cast(state.get())) + { + initiator_j["idleClks"] = idleState->idleClks; + } } else { @@ -82,13 +94,22 @@ void to_json(json &j, const TraceSetup &c) { json state_j; state_j["id"] = state.first; - state_j["numRequests"] = state.second.numRequests; - state_j["rwRatio"] = state.second.rwRatio; - state_j["addressDistribution"] = state.second.addressDistribution; - state_j["addressIncrement"] = state.second.addressIncrement; - state_j["minAddress"] = state.second.minAddress; - state_j["maxAddress"] = state.second.maxAddress; - state_j["clksPerRequest"] = state.second.clksPerRequest; + + if (const auto trafficState = dynamic_cast(state.second.get())) + { + state_j["numRequests"] = trafficState->numRequests; + state_j["rwRatio"] = trafficState->rwRatio; + state_j["addressDistribution"] = trafficState->addressDistribution; + state_j["addressIncrement"] = trafficState->addressIncrement; + state_j["minAddress"] = trafficState->minAddress; + state_j["maxAddress"] = trafficState->maxAddress; + state_j["clksPerRequest"] = trafficState->clksPerRequest; + } + else if (const auto idleState = dynamic_cast(state.second.get())) + { + state_j["idleClks"] = idleState->idleClks; + } + remove_null_values(state_j); states_j.insert(states_j.end(), state_j); } @@ -140,25 +161,40 @@ void from_json(const json &j, TraceSetup &c) { TraceGenerator *generator = new TraceGenerator; - auto process_state = [](const json &state_j) -> std::pair + auto process_state = [](const json &state_j) -> std::pair> { - TraceGeneratorState state{}; + std::unique_ptr state; - state_j.at("numRequests").get_to(state.numRequests); - state_j.at("rwRatio").get_to(state.rwRatio); - state_j.at("addressDistribution").get_to(state.addressDistribution); + if (state_j.contains("idleClks")) + { + // Idle state + auto idleState = new TraceGeneratorIdleState; + state_j.at("idleClks").get_to(idleState->idleClks); - if (state_j.contains("addressIncrement")) - state_j.at("addressIncrement").get_to(state.addressIncrement); + state = std::unique_ptr(idleState); + } + else + { + // Traffic state + auto trafficState = new TraceGeneratorTrafficState; + state_j.at("numRequests").get_to(trafficState->numRequests); + state_j.at("rwRatio").get_to(trafficState->rwRatio); + state_j.at("addressDistribution").get_to(trafficState->addressDistribution); - if (state_j.contains("minAddress")) - state_j.at("minAddress").get_to(state.minAddress); + if (state_j.contains("addressIncrement")) + state_j.at("addressIncrement").get_to(trafficState->addressIncrement); - if (state_j.contains("maxAddress")) - state_j.at("maxAddress").get_to(state.maxAddress); + if (state_j.contains("minAddress")) + state_j.at("minAddress").get_to(trafficState->minAddress); - if (state_j.contains("clksPerRequest")) - state_j.at("clksPerRequest").get_to(state.clksPerRequest); + if (state_j.contains("maxAddress")) + state_j.at("maxAddress").get_to(trafficState->maxAddress); + + if (state_j.contains("clksPerRequest")) + state_j.at("clksPerRequest").get_to(trafficState->clksPerRequest); + + state = std::unique_ptr(trafficState); + } // Default to 0 unsigned int id = 0; @@ -166,7 +202,7 @@ void from_json(const json &j, TraceSetup &c) if (state_j.contains("id")) id = state_j.at("id"); - return {id, state}; + return {id, std::move(state)}; }; if (initiator_j.contains("states")) @@ -174,7 +210,7 @@ void from_json(const json &j, TraceSetup &c) for (const auto &state_j : initiator_j.at("states")) { auto state = process_state(state_j); - generator->states[state.first] = state.second; + generator->states[state.first] = std::move(state.second); } for (const auto &transition_j : initiator_j.at("transitions")) @@ -189,7 +225,7 @@ void from_json(const json &j, TraceSetup &c) else // Only one state will be created { auto state = process_state(initiator_j); - generator->states[state.first] = state.second; + generator->states[state.first] = std::move(state.second); } if (initiator_j.contains("seed")) diff --git a/DRAMSys/library/src/common/configuration/TraceSetup.h b/DRAMSys/library/src/common/configuration/TraceSetup.h index 4340805d..d128dc36 100644 --- a/DRAMSys/library/src/common/configuration/TraceSetup.h +++ b/DRAMSys/library/src/common/configuration/TraceSetup.h @@ -84,6 +84,11 @@ struct TracePlayer : public TrafficInitiator }; struct TraceGeneratorState +{ + virtual ~TraceGeneratorState() = 0; +}; + +struct TraceGeneratorTrafficState : public TraceGeneratorState { uint64_t numRequests; double rwRatio; @@ -94,6 +99,11 @@ struct TraceGeneratorState Optional clksPerRequest; }; +struct TraceGeneratorIdleState : public TraceGeneratorState +{ + uint64_t idleClks; +}; + struct TraceGeneratorStateTransition { unsigned int to; @@ -104,7 +114,7 @@ struct TraceGenerator : public TrafficInitiator { Optional seed; Optional maxTransactions; - std::map states; + std::map> states; std::multimap transitions; }; diff --git a/DRAMSys/library/src/common/configuration/tests/simpletest.cpp b/DRAMSys/library/src/common/configuration/tests/simpletest.cpp index 50716769..bd272ae4 100644 --- a/DRAMSys/library/src/common/configuration/tests/simpletest.cpp +++ b/DRAMSys/library/src/common/configuration/tests/simpletest.cpp @@ -111,10 +111,16 @@ std::unique_ptr getTraceGeneratorOneState( gen->clkMhz = 100; gen->name = "MyTestGen"; - DRAMSysConfiguration::TraceGeneratorState state0{1000, 0.5, DRAMSysConfiguration::AddressDistribution::Random, - {}, {}, {}}; + auto state0 = new DRAMSysConfiguration::TraceGeneratorTrafficState; + state0->numRequests = 1000; + state0->rwRatio = 0.5; + state0->addressDistribution = DRAMSysConfiguration::AddressDistribution::Random; + state0->addressIncrement = {}; + state0->minAddress = {}; + state0->maxAddress = {}; + state0->clksPerRequest = {}; - gen->states[0] = state0; + gen->states[0] = std::unique_ptr(state0); return std::unique_ptr(gen); } @@ -127,14 +133,26 @@ std::unique_ptr getTraceGeneratorMultipleS gen->name = "MyTestGen"; gen->maxPendingReadRequests = 8; - DRAMSysConfiguration::TraceGeneratorState state0{1000, 0.5, DRAMSysConfiguration::AddressDistribution::Sequential, - {256}, {}, {1024}}; + auto state0 = new DRAMSysConfiguration::TraceGeneratorTrafficState; + state0->numRequests = 1000; + state0->rwRatio = 0.5; + state0->addressDistribution = DRAMSysConfiguration::AddressDistribution::Sequential; + state0->addressIncrement = 256; + state0->minAddress = {}; + state0->maxAddress = 1024; + state0->clksPerRequest = {}; - DRAMSysConfiguration::TraceGeneratorState state1{ - 100, 0.75, DRAMSysConfiguration::AddressDistribution::Sequential, {512}, {1024}, {2048}}; + auto state1 = new DRAMSysConfiguration::TraceGeneratorTrafficState; + state1->numRequests = 100; + state1->rwRatio = 0.75; + state1->addressDistribution = DRAMSysConfiguration::AddressDistribution::Sequential; + state1->addressIncrement = 512; + state1->minAddress = 1024; + state1->maxAddress = 2048; + state1->clksPerRequest = {}; - gen->states[0] = state0; - gen->states[1] = state1; + gen->states[0] = std::unique_ptr(state0); + gen->states[1] = std::unique_ptr(state1); DRAMSysConfiguration::TraceGeneratorStateTransition transistion0{1, 1.0}; diff --git a/DRAMSys/simulator/TrafficGenerator.cpp b/DRAMSys/simulator/TrafficGenerator.cpp index cf609702..ad56dc47 100644 --- a/DRAMSys/simulator/TrafficGenerator.cpp +++ b/DRAMSys/simulator/TrafficGenerator.cpp @@ -82,9 +82,9 @@ void TrafficGeneratorIf::sendNextPayload() sc_time generatorClk = getGeneratorClk(); sc_time sendingOffset; if (transactionsSent == 0) - sendingOffset = SC_ZERO_TIME; + sendingOffset = SC_ZERO_TIME + generatorClk * clksToIdle(); else - sendingOffset = (generatorClk * clksPerRequest()) - (sc_time_stamp() % generatorClk); + sendingOffset = (generatorClk * clksPerRequest()) - (sc_time_stamp() % generatorClk) + generatorClk * clksToIdle(); // TODO: do not send two requests in the same cycle sendToTarget(*payload, tlm::BEGIN_REQ, sendingOffset); @@ -103,27 +103,33 @@ TrafficGenerator::TrafficGenerator(const sc_module_name &name, const DRAMSysConf // Perform checks for all states for (const auto &state : conf.states) { - uint64_t minAddress = evaluateMinAddress(state.second); - uint64_t maxAddress = evaluateMaxAddress(state.second); - double rwRatio = state.second.rwRatio; + if (auto trafficState = dynamic_cast(state.second.get())) + { + uint64_t minAddress = evaluateMinAddress(*trafficState); + uint64_t maxAddress = evaluateMaxAddress(*trafficState); + double rwRatio = (*trafficState).rwRatio; - if (minAddress > Configuration::getInstance().memSpec->getSimMemSizeInBytes() - 1) - SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range."); + if (minAddress > Configuration::getInstance().memSpec->getSimMemSizeInBytes() - 1) + SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range."); - if (maxAddress > Configuration::getInstance().memSpec->getSimMemSizeInBytes() - 1) - SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range."); + if (maxAddress > Configuration::getInstance().memSpec->getSimMemSizeInBytes() - 1) + SC_REPORT_FATAL("TrafficGenerator", "minAddress is out of range."); - if (maxAddress < minAddress) - SC_REPORT_FATAL("TrafficGenerator", "maxAddress is smaller than minAddress."); + if (maxAddress < minAddress) + SC_REPORT_FATAL("TrafficGenerator", "maxAddress is smaller than minAddress."); - if (rwRatio < 0 || rwRatio > 1) - SC_REPORT_FATAL("TraceSetup", "Read/Write ratio is not a number between 0 and 1."); + if (rwRatio < 0 || rwRatio > 1) + SC_REPORT_FATAL("TraceSetup", "Read/Write ratio is not a number between 0 and 1."); + } } - uint64_t minAddress = evaluateMinAddress(conf.states.at(currentState)); - uint64_t maxAddress = evaluateMaxAddress(conf.states.at(currentState)); - randomAddressDistribution = std::uniform_int_distribution(minAddress, maxAddress); - currentClksPerRequest = evaluateClksPerRequest(conf.states.at(currentState)); + if (auto trafficState = dynamic_cast(conf.states.at(currentState).get())) + { + uint64_t minAddress = evaluateMinAddress(*trafficState); + uint64_t maxAddress = evaluateMaxAddress(*trafficState); + randomAddressDistribution = std::uniform_int_distribution(minAddress, maxAddress); + currentClksPerRequest = evaluateClksPerRequest(*trafficState); + } calculateTransitions(); } @@ -170,7 +176,8 @@ void TrafficGenerator::calculateTransitions() if (transitionFound) { - totalTransactions += conf.states.at(state).numRequests; + if (auto trafficState = dynamic_cast(conf.states.at(state).get())) + totalTransactions += trafficState->numRequests; if (totalTransactions < maxTransactions) continue; @@ -188,7 +195,8 @@ uint64_t TrafficGenerator::getTotalTransactions() const for (auto state : stateSequence) { - totalTransactions += conf.states.at(state).numRequests; + if (auto trafficState = dynamic_cast(conf.states.at(state).get())) + totalTransactions += trafficState->numRequests; } if (totalTransactions > maxTransactions) @@ -210,10 +218,19 @@ void TrafficGenerator::transitionToNextState() currentState = *stateIt; - uint64_t minAddress = evaluateMinAddress(conf.states.at(currentState)); - uint64_t maxAddress = evaluateMaxAddress(conf.states.at(currentState)); - randomAddressDistribution = std::uniform_int_distribution (minAddress, maxAddress); - currentClksPerRequest = evaluateClksPerRequest(conf.states.at(currentState)); + if (auto idleState = dynamic_cast(conf.states.at(currentState).get())) + { + currentClksToIdle += idleState->idleClks; + transitionToNextState(); + return; + } + else if (auto trafficState = dynamic_cast(conf.states.at(currentState).get())) + { + uint64_t minAddress = evaluateMinAddress(*trafficState); + uint64_t maxAddress = evaluateMaxAddress(*trafficState); + randomAddressDistribution = std::uniform_int_distribution(minAddress, maxAddress); + currentClksPerRequest = evaluateClksPerRequest(*trafficState); + } currentAddress = 0x00; transactionsSentInCurrentState = 0; @@ -221,19 +238,28 @@ void TrafficGenerator::transitionToNextState() void TrafficGenerator::prepareNextPayload() { - if (transactionsSentInCurrentState >= conf.states.at(currentState).numRequests) - transitionToNextState(); + if (auto trafficState = dynamic_cast(conf.states.at(currentState).get())) + { + if (transactionsSentInCurrentState >= trafficState->numRequests) + transitionToNextState(); + } } void TrafficGenerator::payloadSent() { + // Reset clks to idle. + currentClksToIdle = 0; + transactionsSentInCurrentState++; } tlm::tlm_command TrafficGenerator::getNextCommand() { + // An idle state should never reach this method. + auto state = static_cast(conf.states.at(currentState).get()); + tlm_command command; - if (randomDistribution(randomGenerator) < conf.states.at(currentState).rwRatio) + if (randomDistribution(randomGenerator) < state->rwRatio) command = tlm::TLM_READ_COMMAND; else command = tlm::TLM_WRITE_COMMAND; @@ -241,7 +267,7 @@ tlm::tlm_command TrafficGenerator::getNextCommand() return command; } -sc_core::sc_time TrafficGenerator::getGeneratorClk() +sc_core::sc_time TrafficGenerator::getGeneratorClk() const { return generatorClk; } @@ -250,12 +276,15 @@ uint64_t TrafficGenerator::getNextAddress() { using DRAMSysConfiguration::AddressDistribution; - uint64_t minAddress = evaluateMinAddress(conf.states.at(currentState)); - uint64_t maxAddress = evaluateMaxAddress(conf.states.at(currentState)); + // An idle state should never reach this method. + auto state = static_cast(conf.states.at(currentState).get()); - if (conf.states.at(currentState).addressDistribution == AddressDistribution::Sequential) + uint64_t minAddress = evaluateMinAddress(*state); + uint64_t maxAddress = evaluateMaxAddress(*state); + + if (state->addressDistribution == AddressDistribution::Sequential) { - uint64_t addressIncrement = evaluateAddressIncrement(conf.states.at(currentState)); + uint64_t addressIncrement = evaluateAddressIncrement(*state); uint64_t address = currentAddress; currentAddress += addressIncrement; @@ -263,7 +292,7 @@ uint64_t TrafficGenerator::getNextAddress() currentAddress = minAddress; return address; } - else if (conf.states.at(currentState).addressDistribution == AddressDistribution::Random) + else if (state->addressDistribution == AddressDistribution::Random) { return randomAddressDistribution(randomGenerator); } @@ -289,7 +318,7 @@ uint64_t TrafficGenerator::evaluateMaxTransactions(const DRAMSysConfiguration::T return std::numeric_limits::max(); } -uint64_t TrafficGenerator::evaluateMinAddress(const DRAMSysConfiguration::TraceGeneratorState &state) +uint64_t TrafficGenerator::evaluateMinAddress(const DRAMSysConfiguration::TraceGeneratorTrafficState &state) { if (state.minAddress.isValid()) return state.minAddress.getValue(); @@ -297,7 +326,7 @@ uint64_t TrafficGenerator::evaluateMinAddress(const DRAMSysConfiguration::TraceG return 0x00; } -uint64_t TrafficGenerator::evaluateMaxAddress(const DRAMSysConfiguration::TraceGeneratorState &state) +uint64_t TrafficGenerator::evaluateMaxAddress(const DRAMSysConfiguration::TraceGeneratorTrafficState &state) { if (state.maxAddress.isValid()) return state.maxAddress.getValue(); @@ -305,7 +334,7 @@ uint64_t TrafficGenerator::evaluateMaxAddress(const DRAMSysConfiguration::TraceG return Configuration::getInstance().memSpec->getSimMemSizeInBytes() - 1; } -uint64_t TrafficGenerator::evaluateAddressIncrement(const DRAMSysConfiguration::TraceGeneratorState &state) +uint64_t TrafficGenerator::evaluateAddressIncrement(const DRAMSysConfiguration::TraceGeneratorTrafficState &state) { if (state.addressIncrement.isValid()) return state.addressIncrement.getValue(); @@ -313,7 +342,7 @@ uint64_t TrafficGenerator::evaluateAddressIncrement(const DRAMSysConfiguration:: return 0x00; } -uint64_t TrafficGenerator::evaluateClksPerRequest(const DRAMSysConfiguration::TraceGeneratorState &state) +uint64_t TrafficGenerator::evaluateClksPerRequest(const DRAMSysConfiguration::TraceGeneratorTrafficState &state) { if (state.clksPerRequest.isValid()) return state.clksPerRequest.getValue(); @@ -333,7 +362,7 @@ tlm::tlm_command TrafficGeneratorHammer::getNextCommand() return tlm::TLM_READ_COMMAND; } -sc_core::sc_time TrafficGeneratorHammer::getGeneratorClk() +sc_core::sc_time TrafficGeneratorHammer::getGeneratorClk() const { return generatorClk; } diff --git a/DRAMSys/simulator/TrafficGenerator.h b/DRAMSys/simulator/TrafficGenerator.h index a258b6e2..f27c7bba 100644 --- a/DRAMSys/simulator/TrafficGenerator.h +++ b/DRAMSys/simulator/TrafficGenerator.h @@ -55,9 +55,10 @@ private: virtual void prepareNextPayload(){}; virtual uint64_t getNextAddress() = 0; virtual tlm::tlm_command getNextCommand() = 0; - virtual sc_core::sc_time getGeneratorClk() = 0; + virtual sc_core::sc_time getGeneratorClk() const = 0; virtual void payloadSent(){}; - virtual uint64_t clksPerRequest() { return 1; } + virtual uint64_t clksPerRequest() const { return 1; } + virtual uint64_t clksToIdle() const { return 0; } }; class TrafficGenerator : public TrafficGeneratorIf @@ -71,17 +72,18 @@ public: private: static uint64_t evaluateSeed(const DRAMSysConfiguration::TraceGenerator &conf); static uint64_t evaluateMaxTransactions(const DRAMSysConfiguration::TraceGenerator &conf); - static uint64_t evaluateMinAddress(const DRAMSysConfiguration::TraceGeneratorState &state); - static uint64_t evaluateMaxAddress(const DRAMSysConfiguration::TraceGeneratorState &state); - static uint64_t evaluateAddressIncrement(const DRAMSysConfiguration::TraceGeneratorState &state); - static uint64_t evaluateClksPerRequest(const DRAMSysConfiguration::TraceGeneratorState &state); + static uint64_t evaluateMinAddress(const DRAMSysConfiguration::TraceGeneratorTrafficState &state); + static uint64_t evaluateMaxAddress(const DRAMSysConfiguration::TraceGeneratorTrafficState &state); + static uint64_t evaluateAddressIncrement(const DRAMSysConfiguration::TraceGeneratorTrafficState &state); + static uint64_t evaluateClksPerRequest(const DRAMSysConfiguration::TraceGeneratorTrafficState &state); void prepareNextPayload() override; uint64_t getNextAddress() override; tlm::tlm_command getNextCommand() override; - sc_core::sc_time getGeneratorClk() override; + sc_core::sc_time getGeneratorClk() const override; void payloadSent() override; - uint64_t clksPerRequest() override { return currentClksPerRequest; }; + uint64_t clksPerRequest() const override { return currentClksPerRequest; }; + uint64_t clksToIdle() const override { return currentClksToIdle; } void calculateTransitions(); void transitionToNextState(); @@ -96,6 +98,8 @@ private: const uint64_t maxTransactions; + uint64_t currentClksToIdle = 0; + std::vector stateSequence; std::vector::const_iterator stateIt; @@ -114,7 +118,7 @@ private: void prepareNextPayload() override; uint64_t getNextAddress() override; tlm::tlm_command getNextCommand() override; - sc_core::sc_time getGeneratorClk() override; + sc_core::sc_time getGeneratorClk() const override; sc_core::sc_time generatorClk; uint64_t rowIncrement;