length on data strobe different for double data rate and single data rate
This commit is contained in:
@@ -49,7 +49,10 @@ CREATE TABLE Transactions(
|
||||
TBank INTEGER,
|
||||
TRow INTEGER,
|
||||
TColumn INTEGER,
|
||||
Command TEXT);
|
||||
Command TEXT,
|
||||
DataStrobeBegin INTEGER,
|
||||
DataStrobeEnd INTEGER
|
||||
);
|
||||
|
||||
CREATE INDEX ranges_index ON Transactions(Range);
|
||||
CREATE INDEX "phasesTransactions" ON "Phases" ("Transact" ASC);
|
||||
|
||||
@@ -35,7 +35,7 @@ def getTraceLength(connection):
|
||||
@metric
|
||||
def average_response_latency_in_ns(connection):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("""SELECT avg(ranges.end-ranges.begin) FROM transactions INNER JOIN ranges
|
||||
cursor.execute("""SELECT avg(ranges.end-ranges.begin)/1000 FROM transactions INNER JOIN ranges
|
||||
ON transactions.range = ranges.ID where TThread != 0""")
|
||||
|
||||
result = cursor.fetchone()
|
||||
@@ -44,7 +44,7 @@ def average_response_latency_in_ns(connection):
|
||||
@threadMetric
|
||||
def average_response_latency_in_ns(connection, thread):
|
||||
cursor = connection.cursor()
|
||||
query = """SELECT avg(ranges.end-ranges.begin) FROM transactions INNER JOIN ranges
|
||||
query = """SELECT avg(ranges.end-ranges.begin)/1000 FROM transactions INNER JOIN ranges
|
||||
ON transactions.range = ranges.ID where TThread = :Thread """
|
||||
|
||||
cursor.execute(query, {"Thread": thread})
|
||||
|
||||
@@ -89,9 +89,11 @@ void TlmRecorder::setUpTransactionTerminatingPhases()
|
||||
void TlmRecorder::prepareSqlStatements()
|
||||
{
|
||||
insertTransactionString =
|
||||
"INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:bank,:row,:column,:command)";
|
||||
"INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:bank,:row,:column,:command,:dataStrobeBegin,:dataStrobeEnd)";
|
||||
insertRangeString = "INSERT INTO Ranges VALUES (:id,:begin,:end)";
|
||||
updateRangeString = "UPDATE Ranges SET End = :end WHERE ID = :id";
|
||||
updateDataStrobeString = "UPDATE Transactions SET DataStrobeBegin = :begin, DataStrobeEnd = :end WHERE ID = :id";
|
||||
|
||||
insertPhaseString =
|
||||
"INSERT INTO Phases (PhaseName,PhaseBegin,PhaseEnd,Transact) VALUES (:name,:begin,:end,:transaction)";
|
||||
updatePhaseString =
|
||||
@@ -99,11 +101,13 @@ void TlmRecorder::prepareSqlStatements()
|
||||
insertGeneralInfoString =
|
||||
"INSERT INTO GeneralInfo (NumberOfTransactions,TraceEnd,NumberOfBanks,description,clk,UnitOfTime) Values (:numberOfTransactions,:end,:numberOfBanks,:description,:clk,:unitOfTime)";
|
||||
insertDebugMessageString = "INSERT INTO DebugMessages (Time,Message) Values (:time,:message)";
|
||||
|
||||
sqlite3_prepare(db, insertTransactionString.c_str(), -1, &insertTransactionStatement, 0);
|
||||
sqlite3_prepare(db, insertRangeString.c_str(), -1, &insertRangeStatement, 0);
|
||||
sqlite3_prepare(db, updateRangeString.c_str(), -1, &updateRangeStatement, 0);
|
||||
sqlite3_prepare(db, insertPhaseString.c_str(), -1, &insertPhaseStatement, 0);
|
||||
sqlite3_prepare(db, updatePhaseString.c_str(), -1, &updatePhaseStatement, 0);
|
||||
sqlite3_prepare(db, updateDataStrobeString.c_str(), -1, &updateDataStrobeStatement, 0);
|
||||
sqlite3_prepare(db, insertGeneralInfoString.c_str(), -1, &insertGeneralInfoStatement, 0);
|
||||
sqlite3_prepare(db, insertDebugMessageString.c_str(), -1, &insertDebugMessageStatement, 0);
|
||||
}
|
||||
@@ -150,6 +154,8 @@ void TlmRecorder::insertTransactionInDB(unsigned int id, tlm::tlm_generic_payloa
|
||||
sqlite3_bind_int(insertTransactionStatement, 7, extension.getBank().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 8, extension.getRow().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 9, extension.getColumn().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 10, 0);
|
||||
sqlite3_bind_int(insertTransactionStatement, 11, 0);
|
||||
|
||||
executeSqlStatement(insertTransactionStatement);
|
||||
}
|
||||
@@ -181,6 +187,15 @@ void TlmRecorder::updatePhaseEndInDB(string phaseName, const sc_time& time,
|
||||
executeSqlStatement(updatePhaseStatement);
|
||||
}
|
||||
|
||||
void TlmRecorder::updateDataStrobe(const sc_time& begin,const sc_time& end, tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
unsigned int id = getElementFromMap(currentTransactionsInSystem, &trans);
|
||||
sqlite3_bind_int64(updateDataStrobeStatement, 1, begin.value());
|
||||
sqlite3_bind_int64(updateDataStrobeStatement, 2, end.value());
|
||||
sqlite3_bind_int(updateDataStrobeStatement, 3, id);
|
||||
executeSqlStatement(updateDataStrobeStatement);
|
||||
}
|
||||
|
||||
void TlmRecorder::introduceNewTransactionToSystem(const sc_time& time,
|
||||
tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
@@ -242,8 +257,12 @@ string TlmRecorder::getFileContents(string filename)
|
||||
in.close();
|
||||
return (contents);
|
||||
}
|
||||
throw(errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
reportFatal("Error in TraceRecorder", "Could not load sql script from " + filename);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void TlmRecorder::printDebugMessage(std::string message)
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@ public:
|
||||
void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase, sc_time time);
|
||||
void recordPhase(tlm::tlm_generic_payload &trans, std::string name, sc_time begin, sc_time end);
|
||||
void recordDebugMessage(std::string message, sc_time time);
|
||||
void updateDataStrobe(const sc_time& begin, const sc_time& end, tlm::tlm_generic_payload& trans);
|
||||
void closeConnection();
|
||||
|
||||
private:
|
||||
@@ -61,8 +62,8 @@ private:
|
||||
std::vector<tlm::tlm_phase> transactionTerminatingPhases;
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *insertTransactionStatement, *insertRangeStatement, *updateRangeStatement,
|
||||
*insertPhaseStatement, *updatePhaseStatement, *insertGeneralInfoStatement, *insertDebugMessageStatement;
|
||||
*insertPhaseStatement, *updatePhaseStatement, *insertGeneralInfoStatement, *insertDebugMessageStatement, *updateDataStrobeStatement;
|
||||
std::string insertTransactionString, insertRangeString, updateRangeString, insertPhaseString, updatePhaseString, insertGeneralInfoString,
|
||||
insertDebugMessageString;
|
||||
insertDebugMessageString, updateDataStrobeString;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -24,9 +24,11 @@ namespace core {
|
||||
|
||||
std::string ControllerCore::senderName = "Controller Core";
|
||||
|
||||
ControllerCore::ControllerCore(IWrapperConnector& wrapperConnector, std::map<Bank, int>& numberOfPayloads) :
|
||||
config(Configuration::getInstance()), state(&config), wrapper(wrapperConnector), commandChecker(), numberOfPayloads(numberOfPayloads), savedState(
|
||||
&config), commandSequenceGenerator(state), commandSequenceScheduler(*this)
|
||||
ControllerCore::ControllerCore(IWrapperConnector& wrapperConnector,
|
||||
std::map<Bank, int>& numberOfPayloads) :
|
||||
config(Configuration::getInstance()), state(&config), wrapper(wrapperConnector), commandChecker(), numberOfPayloads(
|
||||
numberOfPayloads), savedState(&config), commandSequenceGenerator(state), commandSequenceScheduler(
|
||||
*this)
|
||||
|
||||
{
|
||||
commandChecker[Command::Activate] = new ActivateChecker(config, state);
|
||||
@@ -106,7 +108,7 @@ void ControllerCore::triggerWakeUp(tlm::tlm_generic_payload& payload, sc_time ti
|
||||
|
||||
bool ControllerCore::scheduleRequest(sc_time start, tlm::tlm_generic_payload& payload)
|
||||
{
|
||||
start = clkAlign(start, config.Timings.clk);
|
||||
start = clkAlign(start);
|
||||
state.cleanUp(start);
|
||||
|
||||
saveState();
|
||||
@@ -136,7 +138,7 @@ bool ControllerCore::isBusy(sc_time time, Bank bank)
|
||||
{
|
||||
return (time < lastScheduledCommand.getStart());
|
||||
}
|
||||
else if(lastScheduledCommand.commandIsIn({Command::WriteA, Command::ReadA}))
|
||||
else if (lastScheduledCommand.commandIsIn( { Command::WriteA, Command::ReadA }))
|
||||
{
|
||||
return (time < lastScheduledCommand.getEnd());
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ struct Configuration
|
||||
|
||||
static Configuration& getInstance();
|
||||
|
||||
string MemoryId;
|
||||
string MemoryType;
|
||||
std::string MemoryId;
|
||||
std::string MemoryType;
|
||||
|
||||
//MemSpecification
|
||||
unsigned int NumberOfBanks;
|
||||
@@ -42,7 +42,7 @@ struct Configuration
|
||||
bool AdaptiveOpenPagePolicy;
|
||||
bool RefreshAwareScheduling;
|
||||
unsigned int MaxNrOfTransactions;
|
||||
string Scheduler;
|
||||
std::string Scheduler;
|
||||
unsigned int Capsize;
|
||||
|
||||
private:
|
||||
|
||||
@@ -72,10 +72,11 @@ void MemSpecLoader::loadDDR4(Configuration& config, XMLElement* memspec)
|
||||
double clkMhz = queryDoubleParameter(timings, "clkMhz");
|
||||
sc_time clk = sc_time(1 / clkMhz, SC_US);
|
||||
config.Timings.clk = clk;
|
||||
//TODO
|
||||
|
||||
config.Timings.tRP = clk * queryUIntParameter(timings, "RP");
|
||||
config.Timings.tRAS = clk * queryUIntParameter(timings, "RAS");
|
||||
config.Timings.tRC = clk * queryUIntParameter(timings, "RC");
|
||||
config.Timings.tRTP = clk * queryUIntParameter(timings, "RTP");
|
||||
config.Timings.tRRD_S = clk * queryUIntParameter(timings, "RRD_S");
|
||||
config.Timings.tRRD_L = clk * queryUIntParameter(timings, "RRD_L");
|
||||
config.Timings.tCCD_S = clk * queryUIntParameter(timings, "CCD_S");
|
||||
@@ -135,6 +136,7 @@ void MemSpecLoader::loadWideIO(Configuration& config, XMLElement* memspec)
|
||||
config.Timings.tWR = clk * queryUIntParameter(timings, "WR");
|
||||
config.Timings.tWTR_S = clk * queryUIntParameter(timings, "WTR");
|
||||
config.Timings.tWTR_L = config.Timings.tWTR_S;
|
||||
config.Timings.tRTP = SC_ZERO_TIME; //TODO .. not defined in jedec. bl on datastrobe used
|
||||
config.Timings.tCKESR = clk * queryUIntParameter(timings, "CKESR");
|
||||
config.Timings.tCKE = clk * queryUIntParameter(timings, "CKE");
|
||||
config.Timings.tXP = clk * queryUIntParameter(timings, "XP");
|
||||
|
||||
@@ -32,6 +32,7 @@ struct TimingConfiguration
|
||||
sc_time tRC; //RAS-cycle-time (min time bw 2 succesive ACT to same bank)
|
||||
sc_time tCCD_S; //TODO: relevant? max(bl, tCCD)
|
||||
sc_time tCCD_L;
|
||||
sc_time tRTP; //Read to precharge
|
||||
sc_time tRRD_S; //min time bw 2 succesive ACT to different banks (different bank group)
|
||||
sc_time tRRD_L; //.. (same bank group)
|
||||
sc_time tRCD; //act -> read/write
|
||||
|
||||
@@ -207,7 +207,7 @@ Command PowerDownManager::getWakeUpCommand(PowerDownState state)
|
||||
|
||||
void PowerDownManager::sendPowerDownPayload(sc_time time, Bank bank, Command cmd)
|
||||
{
|
||||
time = clkAlign(time, controller.config.Timings.clk); //TODO is clkaligned already?
|
||||
time = clkAlign(time); //TODO is clkaligned already?
|
||||
|
||||
tlm_generic_payload& payload = getPayload(bank);
|
||||
ScheduledCommand pdn(cmd, time, controller.config.Timings.clk, DramExtension::getExtension(payload));
|
||||
|
||||
@@ -112,7 +112,7 @@ void PowerDownManagerGrouped::wakeUpAllForRefresh(sc_time time)
|
||||
|
||||
void PowerDownManagerGrouped::sendPowerDownPayload(sc_time time, Command cmd)
|
||||
{
|
||||
time = clkAlign(time, controller.config.Timings.clk);
|
||||
time = clkAlign(time);
|
||||
|
||||
//just to find slot
|
||||
tlm_generic_payload& payload = getPayload(Bank(0));
|
||||
|
||||
@@ -79,7 +79,7 @@ void RefreshManager::planNextRefresh()
|
||||
|
||||
void RefreshManager::reInitialize(tlm::tlm_generic_payload& payload, sc_time time)
|
||||
{
|
||||
nextPlannedRefresh = clkAlign(time, controller.config.Timings.clk, Alignment::DOWN);
|
||||
nextPlannedRefresh = clkAlign(time, Alignment::DOWN);
|
||||
planNextRefresh();
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ void RefreshManagerBankwise::RefreshManagerForBank::planNextRefresh()
|
||||
void RefreshManagerBankwise::RefreshManagerForBank::reInitialize(tlm::tlm_generic_payload& payload,
|
||||
sc_time time)
|
||||
{
|
||||
nextPlannedRefresh = clkAlign(time, controller.config.Timings.clk, Alignment::DOWN);
|
||||
nextPlannedRefresh = clkAlign(time, Alignment::DOWN);
|
||||
planNextRefresh();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "ScheduledCommand.h"
|
||||
#include "../utils/Utils.h"
|
||||
#include "../../common/Utils.h"
|
||||
#include "../configuration/Configuration.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -82,5 +83,33 @@ bool ScheduledCommand::commandIsIn(const std::vector<Command>& commandSet) const
|
||||
return isIn(command, commandSet);
|
||||
}
|
||||
|
||||
TimeInterval ScheduledCommand::getIntervalOnDataStrobe() const
|
||||
{
|
||||
sc_assert(
|
||||
getCommand() == Command::Read || getCommand() == Command::ReadA
|
||||
|| getCommand() == Command::Write
|
||||
|| getCommand() == Command::WriteA);
|
||||
|
||||
TimingConfiguration& timings = Configuration::getInstance().Timings;
|
||||
|
||||
sc_time burstLengthOnDataStrobe = getBurstLengthOnDataStrobe(getBurstLength());
|
||||
|
||||
if (getCommand() == Command::Read || getCommand() == Command::ReadA)
|
||||
{
|
||||
return TimeInterval(getStart() + timings.tRL,
|
||||
getStart() + timings.tRL + burstLengthOnDataStrobe);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TimeInterval(getStart() + timings.tWL - timings.clk / 2,
|
||||
getStart() + timings.tWL + burstLengthOnDataStrobe - timings.clk / 2);
|
||||
}
|
||||
}
|
||||
|
||||
bool ScheduledCommand::collidesOnDataStrobe(const ScheduledCommand& cmd) const
|
||||
{
|
||||
return cmd.getIntervalOnDataStrobe().intersects(getIntervalOnDataStrobe());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "../Command.h"
|
||||
#include "../../common/dramExtension.h"
|
||||
#include "../../common/TlmRecorder.h"
|
||||
#include "../utils/Utils.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -52,6 +53,9 @@ public:
|
||||
|
||||
bool commandIsIn(const std::vector<Command>& commandSet) const;
|
||||
|
||||
TimeInterval getIntervalOnDataStrobe() const;
|
||||
|
||||
bool collidesOnDataStrobe(const ScheduledCommand& command) const;
|
||||
|
||||
private:
|
||||
Command command;
|
||||
|
||||
@@ -23,7 +23,7 @@ void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand& command) cons
|
||||
if (lastCommand.getCommand() == Command::Read)
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getStart(),
|
||||
lastCommand.getBurstLength() * config.Timings.clk);
|
||||
max(config.Timings.tRTP , lastCommand.getIntervalOnDataStrobe().getLength()));
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::Write)
|
||||
{
|
||||
|
||||
@@ -23,7 +23,8 @@ void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
{
|
||||
command.delayToMeetConstraint(lastCommand.getEnd(), SC_ZERO_TIME);
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::Read || lastCommand.getCommand() == Command::Write)
|
||||
else if (lastCommand.getCommand() == Command::Read
|
||||
|| lastCommand.getCommand() == Command::Write)
|
||||
{
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::PDNAX)
|
||||
@@ -41,21 +42,6 @@ void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
}
|
||||
}
|
||||
|
||||
sc_time ReadChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
|
||||
Command command) const
|
||||
{
|
||||
assert(command == Command::Read || command == Command::ReadA);
|
||||
|
||||
if (command == Command::Read)
|
||||
{
|
||||
return config.Timings.tRL + config.Timings.clk * payload.get_streaming_width();
|
||||
}
|
||||
else
|
||||
{
|
||||
return config.Timings.clk * payload.get_streaming_width() + max(config.Timings.tRP,config.Timings.tRL);
|
||||
}
|
||||
}
|
||||
|
||||
bool ReadChecker::collidesOnDataStrobe(ScheduledCommand& read) const
|
||||
{
|
||||
for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands)
|
||||
@@ -67,18 +53,32 @@ bool ReadChecker::collidesOnDataStrobe(ScheduledCommand& read) const
|
||||
return false;
|
||||
}
|
||||
|
||||
sc_time ReadChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
|
||||
Command command) const
|
||||
{
|
||||
if (command == Command::Read)
|
||||
{
|
||||
return config.Timings.tRL + getBurstLengthOnDataStrobe(payload.get_streaming_width());
|
||||
}
|
||||
else
|
||||
{
|
||||
return getBurstLengthOnDataStrobe(payload.get_streaming_width()) + max(config.Timings.tRP, config.Timings.tRL);
|
||||
}
|
||||
}
|
||||
|
||||
bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read,
|
||||
ScheduledCommand& strobeCommand) const
|
||||
{
|
||||
//read to read
|
||||
if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA)
|
||||
{
|
||||
bool collision = getIntervalOnDataStrobe(read).intersects(getIntervalOnDataStrobe(strobeCommand));
|
||||
bool collision = read.collidesOnDataStrobe(strobeCommand);
|
||||
|
||||
sc_time tCCD =
|
||||
(getBankGroup(read.getBank()) == getBankGroup(strobeCommand.getBank())) ?
|
||||
config.Timings.tCCD_L : config.Timings.tCCD_S;
|
||||
bool casToCas = (getDistance(read.getStart(), strobeCommand.getStart()) < tCCD) ? true : false;
|
||||
bool casToCas =
|
||||
(getDistance(read.getStart(), strobeCommand.getStart()) < tCCD) ? true : false;
|
||||
|
||||
return collision || casToCas;
|
||||
}
|
||||
@@ -88,7 +88,7 @@ bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read,
|
||||
//read to write
|
||||
if (strobeCommand.getStart() >= read.getStart())
|
||||
{
|
||||
return !(strobeCommand.getStart() >= getIntervalOnDataStrobe(read).end);
|
||||
return strobeCommand.getStart() < read.getIntervalOnDataStrobe().end;
|
||||
}
|
||||
//write to read
|
||||
else
|
||||
@@ -97,7 +97,8 @@ bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read,
|
||||
(getBankGroup(read.getBank()) == getBankGroup(strobeCommand.getBank())) ?
|
||||
config.Timings.tWTR_L : config.Timings.tWTR_S;
|
||||
|
||||
return !(read.getStart()>= getIntervalOnDataStrobe(strobeCommand).end + tWTR);
|
||||
return read.getStart()
|
||||
< clkAlign(strobeCommand.getIntervalOnDataStrobe().end, Alignment::DOWN) + tWTR;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -22,6 +22,7 @@ public:
|
||||
|
||||
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
|
||||
virtual sc_time getExecutionTime(const tlm::tlm_generic_payload& payload, Command command) const override;
|
||||
|
||||
private:
|
||||
const Configuration& config;
|
||||
ControllerState& state;
|
||||
|
||||
@@ -47,13 +47,19 @@ sc_time WriteChecker::getExecutionTime(const tlm::tlm_generic_payload& payload,
|
||||
Command command) const
|
||||
{
|
||||
assert(command == Command::Write || command == Command::WriteA);
|
||||
|
||||
sc_time lengthOnDataStrobe = getBurstLengthOnDataStrobe(payload.get_streaming_width());
|
||||
if(Configuration::getInstance().DataRate == 1)
|
||||
lengthOnDataStrobe -= Configuration::getInstance().Timings.clk;
|
||||
|
||||
|
||||
if (command == Command::Write)
|
||||
{
|
||||
return config.Timings.tWL + config.Timings.clk * (payload.get_streaming_width() - 1);
|
||||
return config.Timings.tWL + lengthOnDataStrobe;
|
||||
}
|
||||
else
|
||||
{
|
||||
return config.Timings.tWL + config.Timings.clk * payload.get_streaming_width() + config.Timings.tWR;
|
||||
return config.Timings.tWL + lengthOnDataStrobe + config.Timings.tWR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +81,7 @@ bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write,
|
||||
if (strobeCommand.getCommand() == Command::Write
|
||||
|| strobeCommand.getCommand() == Command::WriteA)
|
||||
{
|
||||
bool collision = getIntervalOnDataStrobe(write).intersects(getIntervalOnDataStrobe(strobeCommand));
|
||||
bool collision = write.collidesOnDataStrobe(strobeCommand);
|
||||
|
||||
sc_time tCCD =
|
||||
(getBankGroup(write.getBank()) == getBankGroup(strobeCommand.getBank())) ?
|
||||
@@ -94,14 +100,13 @@ bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write,
|
||||
(getBankGroup(write.getBank()) == getBankGroup(strobeCommand.getBank())) ?
|
||||
config.Timings.tWTR_L : config.Timings.tWTR_S;
|
||||
|
||||
return !(strobeCommand.getStart()
|
||||
>= getIntervalOnDataStrobe(write).end + tWTR);
|
||||
return strobeCommand.getStart()
|
||||
< clkAlign(write.getIntervalOnDataStrobe().end, Alignment::DOWN) + tWTR;
|
||||
}
|
||||
|
||||
//read to write
|
||||
else
|
||||
{
|
||||
return !(write.getStart() >= getIntervalOnDataStrobe(strobeCommand).end);
|
||||
return write.getStart() < strobeCommand.getIntervalOnDataStrobe().end;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -34,39 +34,15 @@ sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constr
|
||||
return SC_ZERO_TIME;
|
||||
}
|
||||
|
||||
const sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment)
|
||||
const sc_time clkAlign(sc_time time, Alignment alignment)
|
||||
{
|
||||
sc_time clk = Configuration::getInstance().Timings.clk;
|
||||
if (alignment == UP)
|
||||
return ceil(time / clk) * clk;
|
||||
else
|
||||
return floor(time / clk) * clk;
|
||||
}
|
||||
|
||||
TimeInterval getIntervalOnDataStrobe(const ScheduledCommand& command)
|
||||
{
|
||||
sc_assert(
|
||||
command.getCommand() == Command::Read || command.getCommand() == Command::ReadA
|
||||
|| command.getCommand() == Command::Write
|
||||
|| command.getCommand() == Command::WriteA);
|
||||
|
||||
TimingConfiguration& timings = Configuration::getInstance().Timings;
|
||||
|
||||
sc_assert((command.getBurstLength() / Configuration::getInstance().DataRate) > 0);
|
||||
sc_time burstLength = timings.clk
|
||||
* (command.getBurstLength() / Configuration::getInstance().DataRate);
|
||||
|
||||
if (command.getCommand() == Command::Read || command.getCommand() == Command::ReadA)
|
||||
{
|
||||
return TimeInterval(command.getStart() + timings.tRL,
|
||||
command.getStart() + timings.tRL + burstLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TimeInterval(command.getStart() + timings.tWL,
|
||||
command.getStart() + timings.tWL + burstLength);
|
||||
}
|
||||
}
|
||||
|
||||
bool isClkAligned(sc_time time, sc_time clk)
|
||||
{
|
||||
return !((time / clk) - ceil(time / clk));
|
||||
@@ -99,3 +75,11 @@ BankGroup getBankGroup(Bank bank)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sc_time core::getBurstLengthOnDataStrobe(unsigned int burstlength)
|
||||
{
|
||||
Configuration& config = Configuration::getInstance();
|
||||
sc_assert((burstlength / config.DataRate) > 0);
|
||||
|
||||
return config.Timings.clk * (burstlength / config.DataRate);
|
||||
}
|
||||
|
||||
@@ -11,29 +11,30 @@
|
||||
#include <systemc.h>
|
||||
#include <tlm.h>
|
||||
#include "../../common/dramExtension.h"
|
||||
#include "../scheduling/ScheduledCommand.h"
|
||||
|
||||
namespace core
|
||||
{
|
||||
unsigned int getStartAddress(const Bank& bank);
|
||||
sc_time getDistance(sc_time a, sc_time b);
|
||||
|
||||
struct TimeInterval
|
||||
{
|
||||
sc_time start,end;
|
||||
TimeInterval() : start(SC_ZERO_TIME), end(SC_ZERO_TIME){}
|
||||
TimeInterval(sc_time start,sc_time end) : start(start), end(end){}
|
||||
|
||||
sc_time getLength() {return getDistance(start,end);}
|
||||
bool timeIsInInterval(sc_time time);
|
||||
bool intersects(TimeInterval other);
|
||||
};
|
||||
|
||||
sc_time getDistance(sc_time a, sc_time b);
|
||||
sc_time getBurstLengthOnDataStrobe(unsigned int burstlength);
|
||||
|
||||
struct TimingConfiguration;
|
||||
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint);
|
||||
TimeInterval getIntervalOnDataStrobe(const ScheduledCommand& command);
|
||||
|
||||
enum Alignment {UP, DOWN};
|
||||
const sc_time clkAlign(sc_time time, sc_time clk, Alignment alignment = UP);
|
||||
const sc_time clkAlign(sc_time time, Alignment alignment = UP);
|
||||
bool isClkAligned(sc_time time, sc_time clk);
|
||||
|
||||
BankGroup getBankGroup(Bank bank);
|
||||
|
||||
@@ -61,12 +61,14 @@ public:
|
||||
void buildScheduler()
|
||||
{
|
||||
string selectedScheduler = Configuration::getInstance().Scheduler;
|
||||
if(selectedScheduler == "FR_FCFS")
|
||||
scheduler = new FR_FCFS(*controller,Configuration::getInstance().RefreshAwareScheduling,Configuration::getInstance().AdaptiveOpenPagePolicy);
|
||||
else if(selectedScheduler == "FIFO")
|
||||
if (selectedScheduler == "FR_FCFS")
|
||||
scheduler = new FR_FCFS(*controller,
|
||||
Configuration::getInstance().RefreshAwareScheduling,
|
||||
Configuration::getInstance().AdaptiveOpenPagePolicy);
|
||||
else if (selectedScheduler == "FIFO")
|
||||
scheduler = new Fifo();
|
||||
else
|
||||
reportFatal(name(),"unsupporeted scheduler: " + selectedScheduler);
|
||||
reportFatal(name(), "unsupported scheduler: " + selectedScheduler);
|
||||
}
|
||||
|
||||
void terminateSimulation()
|
||||
@@ -81,57 +83,98 @@ public:
|
||||
{
|
||||
assert(command.getStart() >= sc_time_stamp());
|
||||
|
||||
TimeInterval dataStrobe;
|
||||
|
||||
TlmRecorder& rec = TlmRecorder::getInstance();
|
||||
switch (command.getCommand())
|
||||
{
|
||||
case Command::Read:
|
||||
rec.recordPhase(payload, BEGIN_RD, command.getStart());
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
rec.updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
rec.recordPhase(payload, END_RD, command.getEnd());
|
||||
|
||||
dramPEQ.notify(payload, BEGIN_RD, command.getStart() - sc_time_stamp());
|
||||
dramPEQ.notify(payload, END_RD, command.getEnd() - sc_time_stamp());
|
||||
break;
|
||||
case Command::ReadA:
|
||||
rec.recordPhase(payload, BEGIN_RDA, command.getStart());
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
rec.updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
rec.recordPhase(payload, END_RDA, command.getEnd());
|
||||
|
||||
dramPEQ.notify(payload, BEGIN_RDA, command.getStart() - sc_time_stamp());
|
||||
dramPEQ.notify(payload, END_RDA, command.getEnd() - sc_time_stamp());
|
||||
break;
|
||||
case Command::Write:
|
||||
rec.recordPhase(payload, BEGIN_WR, command.getStart());
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
rec.updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
rec.recordPhase(payload, END_WR, command.getEnd());
|
||||
|
||||
dramPEQ.notify(payload, BEGIN_WR, command.getStart() - sc_time_stamp());
|
||||
dramPEQ.notify(payload, END_WR, command.getEnd() - sc_time_stamp());
|
||||
break;
|
||||
case Command::WriteA:
|
||||
rec.recordPhase(payload, BEGIN_WRA, command.getStart());
|
||||
dataStrobe = command.getIntervalOnDataStrobe();
|
||||
rec.updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
|
||||
rec.recordPhase(payload, END_WRA, command.getEnd());
|
||||
|
||||
dramPEQ.notify(payload, BEGIN_WRA, command.getStart() - sc_time_stamp());
|
||||
dramPEQ.notify(payload, END_WRA, command.getEnd() - sc_time_stamp());
|
||||
break;
|
||||
case Command::AutoRefresh:
|
||||
rec.recordPhase(payload, BEGIN_AUTO_REFRESH, command.getStart());
|
||||
rec.recordPhase(payload, END_AUTO_REFRESH, command.getEnd());
|
||||
|
||||
dramPEQ.notify(payload, BEGIN_AUTO_REFRESH, command.getStart() - sc_time_stamp());
|
||||
dramPEQ.notify(payload, END_AUTO_REFRESH, command.getEnd() - sc_time_stamp());
|
||||
break;
|
||||
case Command::Activate:
|
||||
rec.recordPhase(payload, BEGIN_ACT, command.getStart());
|
||||
rec.recordPhase(payload, END_ACT, command.getEnd());
|
||||
|
||||
dramPEQ.notify(payload, BEGIN_ACT, command.getStart() - sc_time_stamp());
|
||||
dramPEQ.notify(payload, END_ACT, command.getEnd() - sc_time_stamp());
|
||||
break;
|
||||
case Command::Precharge:
|
||||
rec.recordPhase(payload, BEGIN_PRE, command.getStart());
|
||||
rec.recordPhase(payload, END_PRE, command.getEnd());
|
||||
|
||||
dramPEQ.notify(payload, BEGIN_PRE, command.getStart() - sc_time_stamp());
|
||||
dramPEQ.notify(payload, END_PRE, command.getEnd() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PrechargeAll:
|
||||
rec.recordPhase(payload, BEGIN_PRE_ALL, command.getStart());
|
||||
rec.recordPhase(payload, END_PRE_ALL, command.getEnd());
|
||||
|
||||
dramPEQ.notify(payload, BEGIN_PRE_ALL, command.getStart() - sc_time_stamp());
|
||||
dramPEQ.notify(payload, END_PRE_ALL, command.getEnd() - sc_time_stamp());
|
||||
break;
|
||||
case Command::PDNA:
|
||||
dramPEQ.notify(payload, BEGIN_PDNA, command.getStart() - sc_time_stamp());
|
||||
rec.recordPhase(payload, BEGIN_PDNA, command.getStart());
|
||||
break;
|
||||
case Command::PDNP:
|
||||
dramPEQ.notify(payload, BEGIN_PDNP, command.getStart() - sc_time_stamp());
|
||||
rec.recordPhase(payload, BEGIN_PDNP, command.getStart());
|
||||
break;
|
||||
case Command::SREF:
|
||||
dramPEQ.notify(payload, BEGIN_SREF, command.getStart() - sc_time_stamp());
|
||||
rec.recordPhase(payload, BEGIN_SREF, command.getStart());
|
||||
break;
|
||||
case Command::PDNAX:
|
||||
dramPEQ.notify(payload, END_PDNA, command.getStart() - sc_time_stamp());
|
||||
rec.recordPhase(payload, END_PDNA, command.getStart());
|
||||
break;
|
||||
case Command::PDNPX:
|
||||
dramPEQ.notify(payload, END_PDNP, command.getStart() - sc_time_stamp());
|
||||
rec.recordPhase(payload, END_PDNP, command.getStart());
|
||||
break;
|
||||
case Command::SREFX:
|
||||
dramPEQ.notify(payload, END_SREF, command.getStart() - sc_time_stamp());
|
||||
rec.recordPhase(payload, END_SREF, command.getStart());
|
||||
break;
|
||||
default:
|
||||
SC_REPORT_FATAL(0, "unsupported command in controller");
|
||||
@@ -195,7 +238,7 @@ private:
|
||||
|
||||
void scheduleNextPayload(Bank bank)
|
||||
{
|
||||
if(bank.ID() == 5)
|
||||
if (bank.ID() == 5)
|
||||
{
|
||||
int i = 5;
|
||||
++i;
|
||||
@@ -282,8 +325,6 @@ private:
|
||||
|
||||
void dramPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase)
|
||||
{
|
||||
TlmRecorder::getInstance().recordPhase(payload, phase, sc_time_stamp());
|
||||
|
||||
Bank bank = DramExtension::getExtension(payload).getBank();
|
||||
if (phase == BEGIN_RD || phase == BEGIN_WR)
|
||||
{
|
||||
@@ -303,7 +344,7 @@ private:
|
||||
payloadLeavesSystem(payload);
|
||||
scheduleNextPayload(bank);
|
||||
}
|
||||
else if (isIn(phase, { BEGIN_ACT, BEGIN_PRE, BEGIN_PRE_ALL, BEGIN_RDA,BEGIN_WRA }))
|
||||
else if (isIn(phase, { BEGIN_ACT, BEGIN_PRE, BEGIN_PRE_ALL, BEGIN_RDA, BEGIN_WRA }))
|
||||
{
|
||||
sendToDram(payload, phase, SC_ZERO_TIME);
|
||||
}
|
||||
|
||||
@@ -18,35 +18,38 @@ using namespace std;
|
||||
namespace simulation {
|
||||
|
||||
SimulationManager::SimulationManager(sc_module_name name, string memconfig, string memspec,
|
||||
string stl1, unsigned int burstlength1, string stl2,
|
||||
unsigned int burstlenght2, string traceName, string pathToResources,
|
||||
bool silent) :
|
||||
dram("dram"), arbiter("arbiter"), controller("controller"), player1("player1",
|
||||
pathToResources + string("traces/") + stl1,burstlength1, this), player2("player2",
|
||||
pathToResources + string("traces/") + stl2,burstlenght2, this), traceName(traceName)
|
||||
string stl1, unsigned int burstlength1, string stl2, unsigned int burstlenght2,
|
||||
string traceName, string pathToResources, bool silent) :
|
||||
traceName(traceName)
|
||||
|
||||
{
|
||||
SC_THREAD(terminationThread);
|
||||
|
||||
cout << pathToResources + string("configs/memconfigs/") + memconfig << endl;
|
||||
cout << pathToResources + string("configs/memspecs/") + memspec << endl;
|
||||
|
||||
|
||||
xmlAddressDecoder::addressConfigURI = pathToResources + string("configs/addressConfig.xml");
|
||||
TlmRecorder::dbName = traceName;
|
||||
TlmRecorder::sqlScriptURI = pathToResources + string("scripts/createTraceDB.sql");
|
||||
Configuration::memconfigUri = pathToResources + string("configs/memconfigs/") + memconfig;
|
||||
Configuration::memspecUri = pathToResources + string("configs/memspecs/") + memspec;
|
||||
|
||||
player1.iSocket.bind(arbiter.tSockets[0]);
|
||||
player2.iSocket.bind(arbiter.tSockets[1]);
|
||||
arbiter.iSocket.bind(controller.tSocket);
|
||||
controller.iSocket.bind(dram.tSocket);
|
||||
dram = new Dram<>("dram");
|
||||
arbiter = new Arbiter<numberOfTracePlayers,128>("arbiter");
|
||||
controller = new Controller<>("controller");
|
||||
player1 = new TracePlayer<>("player1", pathToResources + string("traces/") + stl1, burstlength1,
|
||||
this);
|
||||
player2 = new TracePlayer<>("player2", pathToResources + string("traces/") + stl2, burstlenght2,
|
||||
this);
|
||||
|
||||
player1->iSocket.bind(arbiter->tSockets[0]);
|
||||
player2->iSocket.bind(arbiter->tSockets[1]);
|
||||
arbiter->iSocket.bind(controller->tSocket);
|
||||
controller->iSocket.bind(dram->tSocket);
|
||||
|
||||
vector<string> whiteList;
|
||||
if(!silent)
|
||||
if (!silent)
|
||||
{
|
||||
whiteList.push_back(controller.name());
|
||||
whiteList.push_back(player2.name());
|
||||
whiteList.push_back(player1.name());
|
||||
whiteList.push_back(controller->name());
|
||||
whiteList.push_back(player2->name());
|
||||
whiteList.push_back(player1->name());
|
||||
whiteList.push_back(this->name());
|
||||
whiteList.push_back(TlmRecorder::senderName);
|
||||
whiteList.push_back(ControllerCore::senderName);
|
||||
@@ -55,14 +58,24 @@ SimulationManager::SimulationManager(sc_module_name name, string memconfig, stri
|
||||
DebugManager::getInstance().addToWhiteList(whiteList);
|
||||
}
|
||||
|
||||
SimulationManager::~SimulationManager()
|
||||
{
|
||||
delete dram;
|
||||
delete arbiter;
|
||||
delete controller;
|
||||
delete player1;
|
||||
delete player2;
|
||||
}
|
||||
|
||||
|
||||
void SimulationManager::startSimulation()
|
||||
{
|
||||
|
||||
clock_t begin = clock();
|
||||
|
||||
DebugManager::getInstance().printDebugMessage(name(), "Starting simulation");
|
||||
player1.start();
|
||||
player2.start();
|
||||
player1->start();
|
||||
player2->start();
|
||||
sc_start();
|
||||
|
||||
clock_t end = clock();
|
||||
@@ -87,13 +100,11 @@ void SimulationManager::terminationThread()
|
||||
{
|
||||
wait(terminateSimulation);
|
||||
DebugManager::getInstance().printDebugMessage(this->name(), "Terminating simulation");
|
||||
controller.terminateSimulation();
|
||||
controller->terminateSimulation();
|
||||
//waits for the termination of all pending powerdown phases in the dram system
|
||||
wait(sc_time(50, SC_NS));
|
||||
TlmRecorder::getInstance().closeConnection();
|
||||
sc_stop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} /* namespace simulation */
|
||||
|
||||
@@ -26,6 +26,7 @@ public:
|
||||
std::string stl1, unsigned int burstlength1, std::string stl2,
|
||||
unsigned int burstlenght2, std::string traceName, std::string pathToResources,
|
||||
bool silent = false);
|
||||
~SimulationManager();
|
||||
void startSimulation();
|
||||
void tracePlayerFinishedCallback(string name) override;
|
||||
|
||||
@@ -34,11 +35,11 @@ private:
|
||||
sc_event terminateSimulation;
|
||||
constexpr static unsigned int numberOfTracePlayers = 2;
|
||||
std::string traceName;
|
||||
Dram<> dram;
|
||||
Arbiter<numberOfTracePlayers, 128> arbiter;
|
||||
Controller<> controller;
|
||||
TracePlayer<> player1;
|
||||
TracePlayer<> player2;
|
||||
Dram<> *dram;
|
||||
Arbiter<numberOfTracePlayers, 128> *arbiter;
|
||||
Controller<> *controller;
|
||||
TracePlayer<> *player1;
|
||||
TracePlayer<> *player2;
|
||||
};
|
||||
|
||||
} /* namespace simulation */
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "SimulationManager.h"
|
||||
#include "../core/configuration/Configuration.h"
|
||||
|
||||
#include <systemc.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace simulation;
|
||||
|
||||
@@ -32,21 +34,15 @@ int sc_main(int argc, char **argv)
|
||||
string resources = pathOfFile(argv[0]) + string("/../resources/");
|
||||
|
||||
string memconfig = "memconfig.xml";
|
||||
string memspec = "MatzesWideIO.xml";
|
||||
string memspec = "MICRON_4Gb_DDR4-1866_8bit_A.xml";
|
||||
// string memspec = "MatzesWideIO.xml";
|
||||
string stl1 = "chstone-sha_32.stl";
|
||||
stl1 = "empty.stl";
|
||||
unsigned int burstlength1 = 8;
|
||||
unsigned int burstlength1 = 4;
|
||||
string stl2 = "mediabench-h263decode_32.stl";
|
||||
stl2 = "trace.stl";
|
||||
unsigned int burstlength2 = 8;
|
||||
string traceName = "unaware_long.tdb";
|
||||
|
||||
Configuration::memspecUri = "/home/jonny/git/dram/dram/resources/configs/memspecs/MatzesWideIO.xml";
|
||||
Configuration::memspecUri = "/home/jonny/git/dram/dram/resources/configs/memspecs/MICRON_4Gb_DDR4-1866_8bit_A.xml";
|
||||
Configuration::memconfigUri = "/home/jonny/git/dram/dram/resources/configs/memconfigs/memconfig.xml";
|
||||
|
||||
// Configuration::memconfigUri = resources + string("configs/memconfigs/") + memconfig;
|
||||
// Configuration::memconfigUri = resources + string("configs/memspecs/") + memspec;
|
||||
// stl2 = "trace.stl";
|
||||
unsigned int burstlength2 = 4;
|
||||
string traceName = "tpr.tdb";
|
||||
|
||||
SimulationManager simulationManager("sim",memconfig,memspec,stl1,burstlength1, stl2,burstlength2, traceName, resources,false);
|
||||
simulationManager.startSimulation();
|
||||
|
||||
Reference in New Issue
Block a user