minor refactoring
This commit is contained in:
@@ -57,7 +57,8 @@ SOURCES += \
|
||||
../src/simulation/main.cpp \
|
||||
../src/common/libDRAMPower.cpp \
|
||||
../src/controller/core/RowBufferStates.cpp \
|
||||
../src/controller/scheduler/Scheduler.cpp
|
||||
../src/controller/scheduler/Scheduler.cpp \
|
||||
../src/controller/scheduler/readwritegrouper.cpp
|
||||
|
||||
HEADERS += \
|
||||
../src/common/third_party/tinyxml2.h \
|
||||
@@ -112,6 +113,7 @@ HEADERS += \
|
||||
../src/simulation/Dram.h \
|
||||
../src/simulation/Arbiter.h \
|
||||
../src/common/libDRAMPower.h \
|
||||
../src/controller/core/RowBufferStates.h
|
||||
../src/controller/core/RowBufferStates.h \
|
||||
../src/controller/scheduler/readwritegrouper.h
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
<parameter id="powerDownMode" type="string" value="Staggered" />
|
||||
<parameter id="powerDownTimeout" type="uint" value="100" />
|
||||
|
||||
<parameter id="databaseRecordingEnabled" type="bool" value="0" />
|
||||
<parameter id="databaseRecordingEnabled" type="bool" value="1" />
|
||||
</memconfig>
|
||||
</memspec>
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
<parameter id="powerDownMode" type="string" value="Staggered" />
|
||||
<parameter id="powerDownTimeout" type="uint" value="100" />
|
||||
|
||||
<parameter id="databaseRecordingEnabled" type="bool" value="0" />
|
||||
<parameter id="databaseRecordingEnabled" type="bool" value="1" />
|
||||
</memconfig>
|
||||
</memspec>
|
||||
|
||||
@@ -17,7 +17,7 @@ bool TlmRecorder::recordingEnabled = true;
|
||||
// ------------- public -----------------------
|
||||
|
||||
TlmRecorder::TlmRecorder() :
|
||||
transactionIDCounter(1), recordingEndTime(SC_ZERO_TIME)
|
||||
totalNumTransactions(1), simulationTimeCoveredByRecording(SC_ZERO_TIME)
|
||||
{
|
||||
if(recordingEnabled)
|
||||
{
|
||||
@@ -73,7 +73,7 @@ void TlmRecorder::recordPhase(tlm::tlm_generic_payload& trans, tlm::tlm_phase ph
|
||||
if (phaseTerminatesTransaction)
|
||||
removeTransactionFromSystem(trans);
|
||||
|
||||
recordingEndTime = time;
|
||||
simulationTimeCoveredByRecording = time;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ void TlmRecorder::recordDebugMessage(std::string message, sc_time time)
|
||||
|
||||
void TlmRecorder::introduceTransactionSystem(tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
unsigned int id = transactionIDCounter++;
|
||||
unsigned int id = totalNumTransactions++;
|
||||
currentTransactionsInSystem[&trans].id = id;
|
||||
currentTransactionsInSystem[&trans].address = trans.get_address();
|
||||
currentTransactionsInSystem[&trans].burstlength = trans.get_streaming_width();
|
||||
@@ -124,7 +124,7 @@ void TlmRecorder::removeTransactionFromSystem(tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
|
||||
RecordingData& recordingData = currentTransactionsInSystem[&trans];
|
||||
Transaction& recordingData = currentTransactionsInSystem[&trans];
|
||||
recordedData.push_back(recordingData);
|
||||
currentTransactionsInSystem.erase(&trans);
|
||||
}
|
||||
@@ -132,11 +132,11 @@ void TlmRecorder::removeTransactionFromSystem(tlm::tlm_generic_payload& trans)
|
||||
void TlmRecorder::commitRecordedDataToDB()
|
||||
{
|
||||
sqlite3_exec(db, "BEGIN;", 0, 0, 0);
|
||||
for(RecordingData& recordingData: recordedData)
|
||||
for(Transaction& recordingData: recordedData)
|
||||
{
|
||||
assert(recordingData.recordedPhases.size() > 0);
|
||||
insertTransactionInDB(recordingData);
|
||||
for(RecordingData::PhaseData& phaseData: recordingData.recordedPhases)
|
||||
for(Transaction::Phase& phaseData: recordingData.recordedPhases)
|
||||
{
|
||||
insertPhaseInDB(phaseData.name,phaseData.interval.start,phaseData.interval.end,recordingData.id);
|
||||
}
|
||||
@@ -151,14 +151,14 @@ void TlmRecorder::commitRecordedDataToDB()
|
||||
}
|
||||
|
||||
|
||||
void TlmRecorder::RecordingData::insertPhase(string name, sc_time begin)
|
||||
void TlmRecorder::Transaction::insertPhase(string name, sc_time begin)
|
||||
{
|
||||
recordedPhases.push_back(PhaseData(name,begin));
|
||||
recordedPhases.push_back(Phase(name,begin));
|
||||
}
|
||||
|
||||
void TlmRecorder::RecordingData::setPhaseEnd(string name, sc_time end)
|
||||
void TlmRecorder::Transaction::setPhaseEnd(string name, sc_time end)
|
||||
{
|
||||
for(PhaseData& data: recordedPhases)
|
||||
for(Phase& data: recordedPhases)
|
||||
{
|
||||
if(data.name == name)
|
||||
{
|
||||
@@ -233,8 +233,8 @@ void TlmRecorder::insertDebugMessageInDB(string message, const sc_time& time)
|
||||
|
||||
void TlmRecorder::insertGeneralInfo()
|
||||
{
|
||||
sqlite3_bind_int64(insertGeneralInfoStatement, 1, transactionIDCounter - 1);
|
||||
sqlite3_bind_int64(insertGeneralInfoStatement, 2, recordingEndTime.value());
|
||||
sqlite3_bind_int64(insertGeneralInfoStatement, 1, totalNumTransactions - 1);
|
||||
sqlite3_bind_int64(insertGeneralInfoStatement, 2, simulationTimeCoveredByRecording.value());
|
||||
sqlite3_bind_int(insertGeneralInfoStatement, 3,
|
||||
core::Configuration::getInstance().NumberOfBanks);
|
||||
sqlite3_bind_int(insertGeneralInfoStatement, 4, core::Configuration::getInstance().Timings.clk.value());
|
||||
@@ -245,7 +245,7 @@ void TlmRecorder::insertGeneralInfo()
|
||||
executeSqlStatement(insertGeneralInfoStatement);
|
||||
}
|
||||
|
||||
void TlmRecorder::insertTransactionInDB(RecordingData& recordingData)
|
||||
void TlmRecorder::insertTransactionInDB(Transaction& recordingData)
|
||||
{
|
||||
sqlite3_bind_int(insertTransactionStatement, 1, recordingData.id);
|
||||
sqlite3_bind_int(insertTransactionStatement, 2, recordingData.id);
|
||||
@@ -319,7 +319,7 @@ void TlmRecorder::closeConnection()
|
||||
commitRecordedDataToDB();
|
||||
insertGeneralInfo();
|
||||
printDebugMessage(
|
||||
"Number of transactions written to DB: " + std::to_string(transactionIDCounter - 1));
|
||||
"Number of transactions written to DB: " + std::to_string(totalNumTransactions - 1));
|
||||
printDebugMessage("tlmPhaseRecorder:\tEnd Recording");
|
||||
sqlite3_close(db);
|
||||
db = NULL;
|
||||
|
||||
@@ -43,10 +43,10 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
struct RecordingData
|
||||
struct Transaction
|
||||
{
|
||||
RecordingData(){}
|
||||
RecordingData(unsigned int id):id(id){}
|
||||
Transaction(){}
|
||||
Transaction(unsigned int id):id(id){}
|
||||
|
||||
unsigned int id;
|
||||
unsigned int address;
|
||||
@@ -55,13 +55,13 @@ private:
|
||||
sc_time timeOfGeneration;
|
||||
TimeInterval timeOnDataStrobe;
|
||||
|
||||
struct PhaseData
|
||||
struct Phase
|
||||
{
|
||||
PhaseData(string name,sc_time begin): name(name), interval(begin,SC_ZERO_TIME){}
|
||||
Phase(string name,sc_time begin): name(name), interval(begin,SC_ZERO_TIME){}
|
||||
string name;
|
||||
TimeInterval interval;
|
||||
};
|
||||
std::vector<PhaseData> recordedPhases;
|
||||
std::vector<Phase> recordedPhases;
|
||||
|
||||
void insertPhase(string name,sc_time begin);
|
||||
void setPhaseEnd(string name,sc_time end);
|
||||
@@ -85,7 +85,7 @@ private:
|
||||
|
||||
void commitRecordedDataToDB();
|
||||
void insertGeneralInfo();
|
||||
void insertTransactionInDB(RecordingData& recordingData);
|
||||
void insertTransactionInDB(Transaction& recordingData);
|
||||
void insertRangeInDB(unsigned int id, const sc_time& begin, const sc_time& end);
|
||||
void insertPhaseInDB(string phaseName, const sc_time& begin, const sc_time& end, unsigned int transactionID);
|
||||
void insertDebugMessageInDB(string message, const sc_time& time);
|
||||
@@ -93,11 +93,11 @@ private:
|
||||
void printDebugMessage(std::string message);
|
||||
|
||||
static const int transactionCommitRate = 1000;
|
||||
vector<RecordingData> recordedData;
|
||||
map<tlm::tlm_generic_payload*, RecordingData> currentTransactionsInSystem;
|
||||
vector<Transaction> recordedData;
|
||||
map<tlm::tlm_generic_payload*, Transaction> currentTransactionsInSystem;
|
||||
|
||||
unsigned int transactionIDCounter;
|
||||
sc_time recordingEndTime;
|
||||
unsigned int totalNumTransactions;
|
||||
sc_time simulationTimeCoveredByRecording;
|
||||
|
||||
std::vector<tlm::tlm_phase> transactionTerminatingPhases;
|
||||
sqlite3 *db;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
//TODO : move to timing specific header
|
||||
sc_time getDistance(sc_time a, sc_time b);
|
||||
|
||||
struct TimeInterval
|
||||
{
|
||||
sc_time start,end;
|
||||
|
||||
@@ -5,9 +5,22 @@
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
/* Static methods
|
||||
*
|
||||
*/
|
||||
|
||||
DramExtension::DramExtension() :
|
||||
thread(0), channel(0), bank(0), bankgroup(0), row(0), column(0), burstlength(0)
|
||||
{
|
||||
}
|
||||
|
||||
DramExtension::DramExtension(const Thread &thread, const Bank &bank, const BankGroup &bankgroup, const Row &row, const Column &column, unsigned int burstlength) :
|
||||
thread(thread), channel(0), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
|
||||
{
|
||||
}
|
||||
|
||||
DramExtension::DramExtension(const Thread &thread, const Channel &channel, const Bank &bank, const BankGroup &bankgroup, const Row &row, const Column &column, unsigned int burstlength) :
|
||||
thread(thread), channel(channel), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
|
||||
{
|
||||
}
|
||||
|
||||
DramExtension& DramExtension::getExtension(const tlm_generic_payload *payload)
|
||||
{
|
||||
DramExtension *result = NULL;
|
||||
@@ -22,108 +35,12 @@ DramExtension& DramExtension::getExtension(const tlm_generic_payload &payload)
|
||||
return DramExtension::getExtension(&payload);
|
||||
}
|
||||
|
||||
bool operator ==(const Thread& lhs, const Thread& rhs)
|
||||
{
|
||||
return lhs.ID() == rhs.ID();
|
||||
}
|
||||
|
||||
bool operator !=(const Thread& lhs, const Thread& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
bool operator <(const Thread& lhs, const Thread& rhs)
|
||||
{
|
||||
return lhs.ID() < rhs.ID();
|
||||
}
|
||||
|
||||
bool operator ==(const Channel& lhs, const Channel& rhs)
|
||||
{
|
||||
return lhs.ID() == rhs.ID();
|
||||
}
|
||||
|
||||
bool operator !=(const Channel& lhs, const Channel& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
BankGroup Bank::getBankGroup()
|
||||
{
|
||||
static std::map<Bank, BankGroup> bankgroups;
|
||||
if (bankgroups.size() == 0)
|
||||
{
|
||||
core::Configuration& config = core::Configuration::getInstance();
|
||||
sc_assert(config.NumberOfBanks % config.NumberOfBankGroups == 0);
|
||||
|
||||
for (unsigned int bank = 0; bank < config.NumberOfBanks; bank++)
|
||||
{
|
||||
unsigned int group = bank % config.NumberOfBankGroups;
|
||||
bankgroups.insert(std::pair<Bank, BankGroup>(Bank(bank), BankGroup(group)));
|
||||
}
|
||||
}
|
||||
|
||||
return getElementFromMap(bankgroups, *this);
|
||||
}
|
||||
|
||||
bool operator ==(const Bank& lhs, const Bank& rhs)
|
||||
{
|
||||
return lhs.ID() == rhs.ID();
|
||||
}
|
||||
|
||||
bool operator !=(const Bank& lhs, const Bank& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
bool operator ==(const BankGroup& lhs, const BankGroup& rhs)
|
||||
{
|
||||
return lhs.ID() == rhs.ID();
|
||||
}
|
||||
|
||||
bool operator !=(const BankGroup& lhs, const BankGroup& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
bool operator <(const Bank& lhs, const Bank& rhs)
|
||||
{
|
||||
return lhs.ID() < rhs.ID();
|
||||
}
|
||||
|
||||
const Row Row::NO_ROW;
|
||||
|
||||
const Row Row::operator ++()
|
||||
{
|
||||
id = (id + 1) % core::Configuration::getInstance().NumberOfRows;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator ==(const Row& lhs, const Row& rhs)
|
||||
{
|
||||
if (lhs.isNoRow != rhs.isNoRow)
|
||||
return false;
|
||||
return lhs.ID() == rhs.ID();
|
||||
}
|
||||
|
||||
bool operator !=(const Row& lhs, const Row& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
bool operator ==(const Column& lhs, const Column& rhs)
|
||||
{
|
||||
return lhs.ID() == rhs.ID();
|
||||
}
|
||||
|
||||
bool operator !=(const Column& lhs, const Column& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
tlm_extension_base* DramExtension::clone() const
|
||||
{
|
||||
return new DramExtension(thread, bank, bankgroup, row, column, burstlength);
|
||||
}
|
||||
|
||||
void DramExtension::copy_from(const tlm_extension_base& ext)
|
||||
{
|
||||
const DramExtension& cpyFrom = static_cast<const DramExtension&>(ext);
|
||||
@@ -135,29 +52,32 @@ void DramExtension::copy_from(const tlm_extension_base& ext)
|
||||
burstlength = cpyFrom.burstlength;
|
||||
}
|
||||
|
||||
const Thread& DramExtension::getThread() const
|
||||
Thread DramExtension::getThread() const
|
||||
{
|
||||
return thread;
|
||||
}
|
||||
const Channel& DramExtension::getChannel() const
|
||||
|
||||
Channel DramExtension::getChannel() const
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
const Bank& DramExtension::getBank() const
|
||||
|
||||
Bank DramExtension::getBank() const
|
||||
{
|
||||
return bank;
|
||||
}
|
||||
const BankGroup& DramExtension::getBankGroup() const
|
||||
|
||||
BankGroup DramExtension::getBankGroup() const
|
||||
{
|
||||
return bankgroup;
|
||||
}
|
||||
|
||||
const Row& DramExtension::getRow() const
|
||||
Row DramExtension::getRow() const
|
||||
{
|
||||
return row;
|
||||
}
|
||||
|
||||
const Column& DramExtension::getColumn() const
|
||||
Column DramExtension::getColumn() const
|
||||
{
|
||||
return column;
|
||||
}
|
||||
@@ -167,7 +87,7 @@ unsigned int DramExtension::getBurstlength() const
|
||||
return burstlength;
|
||||
}
|
||||
|
||||
void DramExtension::increaseRow()
|
||||
void DramExtension::incrementRow()
|
||||
{
|
||||
++row;
|
||||
}
|
||||
@@ -191,3 +111,112 @@ GenerationExtension& GenerationExtension::getExtension(const tlm::tlm_generic_pa
|
||||
sc_assert(result!=NULL);
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
//TODO remove this nonsense, put it in xml
|
||||
BankGroup Bank::getBankGroup()
|
||||
{
|
||||
static std::map<Bank, BankGroup> bankgroups;
|
||||
if (bankgroups.size() == 0)
|
||||
{
|
||||
core::Configuration& config = core::Configuration::getInstance();
|
||||
sc_assert(config.NumberOfBanks % config.NumberOfBankGroups == 0);
|
||||
|
||||
for (unsigned int bank = 0; bank < config.NumberOfBanks; bank++)
|
||||
{
|
||||
unsigned int group = bank % config.NumberOfBankGroups;
|
||||
bankgroups.insert(std::pair<Bank, BankGroup>(Bank(bank), BankGroup(group)));
|
||||
}
|
||||
}
|
||||
|
||||
return getElementFromMap(bankgroups, *this);
|
||||
}
|
||||
|
||||
|
||||
//THREAD
|
||||
bool operator ==(const Thread& lhs, const Thread& rhs)
|
||||
{
|
||||
return lhs.ID() == rhs.ID();
|
||||
}
|
||||
|
||||
bool operator !=(const Thread& lhs, const Thread& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
bool operator <(const Thread& lhs, const Thread& rhs)
|
||||
{
|
||||
return lhs.ID() < rhs.ID();
|
||||
}
|
||||
|
||||
//CHANNEL
|
||||
bool operator ==(const Channel& lhs, const Channel& rhs)
|
||||
{
|
||||
return lhs.ID() == rhs.ID();
|
||||
}
|
||||
|
||||
bool operator !=(const Channel& lhs, const Channel& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
|
||||
//BANKGROUP
|
||||
bool operator ==(const BankGroup& lhs, const BankGroup& rhs)
|
||||
{
|
||||
return lhs.ID() == rhs.ID();
|
||||
}
|
||||
|
||||
bool operator !=(const BankGroup& lhs, const BankGroup& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
//BANK
|
||||
bool operator ==(const Bank& lhs, const Bank& rhs)
|
||||
{
|
||||
return lhs.ID() == rhs.ID();
|
||||
}
|
||||
|
||||
bool operator !=(const Bank& lhs, const Bank& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
bool operator <(const Bank& lhs, const Bank& rhs)
|
||||
{
|
||||
return lhs.ID() < rhs.ID();
|
||||
}
|
||||
|
||||
//ROW
|
||||
const Row Row::NO_ROW;
|
||||
|
||||
bool operator ==(const Row& lhs, const Row& rhs)
|
||||
{
|
||||
if (lhs.isNoRow != rhs.isNoRow)
|
||||
return false;
|
||||
return lhs.ID() == rhs.ID();
|
||||
}
|
||||
|
||||
bool operator !=(const Row& lhs, const Row& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
const Row Row::operator ++()
|
||||
{
|
||||
id = (id + 1) % core::Configuration::getInstance().NumberOfRows;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//COLUMN
|
||||
bool operator ==(const Column& lhs, const Column& rhs)
|
||||
{
|
||||
return lhs.ID() == rhs.ID();
|
||||
}
|
||||
|
||||
bool operator !=(const Column& lhs, const Column& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <iostream>
|
||||
#include <systemc.h>
|
||||
|
||||
|
||||
class Thread
|
||||
{
|
||||
public:
|
||||
@@ -124,6 +125,59 @@ private:
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
|
||||
class DramExtension: public tlm::tlm_extension<DramExtension>
|
||||
{
|
||||
public:
|
||||
DramExtension();
|
||||
DramExtension(const Thread& thread, const Bank& bank, const BankGroup& bankgroup, const Row& row, const Column& column,
|
||||
unsigned int burstlength = 0);
|
||||
DramExtension(const Thread& thread, const Channel& channel, const Bank& bank, const BankGroup& bankgroup, const Row& row,
|
||||
const Column& column, unsigned int burstlength = 0);
|
||||
|
||||
virtual tlm_extension_base* clone() const;
|
||||
virtual void copy_from(const tlm_extension_base& ext);
|
||||
static DramExtension& getExtension(const tlm::tlm_generic_payload *payload);
|
||||
static DramExtension& getExtension(const tlm::tlm_generic_payload &payload);
|
||||
|
||||
Thread getThread() const;
|
||||
Channel getChannel() const;
|
||||
Bank getBank() const;
|
||||
BankGroup getBankGroup() const;
|
||||
Row getRow() const;
|
||||
Column getColumn() const;
|
||||
|
||||
unsigned int getBurstlength() const;
|
||||
void incrementRow();
|
||||
|
||||
private:
|
||||
Thread thread;
|
||||
Channel channel;
|
||||
Bank bank;
|
||||
BankGroup bankgroup;
|
||||
Row row;
|
||||
Column column;
|
||||
unsigned int burstlength;
|
||||
};
|
||||
|
||||
|
||||
// Used to indicate the time when a payload is created (in a traceplayer or in a core)
|
||||
// Note that this time can be different from the time the payload enters the DRAM system
|
||||
//(at that time the phase BEGIN_REQ is recorded), so timeOfGeneration =< time(BEGIN_REQ)
|
||||
class GenerationExtension : public tlm::tlm_extension<GenerationExtension>
|
||||
{
|
||||
public:
|
||||
GenerationExtension(sc_time timeOfGeneration) : timeOfGeneration(timeOfGeneration) {}
|
||||
virtual tlm_extension_base* clone() const;
|
||||
virtual void copy_from(const tlm_extension_base& ext);
|
||||
static GenerationExtension& getExtension(const tlm::tlm_generic_payload *payload);
|
||||
sc_time TimeOfGeneration() const {return timeOfGeneration;}
|
||||
|
||||
private:
|
||||
sc_time timeOfGeneration;
|
||||
};
|
||||
|
||||
|
||||
bool operator==(const Thread &lhs, const Thread &rhs);
|
||||
bool operator!=(const Thread &lhs, const Thread &rhs);
|
||||
bool operator<(const Thread &lhs, const Thread &rhs);
|
||||
@@ -144,73 +198,4 @@ bool operator!=(const Row &lhs, const Row &rhs);
|
||||
bool operator==(const Column &lhs, const Column &rhs);
|
||||
bool operator!=(const Column &lhs, const Column &rhs);
|
||||
|
||||
class DramExtension: public tlm::tlm_extension<DramExtension>
|
||||
{
|
||||
private:
|
||||
Thread thread;
|
||||
Channel channel;
|
||||
Bank bank;
|
||||
BankGroup bankgroup;
|
||||
Row row;
|
||||
Column column;
|
||||
unsigned int burstlength;
|
||||
public:
|
||||
|
||||
DramExtension() :
|
||||
thread(0), channel(0), bank(0), bankgroup(0), row(0), column(0), burstlength(0)
|
||||
{
|
||||
}
|
||||
DramExtension(const Thread& thread, const Bank& bank, const BankGroup& bankgroup, const Row& row, const Column& column,
|
||||
unsigned int burstlength = 0) :
|
||||
thread(thread), channel(0), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
|
||||
{
|
||||
}
|
||||
DramExtension(const Thread& thread, const Channel& channel, const Bank& bank, const BankGroup& bankgroup, const Row& row,
|
||||
const Column& column, unsigned int burstlength = 0) :
|
||||
thread(thread), channel(channel), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
|
||||
{
|
||||
}
|
||||
|
||||
~DramExtension()
|
||||
{
|
||||
}
|
||||
|
||||
virtual tlm_extension_base* clone() const;
|
||||
virtual void copy_from(const tlm_extension_base& ext);
|
||||
|
||||
const Thread& getThread() const;
|
||||
|
||||
const Channel& getChannel() const;
|
||||
|
||||
const Bank& getBank() const;
|
||||
|
||||
const BankGroup& getBankGroup() const;
|
||||
|
||||
const Row& getRow() const;
|
||||
|
||||
const Column& getColumn() const;
|
||||
|
||||
unsigned int getBurstlength() const;
|
||||
|
||||
void increaseRow();
|
||||
|
||||
static DramExtension& getExtension(const tlm::tlm_generic_payload *payload);
|
||||
static DramExtension& getExtension(const tlm::tlm_generic_payload &payload);
|
||||
};
|
||||
|
||||
|
||||
class GenerationExtension : public tlm::tlm_extension<GenerationExtension>
|
||||
{
|
||||
public:
|
||||
GenerationExtension(sc_time timeOfGeneration) : timeOfGeneration(timeOfGeneration) {}
|
||||
virtual tlm_extension_base* clone() const;
|
||||
virtual void copy_from(const tlm_extension_base& ext);
|
||||
static GenerationExtension& getExtension(const tlm::tlm_generic_payload *payload);
|
||||
|
||||
|
||||
sc_time TimeOfGeneration() const {return timeOfGeneration;}
|
||||
private:
|
||||
sc_time timeOfGeneration;
|
||||
};
|
||||
|
||||
#endif /* DRAMEXTENSION_H_ */
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "scheduler/Fifo.h"
|
||||
#include "scheduler/Fr_Fcfs.h"
|
||||
#include "scheduler/PARBS.h"
|
||||
#include "scheduler/readwritegrouper.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace tlm;
|
||||
@@ -54,6 +55,7 @@ public:
|
||||
iSocket.register_nb_transport_bw(this, &Controller<BUSWIDTH>::nb_transport_bw);
|
||||
tSocket.register_nb_transport_fw(this, &Controller<BUSWIDTH>::nb_transport_fw);
|
||||
}
|
||||
|
||||
~Controller()
|
||||
{
|
||||
delete controllerCore;
|
||||
@@ -118,8 +120,9 @@ void Controller<BUSWIDTH>::buildScheduler()
|
||||
if (selectedScheduler == "FR_FCFS")
|
||||
{
|
||||
|
||||
scheduler = new FR_FCFS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,
|
||||
Scheduler* s = new FR_FCFS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,
|
||||
Configuration::getInstance().AdaptiveOpenPagePolicy);
|
||||
scheduler = new ReadWriteGrouper(s);
|
||||
}
|
||||
else if (selectedScheduler == "PAR_BS")
|
||||
{
|
||||
@@ -222,7 +225,7 @@ void Controller<BUSWIDTH>::controllerCorePEQCallback(tlm_generic_payload &payloa
|
||||
{
|
||||
if (phase == REF_TRIGGER)
|
||||
{
|
||||
controllerCore->triggerRefresh(payload, sc_time_stamp());
|
||||
controllerCore->triggerRefresh(payload);
|
||||
}
|
||||
else if (phase == PDN_TRIGGER)
|
||||
{
|
||||
@@ -347,7 +350,7 @@ void Controller<BUSWIDTH>::scheduleNextPayload()
|
||||
if(payload != NULL)
|
||||
{
|
||||
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(payload).getBank(), sc_time_stamp());
|
||||
bool wasScheduledByCore = controllerCore->scheduleRequest(sc_time_stamp(), *payload);
|
||||
bool wasScheduledByCore = controllerCore->scheduleRequest(*payload);
|
||||
if (wasScheduledByCore)
|
||||
{
|
||||
scheduler->removePayload(payload);
|
||||
|
||||
@@ -91,8 +91,9 @@ void ControllerCore::resetState()
|
||||
state = savedState;
|
||||
}
|
||||
|
||||
void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload, sc_time time)
|
||||
void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload)
|
||||
{
|
||||
sc_time time = sc_time_stamp();
|
||||
Bank bank = DramExtension::getExtension(payload).getBank();
|
||||
|
||||
state.cleanUp(time);
|
||||
@@ -105,9 +106,9 @@ void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload, sc_time t
|
||||
}
|
||||
}
|
||||
|
||||
bool ControllerCore::scheduleRequest(sc_time start, tlm::tlm_generic_payload& payload)
|
||||
bool ControllerCore::scheduleRequest(tlm::tlm_generic_payload& payload)
|
||||
{
|
||||
start = clkAlign(start);
|
||||
sc_time start = clkAlign(sc_time_stamp());
|
||||
state.cleanUp(start);
|
||||
|
||||
saveState();
|
||||
@@ -127,8 +128,9 @@ bool ControllerCore::scheduleRequest(sc_time start, tlm::tlm_generic_payload& pa
|
||||
}
|
||||
}
|
||||
|
||||
bool ControllerCore::bankIsBusy(sc_time time, Bank bank)
|
||||
bool ControllerCore::bankIsBusy(Bank bank)
|
||||
{
|
||||
sc_time time = sc_time_stamp();
|
||||
ScheduledCommand lastScheduledCommand = state.getLastScheduledCommand(bank);
|
||||
|
||||
if (lastScheduledCommand.isNoCommand())
|
||||
@@ -173,12 +175,12 @@ const std::vector<Bank>& ControllerCore::getBanks()
|
||||
return banks;
|
||||
}
|
||||
|
||||
std::vector<Bank> ControllerCore::getFreeBanks(sc_time currentTime)
|
||||
std::vector<Bank> ControllerCore::getFreeBanks()
|
||||
{
|
||||
std::vector<Bank> freeBanks;
|
||||
for(Bank bank: getBanks())
|
||||
{
|
||||
if(!bankIsBusy(currentTime, bank))
|
||||
if(!bankIsBusy(bank))
|
||||
freeBanks.push_back(bank);
|
||||
}
|
||||
return freeBanks;
|
||||
|
||||
@@ -27,15 +27,11 @@ public:
|
||||
ControllerCore(IWrapperConnector& wrapper, std::map<Bank, int>& numberOfPayloads);
|
||||
virtual ~ControllerCore() ;
|
||||
|
||||
bool bankIsBusy(sc_time currentTime, Bank bank);
|
||||
bool scheduleRequest(sc_time currentTime, tlm::tlm_generic_payload& payload);
|
||||
void triggerRefresh(tlm::tlm_generic_payload& payload, sc_time time);
|
||||
|
||||
void saveState();
|
||||
void resetState();
|
||||
bool scheduleRequest(tlm::tlm_generic_payload& payload);
|
||||
void triggerRefresh(tlm::tlm_generic_payload& payload);
|
||||
|
||||
const std::vector<Bank>& getBanks();
|
||||
std::vector<Bank> getFreeBanks(sc_time currentTime);
|
||||
std::vector<Bank> getFreeBanks();
|
||||
const RowBufferState& getRowBufferStates(){return state.rowBufferStates;}
|
||||
|
||||
ICommandChecker& getCommandChecker(Command command);
|
||||
@@ -44,7 +40,6 @@ public:
|
||||
Configuration config;
|
||||
ControllerState state;
|
||||
IWrapperConnector& wrapper;
|
||||
|
||||
IPowerDownManager* powerDownManager;
|
||||
IRefreshManager* refreshManager;
|
||||
std::map<Bank,int>& numberOfPayloads;
|
||||
@@ -52,6 +47,9 @@ public:
|
||||
|
||||
private:
|
||||
void send(const CommandSchedule& schedule, tlm::tlm_generic_payload& payload) const;
|
||||
bool bankIsBusy(Bank bank);
|
||||
void saveState();
|
||||
void resetState();
|
||||
|
||||
std::map<Command, ICommandChecker*> commandChecker;
|
||||
ControllerState savedState;
|
||||
|
||||
@@ -55,7 +55,7 @@ void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time
|
||||
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
DramExtension::getExtension(refreshPayloads[bank]).increaseRow();
|
||||
DramExtension::getExtension(refreshPayloads[bank]).incrementRow();
|
||||
}
|
||||
|
||||
planNextRefresh();
|
||||
|
||||
@@ -61,7 +61,7 @@ void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload& payload,
|
||||
controller.state.change(nextRefresh);
|
||||
controller.wrapper.send(nextRefresh, refreshPayload);
|
||||
|
||||
extension.increaseRow();
|
||||
extension.incrementRow();
|
||||
planNextRefresh(extension.getBank());
|
||||
}
|
||||
|
||||
|
||||
@@ -90,8 +90,8 @@ bool ScheduledCommand::commandIsIn(const std::vector<Command>& commandSet) const
|
||||
|
||||
TimeInterval ScheduledCommand::getIntervalOnDataStrobe() const
|
||||
{
|
||||
sc_assert(
|
||||
getCommand() == Command::Read || getCommand() == Command::ReadA
|
||||
//only read and write commands have an assoicated time on the data strobe
|
||||
sc_assert(getCommand() == Command::Read || getCommand() == Command::ReadA
|
||||
|| getCommand() == Command::Write
|
||||
|| getCommand() == Command::WriteA);
|
||||
|
||||
@@ -99,7 +99,7 @@ TimeInterval ScheduledCommand::getIntervalOnDataStrobe() const
|
||||
|
||||
if (getCommand() == Command::Read || getCommand() == Command::ReadA)
|
||||
{
|
||||
return TimeInterval(getStart() + timings.tRL,getStart() + timings.tRL + getReadAccessTime());
|
||||
return TimeInterval(getStart() + timings.tRL, getStart() + timings.tRL + getReadAccessTime());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ void Fifo::schedule(gp* payload)
|
||||
|
||||
gp* Fifo::getNextPayload()
|
||||
{
|
||||
for(Bank bank: controllerCore.getFreeBanks(sc_time_stamp()))
|
||||
for(Bank bank: controllerCore.getFreeBanks())
|
||||
{
|
||||
if(!buffer[bank].empty())
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@ void FR_FCFS::schedule(std::vector<gp*> payloads)
|
||||
|
||||
gp* FR_FCFS::getNextPayload()
|
||||
{
|
||||
for(Bank bank: controllerCore.getFreeBanks(sc_time_stamp()))
|
||||
for(Bank bank: controllerCore.getFreeBanks())
|
||||
{
|
||||
if(!buffer[bank].empty())
|
||||
{
|
||||
|
||||
@@ -18,6 +18,7 @@ class PAR_BS : public Scheduler
|
||||
public:
|
||||
PAR_BS(core::ControllerCore& controllerCore, bool useExternalBankstates, unsigned int capsize);
|
||||
virtual ~PAR_BS();
|
||||
|
||||
virtual bool hasPayloads() override;
|
||||
virtual void schedule(gp* payload) override;
|
||||
virtual gp* getNextPayload() override;
|
||||
@@ -25,6 +26,7 @@ public:
|
||||
|
||||
private:
|
||||
void formBatch();
|
||||
|
||||
core::ControllerCore& controllerCore;
|
||||
bool useExternalBankstates;
|
||||
core::RowBufferState internalBankstates;
|
||||
|
||||
@@ -11,14 +11,8 @@ class Scheduler
|
||||
{
|
||||
public:
|
||||
virtual ~Scheduler(){}
|
||||
|
||||
virtual void schedule(gp* payload) = 0;
|
||||
|
||||
//TODO Rename to payload
|
||||
virtual bool hasPayloads() = 0;
|
||||
/*
|
||||
*Test
|
||||
*/
|
||||
virtual gp* getNextPayload() = 0;
|
||||
virtual void removePayload(gp* payload) = 0;
|
||||
static std::string sendername;
|
||||
|
||||
121
dram/src/controller/scheduler/readwritegrouper.cpp
Normal file
121
dram/src/controller/scheduler/readwritegrouper.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
#include "readwritegrouper.h"
|
||||
|
||||
namespace scheduler{
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
ReadWriteGrouper::ReadWriteGrouper(Scheduler *scheduler):
|
||||
scheduler(scheduler), mode(Mode::read)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ReadWriteGrouper::~ReadWriteGrouper()
|
||||
{
|
||||
delete scheduler;
|
||||
}
|
||||
|
||||
|
||||
void ReadWriteGrouper::removePayload(gp *payload)
|
||||
{
|
||||
scheduler->removePayload(payload);
|
||||
|
||||
//if scheduler is empty now
|
||||
if(!scheduler->hasPayloads())
|
||||
{
|
||||
if(mode == Mode::read && !writeQueue.empty())
|
||||
switchToWriteMode();
|
||||
else if(mode == Mode::readToWrite)
|
||||
switchToWriteMode();
|
||||
else
|
||||
switchToReadMode();
|
||||
}
|
||||
}
|
||||
|
||||
void ReadWriteGrouper::schedule(gp *payload)
|
||||
{
|
||||
tlm_command command = payload->get_command();
|
||||
|
||||
//in read mode hazards could occur by letting a read pass a queued write
|
||||
if(mode == Mode::read)
|
||||
{
|
||||
if(command == TLM_READ_COMMAND)
|
||||
{
|
||||
//if scheduling the read would cause a hazard switch to readToWriteMode and put the read into the readQueue
|
||||
if(schedulingReadCausesHazard(payload))
|
||||
{
|
||||
switchToReadToWriteMode();
|
||||
readQueue.push_back(payload);
|
||||
}
|
||||
else
|
||||
scheduler->schedule(payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
writeQueue.push_back(payload);
|
||||
if(!scheduler->hasPayloads())
|
||||
//there are no reads in the scheduler, so switch directly to write mode
|
||||
switchToWriteMode();
|
||||
}
|
||||
}
|
||||
else if(mode == Mode::readToWrite)
|
||||
{
|
||||
if(command == TLM_READ_COMMAND)
|
||||
readQueue.push_back(payload);
|
||||
else
|
||||
writeQueue.push_back(payload);
|
||||
}
|
||||
else if(mode == Mode::write)
|
||||
{
|
||||
if(command == TLM_READ_COMMAND)
|
||||
readQueue.push_back(payload);
|
||||
else
|
||||
scheduler->schedule(payload);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
gp *ReadWriteGrouper::getNextPayload()
|
||||
{
|
||||
return scheduler->getNextPayload();
|
||||
}
|
||||
|
||||
bool ReadWriteGrouper::hasPayloads()
|
||||
{
|
||||
return scheduler->hasPayloads();
|
||||
}
|
||||
|
||||
|
||||
bool ReadWriteGrouper::schedulingReadCausesHazard(gp *payload)
|
||||
{
|
||||
sc_assert(payload->is_read());
|
||||
for(gp* write: writeQueue)
|
||||
{
|
||||
if(payload->get_address()==write->get_address())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ReadWriteGrouper::switchToReadMode()
|
||||
{
|
||||
mode = Mode::read;
|
||||
for(gp* read: readQueue)
|
||||
scheduler->schedule(read);
|
||||
readQueue.clear();
|
||||
}
|
||||
|
||||
void ReadWriteGrouper::switchToWriteMode()
|
||||
{
|
||||
mode = Mode::write;
|
||||
for(gp* write: writeQueue)
|
||||
scheduler->schedule(write);
|
||||
writeQueue.clear();
|
||||
}
|
||||
|
||||
void ReadWriteGrouper::switchToReadToWriteMode()
|
||||
{
|
||||
mode = Mode::readToWrite;
|
||||
}
|
||||
|
||||
}
|
||||
40
dram/src/controller/scheduler/readwritegrouper.h
Normal file
40
dram/src/controller/scheduler/readwritegrouper.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef READWRITEGROUPER_H
|
||||
#define READWRITEGROUPER_H
|
||||
#include "Scheduler.h"
|
||||
#include <vector>
|
||||
|
||||
namespace scheduler{
|
||||
|
||||
/* Scheduler that batches reads and writes to reduce the overhead when switching from
|
||||
* read to write mode (read-to-write constraints)
|
||||
* The scheduler prioritizes reads. It switches to write mode, when stalling a write would induce a data-hazard
|
||||
* or when there are no reads to process.
|
||||
*/
|
||||
class ReadWriteGrouper : public Scheduler
|
||||
{
|
||||
public:
|
||||
ReadWriteGrouper(Scheduler *scheduler);
|
||||
~ReadWriteGrouper();
|
||||
virtual void schedule(gp* payload) override;
|
||||
virtual bool hasPayloads() override;
|
||||
virtual gp* getNextPayload() override;
|
||||
virtual void removePayload(gp* payload) override;
|
||||
|
||||
private:
|
||||
Scheduler *scheduler;
|
||||
std::vector<gp*> readQueue, writeQueue;
|
||||
//Mode readToWrite is used to process the remaining reads in the readScheduler before
|
||||
//switching to write mode (this is used when a potential hazard causes the scheduler to switch modes)
|
||||
enum class Mode{read,readToWrite, write};
|
||||
Mode mode;
|
||||
|
||||
bool schedulingReadCausesHazard(gp* payload);
|
||||
void switchToReadMode();
|
||||
void switchToWriteMode();
|
||||
void switchToReadToWriteMode();
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // READWRITEGROUPER_H
|
||||
@@ -32,29 +32,17 @@ struct TracePlayer: public sc_module
|
||||
public:
|
||||
tlm_utils::simple_initiator_socket<TracePlayer, BUSWIDTH, tlm::tlm_base_protocol_types> iSocket;
|
||||
TracePlayer(sc_module_name /*name*/, string pathToTrace, unsigned int burstLength,
|
||||
simulation::ISimulation* simulationManager) :
|
||||
payloadEventQueue(this, &TracePlayer::peqCallback), file(pathToTrace), burstlenght(burstLength), numberOfPendingTransactions(
|
||||
0), transactionsSent(0), transactionsReceived(0), simulationManager(
|
||||
simulationManager)
|
||||
{
|
||||
if (!file.is_open())
|
||||
SC_REPORT_FATAL(0, (string("Could not open trace ") + pathToTrace).c_str());
|
||||
simulation::ISimulation* simulationManager);
|
||||
|
||||
this->burstlenght = core::Configuration::getInstance().BurstLength;
|
||||
iSocket.register_nb_transport_bw(this, &TracePlayer::nb_transport_bw);
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
bool fileIsEmpty = file.peek() == std::ifstream::traits_type::eof();
|
||||
if (!fileIsEmpty)
|
||||
{
|
||||
scheduleNextPayload();
|
||||
}
|
||||
}
|
||||
void start();
|
||||
|
||||
private:
|
||||
void generateNextPayload();
|
||||
tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay);
|
||||
void peqCallback(tlm_generic_payload& payload, const tlm_phase& phase);
|
||||
void sendToTarget(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay);
|
||||
tlm_utils::peq_with_cb_and_phase<TracePlayer> payloadEventQueue;
|
||||
|
||||
MemoryManager memoryManager;
|
||||
ifstream file;
|
||||
unsigned int burstlenght;
|
||||
@@ -62,108 +50,135 @@ private:
|
||||
unsigned int transactionsSent;
|
||||
unsigned int transactionsReceived;
|
||||
simulation::ISimulation* simulationManager;
|
||||
};
|
||||
|
||||
void scheduleNextPayload()
|
||||
|
||||
template<unsigned int BUSWIDTH>
|
||||
TracePlayer<BUSWIDTH>::TracePlayer(sc_module_name, string pathToTrace, unsigned int burstLength, simulation::ISimulation *simulationManager) :
|
||||
payloadEventQueue(this, &TracePlayer<BUSWIDTH>::peqCallback), file(pathToTrace), burstlenght(burstLength),
|
||||
numberOfPendingTransactions(0), transactionsSent(0), transactionsReceived(0), simulationManager(simulationManager)
|
||||
{
|
||||
if (!file.is_open())
|
||||
SC_REPORT_FATAL(0, (string("Could not open trace ") + pathToTrace).c_str());
|
||||
|
||||
this->burstlenght = core::Configuration::getInstance().BurstLength;
|
||||
iSocket.register_nb_transport_bw(this, &TracePlayer<BUSWIDTH>::nb_transport_bw);
|
||||
}
|
||||
|
||||
template<unsigned int BUSWIDTH>
|
||||
void TracePlayer<BUSWIDTH>::start()
|
||||
{
|
||||
bool fileIsEmpty = file.peek() == std::ifstream::traits_type::eof();
|
||||
if (!fileIsEmpty)
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
string time, command, address;
|
||||
file >> time >> command >> address;
|
||||
|
||||
//if there is a newline at the end of the .stl
|
||||
if (time.empty() || command.empty() || address.empty())
|
||||
return;
|
||||
|
||||
long parsedAdress = std::stoi(address.c_str(), 0, 16);
|
||||
|
||||
gp* payload = memoryManager.allocate();
|
||||
payload->set_address(parsedAdress);
|
||||
|
||||
if (command == "read")
|
||||
{
|
||||
payload->set_command(TLM_READ_COMMAND);
|
||||
}
|
||||
else if (command == "write")
|
||||
{
|
||||
payload->set_command(TLM_WRITE_COMMAND);
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL(0,
|
||||
(string("Corrupted tracefile, command ") + command + string(" unknown")).c_str());
|
||||
}
|
||||
|
||||
payload->set_data_length(BUSWIDTH / 8);
|
||||
payload->set_response_status(TLM_INCOMPLETE_RESPONSE);
|
||||
payload->set_dmi_allowed(false);
|
||||
payload->set_byte_enable_length(0);
|
||||
payload->set_streaming_width(burstlenght);
|
||||
|
||||
sc_time sendingTime = sc_time(std::stoi(time.c_str()), SC_NS);
|
||||
GenerationExtension* genExtension = new GenerationExtension(sendingTime);
|
||||
payload->set_auto_extension(genExtension);
|
||||
|
||||
if (sendingTime <= sc_time_stamp())
|
||||
{
|
||||
payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
|
||||
}
|
||||
else
|
||||
{
|
||||
payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp());
|
||||
}
|
||||
numberOfPendingTransactions++;
|
||||
}
|
||||
generateNextPayload();
|
||||
}
|
||||
}
|
||||
|
||||
tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay)
|
||||
template<unsigned int BUSWIDTH>
|
||||
void TracePlayer<BUSWIDTH>::generateNextPayload()
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
payloadEventQueue.notify(payload, phase, bwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
string time, command, address;
|
||||
file >> time >> command >> address;
|
||||
|
||||
void peqCallback(tlm_generic_payload& payload, const tlm_phase& phase)
|
||||
{
|
||||
if (phase == BEGIN_REQ)
|
||||
//if there is a newline at the end of the .stl
|
||||
if (time.empty() || command.empty() || address.empty())
|
||||
return;
|
||||
|
||||
long parsedAdress = std::stoi(address.c_str(), 0, 16);
|
||||
|
||||
gp* payload = memoryManager.allocate();
|
||||
payload->set_address(parsedAdress);
|
||||
|
||||
if (command == "read")
|
||||
{
|
||||
payload.acquire();
|
||||
sendToTarget(payload, phase, SC_ZERO_TIME);
|
||||
|
||||
transactionsSent++;
|
||||
DebugManager::getInstance().printDebugMessage(name(),
|
||||
"Sending transaction number: " + std::to_string(transactionsSent));
|
||||
payload->set_command(TLM_READ_COMMAND);
|
||||
}
|
||||
else if (phase == END_REQ)
|
||||
{
|
||||
scheduleNextPayload();
|
||||
}
|
||||
else if (phase == BEGIN_RESP)
|
||||
{
|
||||
sendToTarget(payload, END_RESP, SC_ZERO_TIME);
|
||||
payload.release();
|
||||
|
||||
simulationManager->transactionFinished();
|
||||
numberOfPendingTransactions--;
|
||||
transactionsReceived++;
|
||||
|
||||
DebugManager::getInstance().printDebugMessage(name(),
|
||||
"Pending transactions in core: "
|
||||
+ std::to_string(transactionsSent - transactionsReceived));
|
||||
}
|
||||
else if (phase == END_RESP)
|
||||
else if (command == "write")
|
||||
{
|
||||
payload->set_command(TLM_WRITE_COMMAND);
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL(0, "TracePlayer PEQ was triggered with unknown phase");
|
||||
SC_REPORT_FATAL(0,
|
||||
(string("Corrupted tracefile, command ") + command + string(" unknown")).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void sendToTarget(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay)
|
||||
{
|
||||
tlm_phase TPhase = phase;
|
||||
sc_time TDelay = delay;
|
||||
iSocket->nb_transport_fw(payload, TPhase, TDelay);
|
||||
payload->set_data_length(BUSWIDTH / 8);
|
||||
payload->set_response_status(TLM_INCOMPLETE_RESPONSE);
|
||||
payload->set_dmi_allowed(false);
|
||||
payload->set_byte_enable_length(0);
|
||||
payload->set_streaming_width(burstlenght);
|
||||
|
||||
sc_time sendingTime = sc_time(std::stoi(time.c_str()), SC_NS);
|
||||
GenerationExtension* genExtension = new GenerationExtension(sendingTime);
|
||||
payload->set_auto_extension(genExtension);
|
||||
|
||||
if (sendingTime <= sc_time_stamp())
|
||||
{
|
||||
payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
|
||||
}
|
||||
else
|
||||
{
|
||||
payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp());
|
||||
}
|
||||
numberOfPendingTransactions++;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<unsigned int BUSWIDTH>
|
||||
tlm_sync_enum TracePlayer<BUSWIDTH>::nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay)
|
||||
{
|
||||
payloadEventQueue.notify(payload, phase, bwDelay);
|
||||
return TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
template<unsigned int BUSWIDTH>
|
||||
void TracePlayer<BUSWIDTH>::peqCallback(tlm_generic_payload &payload, const tlm_phase &phase)
|
||||
{
|
||||
if (phase == BEGIN_REQ)
|
||||
{
|
||||
payload.acquire();
|
||||
sendToTarget(payload, phase, SC_ZERO_TIME);
|
||||
|
||||
transactionsSent++;
|
||||
DebugManager::getInstance().printDebugMessage(name(),
|
||||
"Sending transaction number: " + std::to_string(transactionsSent));
|
||||
}
|
||||
else if (phase == END_REQ)
|
||||
{
|
||||
generateNextPayload();
|
||||
}
|
||||
else if (phase == BEGIN_RESP)
|
||||
{
|
||||
sendToTarget(payload, END_RESP, SC_ZERO_TIME);
|
||||
payload.release();
|
||||
|
||||
simulationManager->transactionFinished();
|
||||
numberOfPendingTransactions--;
|
||||
transactionsReceived++;
|
||||
|
||||
DebugManager::getInstance().printDebugMessage(name(),
|
||||
"Pending transactions in core: "
|
||||
+ std::to_string(transactionsSent - transactionsReceived));
|
||||
}
|
||||
else if (phase == END_RESP)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL(0, "TracePlayer PEQ was triggered with unknown phase");
|
||||
}
|
||||
}
|
||||
|
||||
template<unsigned int BUSWIDTH>
|
||||
void TracePlayer<BUSWIDTH>::sendToTarget(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay)
|
||||
{
|
||||
tlm_phase TPhase = phase;
|
||||
sc_time TDelay = delay;
|
||||
iSocket->nb_transport_fw(payload, TPhase, TDelay);
|
||||
}
|
||||
|
||||
#endif /* TRACEPLAYER_H_ */
|
||||
|
||||
Reference in New Issue
Block a user