corrected checkers for non-interleaving reads/writes. Added burst length to db. Added burst functionally to players
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-2055719358" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} -E -P -v -dD "${INPUTS}" -std=c++11">
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-64906255729110141" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} -E -P -v -dD "${INPUTS}" -std=c++11">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
|
||||
@@ -43,6 +43,7 @@ CREATE TABLE Transactions(
|
||||
ID INTEGER PRIMARY KEY,
|
||||
Range INTEGER,
|
||||
Address INTEGER,
|
||||
Burstlength INTEGER,
|
||||
TThread INTEGER,
|
||||
TChannel INTEGER,
|
||||
TBank INTEGER,
|
||||
|
||||
@@ -26,6 +26,11 @@ def getNumberOfBanks(connection):
|
||||
result = cursor.fetchone()
|
||||
return result[0]
|
||||
|
||||
def getTraceLength(connection):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("SELECT TraceEnd FROM GeneralInfo")
|
||||
result = cursor.fetchone()
|
||||
return result[0]
|
||||
|
||||
@metric
|
||||
def average_response_latency_in_ns(connection):
|
||||
@@ -60,6 +65,46 @@ def number_of_precharges(connection):
|
||||
result = cursor.fetchone()
|
||||
return result[0]
|
||||
|
||||
|
||||
def timeInPowerStates(connection):
|
||||
totalTimeAllBanks = getTraceLength(connection)*getNumberOfBanks(connection)
|
||||
cursor = connection.cursor()
|
||||
result = []
|
||||
|
||||
cursor.execute("SELECT SUM(PhaseEnd-PhaseBegin) from Phases where PhaseName = 'PDNA'")
|
||||
timeInPDNA = cursor.fetchone()
|
||||
if(timeInPDNA != None):
|
||||
totalTimeInPDNA = timeInPDNA[0]
|
||||
else:
|
||||
totalTimeInPDNA = 0
|
||||
fractionInPDNA = totalTimeInPDNA*1.0/totalTimeAllBanks
|
||||
result.append(("Time in PDNA (%)", fractionInPDNA*100))
|
||||
print("{0} {1}".format(result[-1][0],result[-1][1]))
|
||||
|
||||
cursor.execute("SELECT SUM(PhaseEnd-PhaseBegin) from Phases where PhaseName = 'PDNP'")
|
||||
timeInPDNP = cursor.fetchone()
|
||||
if(timeInPDNP != None):
|
||||
totalTimeInPDNP = timeInPDNP[0]
|
||||
else:
|
||||
totalTimeInPDNP = 0
|
||||
fractionInPDNP = totalTimeInPDNP*1.0/totalTimeAllBanks
|
||||
result.append(("Time in PDNP (%)", fractionInPDNP*100))
|
||||
print("{0} {1}".format(result[-1][0],result[-1][1]))
|
||||
|
||||
cursor.execute("SELECT SUM(PhaseEnd-PhaseBegin) from Phases where PhaseName = 'SREF'")
|
||||
timeInSREF = cursor.fetchone()
|
||||
if(timeInSREF != None):
|
||||
totalTimeInSREF = timeInSREF[0]
|
||||
else:
|
||||
totalTimeInSREF = 0
|
||||
fractionInSREF = totalTimeInSREF*1.0/totalTimeAllBanks
|
||||
result.append(("Time in SREF (%)", fractionInSREF*100))
|
||||
print("{0} {1}".format(result[-1][0],result[-1][1]))
|
||||
result.insert(0,("Active time (%)", 1-fractionInPDNA-fractionInPDNP-fractionInSREF))
|
||||
print("{0} {1}".format(result[0][0],result[0][1]))
|
||||
|
||||
return result
|
||||
|
||||
def passRatio(connection):
|
||||
|
||||
numberOfPassWins = {}
|
||||
@@ -95,9 +140,14 @@ def passRatio(connection):
|
||||
|
||||
result = []
|
||||
for thread in getThreads(connection):
|
||||
print("Thread {0} passed other threads {1} times and was passed {2} times. Ratio is {3}".format
|
||||
(thread, numberOfPassWins[thread], numberOfPassLosses[thread], numberOfPassWins[thread]*1.0/(numberOfPassWins[thread]+numberOfPassLosses[thread])))
|
||||
result.append(("Thread {0} pass ratio".format(thread), numberOfPassWins[thread]*1.0/(numberOfPassWins[thread]+numberOfPassLosses[thread])))
|
||||
totalPassedInvolved = numberOfPassWins[thread]+numberOfPassLosses[thread]
|
||||
if(totalPassedInvolved > 0):
|
||||
passRatio = numberOfPassWins[thread]*1.0/(numberOfPassWins[thread]+numberOfPassLosses[thread])
|
||||
else:
|
||||
passRatio = 0.5
|
||||
print("Thread {0} passed other threads {1} times and was passed {2} times. Pass ratio is {3}".format
|
||||
(thread, numberOfPassWins[thread], numberOfPassLosses[thread],passRatio))
|
||||
result.append(("Thread {0} pass ratio".format(thread), passRatio))
|
||||
return result
|
||||
|
||||
|
||||
@@ -122,7 +172,7 @@ def calculateMetrics(pathToTrace):
|
||||
calculatedMetrics.append(res)
|
||||
|
||||
calculatedMetrics.extend(passRatio(connection))
|
||||
|
||||
calculatedMetrics.extend(timeInPowerStates(connection))
|
||||
|
||||
connection.close()
|
||||
return calculatedMetrics
|
||||
|
||||
@@ -7,10 +7,11 @@ class DramConfig(object):
|
||||
|
||||
unitOfTime = "ns"
|
||||
nActivateWindow = 0
|
||||
burstLengtht = 2
|
||||
clk = numberOfBanks = 0
|
||||
tRP = tRAS = tRC = tRRD = tRCD = tTAW = tRL = tWL = tWTR = tRFC = tWR = 0
|
||||
tReadLength = tWriteLength = 0
|
||||
bankwiseRefresh = False
|
||||
bankwisePowerdown = False
|
||||
|
||||
def clkAlign(self, value):
|
||||
return math.ceil(1.0*value/self.clk)*self.clk
|
||||
@@ -32,15 +33,21 @@ class DramConfig(object):
|
||||
self.tWR = 2*self.clk
|
||||
self.tTAW = self.clkAlign(50)
|
||||
self.tRFC = self.clkAlign(130)
|
||||
|
||||
self.tReadLength = self.tRL + self.burstLength * self.clk
|
||||
self.tWriteLength = self.tWL + (self.burstLength - 1) *self.clk
|
||||
self.tCKESR = self.clkAlign(max(3*self.clk, 15))
|
||||
|
||||
def __init__(self):
|
||||
self.parseFromXml()
|
||||
|
||||
dramconfig = DramConfig()
|
||||
|
||||
|
||||
def calculateReadLength(burstLength):
|
||||
return dramconfig.tRL + burstLength * dramconfig.clk
|
||||
|
||||
def calculateWriteLength(burstLength):
|
||||
return dramconfig.tWL + burstLength * dramconfig.clk
|
||||
|
||||
|
||||
# ----------- test utils ---------------------------------------
|
||||
|
||||
|
||||
@@ -88,11 +95,23 @@ def commands_are_clockaligned(connection):
|
||||
def commandbus_slots_are_used_once(connection):
|
||||
"""Checks that no two phases on the command bus start at the same time"""
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("SELECT PhaseBegin,count FROM (SELECT phaseBegin,count(phasebegin) AS count FROM Phases WHERE PhaseName NOT IN ('RESP','REQ') GROUP BY phaseBegin) WHERE count>1")
|
||||
result = cursor.fetchone()
|
||||
|
||||
|
||||
if dramconfig.bankwisePowerdown and dramconfig.bankwiseRefresh:
|
||||
excludedPhases = "('REQ','RESP','PRE_ALL')"
|
||||
elif (not dramconfig.bankwisePowerdown and dramconfig.bankwiseRefresh):
|
||||
excludedPhases = "('REQ','RESP','PRE_ALL','PDNA','PDNP','SREF')"
|
||||
elif dramconfig.bankwisePowerdown and not dramconfig.bankwiseRefresh:
|
||||
excludedPhases = "('REQ','RESP','PRE_ALL','AUTO_REFRESH')"
|
||||
else:
|
||||
excludedPhases = "('REQ','RESP','PRE_ALL','PDNA','PDNP','SREF','AUTO_REFRESH')"
|
||||
|
||||
query = """SELECT PhaseBegin,count FROM (SELECT phaseBegin,count(phasebegin) AS count
|
||||
FROM Phases WHERE PhaseName NOT IN """ + excludedPhases + """ AND phasebegin>0 GROUP BY phaseBegin) WHERE count>1"""
|
||||
cursor.execute(query)
|
||||
result = cursor.fetchone()
|
||||
if(result != None):
|
||||
return TestFailed("Slot on commandbus at time {0} is used twice".format(formatTime(result[0])))
|
||||
return TestFailed("Slot on commandbus at time {0} is used multiple times".format(formatTime(result[0])))
|
||||
|
||||
return TestSuceeded()
|
||||
|
||||
@@ -171,29 +190,23 @@ def phases_on_bank_are_sequential(connection):
|
||||
|
||||
@test
|
||||
def phase_lengths_are_correct(connection):
|
||||
query = """SELECT ID,PhaseEnd-PhaseBegin FROM Phases WHERE PhaseName = :command and (PhaseEnd-PhaseBegin)!= :length"""
|
||||
commandLengths = [('RD', dramconfig.tReadLength),
|
||||
('RDA', dramconfig.tReadLength + dramconfig.tRP),
|
||||
('WR', dramconfig.tWriteLength),
|
||||
('WRA', dramconfig.tWriteLength + dramconfig.tRP),
|
||||
('PRE', dramconfig.tRP),
|
||||
('ACT', dramconfig.tRCD),
|
||||
('AUTO_REFRESH', dramconfig.tRFC)]
|
||||
|
||||
for commandLength in commandLengths:
|
||||
command = commandLength[0]
|
||||
length = commandLength[1]
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(query, {"command":command, "length" : length})
|
||||
result = cursor.fetchone()
|
||||
if(result != None):
|
||||
return TestFailed("Phase with ID {0}({1}) has invalid length {2}".format(result[0],command,formatTime(result[1])))
|
||||
|
||||
query = """SELECT phases.ID,PhaseName, PhaseEnd-PhaseBegin,Burstlength FROM Phases INNER JOIN transactions ON transactions.ID = phases.transact """
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(query)
|
||||
|
||||
for currentRow in cursor:
|
||||
command = currentRow[1]
|
||||
commandLength = currentRow[2]
|
||||
burstlength = currentRow[3]
|
||||
if(command == "RD" and commandLength != calculateReadLength(burstlength) or
|
||||
command == "WR" and commandLength != calculateWriteLength(burstLength) or
|
||||
command == "RDA" and commandLength != calculateReadLength(burstlength)+dramconfig.tRP or
|
||||
command == "WRA" and commandLength != calculateReadLength(burstlength)+dramconfig.tRP or
|
||||
(command == "PRE" or command=="PRE_ALL") and commandLength != dramconfig.tRP or
|
||||
command == "AUTO_REFRESH" and commandLength != dramconfig.tRFC):
|
||||
return TestFailed("Phase with ID {0}({1}) has invalid length of {2}".format(currentRow[0],command,formatTime(commandLength)))
|
||||
return TestSuceeded()
|
||||
|
||||
|
||||
|
||||
|
||||
#----------- activate checks ---------------------------------------
|
||||
|
||||
@test
|
||||
@@ -325,6 +338,16 @@ def write_or_read_to_precharge(connection):
|
||||
lastRow = currentRow
|
||||
return TestSuceeded()
|
||||
|
||||
|
||||
@test
|
||||
def sref_active_for_minimal_time(connection):
|
||||
"""Checks if SREF is active for at least a minimal time (JEDEC 229, P. 41)"""
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("SELECT ID, PhaseEnd-PhaseBegin FROM Phases WHERE PhaseName = 'SREF'")
|
||||
for currentRow in cursor:
|
||||
if(currentRow[1] < dramconfig.tCKESR):
|
||||
return TestFailed("SREF with ID {0} is {1} long. Minimal time in SREF is {2}".format(currentRow[0], formatTime(currentRow[1]), dramconfig.tCKESR))
|
||||
return TestSuceeded()
|
||||
# -------------------------- interface methods --------------------
|
||||
|
||||
def runTests(pathToTrace):
|
||||
|
||||
@@ -88,7 +88,7 @@ void TlmRecorder::setUpTransactionTerminatingPhases()
|
||||
void TlmRecorder::prepareSqlStatements()
|
||||
{
|
||||
insertTransactionString =
|
||||
"INSERT INTO Transactions VALUES (:id,:rangeID,:address,:thread,:channel,:bank,:row,:column,:command)";
|
||||
"INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:bank,:row,:column,:command)";
|
||||
insertRangeString = "INSERT INTO Ranges VALUES (:id,:begin,:end)";
|
||||
updateRangeString = "UPDATE Ranges SET End = :end WHERE ID = :id";
|
||||
insertPhaseString =
|
||||
@@ -139,15 +139,16 @@ void TlmRecorder::insertTransactionInDB(unsigned int id, tlm::tlm_generic_payloa
|
||||
sqlite3_bind_int(insertTransactionStatement, 1, id);
|
||||
sqlite3_bind_int(insertTransactionStatement, 2, id);
|
||||
sqlite3_bind_int(insertTransactionStatement, 3, trans.get_address());
|
||||
sqlite3_bind_text(insertTransactionStatement, 9,
|
||||
sqlite3_bind_int(insertTransactionStatement, 4, trans.get_streaming_width());
|
||||
sqlite3_bind_text(insertTransactionStatement, 10,
|
||||
trans.get_command() == tlm::TLM_READ_COMMAND ? "R" : "W", 1, 0);
|
||||
|
||||
const DramExtension& extension = DramExtension::getExtension(trans);
|
||||
sqlite3_bind_int(insertTransactionStatement, 4, extension.getThread().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 5, extension.getChannel().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 6, extension.getBank().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 7, extension.getRow().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 8, extension.getColumn().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 5, extension.getThread().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 6, extension.getChannel().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 7, extension.getBank().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 8, extension.getRow().ID());
|
||||
sqlite3_bind_int(insertTransactionStatement, 9, extension.getColumn().ID());
|
||||
|
||||
executeSqlStatement(insertTransactionStatement);
|
||||
}
|
||||
@@ -258,3 +259,4 @@ void TlmRecorder::closeConnection()
|
||||
sqlite3_close(db);
|
||||
db = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -103,20 +103,20 @@ private:
|
||||
Bank bank;
|
||||
Row row;
|
||||
Column column;
|
||||
|
||||
unsigned int burstlength;
|
||||
public:
|
||||
|
||||
DramExtension():thread(0),channel(0),bank(0),row(0),column(0){}
|
||||
DramExtension(const Thread& thread, const Bank& bank, const Row& row, const Column& column) :
|
||||
thread(thread),channel(0),bank(bank),row(row),column(column){}
|
||||
DramExtension(const Thread& thread,const Channel& channel, const Bank& bank, const Row& row, const Column& column) :
|
||||
thread(thread),channel(channel),bank(bank),row(row),column(column){}
|
||||
DramExtension():thread(0),channel(0),bank(0),row(0),column(0),burstlength(0){}
|
||||
DramExtension(const Thread& thread, const Bank& bank, const Row& row, const Column& column, unsigned int burstlength=0) :
|
||||
thread(thread),channel(0),bank(bank),row(row),column(column), burstlength(burstlength){}
|
||||
DramExtension(const Thread& thread,const Channel& channel, const Bank& bank, const Row& row, const Column& column, unsigned int burstlength=0) :
|
||||
thread(thread),channel(channel),bank(bank),row(row),column(column), burstlength(burstlength){}
|
||||
|
||||
|
||||
~DramExtension(){}
|
||||
virtual tlm_extension_base* clone() const
|
||||
{
|
||||
return new DramExtension(thread, bank, row, column);
|
||||
return new DramExtension(thread, bank, row, column, burstlength);
|
||||
}
|
||||
virtual void copy_from(const tlm_extension_base& ext)
|
||||
{
|
||||
@@ -125,6 +125,7 @@ public:
|
||||
bank = cpyFrom.bank;
|
||||
row = cpyFrom.row;
|
||||
column = cpyFrom.column;
|
||||
burstlength = cpyFrom.burstlength;
|
||||
}
|
||||
|
||||
const Thread& getThread() const{return thread;}
|
||||
@@ -132,6 +133,7 @@ public:
|
||||
const Bank& getBank() const{return bank;}
|
||||
const Row& getRow() const{return row;}
|
||||
const Column& getColumn() const{return column;}
|
||||
const unsigned int getBurstlength() const{return burstlength;}
|
||||
|
||||
|
||||
static const DramExtension& getExtension(const tlm::tlm_generic_payload *payload);
|
||||
|
||||
@@ -19,6 +19,7 @@ xmlAddressDecoder::xmlAddressDecoder(string addressConfigURI)
|
||||
// get channel:
|
||||
TiXmlElement* channel = addressmap->FirstChildElement("channel");
|
||||
|
||||
|
||||
from = getAttribute<unsigned int>(channel, "from");
|
||||
to = getAttribute<unsigned int>(channel, "to");
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
*/
|
||||
|
||||
#include "BankStates.h"
|
||||
#include "ControllerCore.h"
|
||||
#include "../common/DebugManager.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -34,11 +36,13 @@ Row BankStates::getRowInRowBuffer(const Bank &bank) const
|
||||
|
||||
void BankStates::openRowInRowBuffer(const Bank &bank, const Row &row)
|
||||
{
|
||||
DebugManager::getInstance().printDebugMessage(ControllerCore::senderName, "Row buffer for bank " + to_string(bank.ID()) + " is now open");
|
||||
rowsInRowBuffers.at(bank.ID()) = row;
|
||||
}
|
||||
|
||||
void BankStates::closeRowBuffer(const Bank &bank)
|
||||
{
|
||||
DebugManager::getInstance().printDebugMessage(ControllerCore::senderName, "Row buffer for bank " + to_string(bank.ID()) + " is now closed");
|
||||
rowsInRowBuffers.at(bank.ID()) = Row::NO_ROW;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace core{
|
||||
|
||||
struct Configuration
|
||||
{
|
||||
Configuration(): NumberOfBanks(8), NumberOfBankGroups(4), Burstlength(2), Timings(NumberOfBanks), BankwiseRefresh(true),BankwisePowerDown(true),
|
||||
Configuration(): NumberOfBanks(8), NumberOfBankGroups(4), Burstlength(2), Timings(NumberOfBanks), BankwiseRefresh(false),BankwisePowerDown(false),
|
||||
nActivate(2)
|
||||
{}
|
||||
unsigned int NumberOfBanks;
|
||||
|
||||
@@ -79,9 +79,15 @@ void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload, sc_time t
|
||||
if (!powerDownManager->isInSelfRefresh(bank))
|
||||
{
|
||||
if(config.BankwiseRefresh)
|
||||
powerDownManager->wakeUpForRefresh(bank, time);//expect PDNA and PDNP to exit without delay
|
||||
{
|
||||
printDebugMessage("Waking up bank " + to_string(bank.ID()) + " for refresh");
|
||||
powerDownManager->wakeUpForRefresh(bank, time);//expects PDNA and PDNP to exit without delay
|
||||
}
|
||||
else
|
||||
{
|
||||
printDebugMessage("Waking up all banks for refresh");
|
||||
powerDownManager->wakeUpAllForRefresh(time);
|
||||
}
|
||||
|
||||
refreshManager->scheduleRefresh(payload, time);
|
||||
}
|
||||
@@ -96,7 +102,6 @@ bool ControllerCore::scheduleRequest(sc_time start, tlm::tlm_generic_payload& pa
|
||||
{
|
||||
start = clkAlign(start, config.Timings.clk);
|
||||
state.cleanUp(start);
|
||||
payload.set_streaming_width(config.Burstlength);
|
||||
|
||||
saveState();
|
||||
|
||||
|
||||
@@ -45,10 +45,6 @@ void PowerDownManager::sleep(Bank bank, sc_time time)
|
||||
|
||||
sendPowerDownPayload(time, bank, getSleepCommand(getPowerDownState(bank)));
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("Power Down Manager", "Sleep triggered even though already in sleep");
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManager::wakeUp(Bank bank, sc_time time)
|
||||
@@ -260,7 +256,6 @@ void PowerDownManager::init()
|
||||
controller.state.change(pdn);
|
||||
controller.wrapper.send(pdn, payload);
|
||||
powerDownStates[bank] = PowerDownState::PDNPrecharge;
|
||||
//setState(PowerDownState::PDNPrecharge, bank);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,7 @@ PowerDownManagerGrouped::~PowerDownManagerGrouped()
|
||||
|
||||
void PowerDownManagerGrouped::sleep(Bank bank, sc_time time)
|
||||
{
|
||||
assert(!isInPowerDown());//cause nobody calls sleep if already sleeping on all banks
|
||||
|
||||
//all banks can sleep and no pending refresh
|
||||
//all banks can sleep and no pending refresh in system
|
||||
if (!canSleep() || (controller.state.getLastCommand(Command::AutoRefresh).getEnd() > time))
|
||||
return;
|
||||
|
||||
@@ -43,19 +41,20 @@ void PowerDownManagerGrouped::sleep(Bank bank, sc_time time)
|
||||
}
|
||||
else if (state == PowerDownState::AwakeForRefresh)//coming from refresh interrupting power down
|
||||
{
|
||||
//last running refresh triggers sleep
|
||||
if (controller.state.getLastCommand(Command::PDNA).getStart()
|
||||
> controller.state.getLastCommand(Command::PDNP).getStart())
|
||||
setState(PowerDownState::PDNPrecharge);
|
||||
if(controller.state.bankStates.allRowBuffersAreClosed())
|
||||
{
|
||||
if (controller.state.getLastCommand(Command::PDNA).getStart()
|
||||
> controller.state.getLastCommand(Command::PDNP).getStart())
|
||||
setState(PowerDownState::PDNPrecharge);
|
||||
else
|
||||
setState(PowerDownState::PDNSelfRefresh);
|
||||
}
|
||||
else
|
||||
setState(PowerDownState::PDNSelfRefresh);
|
||||
|
||||
{
|
||||
setState(PowerDownState::PDNActive);
|
||||
}
|
||||
sendPowerDownPayload(time, getSleepCommand(getPowerDownState()));
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("PowerDownManagerGrouped", "Sleep triggered even though already in sleep");
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDownManagerGrouped::wakeUp(Bank bank, sc_time time)
|
||||
@@ -105,10 +104,7 @@ void PowerDownManagerGrouped::wakeUpAllForRefresh(sc_time time)
|
||||
{
|
||||
if(isInPowerDown())
|
||||
{
|
||||
for (Bank bank : controller.getBanks())
|
||||
{
|
||||
sendPowerDownPayload(time, getWakeUpCommand(getPowerDownState()));
|
||||
}
|
||||
sendPowerDownPayload(time, getWakeUpCommand(getPowerDownState()));
|
||||
setState(PowerDownState::AwakeForRefresh);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ class CommandSchedule
|
||||
{
|
||||
public:
|
||||
CommandSchedule(tlm::tlm_generic_payload& transaction) :
|
||||
extension(DramExtension::getExtension(&transaction)), burstLength(transaction.get_streaming_width())
|
||||
extension(DramExtension::getExtension(&transaction))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
|
||||
ScheduledCommand& add(Command command, sc_time start, sc_time executionTime)
|
||||
{
|
||||
scheduledCommands.push_back(ScheduledCommand(command, start, executionTime, extension, burstLength));
|
||||
scheduledCommands.push_back(ScheduledCommand(command, start, executionTime, extension));
|
||||
return scheduledCommands.back();
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ public:
|
||||
|
||||
private:
|
||||
std::vector<ScheduledCommand> scheduledCommands;
|
||||
unsigned int burstLength;
|
||||
DramExtension extension;
|
||||
};
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ Row ScheduledCommand::getRow() const
|
||||
|
||||
unsigned int ScheduledCommand::getBurstLength()
|
||||
{
|
||||
return burstLength;
|
||||
return extension.getBurstlength();
|
||||
}
|
||||
|
||||
bool ScheduledCommand::operator ==(const ScheduledCommand& b) const
|
||||
|
||||
@@ -20,15 +20,15 @@ class ScheduledCommand
|
||||
{
|
||||
public:
|
||||
|
||||
ScheduledCommand(Command command, sc_time start, sc_time executionTime, const DramExtension& extension, unsigned int burstLength = 0) :
|
||||
command(command), start(start), executionTime(executionTime),end(start+executionTime), burstLength(burstLength),
|
||||
ScheduledCommand(Command command, sc_time start, sc_time executionTime, const DramExtension& extension) :
|
||||
command(command), start(start), executionTime(executionTime),end(start+executionTime),
|
||||
extension(extension)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ScheduledCommand() :
|
||||
command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME), end(SC_ZERO_TIME), burstLength(0), extension()
|
||||
command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME), end(SC_ZERO_TIME), extension()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -58,7 +58,6 @@ private:
|
||||
sc_time start;
|
||||
sc_time executionTime;
|
||||
sc_time end;
|
||||
unsigned int burstLength;
|
||||
DramExtension extension;
|
||||
};
|
||||
} /* namespace controller */
|
||||
|
||||
@@ -78,22 +78,13 @@ bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read,
|
||||
if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA)
|
||||
{
|
||||
//read to read
|
||||
TimeInterval readOnStrobe = getIntervalOnDataStrobe(read, config.Timings);
|
||||
TimeInterval otherReadOnStrobe = getIntervalOnDataStrobe(strobeCommand, config.Timings);
|
||||
|
||||
if (readOnStrobe.timeIsInInterval(otherReadOnStrobe.start))
|
||||
if(read.getStart() < strobeCommand.getStart())
|
||||
{
|
||||
return !isClkAligned(otherReadOnStrobe.start - readOnStrobe.start,
|
||||
2 * config.Timings.clk);
|
||||
}
|
||||
else if (otherReadOnStrobe.timeIsInInterval(readOnStrobe.start))
|
||||
{
|
||||
return !isClkAligned(readOnStrobe.start - otherReadOnStrobe.start,
|
||||
2 * config.Timings.clk);
|
||||
return (strobeCommand.getStart() - read.getStart() < read.getBurstLength()*config.Timings.clk);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
return (read.getStart() - strobeCommand.getStart() < strobeCommand.getBurstLength()*config.Timings.clk);
|
||||
}
|
||||
}
|
||||
else if (strobeCommand.getCommand() == Command::Write
|
||||
|
||||
@@ -27,7 +27,8 @@ void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
|
||||
}
|
||||
}
|
||||
else if (lastCommand.getCommand() == Command::Read
|
||||
|| lastCommand.getCommand() == Command::Write || lastCommand.getCommand() == Command::PDNAX)
|
||||
|| lastCommand.getCommand() == Command::Write
|
||||
|| lastCommand.getCommand() == Command::PDNAX)
|
||||
{
|
||||
}
|
||||
else
|
||||
@@ -73,8 +74,17 @@ bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write,
|
||||
if (strobeCommand.getCommand() == Command::Write
|
||||
|| strobeCommand.getCommand() == Command::WriteA)
|
||||
{
|
||||
//write to write (implicitly checked by checking the command bus first)
|
||||
return false;
|
||||
//write to write
|
||||
if (write.getStart() < strobeCommand.getStart())
|
||||
{
|
||||
return (strobeCommand.getStart() - write.getStart()
|
||||
< write.getBurstLength() * config.Timings.clk);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (write.getStart() - strobeCommand.getStart()
|
||||
< strobeCommand.getBurstLength() * config.Timings.clk);
|
||||
}
|
||||
}
|
||||
else if (strobeCommand.getCommand() == Command::Read
|
||||
|| strobeCommand.getCommand() == Command::ReadA)
|
||||
|
||||
@@ -132,9 +132,10 @@ private:
|
||||
|
||||
void appendDramExtension(int socketId, tlm_generic_payload& payload)
|
||||
{
|
||||
unsigned int burstlength = payload.get_streaming_width();
|
||||
node n;
|
||||
xmlAddressDecoder::getInstance().getNode(static_cast<unsigned int>(payload.get_address()), &n);
|
||||
DramExtension* extension = new DramExtension(Thread(socketId+1), Channel(n.channel), Bank(n.bank), Row(n.row), Column(n.colum));
|
||||
DramExtension* extension = new DramExtension(Thread(socketId+1), Channel(n.channel), Bank(n.bank), Row(n.row), Column(n.colum),burstlength);
|
||||
payload.set_auto_extension(extension);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -177,7 +177,7 @@ private:
|
||||
|
||||
void scheduleNextPayload(Bank bank)
|
||||
{
|
||||
printDebugMessage("Try to schedule next payload on bank " + to_string(bank.ID()));
|
||||
printDebugMessage("Triggering schedule next payload on bank " + to_string(bank.ID()));
|
||||
if (scheduler->hasTransactionForBank(bank))
|
||||
{
|
||||
|
||||
@@ -188,8 +188,8 @@ private:
|
||||
}
|
||||
if (controller->powerDownManager->isInPowerDown(bank))
|
||||
{
|
||||
printDebugMessage("\t-> break: wake up bank first");
|
||||
controller->powerDownManager->wakeUp(bank, sc_time_stamp());
|
||||
printDebugMessage("\t-> break: wake up power down");
|
||||
return;
|
||||
}
|
||||
else if (controller->powerDownManager->isAwakeForRefresh(bank))
|
||||
@@ -302,7 +302,10 @@ private:
|
||||
{
|
||||
printDebugMessage("Finished auto refresh on bank " + to_string(bank.ID()));
|
||||
if (numberOfPayloadsInSystem[bank] == 0)
|
||||
{
|
||||
printDebugMessage("\t -> Triggering sleep on bank " + to_string(bank.ID()));
|
||||
controller->powerDownManager->sleep(bank, sc_time_stamp());
|
||||
}
|
||||
scheduleNextPayload(DramExtension::getExtension(payload).getBank());
|
||||
}
|
||||
else if (isIn(phase, { END_PRE, END_PRE_ALL, END_ACT }))
|
||||
|
||||
@@ -8,7 +8,7 @@ class ISimulationManager
|
||||
{
|
||||
public:
|
||||
virtual ~ISimulationManager(){}
|
||||
virtual void tracePlayerFinishedCallback() = 0;
|
||||
virtual void tracePlayerFinishedCallback(string name) = 0;
|
||||
};
|
||||
|
||||
} // namespace simulation
|
||||
|
||||
@@ -17,13 +17,15 @@ using namespace std;
|
||||
|
||||
namespace simulation {
|
||||
|
||||
SimulationManager::SimulationManager(sc_module_name name, std::string stl1, std::string stl2,
|
||||
SimulationManager::SimulationManager(sc_module_name name, std::string stl1,
|
||||
unsigned int burstlength1, std::string stl2, unsigned int burstlenght2,
|
||||
std::string traceName, std::string pathToResources) :
|
||||
dram("dram"), arbiter("arbiter"), controller("controller"), player1("player1",
|
||||
pathToResources + string("traces/") + stl1, this), player2("player2",
|
||||
pathToResources + string("traces/") + stl2, this), traceName(traceName)
|
||||
pathToResources + string("traces/") + stl1,burstlength1, this), player2("player2",
|
||||
pathToResources + string("traces/") + stl2,burstlenght2, this), traceName(traceName)
|
||||
|
||||
{
|
||||
|
||||
SC_THREAD(terminationThread);
|
||||
xmlAddressDecoder::addressConfigURI = pathToResources + string("configs/addressConfig.xml");
|
||||
TlmRecorder::dbName = traceName;
|
||||
@@ -38,6 +40,7 @@ SimulationManager::SimulationManager(sc_module_name name, std::string stl1, std:
|
||||
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);
|
||||
whiteList.push_back(PowerDownManager::senderName);
|
||||
@@ -49,21 +52,21 @@ void SimulationManager::startSimulation()
|
||||
|
||||
clock_t begin = clock();
|
||||
|
||||
cout << "Toplevel: simulation start" << std::endl;
|
||||
DebugManager::getInstance().printDebugMessage(name(), "Starting simulation");
|
||||
player1.start();
|
||||
player2.start();
|
||||
sc_start();
|
||||
|
||||
clock_t end = clock();
|
||||
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||
cout << "Simulation took " << elapsed_secs << " seconds." << endl;
|
||||
cout << this->name();
|
||||
|
||||
string p = getenv("trace");
|
||||
string run_tpr = p + " " + traceName;
|
||||
system(run_tpr.c_str());
|
||||
DebugManager::getInstance().printDebugMessage(name(),
|
||||
"Simulation took " + to_string(elapsed_secs) + " seconds");
|
||||
}
|
||||
|
||||
void SimulationManager::tracePlayerFinishedCallback()
|
||||
void SimulationManager::tracePlayerFinishedCallback(string name)
|
||||
{
|
||||
|
||||
DebugManager::getInstance().printDebugMessage(this->name(), "Traceplayer " + name + " finshed");
|
||||
static int finishedPlayers = 0;
|
||||
finishedPlayers++;
|
||||
if (finishedPlayers == numberOfTracePlayers)
|
||||
@@ -75,9 +78,10 @@ void SimulationManager::tracePlayerFinishedCallback()
|
||||
void SimulationManager::terminationThread()
|
||||
{
|
||||
wait(terminateSimulation);
|
||||
DebugManager::getInstance().printDebugMessage(this->name(), "Terminating simulation");
|
||||
controller.terminateSimulation();
|
||||
//waits for the termination of all pending powerdown phases in the dram system
|
||||
wait(sc_time(50,SC_NS));
|
||||
wait(sc_time(50, SC_NS));
|
||||
TlmRecorder::getInstance().closeConnection();
|
||||
sc_stop();
|
||||
}
|
||||
|
||||
@@ -22,10 +22,11 @@ class SimulationManager : public ISimulationManager, public sc_module
|
||||
{
|
||||
public:
|
||||
SC_HAS_PROCESS(SimulationManager);
|
||||
SimulationManager(sc_module_name name,std::string stl1, std::string stl2,
|
||||
std::string traceName, std::string pathToResources);
|
||||
SimulationManager(sc_module_name name, std::string stl1,
|
||||
unsigned int burstlength1, std::string stl2, unsigned int burstlenght2,
|
||||
std::string traceName, std::string pathToResources);
|
||||
void startSimulation();
|
||||
void tracePlayerFinishedCallback() override;
|
||||
void tracePlayerFinishedCallback(string name) override;
|
||||
|
||||
private:
|
||||
void terminationThread();
|
||||
|
||||
@@ -28,28 +28,36 @@ 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,
|
||||
TracePlayer(sc_module_name name, string pathToTrace, unsigned int burstlength,
|
||||
simulation::ISimulationManager* simulationManager) :
|
||||
payloadEventQueue(this, &TracePlayer::peqCallback), file(pathToTrace), numberOfPendingTransactions(
|
||||
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());
|
||||
|
||||
if (!file)
|
||||
{
|
||||
SC_REPORT_FATAL(0, "trace is empty! Simulation stops");
|
||||
}
|
||||
|
||||
iSocket.register_nb_transport_bw(this, &TracePlayer::nb_transport_bw);
|
||||
scheduleNextPayload();
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
bool fileIsEmpty = file.peek() == std::ifstream::traits_type::eof();
|
||||
if (fileIsEmpty)
|
||||
{
|
||||
simulationManager->tracePlayerFinishedCallback(name());
|
||||
}
|
||||
else
|
||||
{
|
||||
scheduleNextPayload();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tlm_utils::peq_with_cb_and_phase<TracePlayer> payloadEventQueue;
|
||||
MemoryManager memoryManager;
|
||||
ifstream file;
|
||||
unsigned int burstlenght;
|
||||
unsigned int numberOfPendingTransactions;
|
||||
unsigned int transactionsSent;
|
||||
unsigned int transactionsReceived;
|
||||
@@ -89,7 +97,7 @@ private:
|
||||
payload->set_response_status(TLM_INCOMPLETE_RESPONSE);
|
||||
payload->set_dmi_allowed(false);
|
||||
payload->set_byte_enable_length(0);
|
||||
payload->set_streaming_width(0);
|
||||
payload->set_streaming_width(burstlenght);
|
||||
|
||||
sc_time sendingTime = sc_time(std::stoi(time.c_str()), SC_NS);
|
||||
if (sendingTime <= sc_time_stamp())
|
||||
@@ -137,7 +145,7 @@ private:
|
||||
+ std::to_string(transactionsSent - transactionsReceived));
|
||||
|
||||
if (numberOfPendingTransactions == 0)
|
||||
simulationManager->tracePlayerFinishedCallback();
|
||||
simulationManager->tracePlayerFinishedCallback(name());
|
||||
}
|
||||
|
||||
else if (phase == END_RESP)
|
||||
|
||||
@@ -17,15 +17,26 @@ string pathOfFile(string file)
|
||||
return file.substr(0, file.find_last_of('/'));
|
||||
}
|
||||
|
||||
void startTraceAnalyzer(string traceName)
|
||||
{
|
||||
string p = getenv("trace");
|
||||
string run_tpr = p + " " + traceName;
|
||||
system(run_tpr.c_str());
|
||||
}
|
||||
|
||||
int sc_main(int argc, char **argv)
|
||||
{
|
||||
sc_set_time_resolution(1, SC_NS);
|
||||
|
||||
string resources = pathOfFile(argv[0]) + string("/../resources/");
|
||||
string stl1 = "chstone-mips_32.stl";
|
||||
string stl2 = "chstone-motion_32.stl";
|
||||
SimulationManager simulationManager("sim",stl1,stl2,"tpr.tdb", resources);
|
||||
unsigned int burstlength1 = 4;
|
||||
string stl2 = "empty.stl";
|
||||
unsigned int burstlength2 = 2;
|
||||
string traceName = "tpr.tdb";
|
||||
SimulationManager simulationManager("sim", stl1,burstlength1, stl2,burstlength2, traceName, resources);
|
||||
simulationManager.startSimulation();
|
||||
startTraceAnalyzer(traceName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user