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.
This commit is contained in:
2022-01-05 13:48:19 +01:00
parent e1e2e9c0f9
commit 3dbb089dcb
5 changed files with 183 additions and 86 deletions

View File

@@ -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<TraceGeneratorTrafficState *>(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<TraceGeneratorIdleState *>(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<TraceGeneratorTrafficState *>(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<TraceGeneratorIdleState *>(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<unsigned int, TraceGeneratorState>
auto process_state = [](const json &state_j) -> std::pair<unsigned int, std::unique_ptr<TraceGeneratorState>>
{
TraceGeneratorState state{};
std::unique_ptr<TraceGeneratorState> 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<TraceGeneratorIdleState>(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<TraceGeneratorTrafficState>(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"))

View File

@@ -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<uint64_t> clksPerRequest;
};
struct TraceGeneratorIdleState : public TraceGeneratorState
{
uint64_t idleClks;
};
struct TraceGeneratorStateTransition
{
unsigned int to;
@@ -104,7 +114,7 @@ struct TraceGenerator : public TrafficInitiator
{
Optional<uint64_t> seed;
Optional<uint64_t> maxTransactions;
std::map<unsigned int, TraceGeneratorState> states;
std::map<unsigned int, std::unique_ptr<TraceGeneratorState>> states;
std::multimap<unsigned int, TraceGeneratorStateTransition> transitions;
};

View File

@@ -111,10 +111,16 @@ std::unique_ptr<DRAMSysConfiguration::TraceGenerator> 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<DRAMSysConfiguration::TraceGeneratorTrafficState>(state0);
return std::unique_ptr<DRAMSysConfiguration::TraceGenerator>(gen);
}
@@ -127,14 +133,26 @@ std::unique_ptr<DRAMSysConfiguration::TraceGenerator> 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<DRAMSysConfiguration::TraceGeneratorTrafficState>(state0);
gen->states[1] = std::unique_ptr<DRAMSysConfiguration::TraceGeneratorTrafficState>(state1);
DRAMSysConfiguration::TraceGeneratorStateTransition transistion0{1, 1.0};

View File

@@ -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<DRAMSysConfiguration::TraceGeneratorTrafficState *>(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<uint64_t>(minAddress, maxAddress);
currentClksPerRequest = evaluateClksPerRequest(conf.states.at(currentState));
if (auto trafficState = dynamic_cast<DRAMSysConfiguration::TraceGeneratorTrafficState *>(conf.states.at(currentState).get()))
{
uint64_t minAddress = evaluateMinAddress(*trafficState);
uint64_t maxAddress = evaluateMaxAddress(*trafficState);
randomAddressDistribution = std::uniform_int_distribution<uint64_t>(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<DRAMSysConfiguration::TraceGeneratorTrafficState *>(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<DRAMSysConfiguration::TraceGeneratorTrafficState *>(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<uint64_t> (minAddress, maxAddress);
currentClksPerRequest = evaluateClksPerRequest(conf.states.at(currentState));
if (auto idleState = dynamic_cast<DRAMSysConfiguration::TraceGeneratorIdleState *>(conf.states.at(currentState).get()))
{
currentClksToIdle += idleState->idleClks;
transitionToNextState();
return;
}
else if (auto trafficState = dynamic_cast<DRAMSysConfiguration::TraceGeneratorTrafficState *>(conf.states.at(currentState).get()))
{
uint64_t minAddress = evaluateMinAddress(*trafficState);
uint64_t maxAddress = evaluateMaxAddress(*trafficState);
randomAddressDistribution = std::uniform_int_distribution<uint64_t>(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<DRAMSysConfiguration::TraceGeneratorTrafficState *>(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<DRAMSysConfiguration::TraceGeneratorTrafficState *>(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<DRAMSysConfiguration::TraceGeneratorTrafficState *>(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<uint64_t>::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;
}

View File

@@ -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<unsigned int> stateSequence;
std::vector<unsigned int>::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;