minor refactoring

This commit is contained in:
robert
2014-07-06 10:34:46 +02:00
parent 8467945a3a
commit b8febb434f
21 changed files with 534 additions and 342 deletions

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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_ */

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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();

View File

@@ -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());
}

View File

@@ -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
{

View File

@@ -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())
{

View File

@@ -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())
{

View File

@@ -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;

View File

@@ -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;

View 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;
}
}

View 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

View File

@@ -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_ */