Relocated the python scripts. They now live in the analyzer directory and are deployed to the output folder when building the analyzer.

Major change to simulation logic in dramSys: Commands in a transaction are now scheduled one at a time, instead of
scheduling a whole transaction at once. Since single commands (e.g. Pre or Act) are not that long, refreshes are allowed to be delayed
to allow a command to finsh. Consequently, the whole loop in the ControllerCore about trying to scheduleding a transaction and aborting it when
it collides with a refresh could be ommitted. Lastly, Fifo_Strict has been added, which is a Fifo Scheduler that forces the read and write transactions, even
between different banks to be executed in order. Fifo and FR_FCFS have been modified to fit into the new scheduling logic.
This commit is contained in:
gernhard2
2015-02-16 08:21:27 +01:00
parent badcc37118
commit f11adf51dc
101 changed files with 1814 additions and 2378 deletions

View File

@@ -4,11 +4,12 @@
#include <iostream>
#include <QFileInfo>
#include <QDebug>
#include <QApplication>
using namespace std;
PythonCaller::PythonCaller(const QString& pathToScripts) :
testModuleName("tests"), testFunctionName("runTests"), metricModuleName("metrics"), metricFunctionName("calculateMetrics"), pathToScripts(pathToScripts.toStdString())
PythonCaller::PythonCaller() :
testModuleName("tests"), testFunctionName("runTests"), metricModuleName("metrics"), metricFunctionName("calculateMetrics"), pathToScripts(QApplication::applicationDirPath().toStdString() +"/scripts")
{
Py_Initialize();
PyObject *sysPath = PySys_GetObject((char*)"path");

View File

@@ -9,7 +9,7 @@
class PythonCaller
{
public:
PythonCaller(const QString& pathToScripts);
PythonCaller();
~PythonCaller();
TraceTestResults runTestsOnTrace(QString pathToTrace);
TraceCalculatedMetrics calculateMetricsOnTrace(QString pathToTrace);
@@ -18,7 +18,7 @@ private:
PyObject *pRunTestsFunction, *pCalculateMetricsFunction;
PyObject* loadFunctionFromModule(std::string moduleName, std::string functionName);
std::string testModuleName, testFunctionName, metricModuleName, metricFunctionName, pathToScripts;
PyObject *callFunctionWithStringArgument(PyObject *function, QString argument);
PyObject *callFunctionWithStringArgument(PyObject *function, QString argument);
};
#endif // PYTHONCALLER_H

View File

@@ -83,9 +83,7 @@ void EvaluationTool::on_btn_test_clicked()
void EvaluationTool::runTests()
{
QString resourcesAbsPath = QApplication::applicationDirPath() + this->resourcesRelPath;
qDebug() << resourcesAbsPath;
PythonCaller pythonCaller(resourcesAbsPath);
PythonCaller pythonCaller;
ui->traceTestTreeWidget->clear();
ui->testLight->setGray();
@@ -118,9 +116,7 @@ void EvaluationTool::on_btn_calculateMetrics_clicked()
void EvaluationTool::calculateMetrics()
{
QString resourcesAbsPath = QApplication::applicationDirPath() + this->resourcesRelPath;
qDebug() << resourcesAbsPath;
PythonCaller pythonCaller(resourcesAbsPath);
PythonCaller pythonCaller;
ui->traceMetricTreeWidget->clear();
for(int row = 0; row < traceFilesModel->rowCount(); ++row)
{

View File

@@ -0,0 +1,617 @@
import sys
import traceback
import sqlite3
import os
import xml.etree.ElementTree as ET
def getPathToConfigs():
return os.path.dirname(os.path.abspath(__file__).replace("/scripts","/configs"))
def getValueFromConfigXML(root, id):
return root.findall(".//parameter[@id='{0}']".format(id))[0].attrib['value']
def getIntValueFromConfigXML(root, id):
return int(root.findall(".//parameter[@id='{0}']".format(id))[0].attrib['value'])
def getMemconfig(connection):
cursor = connection.cursor()
cursor.execute("SELECT Memconfig FROM GeneralInfo")
result = cursor.fetchone()
memconfig = result[0]
return ET.parse(memconfig)
def getMemspec(connection):
cursor = connection.cursor()
cursor.execute("SELECT Memspec FROM GeneralInfo")
result = cursor.fetchone()
memspec = result[0]
return ET.parse(memspec)
def getClock(connection):
cursor = connection.cursor()
cursor.execute("SELECT clk, UnitOfTime FROM GeneralInfo")
result = cursor.fetchone()
return (result[0],result[1])
class DramConfig(object):
memoryType = ""
bankwiseLogic = 0
clk = 0
unitOfTime = ""
dataRate = 0
nActivateWindow = numberOfBanks = 0
clk = 0
tRP = 0 #precharge-time (pre -> act same bank)
tRAS = 0 #active-time (act -> pre same bank)
tRC = 0 #RAS-cycle-time (min time bw 2 succesive ACT to same bank)
tCCD_S = 0 #TODO: relevant? max(bl, tCCD)
tCCD_L = 0
tRTP = 0 #Read to precharge
tRRD_S = 0 #min time bw 2 succesive ACT to different banks (different bank group)
tRRD_L = 0 #.. (same bank group)
tRCD = 0 #act -> read/write
tNAW = 0 #n activate window
tRL = 0 #read latency (read command start to data strobe)
tWL = 0 #write latency
tWR = 0 #write recovery (write to precharge)
tWTR_S = 0 #write to read (different bank group)
tWTR_L = 0 #.. (same bank group)
tCKESR = 0 #min time in sref
tCKE = 0 #min time in pdna or pdnp
tXP = 0 #min delay to row access command after pdnpx pdnax
tXPDLL = 0 #min delay to row access command after pdnpx pdnax for dll commands
tXSR = 0 #min delay to row access command after srefx
tXSRDLL = 0 #min delay to row access command after srefx for dll commands
tAL = 0 #additive delay (delayed execution in dram)
tRFC = 0 #min ref->act delay
def readConfigFromFiles(self, connection):
print("Parsing dram configuration")
memspec = getMemspec(connection)
clkWithUnit = getClock(connection)
self.clk = clkWithUnit[0]
self.unitOfTime = clkWithUnit[1].lower()
print(getMemconfig(connection))
self.bankwiseLogic = getMemconfig(connection).findall("BankwiseLogic")[0].attrib['value']
self.numberOfBanks = getIntValueFromConfigXML(memspec, "nbrOfBanks")
self.burstLength = getIntValueFromConfigXML(memspec, "burstLength")
self.memoryType = getValueFromConfigXML(memspec, "memoryType")
self.dataRate = getIntValueFromConfigXML(memspec, "dataRate")
if(self.memoryType == "WIDEIO_SDR"):
self.nActivateWindow = 2;
self.tRP = self.clk * getIntValueFromConfigXML(memspec, "RP")
self.tRAS = self.clk * getIntValueFromConfigXML(memspec, "RAS")
self.tRC = self.clk * getIntValueFromConfigXML(memspec, "RC")
self.tRRD_S = self.clk * getIntValueFromConfigXML(memspec, "RRD")
self.tRRD_L = self.tRRD_S
self.tCCD_S = self.clk * getIntValueFromConfigXML(memspec, "CCD")
self.tCCD_L = self.tCCD_S
self.tRCD = self.clk * getIntValueFromConfigXML(memspec, "RCD")
self.tNAW = self.clk * getIntValueFromConfigXML(memspec, "TAW")
self.tRL = self.clk * getIntValueFromConfigXML(memspec, "RL")
self.tWL = self.clk * getIntValueFromConfigXML(memspec, "WL")
self.tWR = self.clk * getIntValueFromConfigXML(memspec, "WR")
self.tWTR_S = self.clk * getIntValueFromConfigXML(memspec, "WTR")
self.tWTR_L = self.tWTR_S
self.tRTP = self.clk * getIntValueFromConfigXML(memspec, "RTP");
self.tCKESR = self.clk * getIntValueFromConfigXML(memspec, "CKESR")
self.tCKE = self.clk * getIntValueFromConfigXML(memspec, "CKE")
self.tXP = self.clk * getIntValueFromConfigXML(memspec, "XP")
self.tXPDLL = self.tXP
self.tXSR = self.clk * getIntValueFromConfigXML(memspec, "XS")
self.tXSRDLL = self.tXSR
self.tAL = self.clk * getIntValueFromConfigXML(memspec, "AL")
self.tRFC = self.clk * getIntValueFromConfigXML(memspec, "RFC")
elif(self. memoryType == "DDR4"):
self.nActivateWindow = 4;
self.tRP = self.clk * getIntValueFromConfigXML(memspec, "RP");
self.tRAS = self.clk * getIntValueFromConfigXML(memspec, "RAS");
self.tRC = self.clk * getIntValueFromConfigXML(memspec, "RC");
self.tRTP = self.clk * getIntValueFromConfigXML(memspec, "RTP");
self.tRRD_S = self.clk * getIntValueFromConfigXML(memspec, "RRD_S");
self.tRRD_L = self.clk * getIntValueFromConfigXML(memspec, "RRD_L");
self.tCCD_S = self.clk * getIntValueFromConfigXML(memspec, "CCD_S");
self.tCCD_L = self.clk * getIntValueFromConfigXML(memspec, "CCD_L");
self.tRCD = self.clk * getIntValueFromConfigXML(memspec, "RCD");
self.tNAW = self.clk * getIntValueFromConfigXML(memspec, "FAW");
self.tRL = self.clk * getIntValueFromConfigXML(memspec, "RL");
self.tWL = self.clk * getIntValueFromConfigXML(memspec, "WL");
self.tWR = self.clk * getIntValueFromConfigXML(memspec, "WR");
self.tWTR_S = self.clk * getIntValueFromConfigXML(memspec, "WTR_S");
self.tWTR_L = self.clk * getIntValueFromConfigXML(memspec, "WTR_L");
self.tCKESR = self.clk * getIntValueFromConfigXML(memspec, "CKESR");
self.tCKE = self.clk * getIntValueFromConfigXML(memspec, "CKE");
self.tXP = self.clk * getIntValueFromConfigXML(memspec, "XP");
self.tXPDLL = self.clk * getIntValueFromConfigXML(memspec, "XPDLL");
self.tXSR = self.clk * getIntValueFromConfigXML(memspec, "XS");
self.tXSRDLL = self.clk * getIntValueFromConfigXML(memspec, "XSDLL");
self.tAL = self.clk * getIntValueFromConfigXML(memspec, "AL");
self.tRFC = self.clk * getIntValueFromConfigXML(memspec, "RFC");
else:
raise Exception("MemoryType not supported yet. Insert a coin into the coin machine and try again")
def clkAlign(self, value):
return math.ceil(1.0*value/self.clk)*self.clk
def getWriteAccessTime(self):
if(self.dataRate == 1):
return self.clk*(self.burstLength - 1)
elif (self.memoryType == "DDR4"):
return self.clk*self.burstLength/self.dataRate
def getReadAccessTime(self):
return self.burstLength/self.dataRate * dramconfig.clk
def __init__(self):
pass
dramconfig = DramConfig()
def calculateReadLength(burstLength):
return dramconfig.tRL + burstLength * dramconfig.clk
def calculateWriteLength(burstLength):
return dramconfig.tWL + burstLength * dramconfig.clk
# ----------- test utils ---------------------------------------
tests = []
def test(function):
tests.append(function)
return function
class TestResult(object):
passed = True
message = ''
def __init__(self, passed = True, message = ''):
self.passed = passed
self.message = message
def TestSuceeded():
return TestResult()
def TestFailed(message):
return TestResult(False,message);
def formatTime(time):
return ('{0} {1}'.format(time, dramconfig.unitOfTime))
# ----------- checks ---------------------------------------
@test
def commands_are_clockaligned(connection):
"""Checks that all commands on the command bus are aligned to the system clock"""
cursor = connection.cursor()
query = "select ID,PhaseBegin,PhaseEnd from phases where phaseName NOT IN ('REQ','RESP') AND (phaseBegin%:clk!=0 OR phaseEnd%:clk!=0)"
cursor.execute(query, {"clk": dramconfig.clk})
result = cursor.fetchone()
if(result != None):
return TestFailed("Command with PhaseID {0} starts at {1} and ends at. One of those times. is not aligned to system clock ({2})"
.format(result[0], formatTime(result[1]), formatTime(result[2]), formatTime(dramconfig.clk)))
return TestSuceeded()
@test
def commandbus_slots_are_used_once(connection):
"""Checks that no two phases on the command bus start at the same time"""
cursor = connection.cursor()
if dramconfig.bankwiseLogic:
excludedPhases = "('REQ','RESP','PRE_ALL')"
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 multiple times".format(formatTime(result[0])))
return TestSuceeded()
@test
def phase_transitions_are_valid(connection):
"""Checks that all transition of two consequtive phases on the same bank are valid"""
cursor = connection.cursor()
validTransitions = {}
if(dramconfig.bankwiseLogic):
validTransitions['PRE'] = set(['ACT', 'AUTO_REFRESH'])
validTransitions['ACT'] = set(['RD', 'RDA', 'WR', 'WRA', 'PRE', 'PRE_ALL'])
validTransitions['RD'] = set(['PRE','RD','RDA', 'WR', 'WRA', 'PDNA'])
validTransitions['WR'] = set(['PRE', 'RD','RDA', 'WR', 'WRA', 'PDNA'])
validTransitions['RDA'] = set(['ACT', 'AUTO_REFRESH', 'PDNP'])
validTransitions['WRA'] = set(['ACT', 'AUTO_REFRESH', 'PDNP'])
validTransitions['AUTO_REFRESH'] = set(['ACT', 'PDNP', 'SREF'])
validTransitions['PDNA'] = set(['PRE', 'RD','RDA', 'WR', 'WRA', 'AUTO_REFRESH'])
validTransitions['PDNP'] = set(['ACT', 'AUTO_REFRESH'])
validTransitions['SREF'] = set(['ACT'])
else:
validTransitions['PRE'] = set(['ACT'])
validTransitions['PRE_ALL'] = set(['AUTO_REFRESH'])
validTransitions['ACT'] = set(['RD', 'RDA', 'WR', 'WRA', 'PRE_ALl'])
validTransitions['RD'] = set(['PRE', 'PRE_ALL','RD','RDA', 'WR', 'WRA', 'PDNA'])
validTransitions['WR'] = set(['PRE', 'PRE_ALL','RD','RDA', 'WR', 'WRA', 'PDNA'])
validTransitions['RDA'] = set(['PRE_ALL', 'ACT', 'AUTO_REFRESH', 'PDNA', 'PDNP'])
validTransitions['WRA'] = set(['PRE_ALL', 'ACT', 'AUTO_REFRESH', 'PDNA', 'PDNP'])
validTransitions['AUTO_REFRESH'] = set(['PRE_ALL', 'ACT','AUTO_REFRESH', 'PDNA', 'PDNP', 'SREF'])
validTransitions['PDNA'] = set(['PRE','PRE_ALL','ACT', 'RD', 'RDA', 'WR', 'WRA', 'AUTO_REFRESH', 'PDNA', 'PDNP'])
validTransitions['PDNP'] = set(['PRE_ALL', 'ACT', 'AUTO_REFRESH', 'PDNA', 'PDNP'])
validTransitions['SREF'] = set(['PRE_ALL', 'ACT', 'AUTO_REFRESH', 'PDNA', 'PDNP'])
query = """SELECT PhaseName, phases.ID FROM phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE TBank=:bank
AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin"""
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query, {"bank": bankNumber})
lastRow = cursor.fetchone()
for currentRow in cursor:
currentPhase = currentRow[0]
lastPhase = lastRow[0]
if(currentPhase not in validTransitions[lastPhase]):
return TestFailed("Phase {0}({1}) is not allowed to follow phase {2}({3})".format(currentRow[1],currentPhase,lastRow[1],lastPhase))
lastRow = currentRow
return TestSuceeded()
def timing_constraint(FirstPhase, SecondPhase):
FirstPhaseName = FirstPhase[0]
SecondPhaseName = SecondPhase[0]
if(FirstPhaseName == "PRE" or FirstPhaseName == "PRE_ALL"):
return dramconfig.tRP
elif(FirstPhaseName == "ACT"):
return dramconfig.tRCD
elif(FirstPhaseName == "RD"):
if(SecondPhaseName in ["PRE, PRE_ALL"]):
return dramconfig.tRTP
elif(SecondPhaseName in ["RD, RDA"]):
return max(dramconfig.tCCD_L, getReadAccessTime())
elif(SecondPhase in ["WR","WRA"]):
return dramconfig.tRL + getReadAccessTime() - dramconfig.tWL + 2*dramconfig.clk
elif(SecondPhase == "PDNA" ):
return dramconfig.tRL + getReadAccessTime() + dramconfig.clk
elif(FirstPhaseName == "WR"):
if(SecondPhaseName in ["PRE, PRE_ALL", "PDNA"]):
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR
elif(SecondPhaseName in ["RD, RDA"]):
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWTR_L
elif(SecondPhaseName in ["WR, WRA"]):
return max(dramconfig.tCCD_L, burstlength/dramconfig.dataRate)
elif(FirstPhaseName == "RDA"):
if(SecondPhaseName in ["ACT", "PRE_ALL", "AUTO_REFRESH"]):
return dramconfig.tRTP + dramconfig.tRP
elif(SecondPhaseName in ["PDNA","PDNP"]):
return dramconfig.tRL + getReadAccessTime() + dramconfig.clk
elif(FirstPhaseName == "WRA"):
if(SecondPhaseName in ["ACT", "PRE_ALL", "AUTO_REFRESH"]):
return dramconfig.tWL + getWriteAccessTime() + dramconfig.tWR + dramconfig.tRP
elif(SecondPhaseName in ["PDNA","PDNP"]):
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR + dramconfig.clk
elif(FirstPhaseName == "AUTO_REFRESH"):
return dramconfig.tRFC
elif(FirstPhaseName in ["PDNA","PDNP"]):
return (FirstPhase[3] - FirstPhase[2]) + dramconfig.tXP - dramconfig.clk
elif(FirstPhaseName == "SREF"):
return (FirstPhase[3] - FirstPhase[2]) + dramconfig.tXSR - dramconfig.clk
return 0
@test
def timing_constraits_on_the_same_bank_hold(connection):
"""Checks that all transitions of two consequtive phases on the same bank meet their timing constraints"""
cursor = connection.cursor()
validTransitions = {}
query = """SELECT PhaseName, phases.ID,PhaseBegin,PhaseEnd FROM phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE TBank=:bank
AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin"""
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query, {"bank": bankNumber})
lastRow = cursor.fetchone()
for currentRow in cursor:
constraint = timing_constraint(lastRow,currentRow)
if(currentRow[2] - lastRow[2] + constraint < 0):
return TestFailed("Phase {0}({1}) starts {2} after Start of Phase {3}({4}). Minimal time is {5}".format(
currentRow[1],currentRow[0],formatTime(currentRow[2]-lastRow[2]),lastRow[1],lastRow[0], formatTime(constraint)))
lastRow = currentRow
return TestSuceeded()
@test
def row_buffer_is_used_correctly(connection):
"""Checks that each bank's row buffer is used correctly"""
cursor = connection.cursor()
query = """SELECT PhaseName, phases.ID FROM phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE TBank=:bank
AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin"""
#phases that precharge the bank and close the rowbuffer
prechargingPhases = set(['PRE','PRE_ALL','RDA','WRA'])
#phases that require the bank to be in active state and the rowbuffer to be opened
accessingPhases = set(['RD','RDA', 'WR', 'WRA', 'PRE'])
#phases that require the bank to be in precharged state and the robuffer to be closed
idlePhases = set(['ACT', 'PDNP', 'AUTO_REFRESH', 'SREF'])
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query,{"bank": bankNumber})
rowBufferIsClosed = True
for currentRow in cursor:
if(currentRow[0] in accessingPhases and rowBufferIsClosed == True):
return TestFailed("Phase {0}({1}) acesses a closed rowbuffer".format(currentRow[1], currentRow[0]))
if(currentRow[0] in idlePhases and rowBufferIsClosed == False):
return TestFailed("Phase {0}({1}) needs a closed rowbuffer".format(currentRow[1], currentRow[0]))
if(currentRow[0] == 'ACT'):
rowBufferIsClosed = False
if(currentRow[0] in prechargingPhases):
rowBufferIsClosed = True
return TestSuceeded()
#----------- activate checks ---------------------------------------
@test
def activate_to_activate_holds(connection):
"""Checks that all activates are far enough apart(JESD229 229, P. 27)"""
cursor = connection.cursor()
cursor.execute("SELECT phases.ID,PhaseBegin,TBankGroup FROM Phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE PhaseName = 'ACT' ORDER BY PhaseBegin")
lastRow = cursor.fetchone()
for currentRow in cursor:
timeBetweenActivates = currentRow[1] - lastRow[1]
if (currentRow[2] == lastRow[2]):
minTime = dramconfig.tRRD_L
else:
minTime = dramconfig.tRRD_S
if(timeBetweenActivates < minTime):
return TestFailed("Activates with PhaseIDs {0} and {1} are {2} apart. Minimum time between two activates is {3}".
format(currentRow[0], lastRow[0],formatTime(timeBetweenActivates), formatTime(minTime)))
lastRow = currentRow
return TestSuceeded()
@test
def activate_to_activate_on_same_bank_holds(connection):
"""Checks that all activates on the same bank are far enough apart (JEDEC 229, P. 27)"""
cursor = connection.cursor()
query = "SELECT Phases.ID,PhaseBegin from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID WHERE PhaseName = 'ACT' AND TBANK = :bank ORDER BY PhaseBegin"
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query,{"bank": bankNumber})
lastRow = cursor.fetchone()
for currentRow in cursor:
timeBetweenActivates = currentRow[1] - lastRow[1];
if(timeBetweenActivates < dramconfig.tRC):
return TestFailed("Activates with PhaseIDs {0} and {1} are {2} apart. Minimum time between two activates is {3}, since they are on the same bank({4})".
format(currentRow[0], lastRow[0],formatTime(timeBetweenActivates), dramconfig.tRC))
else:
lastRow = currentRow
return TestSuceeded()
@test
def n_activate_window_holds(connection):
"""Checks that the n-Activate constraint is met everywhere(JEDEC 229, P. 27)"""
cursor = connection.cursor()
cursor.execute("SELECT ID,PhaseBegin from Phases WHERE PhaseName = 'ACT' ORDER BY PhaseBegin")
activateWindow = []
for currentRow in cursor:
activateWindow.append(currentRow[1])
if(len(activateWindow) > dramconfig.nActivateWindow + 1):
activateWindow.pop(0)
if(activateWindow[dramconfig.nActivateWindow] - activateWindow[0] < dramconfig.tNAW):
return TestFailed("Activate with PhaseID {0} and the {1} preceeding activates violate the '{1} activate window' constraint."
" No more than {1} activates should be in rolling time window of {2}".format(currentRow[0], dramconfig.nActivateWindow,formatTime(dramconfig.tNAW)))
return TestSuceeded()
# ----------- read/write checks ---------------------------------------
@test
def read_to_read_holds(connection):
"""Check that the read operations do not intefere with each other on the data bus"""
cursor = connection.cursor()
cursor.execute("SELECT phases.ID,PhaseBegin,TBankGroup FROM Phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE PhaseName IN ('RD','RDA') ORDER BY PhaseBegin")
lastRow = cursor.fetchone()
for currentRow in cursor:
timeBetweenReads = currentRow[1] - lastRow[1]
if (currentRow[2] == lastRow[2]):
minTime = max(dramconfig.tCCD_L,dramconfig.getReadAccessTime())
else:
minTime = max(dramconfig.tCCD_S,dramconfig.getReadAccessTime())
if(timeBetweenReads < minTime):
return TestFailed("Reads with PhaseIDs {0} and {1} are {2} apart. Minimum time between two reads is {3}".format(currentRow[0], lastRow[0],formatTime(timeBetweenReads), minTime))
lastRow = currentRow
return TestSuceeded()
@test
def write_to_write_holds(connection):
"""Check that the write operations do not intefere with each other on the data bus"""
cursor = connection.cursor()
cursor.execute("SELECT phases.ID,PhaseBegin,TBankGroup FROM Phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE PhaseName IN ('WR','WRA') ORDER BY PhaseBegin")
lastRow = cursor.fetchone()
for currentRow in cursor:
timeBetweenWrites = currentRow[1] - lastRow[1]
if (currentRow[2] == lastRow[2]):
minTime = max(dramconfig.tCCD_L,dramconfig.getWriteAccessTime())
else:
minTime = max(dramconfig.tCCD_S,dramconfig.getWriteAccessTime())
if(timeBetweenWrites < minTime):
return TestFailed("Writes with PhaseIDs {0} and {1} are {2} apart. Minimum time between two writes is {3}".format(currentRow[0], lastRow[0],formatTime(timeBetweenWrites), minTime))
lastRow = currentRow
return TestSuceeded()
@test
def write_to_read_and_read_to_write_hold(connection):
"""Checks that read and write operation do not interfere with each other on the data bus
and that the write-to-read constraint is met"""
cursor = connection.cursor()
query = """SELECT Phases.ID,PhaseBegin,PhaseName,TBankGroup from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID
WHERE PhaseName IN ('RD','WR','RDA','WRA') ORDER BY PhaseBegin"""
cursor.execute(query)
lastRow = cursor.fetchone()
for currentRow in cursor:
if(currentRow[2] in ["RD","RDA"] and lastRow[2] in ["WR","WRA"]):
#write to read
if (currentRow[3] == lastRow[3]):
tWTR = dramconfig.tWTR_L
else:
tWTR = dramconfig.tWTR_S
minWriteToRead = dramconfig.tWL + dramconfig.getWriteAccessTime() + tWTR
writeToRead = currentRow[1] - lastRow[1]
if(writeToRead < minWriteToRead ):
return TestFailed("Read {0} starts {1} after start of write {2}. Minimum time is {3}".
format(currentRow[0],formatTime(writeToRead),lastRow[0], formatTime(minWriteToRead)))
elif(currentRow[2] in ["WR","WRA"] and lastRow[2] in ["RD","RDA"]):
#read to write
minReadToWrite = dramconfig.tRL + dramconfig.getReadAccessTime() - dramconfig.tWL + dramconfig.clk * 2
readToWrite = currentRow[1] - lastRow[1]
if(readToWrite < minReadToWrite ):
return TestFailed("Write {0} starts {1} after start of read {2}. Minimum time is {3}".
format(currentRow[0],formatTime(readToWrite),lastRow[0], formatTime(minWriteToRead)))
lastRow = currentRow
return TestSuceeded()
@test
def read_holds_dll_constraint_after_sref(connection):
"""Checks that all read operations are delayed long enough after the end of the self refresh powerdown state"""
cursor = connection.cursor()
query = """SELECT Phases.ID,PhaseBegin,PhaseName,TBankGroup from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID AND TBank = :bank
WHERE PhaseName IN ('RD', 'RDA', 'SREF') ORDER BY PhaseBegin"""
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query,{"bank": bankNumber})
lastRow = cursor.fetchone()
for currentRow in cursor:
if(currentRow[2] in ["RD","RDA"] and lastRow[2] == 'SREF'):
srefEndToRead = currentRow[1] - (lastRow[1] - dramconfig.clk)
if(srefEndToRead < dramconfig.tXSRDLL ):
return TestFailed("Read {0} starts {1} after end of sref {2}. Minimum time is {3}".
format(currentRow[0],formatTime(srefEndToRead),lastRow[0], formatTime(dramconfig.tXSRDLL)))
lastRow = currentRow
return TestSuceeded()
# ----------- powerdown checks ---------------------------------------
# @test
# def sref_active_for_minimal_time(connection):
# """Checks that after entering self refresh powerndown state, the state is active for a minimal time (JEDEC 229, P. 41)"""
#
# cursor = connection.cursor()
# cursor.execute("SELECT ID, PhaseEnd-clk-PhaseBegin FROM Phases, GeneralInfo 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()
# @test
# def pdna_pdnp_active_for_minimal_time(connection):
# """Checks that after entering active/precharged powerdown, the state is active for a minimal time (JEDEC 229, P. 41)"""
#
# cursor = connection.cursor()
# cursor.execute("SELECT ID,PhaseName, PhaseEnd-PhaseBegin FROM Phases, GeneralInfo WHERE PhaseName IN ('PDNA', 'PDNP') ")
# for currentRow in cursor:
# if(currentRow[2] < dramconfig.tCKE):
# return TestFailed("{0} with ID {1} is {2} long. Minimal time in SREF is {3}".format(currentRow[1], currentRow[0], formatTime(currentRow[2]), dramconfig.tCKE))
# return TestSuceeded()
# -------------------------- interface methods --------------------
def runTests(pathToTrace):
connection = sqlite3.connect(pathToTrace)
dramconfig.readConfigFromFiles(connection)
testResults = []
numberOfFailedTest = 0
print("================================")
print("RUNNING TEST ON {0}".format(pathToTrace))
print("-----------------------------\n")
for test in tests:
testResult = test(connection)
testName = test.__name__.replace("_"," ")
testResults.append((testName, testResult.passed,testResult.message))
if(testResult.passed):
print("[passed] {0}".format(testName))
else:
print("[failed] {0} failed. Message: {1}".format(testName, testResult.message))
numberOfFailedTest = numberOfFailedTest + 1
print("\n-----------------------------")
if(numberOfFailedTest == 0):
print("All tests passed")
else:
print("{0} of {1} tests passed".format(len(tests) - numberOfFailedTest,len(tests)))
print("================================")
connection.close()
return testResults
if __name__ == "__main__":
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w')
for i in range(1,len(sys.argv)):
runTests(sys.argv[i])

View File

@@ -16,6 +16,11 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = traceAnalyzer
TEMPLATE = app
#copy python scripts
config.path = $${OUT_PWD}/scripts
config.files = scripts/*
INSTALLS += config
SOURCES += main.cpp\
businessObjects/transaction.cpp \
businessObjects/timespan.cpp \
@@ -95,7 +100,11 @@ FORMS += \
evaluationtool.ui
OTHER_FILES += \
common/static/createTraceDB.sql
common/static/createTraceDB.sql \
tests.py \
metrics.py \
scripts/metrics.py \
scripts/tests.py
QMAKE_CXXFLAGS += -std=c++11
QMAKE_CXXFLAGS += -Xlinker -export-dynamic

View File

@@ -57,22 +57,22 @@ SOURCES += \
../src/controller/core/scheduling/checker/PowerDownChecker.cpp \
../src/controller/core/scheduling/checker/ActivateChecker.cpp \
../src/controller/core/scheduling/ScheduledCommand.cpp \
../src/controller/core/scheduling/CommandSequenceScheduler.cpp \
../src/controller/core/scheduling/CommandSequenceGenerator.cpp \
../src/controller/core/TimingCalculation.cpp \
../src/controller/core/Slots.cpp \
../src/controller/core/ControllerState.cpp \
../src/controller/core/ControllerCore.cpp \
../src/controller/core/Command.cpp \
../src/simulation/SimulationManager.cpp \
../src/simulation/Simulation.cpp \
../src/simulation/MemoryManager.cpp \
../src/simulation/main.cpp \
../src/controller/core/RowBufferStates.cpp \
../src/controller/scheduler/Scheduler.cpp \
../src/controller/scheduler/readwritegrouper.cpp \
../src/controller/core/configuration/ConfigurationLoader.cpp \
../src/controller/core/powerdown/NoPowerDown.cpp
../src/controller/core/powerdown/NoPowerDown.cpp \
../src/controller/Command.cpp \
../src/controller/Controller.cpp \
../src/controller/ControllerState.cpp \
../src/controller/RowBufferStates.cpp \
../src/controller/scheduler/IScheduler.cpp \
../src/controller/scheduler/FifoStrict.cpp
HEADERS += \
../src/common/third_party/tinyxml2.h \
@@ -88,7 +88,6 @@ HEADERS += \
../src/controller/core/powerdown/PowerDownManagerBankwise.h \
../src/controller/core/powerdown/PowerDownManager.h \
../src/controller/scheduler/ThreadLoad.h \
../src/controller/scheduler/Scheduler.h \
../src/controller/scheduler/PARBS.h \
../src/controller/scheduler/Fr_Fcfs.h \
../src/controller/scheduler/Fifo.h \
@@ -106,15 +105,9 @@ HEADERS += \
../src/controller/core/scheduling/checker/ActivateChecker.h \
../src/controller/core/scheduling/Trigger.h \
../src/controller/core/scheduling/ScheduledCommand.h \
../src/controller/core/scheduling/CommandSequenceScheduler.h \
../src/controller/core/scheduling/CommandSequenceGenerator.h \
../src/controller/core/scheduling/CommandSchedule.h \
../src/controller/core/TimingCalculation.h \
../src/controller/core/Slots.h \
../src/controller/core/IWrapperConnector.h \
../src/controller/core/ControllerState.h \
../src/controller/core/ControllerCore.h \
../src/controller/core/Command.h \
../src/simulation/TracePlayer.h \
../src/simulation/SimulationManager.h \
../src/simulation/Simulation.h \
@@ -122,13 +115,19 @@ HEADERS += \
../src/simulation/Dram.h \
../src/simulation/Arbiter.h \
../src/common/libDRAMPower.h \
../src/controller/core/RowBufferStates.h \
../src/controller/scheduler/readwritegrouper.h \
../src/simulation/ReorderBuffer.h \
../src/controller/core/configuration/MemSpec.h \
../src/simulation/StlPlayer.h \
../src/simulation/TracePlayerListener.h \
../src/simulation/TraceGenerator.h \
../src/controller/core/powerdown/NoPowerDown.h
../src/controller/core/powerdown/NoPowerDown.h \
../src/controller/Command.h \
../src/controller/RowBufferStates.h \
../src/controller/ControllerState.h \
../src/controller/core/powerdown/IPowerDownManager.h \
../src/controller/scheduler/IScheduler.h \
../src/controller/scheduler/FifoStrict.h \
../src/controller/IController.h
../src/controller/core/configuration/ConfigurationLoader.h

View File

@@ -1,11 +1,9 @@
<memconfig>
<BankwiseLogic value="0"/>
<OpenPagePolicy value="1" />
<AdaptiveOpenPagePolicy value="0" />
<RefreshAwareScheduling value="1" />
<MaxNrOfTransactions value="50" />
<Scheduler value="FIFO" />
<Capsize value="5" />
<PowerDownMode value="Staggered" />
<PowerDownMode value="TimeoutPDN" />
<PowerDownTimeout value="100" />
</memconfig>
</memconfig>

View File

@@ -1,12 +1,10 @@
<memconfig>
<BankwiseLogic value="0"/>
<OpenPagePolicy value="1" />
<AdaptiveOpenPagePolicy value="0" />
<RefreshAwareScheduling value="1" />
<MaxNrOfTransactions value="50" />
<Scheduler value="FR_FCFS" />
<Capsize value="5" />
<PowerDownMode value="NoPowerDown" />
<PowerDownMode value="TimeoutPDN" />
<PowerDownTimeout value="100" />
<!--
<Buswidth value="128" />

View File

@@ -1,17 +0,0 @@
import stlGenerator
stlGenerator = stlGenerator.StlGenerator()
def simple_frfcfs():
stlGenerator.clear()
stlGenerator.addAction(0, 0)
stlGenerator.addAction(0, 1)
stlGenerator.addAction(2, 0)
stlGenerator.addAction(3, 0)
stlGenerator.addAction(4, 0)
stlGenerator.addAction(5, 0)
stlGenerator.generateStl('../traces/test2.stl')
if __name__ == '__main__':
simple_frfcfs();

View File

@@ -1,123 +0,0 @@
import xml.etree.ElementTree as ET
import re
import sys
import os
class DramConfigReader:
maxValues = {}
startBits = {}
endBits = {}
def __extractAdressEncoding(self, root, elementName):
rowElement = root[0].find(elementName)
rowBitFrom, rowBitsTo = int(
rowElement.attrib['from']), int(rowElement.attrib['to'])
rowBitRange = rowBitsTo - rowBitFrom + 1
maxRow = 2 ** rowBitRange - 1
print('{0}: range {1}..{2}'.format(elementName, 0, maxRow))
self.startBits[elementName] = rowBitFrom
self.endBits[elementName] = rowBitsTo
self.maxValues[elementName] = maxRow
def __init__(self):
root = ET.parse(
os.path.dirname(os.path.realpath(sys.argv[0])) + '/../configs/addressConfig.xml').getroot()
self.__extractAdressEncoding(root, 'channel')
self.__extractAdressEncoding(root, 'bank')
self.__extractAdressEncoding(root, 'row')
self.__extractAdressEncoding(root, 'colum')
print(self.startBits)
print(self.endBits)
class StlReader:
# __dramConfigReader = DramConfigReader()
# def onesMask(self, numberOfOnes):
# result = 0
# for i in range(numberOfOnes):
# result = result | 1 << i
# return result
# def parseAttributeFromAddress(self, address, element):
# return (address >> self.__dramConfigReader.startBits[element]) & self.onesMask(self.__dramConfigReader.endBits[element] - self.__dramConfigReader.startBits[element] + 1)
# def formatStlLine(self, line):
# try:
# found = re.search('0x[0-9,a-f]+', line).group(0)
# address = int(found, 16)
# decodedAddress = '[Channel: {0} Bank: {0} Row:{1} Col:{2}]'.format(self.parseAttributeFromAddress(address, 'channel'),
# self.parseAttributeFromAddress(address, 'bank'), self.parseAttributeFromAddress(address, 'row'), self.parseAttributeFromAddress(address, 'colum'))
# return line.replace("\n", " ") + decodedAddress
# except AttributeError:
# return ''
def printStlPretty(self, filename):
f = open(filename)
for line in f.readlines():
#print(self.formatStlLine(line))
found = re.search('0x[0-9,a-f]+', line).group(0)
address = int(found, 16)
print(format(address, '032b')) #+ " " + self.formatStlLine(line))
# class StlGenerator:
# __actions = []
# __time = 0
# __dramConfigReader = DramConfigReader()
# def clear(self):
# self.__actions = []
# self.__time = 0
# def setTime(self, time):
# self.__time = time
# def addAction(self, bank, row, channel=0, RD_WR='read'):
# tupel = (self.__time, RD_WR, self.__generateAdress(channel, bank, row))
# self.__actions.append(tupel)
# def setTimeAndAddAction(self, time, bank, row, channel=0, RD_WR='read'):
# self.setTime(self, time)
# self.addAction(self, bank, row, channel, RD_WR)
# def addLoad(self, banks, rows, channel=0, RD_WR='read'):
# for bank in banks:
# for row in rows:
# self.addAction(bank, row, channel, RD_WR)
# def setTimeAndAddLoad(self, time, banks, rows, channel=0, RD_WR='read'):
# self.setTime(self, time)
# self.addLoad(banks, rows, channel, RD_WR)
# def generateStl(self, filename):
# f = open(filename, 'w')
# tmp = []
# for tupel in self.__actions:
# tmp.append('{0}: {1} {2:#x}'.format(tupel[0], tupel[1], tupel[2]))
# result = '\n'.join(tmp)
# f.write(result)
# f.close()
# print(
# '<---------------------- Generated stl {0} ---------------------->'.format(filename))
# print(result)
# print(
# '<---------------------- End generated stl ---------------------->'.format(filename))
# def __generateAdress(self, channel, bank, row):
# if(channel > self.__dramConfigReader.maxValues['channel']):
# raise(BaseException('Channel argument out of range'))
# if(bank > self.__dramConfigReader.maxValues['bank']):
# raise(BaseException('Bank argument out of range'))
# if(row > self.__dramConfigReader.maxValues['row']):
# raise(BaseException('Row argument out of range'))
# return (channel << self.__dramConfigReader.startBits['channel']) | (bank << self.__dramConfigReader.startBits['bank']) | (row << self.__dramConfigReader.startBits['row'])
# def __init__(self):
# pass
if __name__ == '__main__':
if(len(sys.argv) > 1):
stlReader = StlReader()
for line in sys.argv[1:]:
stlReader.printStlPretty(line)

View File

@@ -1,617 +0,0 @@
import sys
import traceback
import sqlite3
import os
import xml.etree.ElementTree as ET
def getPathToConfigs():
return os.path.dirname(os.path.abspath(__file__).replace("/scripts","/configs"))
def getValueFromConfigXML(root, id):
return root.findall(".//parameter[@id='{0}']".format(id))[0].attrib['value']
def getIntValueFromConfigXML(root, id):
return int(root.findall(".//parameter[@id='{0}']".format(id))[0].attrib['value'])
def getMemconfig(connection):
cursor = connection.cursor()
cursor.execute("SELECT Memconfig FROM GeneralInfo")
result = cursor.fetchone()
memconfig = getPathToConfigs() + "/memconfigs/" + result[0]
return ET.parse(memconfig)
def getMemspec(connection):
cursor = connection.cursor()
cursor.execute("SELECT Memspec FROM GeneralInfo")
result = cursor.fetchone()
memspec = getPathToConfigs() + "/memspecs/" + result[0]
return ET.parse(memspec)
def getClock(connection):
cursor = connection.cursor()
cursor.execute("SELECT clk, UnitOfTime FROM GeneralInfo")
result = cursor.fetchone()
return (result[0],result[1])
class DramConfig(object):
memoryType = ""
bankwiseLogic = 0
clk = 0
unitOfTime = ""
dataRate = 0
nActivateWindow = numberOfBanks = 0
clk = 0
tRP = 0 #precharge-time (pre -> act same bank)
tRAS = 0 #active-time (act -> pre same bank)
tRC = 0 #RAS-cycle-time (min time bw 2 succesive ACT to same bank)
tCCD_S = 0 #TODO: relevant? max(bl, tCCD)
tCCD_L = 0
tRTP = 0 #Read to precharge
tRRD_S = 0 #min time bw 2 succesive ACT to different banks (different bank group)
tRRD_L = 0 #.. (same bank group)
tRCD = 0 #act -> read/write
tNAW = 0 #n activate window
tRL = 0 #read latency (read command start to data strobe)
tWL = 0 #write latency
tWR = 0 #write recovery (write to precharge)
tWTR_S = 0 #write to read (different bank group)
tWTR_L = 0 #.. (same bank group)
tCKESR = 0 #min time in sref
tCKE = 0 #min time in pdna or pdnp
tXP = 0 #min delay to row access command after pdnpx pdnax
tXPDLL = 0 #min delay to row access command after pdnpx pdnax for dll commands
tXSR = 0 #min delay to row access command after srefx
tXSRDLL = 0 #min delay to row access command after srefx for dll commands
tAL = 0 #additive delay (delayed execution in dram)
tRFC = 0 #min ref->act delay
def readConfigFromFiles(self, connection):
print("Parsing dram configuration")
memspec = getMemspec(connection)
clkWithUnit = getClock(connection)
self.clk = clkWithUnit[0]
self.unitOfTime = clkWithUnit[1].lower()
self.bankwiseLogic = getIntValueFromConfigXML(getMemconfig(connection), "bankwiseLogic")
self.numberOfBanks = getIntValueFromConfigXML(memspec, "nbrOfBanks")
self.burstLength = getIntValueFromConfigXML(memspec, "burstLength")
self.memoryType = getValueFromConfigXML(memspec, "memoryType")
self.dataRate = getIntValueFromConfigXML(memspec, "dataRate")
if(self.memoryType == "WIDEIO_SDR"):
self.nActivateWindow = 2;
self.tRP = self.clk * getIntValueFromConfigXML(memspec, "RP")
self.tRAS = self.clk * getIntValueFromConfigXML(memspec, "RAS")
self.tRC = self.clk * getIntValueFromConfigXML(memspec, "RC")
self.tRRD_S = self.clk * getIntValueFromConfigXML(memspec, "RRD")
self.tRRD_L = self.tRRD_S
self.tCCD_S = self.clk * getIntValueFromConfigXML(memspec, "CCD")
self.tCCD_L = self.tCCD_S
self.tRCD = self.clk * getIntValueFromConfigXML(memspec, "RCD")
self.tNAW = self.clk * getIntValueFromConfigXML(memspec, "TAW")
self.tRL = self.clk * getIntValueFromConfigXML(memspec, "RL")
self.tWL = self.clk * getIntValueFromConfigXML(memspec, "WL")
self.tWR = self.clk * getIntValueFromConfigXML(memspec, "WR")
self.tWTR_S = self.clk * getIntValueFromConfigXML(memspec, "WTR")
self.tWTR_L = self.tWTR_S
self.tRTP = self.clk * getIntValueFromConfigXML(memspec, "RTP");
self.tCKESR = self.clk * getIntValueFromConfigXML(memspec, "CKESR")
self.tCKE = self.clk * getIntValueFromConfigXML(memspec, "CKE")
self.tXP = self.clk * getIntValueFromConfigXML(memspec, "XP")
self.tXPDLL = self.tXP
self.tXSR = self.clk * getIntValueFromConfigXML(memspec, "XS")
self.tXSRDLL = self.tXSR
self.tAL = self.clk * getIntValueFromConfigXML(memspec, "AL")
self.tRFC = self.clk * getIntValueFromConfigXML(memspec, "RFC")
elif(self. memoryType == "DDR4"):
self.nActivateWindow = 4;
self.tRP = self.clk * getIntValueFromConfigXML(memspec, "RP");
self.tRAS = self.clk * getIntValueFromConfigXML(memspec, "RAS");
self.tRC = self.clk * getIntValueFromConfigXML(memspec, "RC");
self.tRTP = self.clk * getIntValueFromConfigXML(memspec, "RTP");
self.tRRD_S = self.clk * getIntValueFromConfigXML(memspec, "RRD_S");
self.tRRD_L = self.clk * getIntValueFromConfigXML(memspec, "RRD_L");
self.tCCD_S = self.clk * getIntValueFromConfigXML(memspec, "CCD_S");
self.tCCD_L = self.clk * getIntValueFromConfigXML(memspec, "CCD_L");
self.tRCD = self.clk * getIntValueFromConfigXML(memspec, "RCD");
self.tNAW = self.clk * getIntValueFromConfigXML(memspec, "FAW");
self.tRL = self.clk * getIntValueFromConfigXML(memspec, "RL");
self.tWL = self.clk * getIntValueFromConfigXML(memspec, "WL");
self.tWR = self.clk * getIntValueFromConfigXML(memspec, "WR");
self.tWTR_S = self.clk * getIntValueFromConfigXML(memspec, "WTR_S");
self.tWTR_L = self.clk * getIntValueFromConfigXML(memspec, "WTR_L");
self.tCKESR = self.clk * getIntValueFromConfigXML(memspec, "CKESR");
self.tCKE = self.clk * getIntValueFromConfigXML(memspec, "CKE");
self.tXP = self.clk * getIntValueFromConfigXML(memspec, "XP");
self.tXPDLL = self.clk * getIntValueFromConfigXML(memspec, "XPDLL");
self.tXSR = self.clk * getIntValueFromConfigXML(memspec, "XS");
self.tXSRDLL = self.clk * getIntValueFromConfigXML(memspec, "XSDLL");
self.tAL = self.clk * getIntValueFromConfigXML(memspec, "AL");
self.tRFC = self.clk * getIntValueFromConfigXML(memspec, "RFC");
else:
raise Exception("MemoryType not supported yet. Insert a coin into the coin machine and try again")
def clkAlign(self, value):
return math.ceil(1.0*value/self.clk)*self.clk
def getWriteAccessTime(self):
if(self.dataRate == 1):
return self.clk*(self.burstLength - 1)
elif (self.memoryType == "DDR4"):
return self.clk*self.burstLength/self.dataRate
def getReadAccessTime(self):
return self.burstLength/self.dataRate * dramconfig.clk
def __init__(self):
pass
dramconfig = DramConfig()
def calculateReadLength(burstLength):
return dramconfig.tRL + burstLength * dramconfig.clk
def calculateWriteLength(burstLength):
return dramconfig.tWL + burstLength * dramconfig.clk
# ----------- test utils ---------------------------------------
tests = []
def test(function):
tests.append(function)
return function
class TestResult(object):
passed = True
message = ''
def __init__(self, passed = True, message = ''):
self.passed = passed
self.message = message
def TestSuceeded():
return TestResult()
def TestFailed(message):
return TestResult(False,message);
def formatTime(time):
return ('{0} {1}'.format(time, dramconfig.unitOfTime))
# ----------- checks ---------------------------------------
@test
def commands_are_clockaligned(connection):
"""Checks that all commands on the command bus are aligned to the system clock"""
cursor = connection.cursor()
query = "select ID,PhaseBegin,PhaseEnd from phases where phaseName NOT IN ('REQ','RESP') AND (phaseBegin%:clk!=0 OR phaseEnd%:clk!=0)"
cursor.execute(query, {"clk": dramconfig.clk})
result = cursor.fetchone()
if(result != None):
return TestFailed("Command with PhaseID {0} starts at {1} and ends at. One of those times. is not aligned to system clock ({2})"
.format(result[0], formatTime(result[1]), formatTime(result[2]), formatTime(dramconfig.clk)))
return TestSuceeded()
@test
def commandbus_slots_are_used_once(connection):
"""Checks that no two phases on the command bus start at the same time"""
cursor = connection.cursor()
if dramconfig.bankwiseLogic:
excludedPhases = "('REQ','RESP','PRE_ALL')"
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 multiple times".format(formatTime(result[0])))
return TestSuceeded()
@test
def phase_transitions_are_valid(connection):
"""Checks that all transition of two consequtive phases on the same bank are valid"""
cursor = connection.cursor()
validTransitions = {}
if(dramconfig.bankwiseLogic):
validTransitions['PRE'] = set(['ACT', 'AUTO_REFRESH'])
validTransitions['ACT'] = set(['RD', 'RDA', 'WR', 'WRA'])
validTransitions['RD'] = set(['PRE','RD','RDA', 'WR', 'WRA', 'PDNA'])
validTransitions['WR'] = set(['PRE', 'RD','RDA', 'WR', 'WRA', 'PDNA'])
validTransitions['RDA'] = set(['ACT', 'AUTO_REFRESH', 'PDNP'])
validTransitions['WRA'] = set(['ACT', 'AUTO_REFRESH', 'PDNP'])
validTransitions['AUTO_REFRESH'] = set(['ACT', 'PDNP', 'SREF'])
validTransitions['PDNA'] = set(['PRE', 'RD','RDA', 'WR', 'WRA', 'AUTO_REFRESH'])
validTransitions['PDNP'] = set(['ACT', 'AUTO_REFRESH'])
validTransitions['SREF'] = set(['ACT'])
else:
validTransitions['PRE'] = set(['ACT'])
validTransitions['PRE_ALL'] = set(['AUTO_REFRESH'])
validTransitions['ACT'] = set(['RD', 'RDA', 'WR', 'WRA'])
validTransitions['RD'] = set(['PRE', 'PRE_ALL','RD','RDA', 'WR', 'WRA', 'PDNA'])
validTransitions['WR'] = set(['PRE', 'PRE_ALL','RD','RDA', 'WR', 'WRA', 'PDNA'])
validTransitions['RDA'] = set(['PRE_ALL', 'ACT', 'AUTO_REFRESH', 'PDNA', 'PDNP'])
validTransitions['WRA'] = set(['PRE_ALL', 'ACT', 'AUTO_REFRESH', 'PDNA', 'PDNP'])
validTransitions['AUTO_REFRESH'] = set(['PRE_ALL', 'ACT','AUTO_REFRESH', 'PDNA', 'PDNP', 'SREF'])
validTransitions['PDNA'] = set(['PRE','PRE_ALL','ACT', 'RD', 'RDA', 'WR', 'WRA', 'AUTO_REFRESH', 'PDNA', 'PDNP'])
validTransitions['PDNP'] = set(['PRE_ALL', 'ACT', 'AUTO_REFRESH', 'PDNA', 'PDNP'])
validTransitions['SREF'] = set(['PRE_ALL', 'ACT', 'AUTO_REFRESH', 'PDNA', 'PDNP'])
query = """SELECT PhaseName, phases.ID FROM phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE TBank=:bank
AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin"""
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query, {"bank": bankNumber})
lastRow = cursor.fetchone()
for currentRow in cursor:
currentPhase = currentRow[0]
lastPhase = lastRow[0]
if(currentPhase not in validTransitions[lastPhase]):
return TestFailed("Phase {0}({1}) is not allowed to follow phase {2}({3})".format(currentRow[1],currentPhase,lastRow[1],lastPhase))
lastRow = currentRow
return TestSuceeded()
def timing_constraint(FirstPhase, SecondPhase):
FirstPhaseName = FirstPhase[0]
SecondPhaseName = SecondPhase[0]
if(FirstPhaseName == "PRE" or FirstPhaseName == "PRE_ALL"):
return dramconfig.tRP
elif(FirstPhaseName == "ACT"):
return dramconfig.tRCD
elif(FirstPhaseName == "RD"):
if(SecondPhaseName in ["PRE, PRE_ALL"]):
return dramconfig.tRTP
elif(SecondPhaseName in ["RD, RDA"]):
return max(dramconfig.tCCD_L, getReadAccessTime())
elif(SecondPhase in ["WR","WRA"]):
return dramconfig.tRL + getReadAccessTime() - dramconfig.tWL + 2*dramconfig.clk
elif(SecondPhase == "PDNA" ):
return dramconfig.tRL + getReadAccessTime() + dramconfig.clk
elif(FirstPhaseName == "WR"):
if(SecondPhaseName in ["PRE, PRE_ALL", "PDNA"]):
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR
elif(SecondPhaseName in ["RD, RDA"]):
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWTR_L
elif(SecondPhaseName in ["WR, WRA"]):
return max(dramconfig.tCCD_L, burstlength/dramconfig.dataRate)
elif(FirstPhaseName == "RDA"):
if(SecondPhaseName in ["ACT", "PRE_ALL", "AUTO_REFRESH"]):
return dramconfig.tRTP + dramconfig.tRP
elif(SecondPhaseName in ["PDNA","PDNP"]):
return dramconfig.tRL + getReadAccessTime() + dramconfig.clk
elif(FirstPhaseName == "WRA"):
if(SecondPhaseName in ["ACT", "PRE_ALL", "AUTO_REFRESH"]):
return dramconfig.tWL + getWriteAccessTime() + dramconfig.tWR + dramconfig.tRP
elif(SecondPhaseName in ["PDNA","PDNP"]):
return dramconfig.tWL + dramconfig.getWriteAccessTime() + dramconfig.tWR + dramconfig.clk
elif(FirstPhaseName == "AUTO_REFRESH"):
return dramconfig.tRFC
elif(FirstPhaseName in ["PDNA","PDNP"]):
return (FirstPhase[3] - FirstPhase[2]) + dramconfig.tXP - dramconfig.clk
elif(FirstPhaseName == "SREF"):
return (FirstPhase[3] - FirstPhase[2]) + dramconfig.tXSR - dramconfig.clk
return 0
@test
def timing_constraits_on_the_same_bank_hold(connection):
"""Checks that all transitions of two consequtive phases on the same bank meet their timing constraints"""
cursor = connection.cursor()
validTransitions = {}
query = """SELECT PhaseName, phases.ID,PhaseBegin,PhaseEnd FROM phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE TBank=:bank
AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin"""
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query, {"bank": bankNumber})
lastRow = cursor.fetchone()
for currentRow in cursor:
constraint = timing_constraint(lastRow,currentRow)
if(currentRow[2] - lastRow[2] + constraint < 0):
return TestFailed("Phase {0}({1}) starts {2} after Start of Phase {3}({4}). Minimal time is {5}".format(
currentRow[1],currentRow[0],formatTime(currentRow[2]-lastRow[2]),lastRow[1],lastRow[0], formatTime(constraint)))
lastRow = currentRow
return TestSuceeded()
@test
def row_buffer_is_used_correctly(connection):
"""Checks that each bank's row buffer is used correctly"""
cursor = connection.cursor()
query = """SELECT PhaseName, phases.ID FROM phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE TBank=:bank
AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin"""
#phases that precharge the bank and close the rowbuffer
prechargingPhases = set(['PRE','PRE_ALL','RDA','WRA'])
#phases that require the bank to be in active state and the rowbuffer to be opened
accessingPhases = set(['RD','RDA', 'WR', 'WRA', 'PRE'])
#phases that require the bank to be in precharged state and the robuffer to be closed
idlePhases = set(['ACT', 'PDNP', 'AUTO_REFRESH', 'SREF'])
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query,{"bank": bankNumber})
rowBufferIsClosed = True
for currentRow in cursor:
if(currentRow[0] in accessingPhases and rowBufferIsClosed == True):
return TestFailed("Phase {0}({1}) acesses a closed rowbuffer".format(currentRow[1], currentRow[0]))
if(currentRow[0] in idlePhases and rowBufferIsClosed == False):
return TestFailed("Phase {0}({1}) needs a closed rowbuffer".format(currentRow[1], currentRow[0]))
if(currentRow[0] == 'ACT'):
rowBufferIsClosed = False
if(currentRow[0] in prechargingPhases):
rowBufferIsClosed = True
return TestSuceeded()
#----------- activate checks ---------------------------------------
@test
def activate_to_activate_holds(connection):
"""Checks that all activates are far enough apart(JESD229 229, P. 27)"""
cursor = connection.cursor()
cursor.execute("SELECT phases.ID,PhaseBegin,TBankGroup FROM Phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE PhaseName = 'ACT' ORDER BY PhaseBegin")
lastRow = cursor.fetchone()
for currentRow in cursor:
timeBetweenActivates = currentRow[1] - lastRow[1]
if (currentRow[2] == lastRow[2]):
minTime = dramconfig.tRRD_L
else:
minTime = dramconfig.tRRD_S
if(timeBetweenActivates < minTime):
return TestFailed("Activates with PhaseIDs {0} and {1} are {2} apart. Minimum time between two activates is {3}".
format(currentRow[0], lastRow[0],formatTime(timeBetweenActivates), formatTime(minTime)))
lastRow = currentRow
return TestSuceeded()
@test
def activate_to_activate_on_same_bank_holds(connection):
"""Checks that all activates on the same bank are far enough apart (JEDEC 229, P. 27)"""
cursor = connection.cursor()
query = "SELECT Phases.ID,PhaseBegin from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID WHERE PhaseName = 'ACT' AND TBANK = :bank ORDER BY PhaseBegin"
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query,{"bank": bankNumber})
lastRow = cursor.fetchone()
for currentRow in cursor:
timeBetweenActivates = currentRow[1] - lastRow[1];
if(timeBetweenActivates < dramconfig.tRC):
return TestFailed("Activates with PhaseIDs {0} and {1} are {2} apart. Minimum time between two activates is {3}, since they are on the same bank({4})".
format(currentRow[0], lastRow[0],formatTime(timeBetweenActivates), dramconfig.tRC))
else:
lastRow = currentRow
return TestSuceeded()
@test
def n_activate_window_holds(connection):
"""Checks that the n-Activate constraint is met everywhere(JEDEC 229, P. 27)"""
cursor = connection.cursor()
cursor.execute("SELECT ID,PhaseBegin from Phases WHERE PhaseName = 'ACT' ORDER BY PhaseBegin")
activateWindow = []
for currentRow in cursor:
activateWindow.append(currentRow[1])
if(len(activateWindow) > dramconfig.nActivateWindow + 1):
activateWindow.pop(0)
if(activateWindow[dramconfig.nActivateWindow] - activateWindow[0] < dramconfig.tNAW):
return TestFailed("Activate with PhaseID {0} and the {1} preceeding activates violate the '{1} activate window' constraint."
" No more than {1} activates should be in rolling time window of {2}".format(currentRow[0], dramconfig.nActivateWindow,formatTime(dramconfig.tNAW)))
return TestSuceeded()
# ----------- read/write checks ---------------------------------------
@test
def read_to_read_holds(connection):
"""Check that the read operations do not intefere with each other on the data bus"""
cursor = connection.cursor()
cursor.execute("SELECT phases.ID,PhaseBegin,TBankGroup FROM Phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE PhaseName IN ('RD','RDA') ORDER BY PhaseBegin")
lastRow = cursor.fetchone()
for currentRow in cursor:
timeBetweenReads = currentRow[1] - lastRow[1]
if (currentRow[2] == lastRow[2]):
minTime = max(dramconfig.tCCD_L,dramconfig.getReadAccessTime())
else:
minTime = max(dramconfig.tCCD_S,dramconfig.getReadAccessTime())
if(timeBetweenReads < minTime):
return TestFailed("Reads with PhaseIDs {0} and {1} are {2} apart. Minimum time between two reads is {3}".format(currentRow[0], lastRow[0],formatTime(timeBetweenReads), minTime))
lastRow = currentRow
return TestSuceeded()
@test
def write_to_write_holds(connection):
"""Check that the write operations do not intefere with each other on the data bus"""
cursor = connection.cursor()
cursor.execute("SELECT phases.ID,PhaseBegin,TBankGroup FROM Phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE PhaseName IN ('WR','WRA') ORDER BY PhaseBegin")
lastRow = cursor.fetchone()
for currentRow in cursor:
timeBetweenWrites = currentRow[1] - lastRow[1]
if (currentRow[2] == lastRow[2]):
minTime = max(dramconfig.tCCD_L,dramconfig.getWriteAccessTime())
else:
minTime = max(dramconfig.tCCD_S,dramconfig.getWriteAccessTime())
if(timeBetweenWrites < minTime):
return TestFailed("Writes with PhaseIDs {0} and {1} are {2} apart. Minimum time between two writes is {3}".format(currentRow[0], lastRow[0],formatTime(timeBetweenWrites), minTime))
lastRow = currentRow
return TestSuceeded()
@test
def write_to_read_and_read_to_write_hold(connection):
"""Checks that read and write operation do not interfere with each other on the data bus
and that the write-to-read constraint is met"""
cursor = connection.cursor()
query = """SELECT Phases.ID,PhaseBegin,PhaseName,TBankGroup from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID
WHERE PhaseName IN ('RD','WR','RDA','WRA') ORDER BY PhaseBegin"""
cursor.execute(query)
lastRow = cursor.fetchone()
for currentRow in cursor:
if(currentRow[2] in ["RD","RDA"] and lastRow[2] in ["WR","WRA"]):
#write to read
if (currentRow[3] == lastRow[3]):
tWTR = dramconfig.tWTR_L
else:
tWTR = dramconfig.tWTR_S
minWriteToRead = dramconfig.tWL + dramconfig.getWriteAccessTime() + tWTR
writeToRead = currentRow[1] - lastRow[1]
if(writeToRead < minWriteToRead ):
return TestFailed("Read {0} starts {1} after start of write {2}. Minimum time is {3}".
format(currentRow[0],formatTime(writeToRead),lastRow[0], formatTime(minWriteToRead)))
elif(currentRow[2] in ["WR","WRA"] and lastRow[2] in ["RD","RDA"]):
#read to write
minReadToWrite = dramconfig.tRL + dramconfig.getReadAccessTime() - dramconfig.tWL + dramconfig.clk * 2
readToWrite = currentRow[1] - lastRow[1]
if(readToWrite < minReadToWrite ):
return TestFailed("Write {0} starts {1} after start of read {2}. Minimum time is {3}".
format(currentRow[0],formatTime(readToWrite),lastRow[0], formatTime(minWriteToRead)))
lastRow = currentRow
return TestSuceeded()
@test
def read_holds_dll_constraint_after_sref(connection):
"""Checks that all read operations are delayed long enough after the end of the self refresh powerdown state"""
cursor = connection.cursor()
query = """SELECT Phases.ID,PhaseBegin,PhaseName,TBankGroup from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID AND TBank = :bank
WHERE PhaseName IN ('RD', 'RDA', 'SREF') ORDER BY PhaseBegin"""
for bankNumber in range(dramconfig.numberOfBanks):
cursor.execute(query,{"bank": bankNumber})
lastRow = cursor.fetchone()
for currentRow in cursor:
if(currentRow[2] in ["RD","RDA"] and lastRow[2] == 'SREF'):
srefEndToRead = currentRow[1] - (lastRow[1] - dramconfig.clk)
if(srefEndToRead < dramconfig.tXSRDLL ):
return TestFailed("Read {0} starts {1} after end of sref {2}. Minimum time is {3}".
format(currentRow[0],formatTime(srefEndToRead),lastRow[0], formatTime(dramconfig.tXSRDLL)))
lastRow = currentRow
return TestSuceeded()
# ----------- powerdown checks ---------------------------------------
# @test
# def sref_active_for_minimal_time(connection):
# """Checks that after entering self refresh powerndown state, the state is active for a minimal time (JEDEC 229, P. 41)"""
#
# cursor = connection.cursor()
# cursor.execute("SELECT ID, PhaseEnd-clk-PhaseBegin FROM Phases, GeneralInfo 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()
# @test
# def pdna_pdnp_active_for_minimal_time(connection):
# """Checks that after entering active/precharged powerdown, the state is active for a minimal time (JEDEC 229, P. 41)"""
#
# cursor = connection.cursor()
# cursor.execute("SELECT ID,PhaseName, PhaseEnd-PhaseBegin FROM Phases, GeneralInfo WHERE PhaseName IN ('PDNA', 'PDNP') ")
# for currentRow in cursor:
# if(currentRow[2] < dramconfig.tCKE):
# return TestFailed("{0} with ID {1} is {2} long. Minimal time in SREF is {3}".format(currentRow[1], currentRow[0], formatTime(currentRow[2]), dramconfig.tCKE))
# return TestSuceeded()
# -------------------------- interface methods --------------------
def runTests(pathToTrace):
print(pathToTrace)
connection = sqlite3.connect(pathToTrace)
dramconfig.readConfigFromFiles(connection)
testResults = []
numberOfFailedTest = 0
print("================================")
print("RUNNING TEST ON {0}".format(pathToTrace))
print("-----------------------------\n")
for test in tests:
testResult = test(connection)
testName = test.__name__.replace("_"," ")
testResults.append((testName, testResult.passed,testResult.message))
if(testResult.passed):
print("[passed] {0}".format(testName))
else:
print("[failed] {0} failed. Message: {1}".format(testName, testResult.message))
numberOfFailedTest = numberOfFailedTest + 1
print("\n-----------------------------")
if(numberOfFailedTest == 0):
print("All tests passed")
else:
print("{0} of {1} tests passed".format(len(tests) - numberOfFailedTest,len(tests)))
print("================================")
connection.close()
return testResults
if __name__ == "__main__":
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w')
for i in range(1,len(sys.argv)):
runTests(sys.argv[i])

View File

@@ -1,22 +0,0 @@
<simulation id="datasizes">
<memspec>JEDEC_256Mb_WIDEIO_SDR-266_128bit.xml</memspec>
<addressmapping>am_wideioFourBanks.xml</addressmapping>
<memconfigs>
<memconfig>fr_fcfs_unaware.xml</memconfig>
</memconfigs>
<trace-setups>
<trace-setup id="1">
<device >chstone-aes_32.stl</device>
<device >chstone-motion_32.stl</device>
</trace-setup>
<trace-setup id="2">
<device >chstone-motion_32.stl</device>
<device >chstone-jpeg_32.stl</device>
</trace-setup>
</trace-setups>
</simulation>

View File

@@ -1,25 +1,25 @@
<simulation>
<simconfig>
<Debug value="1" />
<Debug value="1" />
<DatabaseRecording value="1" />
<PowerAnalysys value="0" />
</simconfig>
<memspecs>
<memspec src="/home/jonny/newconfigs/mems.xml"></memspec>
<memspec src="/home/gernhard2/projects/dram.vp.system/dram/resources/configs/memspecs/WideIO.xml"></memspec>
</memspecs>
<addressmappings>
<addressmapping src="/home/jonny/newconfigs/amc.xml"></addressmapping>
<addressmapping src="/home/gernhard2/projects/dram.vp.system/dram/resources/configs/amconfigs/am_wideio.xml"></addressmapping>
</addressmappings>
<memconfigs>
<memconfig src="/home/jonny/newconfigs/memc.xml">
</memconfig>
<memconfig src="/home/gernhard2/projects/dram.vp.system/dram/resources/configs/memconfigs/fifo.xml"/>
</memconfigs>
<tracesetups>
<tracesetup id="medium">
<!--<device clkMhz="200">test.stl</device>-->
<device clkMhz="200">small.stl</device>
<tracesetups>
<tracesetup id="fifo">
<!--<device clkMhz="200">test.stl</device>-->
<device clkMhz="200">mediabench-epic_32.stl</device>
</tracesetup>
</tracesetups>
</simulation>

View File

@@ -6,12 +6,12 @@
*/
#include "DebugManager.h"
#include "../controller/core/configuration/Configuration.h"
using namespace std;
void DebugManager::printDebugMessage(string sender, string message)
{
#ifndef NDEBUG
if (whiteList.count(sender))
if(Configuration::getInstance().Debug)
{
if (writeToConsole)
cout << " at " << sc_time_stamp() << "\t in " << sender << "\t: " << message << endl;
@@ -19,7 +19,6 @@ void DebugManager::printDebugMessage(string sender, string message)
if (writeToFile && debugFile)
debugFile << " at " << sc_time_stamp() << " in " << sender << "\t: " << message << "\n";
}
#endif
}
void DebugManager::openDebugFile(string filename)
@@ -29,17 +28,6 @@ void DebugManager::openDebugFile(string filename)
debugFile.open(filename);
}
void DebugManager::addToWhiteList(string sender)
{
whiteList.insert(sender);
}
void DebugManager::addToWhiteList(vector<string> senders)
{
for (string sender : senders)
addToWhiteList(sender);
}
DebugManager::DebugManager() :
writeToConsole(true), writeToFile(true)
{

View File

@@ -28,15 +28,11 @@ public:
void printDebugMessage(std::string sender, std::string message);
void openDebugFile(std::string filename);
void addToWhiteList(std::string sender);
void addToWhiteList(std::vector<std::string> senders);
private:
DebugManager();
DebugManager(const DebugManager&){}
ofstream debugFile;
std::set<std::string> whiteList;
};
#endif /* DEBUGMANAGER_H_ */

View File

@@ -158,12 +158,17 @@ void TlmRecorder::Transaction::insertPhase(string name, sc_time begin)
void TlmRecorder::Transaction::setPhaseEnd(string name, sc_time end)
{
for(Phase& data: recordedPhases)
// Find the latest recorder phase for that transaction with a matching name and update it
// Note: Transaction have the same phase multiple times (e.g. PRE->ACT->REF->ACT->RD) only update the latest
// one that has been recorder
for(int i = recordedPhases.size() - 1; i >= 0;i--)
{
Phase& data = recordedPhases[i];
if(data.name == name)
{
data.interval.end = end;
return;
}
}
SC_REPORT_FATAL("Recording Error", "While trying to set phase end: phaseBegin has not been recorded");
@@ -240,8 +245,8 @@ void TlmRecorder::insertGeneralInfo()
sqlite3_bind_int64(insertGeneralInfoStatement, 1, totalNumTransactions - 1);
sqlite3_bind_int64(insertGeneralInfoStatement, 2, simulationTimeCoveredByRecording.value());
sqlite3_bind_int(insertGeneralInfoStatement, 3,
core::Configuration::getInstance().memSpec.NumberOfBanks);
sqlite3_bind_int(insertGeneralInfoStatement, 4, core::Configuration::getInstance().memSpec.clk.value());
Configuration::getInstance().memSpec.NumberOfBanks);
sqlite3_bind_int(insertGeneralInfoStatement, 4, Configuration::getInstance().memSpec.clk.value());
sqlite3_bind_text(insertGeneralInfoStatement, 5, "PS", 2, NULL);
sqlite3_bind_text(insertGeneralInfoStatement, 6, memconfig.c_str(), memconfig.length(), NULL);
sqlite3_bind_text(insertGeneralInfoStatement, 7, memspec.c_str(), memspec.length(), NULL);

View File

@@ -35,6 +35,26 @@ DramExtension& DramExtension::getExtension(const tlm_generic_payload &payload)
return DramExtension::getExtension(&payload);
}
Bank DramExtension::getBank(const tlm_generic_payload *payload)
{
return DramExtension::getExtension(payload).getBank();
}
Bank DramExtension::getBank(const tlm_generic_payload &payload)
{
return DramExtension::getBank(&payload);
}
Row DramExtension::getRow(const tlm_generic_payload *payload)
{
return DramExtension::getExtension(payload).getRow();
}
Row DramExtension::getRow(const tlm_generic_payload &payload)
{
return DramExtension::getRow(&payload);
}
tlm_extension_base* DramExtension::clone() const
{
@@ -184,7 +204,7 @@ bool operator !=(const Row& lhs, const Row& rhs)
const Row Row::operator ++()
{
id = (id + 1) % core::Configuration::getInstance().memSpec.NumberOfRows;
id = (id + 1) % Configuration::getInstance().memSpec.NumberOfRows;
return *this;
}

View File

@@ -76,6 +76,12 @@ public:
return 0;
}
std::string toString()
{
return std::to_string(id);
}
private:
unsigned int id;
};
@@ -135,9 +141,16 @@ public:
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);
// Used for convience, caller could also use getExtension(..) to access these field
static Bank getBank(const tlm::tlm_generic_payload *payload);
static Bank getBank(const tlm::tlm_generic_payload &payload);
static Row getRow(const tlm::tlm_generic_payload *payload);
static Row getRow(const tlm::tlm_generic_payload &payload);
Thread getThread() const;
Channel getChannel() const;
Bank getBank() const;

Submodule dram/src/common/third_party/DRAMPower updated: 7723662db4...e39b6d6668

View File

@@ -52,8 +52,8 @@ DecodedAddress xmlAddressDecoder::decodeAddress(sc_dt::uint64 addr)
//result.rank = (addr & masks["rank"]) >> shifts["rank"];
//result.bankgroup = (addr & masks["bankgroup"]) >> shifts["bankgroup"];
result.bank = (addr & masks["bank"]) >> shifts["bank"];
result.bankgroup = result.bank % core::Configuration::getInstance().memSpec.NumberOfBankGroups;
result.rank = result.bank % core::Configuration::getInstance().memSpec.NumberOfRanks;
result.bankgroup = result.bank % Configuration::getInstance().memSpec.NumberOfBankGroups;
result.rank = result.bank % Configuration::getInstance().memSpec.NumberOfRanks;
result.row = (addr & masks["row"]) >> shifts["row"];
result.column = (addr & masks["column"]) >> shifts["column"];
result.bytes = (addr & masks["bytes"]) >> shifts["bytes"];

View File

@@ -0,0 +1,78 @@
#include "Command.h"
#include <systemc.h>
std::string commandToString(Command command)
{
switch (command)
{
case Command::Read:
return "RD";
break;
case Command::ReadA:
return "RDA";
break;
case Command::Write:
return "WR";
break;
case Command::WriteA:
return "WRA";
break;
case Command::Precharge:
return "PRE";
break;
case Command::Activate:
return "ACT";
break;
case Command::PrechargeAll:
return "PRE_ALL";
break;
case Command::AutoRefresh:
return "AUTO_REFRESH";
break;
case Command::PDNA:
return "PDNA";
break;
case Command::PDNAX:
return "PDNAX";
break;
case Command::PDNP:
return "PDNP";
break;
case Command::PDNPX:
return "PDNPX";
break;
case Command::SREF:
return "SREF";
break;
case Command::SREFX:
return "SREFX";
break;
default:
SC_REPORT_FATAL("command", "commandToString was called with unknown command");
break;
}
return "";
}
const std::vector<Command>& getAllCommands()
{
static std::vector<Command> allCommands( { Command::Precharge, Command::PrechargeAll,
Command::Activate, Command::Read, Command::Write, Command::ReadA, Command::WriteA,
Command::AutoRefresh, Command::PDNA, Command::PDNAX, Command::PDNP, Command::PDNPX,
Command::SREF, Command::SREFX });
return allCommands;
}
bool commandIsIn(Command command, std::vector<Command> commands)
{
for (Command c : commands)
{
if (c == command)
return true;
}
return false;
}

View File

@@ -10,16 +10,10 @@
#include <string>
#include <vector>
namespace core {
enum class Command {NOP, Precharge, PrechargeAll, Activate, Read, Write, ReadA, WriteA, AutoRefresh, PDNA, PDNAX, PDNP, PDNPX, SREF, SREFX};
std::string commandToString(Command command);
const std::vector<Command>& getAllCommands();
typedef std::vector<Command> CommandSequence;
} /* namespace controller */
bool commandIsIn(Command command, std::vector<Command> commands);
#endif /* COMMAND_H_ */

View File

@@ -25,26 +25,24 @@
#include "../common/Utils.h"
#include "core/configuration/Configuration.h"
#include "core/configuration/MemSpec.h"
#include "core/Command.h"
#include "Command.h"
#include "core/ControllerCore.h"
#include "core/ControllerState.h"
#include "core/IWrapperConnector.h"
#include "ControllerState.h"
#include "IController.h"
#include "core/powerdown/IPowerDownManager.h"
#include "core/scheduling/ScheduledCommand.h"
#include "core/scheduling/Trigger.h"
#include "core/TimingCalculation.h"
#include "scheduler/Fifo.h"
#include "scheduler/FifoStrict.h"
#include "scheduler/Fr_Fcfs.h"
#include "scheduler/PARBS.h"
#include "scheduler/readwritegrouper.h"
#include "scheduler/IScheduler.h"
using namespace std;
using namespace tlm;
using namespace core;
using namespace scheduler;
template<unsigned int BUSWIDTH = 128>
struct Controller: public sc_module, public IWrapperConnector
struct Controller: public sc_module, public IController
{
public:
Controller(sc_module_name /*name*/) :
@@ -59,7 +57,7 @@ public:
~Controller()
{
delete controllerCore;
delete controllerCore;
delete scheduler;
}
@@ -69,7 +67,6 @@ public:
virtual void send(const ScheduledCommand& command, tlm_generic_payload& payload) override;
virtual void send(Trigger trigger, sc_time time, tlm_generic_payload& payload) override;
tlm_utils::simple_initiator_socket<Controller, BUSWIDTH, tlm::tlm_base_protocol_types> iSocket;
tlm_utils::simple_target_socket<Controller, BUSWIDTH, tlm::tlm_base_protocol_types> tSocket;
@@ -78,10 +75,7 @@ private:
void payloadEntersSystem(tlm_generic_payload& payload);
void payloadLeavesSystem(tlm_generic_payload& payload);
unsigned int getTotalNumberOfPayloadsInSystem();
void scheduleNextFromScheduler();
//FIFO HACK
void scheduleDirectly(gp* payload);
void scheduleNextFromScheduler(Bank bank);
// --- FRONTEND ------
tlm_sync_enum nb_transport_fw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& fwDelay);
@@ -96,12 +90,13 @@ private:
// ------- CONTROLLER CORE ---------
void controllerCorePEQCallback(tlm_generic_payload& payload, const tlm_phase& phase);
//Helpers TODO move them
// Helpers TODO move them
void printDebugMessage(string message);
bool containsPhase(tlm_phase phase, std::vector<tlm_phase> phases);
ControllerCore* controllerCore;
Scheduler* scheduler;
//Scheduler* scheduler;
IScheduler* scheduler;
std::map<Bank, int> numberOfPayloadsInSystem;
std::vector<gp* > refreshCollisionRequets;
tlm::tlm_generic_payload* backpressure = NULL;
@@ -123,23 +118,27 @@ void Controller<BUSWIDTH>::buildScheduler()
{
string selectedScheduler = Configuration::getInstance().Scheduler;
if (selectedScheduler == "FR_FCFS")
if (selectedScheduler == "FIFO")
{
scheduler = new FR_FCFS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,Configuration::getInstance().AdaptiveOpenPagePolicy);
scheduler = new Fifo(*controllerCore);
}
else if (selectedScheduler == "PAR_BS")
else if (selectedScheduler == "FIFO_STRICT")
{
scheduler = new PAR_BS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,
Configuration::getInstance().Capsize);
scheduler = new FifoStrict(*this, *controllerCore);
}
else if (selectedScheduler == "FIFO")
else if (selectedScheduler == "FR_FCFS")
{
scheduler = new Fifo(*controllerCore);
}
else if (selectedScheduler == "Grouper")
{
scheduler = new ReadWriteGrouper(*controllerCore);
scheduler = new FR_FCFS(*controllerCore);
}
// else if (selectedScheduler == "PAR_BS")
// {
// scheduler = new PAR_BS(*controllerCore, Configuration::getInstance().RefreshAwareScheduling,
// Configuration::getInstance().Capsize);
// }
// else if (selectedScheduler == "Grouper")
// {
// scheduler = new ReadWriteGrouper(*controllerCore);
// }
else
reportFatal(name(), "unsupported scheduler: " + selectedScheduler);
}
@@ -152,6 +151,7 @@ void Controller<BUSWIDTH>::send(const ScheduledCommand &command, tlm_generic_pay
switch (command.getCommand())
{
//TODO: refactor tlm recorder
case Command::Read:
dataStrobe = command.getIntervalOnDataStrobe();
TlmRecorder::getInstance().updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
@@ -284,11 +284,22 @@ void Controller<BUSWIDTH>::controllerCorePEQCallback(tlm_generic_payload &payloa
}
else
{
Bank bank = DramExtension::getExtension(payload).getBank();
Bank bank = DramExtension::getBank(payload);
sendToDram(payload, phase, SC_ZERO_TIME);
if (phase == BEGIN_RD || phase == BEGIN_WR)
scheduleNextFromScheduler();
{
if(Configuration::getInstance().Scheduler == "FIFO_STRICT")
{
// special case for the Fifo_strict scheduler, because it may have to unblock
// the current front element
dynamic_cast<FifoStrict*>(scheduler)->NotifyBeginRD();
}
else
{
scheduleNextFromScheduler(DramExtension::getBank(payload));
}
}
else if (phase == BEGIN_REFB)
printDebugMessage("Entering REFB on bank " + to_string(bank.ID()));
else if (phase == BEGIN_REFA)
@@ -343,17 +354,13 @@ void Controller<BUSWIDTH>::frontendPEQCallback(tlm_generic_payload &payload, con
payload.set_response_status(tlm::TLM_OK_RESPONSE);
sendToFrontend(payload, END_REQ, SC_ZERO_TIME);
//FIFO HACK
if(Configuration::getInstance().Scheduler == "FIFO")
{
scheduleDirectly(&payload);
}
//Original
else
{
scheduler->schedule(&payload);
scheduleNextFromScheduler();
}
scheduler->schedule(&payload);
// Since we are triggering the scheduling of the next action on the bank
// because of an incoming transaction, we have to check if the bank
// is still busy. If it is, we let the end of the command which is currently in
// progress trigger the next scheduling
scheduleNextFromScheduler(DramExtension::getExtension(payload).getBank());
}
else if (phase == END_RESP)
{
@@ -363,15 +370,14 @@ void Controller<BUSWIDTH>::frontendPEQCallback(tlm_generic_payload &payload, con
backpressure->set_response_status(tlm::TLM_OK_RESPONSE);
sendToFrontend(*backpressure, END_REQ, SC_ZERO_TIME);
//FIFO HACK
if(Configuration::getInstance().Scheduler == "FIFO")
scheduler->schedule(backpressure);
// Since we are triggering the scheduling of the next action on the bank
// because of an incoming transaction, we have to check if the bank
// is still busy. If it is, we let the end of the command which is currently in
// progress trigger the next scheduling
if(!controllerCore->bankIsBusy(DramExtension::getBank(payload)))
{
scheduleDirectly(backpressure);
}
else
{
scheduler->schedule(backpressure);
scheduleNextFromScheduler();
scheduleNextFromScheduler(DramExtension::getExtension(backpressure).getBank());
}
backpressure = NULL;
}
@@ -417,33 +423,19 @@ unsigned int Controller<BUSWIDTH>::getTotalNumberOfPayloadsInSystem()
return sum;
}
//FIFO HACK!
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::scheduleDirectly(gp* payload)
void Controller<BUSWIDTH>::scheduleNextFromScheduler(Bank bank)
{
if(!controllerCore->scheduleRequest(*payload))
if(controllerCore->bankIsBusy(bank))
{
refreshCollisionRequets.push_back(payload);
return;
}
}
template<unsigned int BUSWIDTH>
void Controller<BUSWIDTH>::scheduleNextFromScheduler()
{
if(scheduler->hasPayloads())
pair<Command, tlm::tlm_generic_payload*> nextRequest = scheduler->getNextRequest(bank);
if(nextRequest.second != NULL)
{
tlm_generic_payload* payload = scheduler->getNextPayload();
if(payload != NULL)
{
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(payload).getBank(), sc_time_stamp());
bool wasScheduledByCore = controllerCore->scheduleRequest(*payload);
if (wasScheduledByCore)
{
scheduler->removePayload(payload);
printDebugMessage("\t-> Next payload was scheduled by core");
}
}
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(nextRequest.second).getBank(), sc_time_stamp());
controllerCore->scheduleRequest(nextRequest.first, *nextRequest.second);
printDebugMessage("\t-> Next payload was scheduled by core");
}
}
@@ -469,44 +461,53 @@ void Controller<BUSWIDTH>::dramPEQCallback(tlm_generic_payload &payload, const t
Bank bank = DramExtension::getExtension(payload).getBank();
printDebugMessage("Received " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()) + " from DRAM");
if (phase == BEGIN_RD || phase == BEGIN_WR)
{
scheduleNextFromScheduler();
sendToDram(payload, phase, SC_ZERO_TIME);
}
else if (phase == END_RD || phase == END_WR)
if (phase == END_RD || phase == END_WR)
{
sendToFrontend(payload, BEGIN_RESP, SC_ZERO_TIME);
}
else if (phase == END_RDA || phase == END_WRA)
{
sendToFrontend(payload, BEGIN_RESP, SC_ZERO_TIME);
scheduleNextFromScheduler();
scheduleNextFromScheduler(bank);
}
else if (phase == END_REFA || phase == END_REFB)
else if (phase == END_REFA)
{
printDebugMessage("Finished auto refresh on bank " + to_string(bank.ID()));
printDebugMessage("Finished auto refresh on all banks ");
if(numberOfPayloadsInSystem[bank] == 0)
controllerCore->powerDownManager->sleep(bank,sc_time_stamp());
//FIFO HACK
if(Configuration::getInstance().Scheduler == "FIFO")
for(Bank bank : controllerCore->getBanks())
{
std::vector<gp*> collidedReq = this->refreshCollisionRequets;
refreshCollisionRequets.clear();
for(gp* payload : collidedReq)
if(numberOfPayloadsInSystem[bank] == 0)
{
scheduleDirectly(payload);
controllerCore->powerDownManager->sleep(bank,sc_time_stamp());
}
else
{
scheduleNextFromScheduler(bank);
}
}
else
{
scheduleNextFromScheduler();
}
}
else if (containsPhase(phase, { END_PRE, END_PRE_ALL, END_ACT }))
else if(phase == END_REFB)
{
printDebugMessage("Finished auto refresh on bank " + to_string(bank.ID()));
if(numberOfPayloadsInSystem[bank] == 0)
{
controllerCore->powerDownManager->sleep(bank,sc_time_stamp());
}
else
{
scheduleNextFromScheduler(bank);
}
scheduleNextFromScheduler(bank);
}
else if (containsPhase(phase, { END_PRE, END_ACT }))
{
scheduleNextFromScheduler(bank);
}
else if(phase == END_PRE_ALL)
{
// No need to trigger anything for a END_PRE_ALL. It is followed by a AUTO_REFRESH anyway (in our current
// scheduler implementation)
}
else
{

View File

@@ -7,9 +7,8 @@
#include "ControllerState.h"
#include <algorithm>
#include "TimingCalculation.h"
#include "core/TimingCalculation.h"
namespace core {
const ScheduledCommand ControllerState::getLastCommand(Command command, Bank bank) //TODO const reference? and make const
{
@@ -116,5 +115,3 @@ void ControllerState::cleanUp(sc_time time)
if(time >= config->memSpec.tActHistory())
lastActivates.erase(lastActivates.begin(), lastActivates.lower_bound(time - config->memSpec.tActHistory()));
}
} /* namespace controller */

View File

@@ -10,15 +10,12 @@
#include <systemc.h>
#include "RowBufferStates.h"
#include "scheduling/ScheduledCommand.h"
#include "Slots.h"
#include "configuration/Configuration.h"
#include "core/Slots.h"
#include "core/configuration/Configuration.h"
#include <map>
#include <set>
#include <list>
namespace core {
class ControllerState
{
public:
@@ -54,6 +51,5 @@ private:
Configuration* config;
};
} /* namespace controller */
#endif /* CONTROLLER_STATE_H_ */

View File

@@ -0,0 +1,23 @@
#ifndef ICONTROLLER_H
#define ICONTROLLER_H
#include <systemc.h>
#include "core/scheduling/ScheduledCommand.h"
#include "core/scheduling/Trigger.h"
// Utiliy class to pass around the Controller class to the controller Core and various schedulers, without having to propagate the template defintions
// throughout all classes
class IController
{
public:
virtual ~IController() {}
virtual void send(const ScheduledCommand& command,tlm::tlm_generic_payload& payload) = 0;
virtual void send(Trigger trigger, sc_time time, tlm::tlm_generic_payload& payload) = 0;
virtual void scheduleNextFromScheduler(Bank bank) = 0;
};
#endif // ICONTROLLER_H

View File

@@ -6,15 +6,12 @@
*/
#include "RowBufferStates.h"
#include "ControllerCore.h"
#include "../../common/DebugManager.h"
#include "../../common/Utils.h"
#include "core/ControllerCore.h"
#include "../common/DebugManager.h"
#include "../common/Utils.h"
using namespace std;
namespace core
{
RowBufferState::RowBufferState()
{
closeAllRowBuffers();
@@ -64,5 +61,4 @@ void RowBufferState::closeAllRowBuffers()
}
}
}

View File

@@ -8,10 +8,7 @@
#ifndef ROWBUFFERSTATES_H_
#define ROWBUFFERSTATES_H_
#include <map>
#include "../../common/dramExtension.h"
namespace core
{
#include "../common/dramExtension.h"
class RowBufferState {
public:
@@ -30,6 +27,4 @@ private:
std::map<Bank,Row> rowsInRowBuffers;
};
}
#endif /* BANKSTATES_H_ */

View File

@@ -1,71 +0,0 @@
#include "Command.h"
#include <systemc.h>
namespace core {
std::string commandToString(Command command)
{
switch (command)
{
case Command::Read:
return "RD";
break;
case Command::ReadA:
return "RDA";
break;
case Command::Write:
return "WR";
break;
case Command::WriteA:
return "WRA";
break;
case Command::Precharge:
return "PRE";
break;
case Command::Activate:
return "ACT";
break;
case Command::PrechargeAll:
return "PRE_ALL";
break;
case Command::AutoRefresh:
return "AUTO_REFRESH";
break;
case Command::PDNA:
return "PDNA";
break;
case Command::PDNAX:
return "PDNAX";
break;
case Command::PDNP:
return "PDNP";
break;
case Command::PDNPX:
return "PDNPX";
break;
case Command::SREF:
return "SREF";
break;
case Command::SREFX:
return "SREFX";
break;
default:
SC_REPORT_FATAL("command", "commandToString was called with unknown command");
break;
}
return "";
}
const std::vector<Command>& getAllCommands()
{
static std::vector<Command> allCommands( { Command::Precharge, Command::PrechargeAll,
Command::Activate, Command::Read, Command::Write, Command::ReadA, Command::WriteA,
Command::AutoRefresh, Command::PDNA, Command::PDNAX, Command::PDNP, Command::PDNPX,
Command::SREF, Command::SREFX });
return allCommands;
}
}

View File

@@ -27,13 +27,12 @@
#include "../../common/DebugManager.h"
namespace core {
std::string ControllerCore::senderName = "Controller Core";
ControllerCore::ControllerCore(IWrapperConnector& wrapperConnector, std::map<Bank, int>& numberOfPayloads) :
config(Configuration::getInstance()), state(&config), wrapper(wrapperConnector), numberOfPayloads(
numberOfPayloads), commandChecker(), savedState(&config), commandSequenceGenerator(state), commandSequenceScheduler(*this)
ControllerCore::ControllerCore(IController& wrapperConnector, std::map<Bank, int>& numberOfPayloads) :
config(Configuration::getInstance()), state(&config), controller(wrapperConnector), numberOfPayloads(
numberOfPayloads), commandChecker()
{
commandChecker[Command::Activate] = new ActivateChecker(config, state);
@@ -92,16 +91,6 @@ ControllerCore::~ControllerCore()
delete powerDownManager;
}
void ControllerCore::saveState()
{
savedState = state;
}
void ControllerCore::resetState()
{
state = savedState;
}
void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload)
{
sc_time time = sc_time_stamp();
@@ -117,28 +106,28 @@ void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload)
}
}
bool ControllerCore::scheduleRequest(tlm::tlm_generic_payload& payload)
void ControllerCore::scheduleRequest(Command command, tlm::tlm_generic_payload &payload)
{
sc_time start = clkAlign(sc_time_stamp());
state.cleanUp(start);
saveState();
CommandSequence sequence = commandSequenceGenerator.generateCommandSequence(payload);
CommandSchedule schedule = commandSequenceScheduler.schedule(sequence, start, payload);
if (refreshManager->hasCollision(schedule))
{
resetState();
return false;
}
else
{
send(schedule, payload);
return true;
}
ScheduledCommand scheduledCommand = schedule(command, start, payload);
state.change(scheduledCommand);
controller.send(scheduledCommand, payload);
}
ScheduledCommand ControllerCore::schedule(Command command, sc_time start,
tlm::tlm_generic_payload& payload)
{
ControllerCore::printDebugMessage("Scheduling command " + commandToString(command) + " on " + DramExtension::getBank(payload).toString());
ICommandChecker& checker = getCommandChecker(command);
sc_time executionTime = getExecutionTime(command, payload);
ScheduledCommand scheduledCommand(command, start, executionTime, DramExtension::getExtension(payload));
checker.delayToSatisfyConstraints(scheduledCommand);
return scheduledCommand;
}
bool ControllerCore::bankIsBusy(Bank bank)
{
sc_time time = sc_time_stamp();
@@ -148,9 +137,10 @@ bool ControllerCore::bankIsBusy(Bank bank)
return false;
else if (lastScheduledCommand.commandIsIn( { Command::Write, Command::Read }))
{
// Read and writes can overlap, so the bank should not be busy during a rd/wr
return (time < lastScheduledCommand.getStart());
}
else if (lastScheduledCommand.commandIsIn( { Command::WriteA, Command::ReadA }))
else if (lastScheduledCommand.commandIsIn( { Command::WriteA, Command::ReadA, Command::Precharge, Command::PrechargeAll, Command::Activate }))
{
return (time < lastScheduledCommand.getEnd());
}
@@ -165,7 +155,7 @@ bool ControllerCore::bankIsBusy(Bank bank)
}
else
{
SC_REPORT_FATAL("Core", "Last command in command sequence was activate or precharge. This really doesn't make sense :D.");
SC_REPORT_FATAL("Core", "Last command unkown");
return false;
}
@@ -197,14 +187,6 @@ std::vector<Bank> ControllerCore::getFreeBanks()
return freeBanks;
}
void ControllerCore::send(const CommandSchedule& schedule, tlm::tlm_generic_payload& payload) const
{
for (const ScheduledCommand& cmd : schedule.getScheduledCommands())
{
wrapper.send(cmd, payload);
}
}
ICommandChecker& ControllerCore::getCommandChecker(Command command)
{
return *getElementFromMap(commandChecker, command);
@@ -215,5 +197,4 @@ void ControllerCore::printDebugMessage(string message)
DebugManager::getInstance().printDebugMessage(ControllerCore::senderName, message);
}
} /* namespace controller */

View File

@@ -10,53 +10,46 @@
#include <tlm.h>
#include <map>
#include "IWrapperConnector.h"
#include <utility>
#include "../IController.h"
#include "configuration/Configuration.h"
#include "powerdown/PowerDownManager.h"
#include "refresh/IRefreshManager.h"
#include "scheduling/CommandSequenceGenerator.h"
#include "scheduling/checker/ICommandChecker.h"
#include "scheduling/CommandSequenceScheduler.h"
#include "../../common/TlmRecorder.h"
#include "../RowBufferStates.h"
#include "../ControllerState.h"
namespace core {
class ControllerCore
{
public:
ControllerCore(IWrapperConnector& wrapper, std::map<Bank, int>& numberOfPayloads);
ControllerCore(IController& controller, std::map<Bank, int>& numberOfPayloads);
virtual ~ControllerCore() ;
bool scheduleRequest(tlm::tlm_generic_payload& payload);
void scheduleRequest(Command command, tlm::tlm_generic_payload& payload);
void triggerRefresh(tlm::tlm_generic_payload& payload);
const std::vector<Bank>& getBanks();
std::vector<Bank> getFreeBanks();
const RowBufferState& getRowBufferStates(){return state.rowBufferStates;}
bool bankIsBusy(Bank bank);
ICommandChecker& getCommandChecker(Command command);
static void printDebugMessage(string message);
ICommandChecker& getCommandChecker(Command command); static void printDebugMessage(string message);
Configuration config;
ControllerState state;
IWrapperConnector& wrapper;
IController& controller;
IPowerDownManager* powerDownManager;
IRefreshManager* refreshManager;
std::map<Bank,int>& numberOfPayloads;
static std::string senderName;
private:
void send(const CommandSchedule& schedule, tlm::tlm_generic_payload& payload) const;
bool bankIsBusy(Bank bank);
void saveState();
void resetState();
ScheduledCommand schedule(Command command, sc_time start, tlm::tlm_generic_payload &payload);
std::map<Command, ICommandChecker*> commandChecker;
ControllerState savedState;
CommandSequenceGenerator commandSequenceGenerator;
CommandSequenceScheduler commandSequenceScheduler;
};
} /* namespace controller */
#endif /* CONTROLLER_H_ */

View File

@@ -1,28 +0,0 @@
/*
* IInternalScheduler.h
*
* Created on: Mar 13, 2014
* Author: jonny
*/
#ifndef IINTERNALSCHEDULER_H_
#define IINTERNALSCHEDULER_H_
#include <systemc.h>
#include "scheduling/ScheduledCommand.h"
#include "scheduling/Trigger.h"
namespace core
{
class IWrapperConnector
{
public:
virtual ~IWrapperConnector() {}
virtual void send(const core::ScheduledCommand& command,tlm::tlm_generic_payload& payload) = 0;
virtual void send(Trigger trigger, sc_time time, tlm::tlm_generic_payload& payload) = 0;
};
}
#endif /* IINTERNALSCHEDULER_H_ */

View File

@@ -8,7 +8,6 @@
#include "Slots.h"
#include "TimingCalculation.h"
namespace core {
Slots::Slots(sc_time clk) :
clk(clk)
@@ -60,4 +59,3 @@ void Slots::blockSlots(sc_time begin, sc_time end, bool excludeBorders)
}
} /* namespace core */

View File

@@ -11,7 +11,6 @@
#include <set>
#include "scheduling/ScheduledCommand.h"
namespace core {
class Slots
{
@@ -30,6 +29,5 @@ private:
};
} /* namespace core */
#endif /* SLOTS_H_ */

View File

@@ -12,7 +12,6 @@
#include "configuration/Configuration.h"
#include "../../common/Utils.h"
namespace core {
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint)
@@ -129,5 +128,4 @@ sc_time getWriteAccessTime()
}
}
}

View File

@@ -11,10 +11,8 @@
#include <systemc.h>
#include <tlm.h>
#include "../../common/dramExtension.h"
#include "Command.h"
#include "../Command.h"
namespace core
{
sc_time getMinExecutionTimeForPowerDownCmd(Command command);
sc_time getExecutionTime(Command command, tlm::tlm_generic_payload& payload);
@@ -28,6 +26,4 @@ const sc_time clkAlign(sc_time time, Alignment alignment = UP);
bool isClkAligned(sc_time time, sc_time clk);
const sc_time FrequencyToClk(double frequencyMhz);
}
#endif /* UTILS_H_ */

View File

@@ -11,8 +11,6 @@
using namespace std;
namespace core{
string Configuration::memspecUri = "";
string Configuration::memconfigUri = "";
@@ -66,10 +64,6 @@ void Configuration::setParameter(std::string name, std::string value)
BankwiseLogic = string2bool(value);
else if(name == "OpenPagePolicy")
OpenPagePolicy = string2bool(value);
else if(name == "AdaptiveOpenPagePolicy")
AdaptiveOpenPagePolicy = string2bool(value);
else if(name == "RefreshAwareScheduling")
RefreshAwareScheduling = string2bool(value);
else if(name == "MaxNrOfTransactions")
MaxNrOfTransactions = string2int(value);
else if(name == "Scheduler")
@@ -113,5 +107,4 @@ void Configuration::setParameters(std::map<std::string, std::string> parameterMa
}
}
} /* namespace core */

View File

@@ -12,8 +12,6 @@
#include <string>
#include "MemSpec.h"
namespace core{
enum class EPowerDownMode{NoPowerDown, Staggered, TimeoutPDN, TimeoutSREF};
@@ -31,8 +29,6 @@ struct Configuration
//MemConfig
bool BankwiseLogic = false;
bool OpenPagePolicy = true;
bool AdaptiveOpenPagePolicy = false;
bool RefreshAwareScheduling = false;
unsigned int MaxNrOfTransactions = 50;
std::string Scheduler;
unsigned int Capsize = 5;
@@ -60,7 +56,5 @@ private:
unsigned int powerDownTimeoutInClk = 3;
};
} /* namespace core */
#endif /* CONFIGURATION_H_ */

View File

@@ -12,8 +12,6 @@
using namespace tinyxml2;
using namespace std;
namespace core {
void ConfigurationLoader::loadSimConfig(Configuration& config, string simconfigUri)
{
tinyxml2::XMLDocument doc;
@@ -23,28 +21,6 @@ void ConfigurationLoader::loadSimConfig(Configuration& config, string simconfigU
loadConfig(config, simconfig);
}
void ConfigurationLoader::loadMemConfig(Configuration& config, string memconfigUri)
{
tinyxml2::XMLDocument doc;
loadXML(memconfigUri, doc);
XMLElement* memconfig = doc.FirstChildElement("memconfig");
loadConfig(config, memconfig);
}
void ConfigurationLoader::loadMemConfig(Configuration& config, XMLElement* memconfig)
{
if(memconfig->Attribute("src"))
{
XMLDocument doc;
string src(memconfig->Attribute("src"));
loadXML(src, doc);
loadMemConfig(config, doc.FirstChildElement("memconfig"));
}
loadConfig(config, memconfig);
}
void ConfigurationLoader::loadSimConfig(Configuration& config, XMLElement* simconfig)
{
if(simconfig->Attribute("src"))
@@ -103,6 +79,28 @@ void ConfigurationLoader::loadMemSpec(Configuration& config, XMLElement* memspec
}
}
void ConfigurationLoader::loadMemConfig(Configuration& config, string memconfigUri)
{
tinyxml2::XMLDocument doc;
loadXML(memconfigUri, doc);
XMLElement* memconfig = doc.FirstChildElement("memconfig");
loadConfig(config, memconfig);
}
void ConfigurationLoader::loadMemConfig(Configuration& config, XMLElement* memconfig)
{
if(memconfig->Attribute("src"))
{
XMLDocument doc;
string src(memconfig->Attribute("src"));
config.memconfigUri = src;
loadXML(src, doc);
loadMemConfig(config, doc.FirstChildElement("memconfig"));
}
loadConfig(config, memconfig);
}
void ConfigurationLoader::loadDDR4(Configuration& config, XMLElement* memspec)
{
//MemArchitecture
@@ -207,4 +205,3 @@ void ConfigurationLoader::loadWideIO(Configuration& config, XMLElement* memspec)
}
} /* namespace core */

View File

@@ -13,8 +13,6 @@
#include "../../../common/Utils.h"
#include "Configuration.h"
namespace core {
class ConfigurationLoader
{
public:
@@ -35,6 +33,5 @@ private:
static void loadWideIO(Configuration& config, tinyxml2::XMLElement* memspec);
};
} /* namespace core */
#endif /* CONFIGURATIONLOADER_H_ */

View File

@@ -12,7 +12,6 @@
#include <map>
#include "../../../common/dramExtension.h"
namespace core{
struct RefreshTiming
{
@@ -89,7 +88,6 @@ struct MemSpec
sc_time tDataStrobeHistory(){return tWTR_L;}
};
} /* namespace core */
#endif /* MemSpec_H_ */

View File

@@ -10,11 +10,9 @@
#include <systemc.h>
#include "../../../common/dramExtension.h"
#include "../Command.h"
#include "../../Command.h"
namespace core {
enum class PowerDownState
{
Awake, AwakeForRefresh, PDNActive, PDNPrecharge, PDNSelfRefresh
@@ -99,6 +97,5 @@ inline std::string powerDownStateToString(PowerDownState powerDownState)
}
}
} /* namespace core */
#endif /* IPOWERDOWNMANAGER_H_ */

View File

@@ -1,26 +1,26 @@
#include "NoPowerDown.h"
void core::NoPowerDown::triggerSleep(Bank /*bank*/, sc_time /*time*/)
void NoPowerDown::triggerSleep(Bank /*bank*/, sc_time /*time*/)
{
return;
}
void core::NoPowerDown::sleep(Bank /*bank*/, sc_time /*time*/)
void NoPowerDown::sleep(Bank /*bank*/, sc_time /*time*/)
{
return;
}
void core::NoPowerDown::wakeUp(Bank /*bank*/, sc_time /*time*/)
void NoPowerDown::wakeUp(Bank /*bank*/, sc_time /*time*/)
{
return;
}
void core::NoPowerDown::wakeUpForRefresh(Bank /*bank*/, sc_time /*time*/)
void NoPowerDown::wakeUpForRefresh(Bank /*bank*/, sc_time /*time*/)
{
return;
}
bool core::NoPowerDown::isInSelfRefresh(Bank /*bank*/)
bool NoPowerDown::isInSelfRefresh(Bank /*bank*/)
{
return false;
}

View File

@@ -15,7 +15,6 @@
#include "../scheduling/ScheduledCommand.h"
namespace core {
class NoPowerDown: public IPowerDownManager
{
@@ -32,6 +31,6 @@ public:
virtual bool isInSelfRefresh(Bank bank) override;
};
}
#endif // NOPOWERDOWN_H

View File

@@ -17,10 +17,9 @@
using namespace tlm;
using namespace std;
namespace core {
PowerDownManager::PowerDownManager(ControllerCore& controller) :
controller(controller)
controllerCore(controller)
{
powerDownState = PowerDownState::Awake;
for (Bank bank : controller.getBanks())
@@ -43,14 +42,14 @@ void PowerDownManager::sleep(Bank bank, sc_time time)
if (state == PowerDownState::Awake) //coming from active
{
state = controller.state.rowBufferStates.allRowBuffersAreClosed() ? PowerDownState::PDNPrecharge : PowerDownState::PDNActive;
state = controllerCore.state.rowBufferStates.allRowBuffersAreClosed() ? PowerDownState::PDNPrecharge : PowerDownState::PDNActive;
}
else if (state == PowerDownState::AwakeForRefresh) //coming from refresh interrupting power down
{
sc_assert(controller.state.rowBufferStates.allRowBuffersAreClosed());
sc_assert(controllerCore.state.rowBufferStates.allRowBuffersAreClosed());
if (controller.state.getLastCommand(Command::PDNA).getStart()
>= controller.state.getLastCommand(Command::PDNP).getStart())
if (controllerCore.state.getLastCommand(Command::PDNA).getStart()
>= controllerCore.state.getLastCommand(Command::PDNP).getStart())
state = PowerDownState::PDNPrecharge;
else
{
@@ -62,9 +61,9 @@ void PowerDownManager::sleep(Bank bank, sc_time time)
ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd),
DramExtension::getExtension(powerDownPayloads[bank]));
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
if (state != PowerDownState::PDNSelfRefresh && controller.refreshManager->hasCollision(pdn))
if (state != PowerDownState::PDNSelfRefresh && controllerCore.refreshManager->hasCollision(pdn))
{
return;
}
@@ -86,10 +85,10 @@ void PowerDownManager::wakeUp(Bank bank, sc_time time)
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState);
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, powerDownPayloads[bank]),
DramExtension::getExtension(powerDownPayloads[bank]));
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
if (cmd == Command::SREFX)
controller.refreshManager->reInitialize(bank, pdn.getEnd());
controllerCore.refreshManager->reInitialize(bank, pdn.getEnd());
setPowerDownState(PowerDownState::Awake);
sendPowerDownPayloads(pdn);
@@ -111,14 +110,15 @@ void PowerDownManager::wakeUpForRefresh(Bank bank, sc_time time)
void PowerDownManager::sendPowerDownPayloads(ScheduledCommand& cmd)
{
controller.state.bus.moveCommandToNextFreeSlot(cmd);
for (Bank bank : controller.getBanks())
controllerCore.state.bus.moveCommandToNextFreeSlot(cmd);
for (Bank bank : controllerCore.getBanks())
{
tlm_generic_payload& payloadToSend = powerDownPayloads[bank];
ScheduledCommand pdnToSend(cmd.getCommand(), cmd.getStart(), cmd.getExecutionTime(),
DramExtension::getExtension(payloadToSend));
controller.state.change(pdnToSend);
controller.wrapper.send(pdnToSend, payloadToSend);
controllerCore.state.change(pdnToSend);
controllerCore.controller.send(pdnToSend, payloadToSend);
}
}
@@ -137,9 +137,9 @@ bool PowerDownManager::isInPowerDown()
bool PowerDownManager::canSleep()
{
for (Bank bank : controller.getBanks())
for (Bank bank : controllerCore.getBanks())
{
if (!controller.numberOfPayloads[bank] == 0)
if (!controllerCore.numberOfPayloads[bank] == 0)
return false;
}
return true;
@@ -160,6 +160,5 @@ void PowerDownManager::triggerSleep(Bank bank, sc_time time)
sleep(bank, time);
}
} /* namespace core */

View File

@@ -10,14 +10,13 @@
#include "PowerDownManagerBankwise.h"
namespace core {
class ControllerCore;
class PowerDownManager: public IPowerDownManager
{
public:
PowerDownManager(ControllerCore& controller);
PowerDownManager(ControllerCore& controllerCore);
virtual ~PowerDownManager();
virtual void triggerSleep(Bank bank, sc_time time) override;
@@ -35,9 +34,8 @@ private:
PowerDownState powerDownState;
std::map<Bank, tlm::tlm_generic_payload> powerDownPayloads;
ControllerCore& controller;
ControllerCore& controllerCore;
};
} /* namespace core */
#endif /* POWERDOWNMANAGER_H_ */

View File

@@ -12,12 +12,11 @@
using namespace tlm;
namespace core {
std::string PowerDownManagerBankwise::senderName = "pdn manager";
PowerDownManagerBankwise::PowerDownManagerBankwise(ControllerCore& controller) :
controller(controller)
controllerCore(controller)
{
for (Bank bank : controller.getBanks())
{
@@ -36,14 +35,14 @@ void PowerDownManagerBankwise::sleep(Bank bank, sc_time time)
PowerDownState state = powerDownStates[bank];
if (state == PowerDownState::Awake) //coming from active
{
state = controller.state.rowBufferStates.rowBufferIsOpen(bank) ? PowerDownState::PDNActive : PowerDownState::PDNPrecharge;
state = controllerCore.state.rowBufferStates.rowBufferIsOpen(bank) ? PowerDownState::PDNActive : PowerDownState::PDNPrecharge;
}
else if (state == PowerDownState::AwakeForRefresh) //coming from refresh interrupting power down
{
sc_assert(!controller.state.rowBufferStates.rowBufferIsOpen(bank));
sc_assert(!controllerCore.state.rowBufferStates.rowBufferIsOpen(bank));
if (controller.state.getLastCommand(Command::PDNA, bank).getStart()
>= controller.state.getLastCommand(Command::PDNP, bank).getStart())
if (controllerCore.state.getLastCommand(Command::PDNA, bank).getStart()
>= controllerCore.state.getLastCommand(Command::PDNP, bank).getStart())
state = PowerDownState::PDNPrecharge;
else
{
@@ -53,9 +52,9 @@ void PowerDownManagerBankwise::sleep(Bank bank, sc_time time)
Command cmd = IPowerDownManager::getSleepCommand(state);
ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd), DramExtension::getExtension(payload));
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
if (state != PowerDownState::PDNSelfRefresh && controller.refreshManager->hasCollision(pdn))
if (state != PowerDownState::PDNSelfRefresh && controllerCore.refreshManager->hasCollision(pdn))
{
return;
}
@@ -78,10 +77,10 @@ void PowerDownManagerBankwise::wakeUp(Bank bank, sc_time time)
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownStates[bank]);
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, powerDownPayloads[bank]),
DramExtension::getExtension(powerDownPayloads[bank]));
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
if (cmd == Command::SREFX)
controller.refreshManager->reInitialize(bank, pdn.getEnd());
controllerCore.refreshManager->reInitialize(bank, pdn.getEnd());
setState(PowerDownState::Awake, bank);
sendPowerDownPayload(pdn);
@@ -133,14 +132,14 @@ void PowerDownManagerBankwise::setState(PowerDownState state, Bank bank)
void PowerDownManagerBankwise::sendPowerDownPayload(ScheduledCommand& pdn)
{
controller.state.bus.moveCommandToNextFreeSlot(pdn);
controller.state.change(pdn);
controller.wrapper.send(pdn, powerDownPayloads[pdn.getBank()]);
controllerCore.state.bus.moveCommandToNextFreeSlot(pdn);
controllerCore.state.change(pdn);
controllerCore.controller.send(pdn, powerDownPayloads[pdn.getBank()]);
}
bool PowerDownManagerBankwise::canSleep(Bank bank)
{
return controller.numberOfPayloads[bank] == 0;
return controllerCore.numberOfPayloads[bank] == 0;
}
void PowerDownManagerBankwise::triggerSleep(Bank bank, sc_time time)
@@ -148,6 +147,5 @@ void PowerDownManagerBankwise::triggerSleep(Bank bank, sc_time time)
sleep(bank, time);
}
}/* namespace core */

View File

@@ -12,19 +12,18 @@
#include <tlm.h>
#include <map>
#include <string>
#include "../Command.h"
#include "../../Command.h"
#include "../../../common/dramExtension.h"
#include "../scheduling/ScheduledCommand.h"
#include "IPowerDownManager.h"
namespace core {
class ControllerCore;
class PowerDownManagerBankwise: public IPowerDownManager
{
public:
PowerDownManagerBankwise(ControllerCore& controller);
PowerDownManagerBankwise(ControllerCore& controllerCore);
virtual ~PowerDownManagerBankwise()
{
}
@@ -41,7 +40,7 @@ private:
virtual bool isAwake(Bank bank);
virtual bool isAwakeForRefresh(Bank bank);
ControllerCore& controller;
ControllerCore& controllerCore;
std::map<Bank, tlm::tlm_generic_payload> powerDownPayloads;
std::map<Bank, PowerDownState> powerDownStates;
@@ -55,6 +54,5 @@ private:
void sendPowerDownPayload(ScheduledCommand& pdn);
};
}/* namespace core */
#endif /* POWERDOWNMANAGERBANKWISE_H_ */

View File

@@ -12,9 +12,8 @@
using namespace tlm;
namespace core {
PowerDownManagerTimeout::PowerDownManagerTimeout(ControllerCore& controller): controller(controller)
PowerDownManagerTimeout::PowerDownManagerTimeout(ControllerCore& controller): controllerCore(controller)
{
for (Bank bank : controller.getBanks())
{
@@ -29,12 +28,12 @@ PowerDownManagerTimeout::~PowerDownManagerTimeout()
void PowerDownManagerTimeout::sleep(Bank bank, sc_time time)
{
if(canSleep() && !isInPowerDown() && (time - controller.state.getLastScheduledCommand().getEnd()) >= Configuration::getInstance().getPowerDownTimeout())
if(canSleep() && !isInPowerDown() && (time - controllerCore.state.getLastScheduledCommand().getEnd()) >= Configuration::getInstance().getPowerDownTimeout())
{
PowerDownState newState;
if(Configuration::getInstance().PowerDownMode == EPowerDownMode::TimeoutPDN)
{
newState = controller.state.rowBufferStates.allRowBuffersAreClosed() ? PowerDownState::PDNPrecharge : PowerDownState::PDNActive;
newState = controllerCore.state.rowBufferStates.allRowBuffersAreClosed() ? PowerDownState::PDNPrecharge : PowerDownState::PDNActive;
}
else
{
@@ -45,9 +44,9 @@ void PowerDownManagerTimeout::sleep(Bank bank, sc_time time)
ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd),
DramExtension::getExtension(powerDownPayloads[bank]));
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
if (controller.refreshManager->hasCollision(pdn))
if (controllerCore.refreshManager->hasCollision(pdn))
{
return;
}
@@ -79,10 +78,10 @@ void PowerDownManagerTimeout::wakeUp(Bank bank, sc_time time)
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState);
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, powerDownPayloads[bank]),
DramExtension::getExtension(powerDownPayloads[bank]));
controller.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
if (cmd == Command::SREFX)
controller.refreshManager->reInitialize(bank, pdn.getEnd());
controllerCore.refreshManager->reInitialize(bank, pdn.getEnd());
setPowerDownState(PowerDownState::Awake);
sendPowerDownPayloads(pdn);
@@ -106,7 +105,7 @@ void PowerDownManagerTimeout::triggerSleep(Bank /*bank*/, sc_time time)
{
if(canSleep() && !isInPowerDown())
{
controller.wrapper.send(PDNTrigger, time + controller.config.getPowerDownTimeout(), powerDownPayloads[Bank(0)]);
controllerCore.controller.send(PDNTrigger, time + controllerCore.config.getPowerDownTimeout(), powerDownPayloads[Bank(0)]);
}
}
@@ -117,9 +116,9 @@ bool PowerDownManagerTimeout::isInSelfRefresh(Bank /*bank*/)
bool PowerDownManagerTimeout::canSleep()
{
for (Bank bank : controller.getBanks())
for (Bank bank : controllerCore.getBanks())
{
if (!controller.numberOfPayloads[bank] == 0)
if (!controllerCore.numberOfPayloads[bank] == 0)
return false;
}
return true;
@@ -127,15 +126,14 @@ bool PowerDownManagerTimeout::canSleep()
void PowerDownManagerTimeout::sendPowerDownPayloads(ScheduledCommand& cmd)
{
controller.state.bus.moveCommandToNextFreeSlot(cmd);
for (Bank bank : controller.getBanks())
controllerCore.state.bus.moveCommandToNextFreeSlot(cmd);
for (Bank bank : controllerCore.getBanks())
{
tlm_generic_payload& payloadToSend = powerDownPayloads[bank];
ScheduledCommand pdnToSend(cmd.getCommand(), cmd.getStart(), cmd.getExecutionTime(),
DramExtension::getExtension(payloadToSend));
controller.state.change(pdnToSend);
controller.wrapper.send(pdnToSend, payloadToSend);
controllerCore.state.change(pdnToSend);
controllerCore.controller.send(pdnToSend, payloadToSend);
}
}
}

View File

@@ -14,13 +14,12 @@
#include "../scheduling/ScheduledCommand.h"
#include <map>
namespace core {
class ControllerCore;
class PowerDownManagerTimeout: public core::IPowerDownManager
class PowerDownManagerTimeout: public IPowerDownManager
{
public:
PowerDownManagerTimeout(ControllerCore& controller);
PowerDownManagerTimeout(ControllerCore& controllerCore);
virtual ~PowerDownManagerTimeout();
virtual void triggerSleep(Bank bank, sc_time time);
@@ -32,7 +31,7 @@ public:
virtual bool isInSelfRefresh(Bank bank);
private:
bool canSleep();
ControllerCore& controller;
ControllerCore& controllerCore;
std::map<Bank, tlm::tlm_generic_payload> powerDownPayloads;
void sendPowerDownPayloads(ScheduledCommand& cmd);
@@ -42,6 +41,6 @@ private:
bool isInPowerDown();
};
}
#endif /* POWERDOWNMANAGERTIMEOUT_H_ */

View File

@@ -2,15 +2,13 @@
#define IREFRESHMANAGER_H_
#include <systemc.h>
#include "../scheduling/CommandSchedule.h"
#include "../scheduling/ScheduledCommand.h"
namespace core {
class IRefreshManager
{
public:
virtual ~IRefreshManager(){};
virtual bool hasCollision(const CommandSchedule& schedule) = 0;
virtual bool hasCollision(const ScheduledCommand& command) = 0;
virtual void scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) = 0;
virtual void reInitialize(Bank bank, sc_time time) = 0;
@@ -19,6 +17,5 @@ public:
virtual bool isInvalidated(tlm::tlm_generic_payload& payload, sc_time time) = 0;
};
} // namespace core
#endif

View File

@@ -12,12 +12,14 @@
#include "../TimingCalculation.h"
using namespace tlm;
namespace core {
RefreshManager::RefreshManager(ControllerCore& controller) :
controller(controller), timing(controller.config.memSpec.refreshTimings[Bank(0)]), nextPlannedRefresh(SC_ZERO_TIME)
controllerCore(controller), timing(controller.config.memSpec.refreshTimings[Bank(0)]), nextPlannedRefresh(SC_ZERO_TIME)
{
setupTransactions();
for (Bank bank : controller.getBanks())
{
setUpDummy(refreshPayloads[bank], bank);
}
planNextRefresh();
}
@@ -25,58 +27,48 @@ RefreshManager::~RefreshManager()
{
}
bool RefreshManager::hasCollision(const CommandSchedule& schedule)
{
return schedule.getStart() < controller.state.getLastCommand(Command::AutoRefresh).getEnd() || schedule.getEnd() > nextPlannedRefresh;
}
bool RefreshManager::hasCollision(const ScheduledCommand& command)
{
return command.getStart() < controller.state.getLastCommand(Command::AutoRefresh).getEnd() || command.getEnd() > nextPlannedRefresh;
return command.getStart() < controllerCore.state.getLastCommand(Command::AutoRefresh).getEnd() || command.getEnd() > nextPlannedRefresh;
}
void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time)
{
sc_assert(!isInvalidated(payload, time));
if (!controller.state.rowBufferStates.allRowBuffersAreClosed())
if (!controllerCore.state.rowBufferStates.allRowBuffersAreClosed())
{
ScheduledCommand precharge(Command::PrechargeAll, time, getExecutionTime(Command::PrechargeAll, refreshPayloads[Bank(0)]),
DramExtension::getExtension(refreshPayloads[Bank(0)]));
controller.getCommandChecker(Command::PrechargeAll).delayToSatisfyConstraints(precharge);
sendToAllBanks(precharge);
ScheduledCommand prechargeAllMaster(Command::PrechargeAll, time, getExecutionTime(Command::PrechargeAll, refreshPayloads[Bank(0)]),
refreshPayloads[Bank(0)]);
controllerCore.getCommandChecker(Command::PrechargeAll).delayToSatisfyConstraints(prechargeAllMaster);
for (Bank bank : controllerCore.getBanks())
{
ScheduledCommand prechargeAll(Command::PrechargeAll, prechargeAllMaster.getStart(), prechargeAllMaster.getExecutionTime(),
refreshPayloads[bank]);
controllerCore.state.change(prechargeAll);
controllerCore.controller.send(prechargeAll, refreshPayloads[bank]);
}
}
ScheduledCommand nextRefresh(Command::AutoRefresh, time, getExecutionTime(Command::AutoRefresh, refreshPayloads[Bank(0)]),
DramExtension::getExtension(refreshPayloads[Bank(0)]));
controller.getCommandChecker(Command::AutoRefresh).delayToSatisfyConstraints(nextRefresh);
sendToAllBanks(nextRefresh);
for (Bank bank : controller.getBanks())
for (Bank bank : controllerCore.getBanks())
{
ScheduledCommand refresh(Command::AutoRefresh, time, getExecutionTime(Command::AutoRefresh, refreshPayloads[bank]),
DramExtension::getExtension(refreshPayloads[bank]));
controllerCore.getCommandChecker(Command::AutoRefresh).delayToSatisfyConstraints(refresh);
controllerCore.state.change(refresh);
controllerCore.controller.send(refresh, refreshPayloads[bank]);
DramExtension::getExtension(refreshPayloads[bank]).incrementRow();
}
planNextRefresh();
}
void RefreshManager::sendToAllBanks(ScheduledCommand& command)
{
for (Bank bank : controller.getBanks())
{
tlm_generic_payload& payload = refreshPayloads[bank];
DramExtension extension = DramExtension::getExtension(payload);
ScheduledCommand cmd(command.getCommand(), command.getStart(), command.getExecutionTime(), extension);
controller.state.change(cmd);
controller.wrapper.send(cmd, payload);
}
}
void RefreshManager::planNextRefresh()
{
nextPlannedRefresh += timing.tREFI;
controller.wrapper.send(REFTrigger, nextPlannedRefresh, refreshPayloads[Bank(0)]);
controllerCore.controller.send(REFTrigger, nextPlannedRefresh, refreshPayloads[Bank(0)]);
}
void RefreshManager::reInitialize(Bank /*bank*/, sc_time time)
@@ -85,17 +77,8 @@ void RefreshManager::reInitialize(Bank /*bank*/, sc_time time)
planNextRefresh();
}
bool core::RefreshManager::isInvalidated(tlm::tlm_generic_payload& payload, sc_time time)
bool RefreshManager::isInvalidated(tlm::tlm_generic_payload& payload, sc_time time)
{
return nextPlannedRefresh > time;
}
void RefreshManager::setupTransactions()
{
for (Bank bank : controller.getBanks())
{
setUpDummy(refreshPayloads[bank], bank);
}
}
} /* namespace core */

View File

@@ -11,35 +11,28 @@
#include "IRefreshManager.h"
#include "../configuration/MemSpec.h"
namespace core {
class ControllerCore;
class RefreshManager : public IRefreshManager
{
public:
RefreshManager(ControllerCore& controller);
RefreshManager(ControllerCore& controllerCore);
virtual ~RefreshManager();
virtual bool hasCollision(const CommandSchedule& schedule) override;
virtual bool hasCollision(const ScheduledCommand& command) override;
virtual void scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) override;
void reInitialize(Bank bank, sc_time time) override;
virtual bool isInvalidated(tlm::tlm_generic_payload& payload, sc_time time) override;
private:
ControllerCore& controller;
ControllerCore& controllerCore;
RefreshTiming& timing;
sc_time nextPlannedRefresh;
std::map<Bank, tlm::tlm_generic_payload> refreshPayloads;
void planNextRefresh();
void sendToAllBanks(ScheduledCommand& command);
void setupTransactions();
};
} /* namespace core */
#endif /* REFRESHMANAGER_H_ */

View File

@@ -12,10 +12,9 @@
using namespace std;
namespace core {
RefreshManagerBankwise::RefreshManagerBankwise(ControllerCore& controller) :
controller(controller)
controllerCore(controller)
{
for (Bank bank : controller.getBanks())
{
@@ -28,15 +27,9 @@ RefreshManagerBankwise::~RefreshManagerBankwise()
{
}
bool RefreshManagerBankwise::hasCollision(const CommandSchedule& schedule)
{
return schedule.getStart() < controller.state.getLastCommand(Command::AutoRefresh, schedule.getBank()).getEnd()
|| schedule.getEnd() > nextPlannedRefreshs[schedule.getBank()];
}
bool RefreshManagerBankwise::hasCollision(const ScheduledCommand& command)
{
return command.getStart() < controller.state.getLastCommand(Command::AutoRefresh, command.getBank()).getEnd()
return command.getStart() < controllerCore.state.getLastCommand(Command::AutoRefresh, command.getBank()).getEnd()
|| command.getEnd() > nextPlannedRefreshs[command.getBank()];}
void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time)
@@ -47,19 +40,19 @@ void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload& payload,
DramExtension& extension = DramExtension::getExtension(refreshPayload);
if (controller.state.rowBufferStates.rowBufferIsOpen(extension.getBank()))
if (controllerCore.state.rowBufferStates.rowBufferIsOpen(extension.getBank()))
{
ScheduledCommand precharge(Command::Precharge, time, getExecutionTime(Command::Precharge, refreshPayload), extension);
controller.getCommandChecker(Command::Precharge).delayToSatisfyConstraints(precharge);
controller.state.change(precharge);
controller.wrapper.send(precharge, refreshPayload);
controllerCore.getCommandChecker(Command::Precharge).delayToSatisfyConstraints(precharge);
controllerCore.state.change(precharge);
controllerCore.controller.send(precharge, refreshPayload);
}
ScheduledCommand nextRefresh(Command::AutoRefresh, time, getExecutionTime(Command::AutoRefresh, refreshPayload), extension);
controller.getCommandChecker(Command::AutoRefresh).delayToSatisfyConstraints(nextRefresh);
controller.state.change(nextRefresh);
controller.wrapper.send(nextRefresh, refreshPayload);
ScheduledCommand refresh(Command::AutoRefresh, time, getExecutionTime(Command::AutoRefresh, refreshPayload), extension);
controllerCore.getCommandChecker(Command::AutoRefresh).delayToSatisfyConstraints(refresh);
controllerCore.state.change(refresh);
controllerCore.controller.send(refresh, refreshPayload);
extension.incrementRow();
planNextRefresh(extension.getBank());
@@ -68,7 +61,7 @@ void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload& payload,
void RefreshManagerBankwise::planNextRefresh(Bank bank)
{
nextPlannedRefreshs[bank] += Configuration::getInstance().memSpec.refreshTimings[bank].tREFI;
controller.wrapper.send(REFTrigger, nextPlannedRefreshs[bank], refreshPayloads[bank]);
controllerCore.controller.send(REFTrigger, nextPlannedRefreshs[bank], refreshPayloads[bank]);
}
void RefreshManagerBankwise::reInitialize(Bank bank, sc_time time)
@@ -82,5 +75,4 @@ bool RefreshManagerBankwise::isInvalidated(tlm::tlm_generic_payload& payload, sc
return nextPlannedRefreshs[DramExtension::getExtension(payload).getBank()] > time;
}
} /* namespace core */

View File

@@ -8,23 +8,20 @@
#ifndef BANKWISEREFRESHMANAGER_H_
#define BANKWISEREFRESHMANAGER_H_
#include "../scheduling/CommandSchedule.h"
#include "../../../common/dramExtension.h"
#include "../configuration/MemSpec.h"
#include "IRefreshManager.h"
namespace core {
class ControllerCore;
class RefreshManagerBankwise : public IRefreshManager
{
public:
RefreshManagerBankwise(ControllerCore& controller);
RefreshManagerBankwise(ControllerCore& controllerCore);
virtual ~RefreshManagerBankwise();
virtual bool hasCollision(const CommandSchedule& schedule) override;
virtual bool hasCollision(const ScheduledCommand& command) override;
virtual bool hasCollision(const ScheduledCommand& command) override;
virtual void scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) override;
void reInitialize(Bank bank, sc_time time) override;
@@ -33,7 +30,7 @@ public:
private:
ControllerCore& controller;
ControllerCore& controllerCore;
std::map<Bank, tlm::tlm_generic_payload> refreshPayloads;
std::map<Bank, sc_time> nextPlannedRefreshs;
@@ -41,6 +38,5 @@ private:
void planNextRefresh(Bank bank);
};
} /* namespace controller */
#endif /* BANKWISEREFRESHMANAGER_H_ */

View File

@@ -1,67 +0,0 @@
/*
* CommandSchedule.h
*
* Created on: Mar 5, 2014
* Author: jonny
*/
#ifndef COMMANDSCHEDULE_H_
#define COMMANDSCHEDULE_H_
#include <vector>
#include "../../../common/dramExtension.h"
#include "../../../common/TlmRecorder.h"
#include "ScheduledCommand.h"
namespace core {
class CommandSchedule
{
public:
CommandSchedule(tlm::tlm_generic_payload& transaction) :
extension(DramExtension::getExtension(&transaction))
{
}
virtual ~CommandSchedule()
{
}
ScheduledCommand& add(Command command, sc_time start, sc_time executionTime)
{
scheduledCommands.push_back(ScheduledCommand(command, start, executionTime, extension));
return scheduledCommands.back();
}
const std::vector<ScheduledCommand>& getScheduledCommands() const
{
return scheduledCommands;
}
sc_time getStart() const
{
return scheduledCommands.front().getStart();
}
sc_time getEnd() const
{
return scheduledCommands.back().getEnd();
}
sc_time getExecutionTime() const
{
return scheduledCommands.back().getEnd() - scheduledCommands.front().getStart();
}
Bank getBank() const
{
return extension.getBank();
}
private:
std::vector<ScheduledCommand> scheduledCommands;
DramExtension extension;
};
} /* namespace controller */
#endif /* COMMANDSCHEDULE_H_ */

View File

@@ -1,88 +0,0 @@
/*
* CommandSequenceGenerator.cpp
*
* Created on: Mar 5, 2014
* Author: jonny
*/
#include "CommandSequenceGenerator.h"
#include "../../../common/dramExtension.h"
#include "../configuration/Configuration.h"
using namespace std;
namespace core {
CommandSequence CommandSequenceGenerator::generateCommandSequence(tlm::tlm_generic_payload& transaction)
{
const DramExtension& extension = DramExtension::getExtension(&transaction);
Bank bank = extension.getBank();
Row row = extension.getRow();
CommandSequence result;
if (!controllerState.rowBufferStates.rowBufferIsOpen(bank))
{
return getBankMissCommandSequence(transaction);
}
else if (controllerState.rowBufferStates.getRowInRowBuffer(bank) != row)
{
return getRowMissCommandSequence(transaction);
}
else
{
return getRowHitCommandSequence(transaction);
}
}
CommandSequence CommandSequenceGenerator::generateCommandSequence(
tlm::tlm_generic_payload* transaction)
{
return generateCommandSequence(*transaction);
}
CommandSequence CommandSequenceGenerator::getBankMissCommandSequence(tlm::tlm_generic_payload& transaction)
{
vector<Command> result;
result.push_back(Command::Activate);
result.push_back(getReadWriteCommand(transaction));
return result;
}
CommandSequence CommandSequenceGenerator::getRowMissCommandSequence(tlm::tlm_generic_payload& transaction)
{
vector<Command> result;
result.push_back(Command::Precharge);
result.push_back(Command::Activate);
result.push_back(getReadWriteCommand(transaction));
return result;
}
CommandSequence CommandSequenceGenerator::getRowHitCommandSequence(tlm::tlm_generic_payload& transaction)
{
vector<Command> result;
result.push_back(getReadWriteCommand(transaction));
return result;
}
Command CommandSequenceGenerator::getReadWriteCommand(tlm::tlm_generic_payload& transaction)
{
if (transaction.get_command() == tlm::TLM_READ_COMMAND)
{
if(Configuration::getInstance().OpenPagePolicy)
return Command::Read;
else
return Command::ReadA;
}
else
{
if(Configuration::getInstance().OpenPagePolicy)
return Command::Write;
else
return Command::WriteA;
}
}
} /* namespace controller */

View File

@@ -1,37 +0,0 @@
/*
* CommandGenerator.h
*
* Created on: Mar 5, 2014
* Author: jonny
*/
#ifndef COMMANDGENERATOR_H_
#define COMMANDGENERATOR_H_
#include <tlm.h>
#include <vector>
#include "../ControllerState.h"
#include "../Command.h"
namespace core {
class CommandSequenceGenerator {
public:
CommandSequenceGenerator(const ControllerState& controllerState) : controllerState(controllerState) {}
virtual ~CommandSequenceGenerator() {}
CommandSequence generateCommandSequence(tlm::tlm_generic_payload& transaction);
CommandSequence generateCommandSequence(tlm::tlm_generic_payload* transaction);
private:
const ControllerState& controllerState;
Command getReadWriteCommand(tlm::tlm_generic_payload& transaction);
CommandSequence getBankMissCommandSequence(tlm::tlm_generic_payload& transaction);
CommandSequence getRowMissCommandSequence(tlm::tlm_generic_payload& transaction);
CommandSequence getRowHitCommandSequence(tlm::tlm_generic_payload& transaction);
};
} /* namespace controller */
#endif /* COMMANDGENERATOR_H_ */

View File

@@ -1,37 +0,0 @@
/*
* CommandSequenceScheduler.cpp
*
* Created on: Mar 9, 2014
* Author: jonny
*/
#include "CommandSequenceScheduler.h"
#include "../ControllerCore.h"
#include "../../../common/DebugManager.h"
#include "../TimingCalculation.h"
namespace core {
CommandSchedule CommandSequenceScheduler::schedule(CommandSequence commands, sc_time start,
tlm::tlm_generic_payload& transaction)
{
CommandSchedule schedule(transaction);
for (Command cmd : commands)
{
ControllerCore::printDebugMessage("Scheduling command " + commandToString(cmd));
ICommandChecker& checker = controller.getCommandChecker(cmd);
sc_time executionTime = getExecutionTime(cmd,transaction);
ScheduledCommand& scheduledCommand = schedule.add(cmd, start, executionTime);
checker.delayToSatisfyConstraints(scheduledCommand);
sc_assert(scheduledCommand.getStart()>=start && scheduledCommand.getStart() < scheduledCommand.getEnd());
controller.state.change(scheduledCommand);
}
return schedule;
}
} /* namespace controller */

View File

@@ -1,31 +0,0 @@
/*
* CommandSequenceScheduler.h
*
* Created on: Mar 9, 2014
* Author: jonny
*/
#ifndef COMMANDSEQUENCESCHEDULER_H_
#define COMMANDSEQUENCESCHEDULER_H_
#include "CommandSchedule.h"
namespace core {
class ControllerCore;
class CommandSequenceScheduler
{
public:
CommandSequenceScheduler(ControllerCore& controller) : controller(controller){}
virtual ~CommandSequenceScheduler(){}
CommandSchedule schedule(CommandSequence commands, sc_time start, tlm::tlm_generic_payload& transaction);
private:
ControllerCore& controller;
};
} /* namespace controller */
#endif /* COMMANDSEQUENCESCHEDULER_H_ */

View File

@@ -9,8 +9,6 @@
#include "../../../common/Utils.h"
#include "../configuration/Configuration.h"
namespace core {
bool ScheduledCommand::isNoCommand() const
{
return (command == Command::NOP && start == SC_ZERO_TIME && executionTime == SC_ZERO_TIME && end == SC_ZERO_TIME);
@@ -38,7 +36,9 @@ void ScheduledCommand::delayStart(sc_time delay)
setStart(start+delay);
}
void ScheduledCommand::delayToMeetConstraint(sc_time previous, sc_time constraint)
// Delays the command so that its start is at least value(constraint) from timepoint previous apart.
// If passed a constraint of 0ns, method will make sure that command starts no earlier than at timepoint previous
void ScheduledCommand::establishMinDistanceFromStart(sc_time previous, sc_time constraint)
{
delayStart(getDelayToMeetConstraint(previous, start, constraint));
}
@@ -106,7 +106,3 @@ TimeInterval ScheduledCommand::getIntervalOnDataStrobe() const
return TimeInterval(getStart() + timings.tWL - timings.clk / 2, getStart() + timings.tWL + getWriteAccessTime() - timings.clk / 2);
}
}
}

View File

@@ -10,12 +10,11 @@
#include <systemc.h>
#include <tlm.h>
#include "../Command.h"
#include "../../Command.h"
#include "../../../common/dramExtension.h"
#include "../../../common/TlmRecorder.h"
#include "../../../common/Utils.h"
namespace core {
class ScheduledCommand
{
@@ -27,6 +26,11 @@ public:
{
}
ScheduledCommand(Command command, sc_time start, sc_time executionTime, const tlm::tlm_generic_payload& payload) :
ScheduledCommand(command, start, executionTime, DramExtension::getExtension(payload))
{
}
ScheduledCommand() :
command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME), end(SC_ZERO_TIME), extension()
@@ -39,7 +43,7 @@ public:
const sc_time getStart() const;
void setStart(sc_time newStart);
void delayStart(sc_time delay);
void delayToMeetConstraint(sc_time previous, sc_time constraint);
void establishMinDistanceFromStart(sc_time previous, sc_time constraint);
sc_time getEnd() const;
Command getCommand() const;
@@ -63,6 +67,5 @@ private:
sc_time end;
DramExtension extension;
};
} /* namespace controller */
#endif /* SCHEDULEDCOMMAND_H_ */

View File

@@ -8,10 +8,8 @@
#ifndef TRIGGER_H_
#define TRIGGER_H_
namespace core {
enum Trigger {REFTrigger, PDNTrigger};
} /* namespace controller */
#endif /* TRIGGER_H_ */

View File

@@ -10,12 +10,10 @@
#include "ActivateChecker.h"
#include "../../TimingCalculation.h"
#include "../../../../common/DebugManager.h"
#include "../../Command.h"
#include "../../../Command.h"
#include "../../../../common/Utils.h"
#include <iostream>
namespace core {
void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
sc_assert(command.getCommand() == Command::Activate);
@@ -25,28 +23,28 @@ void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
if (lastCommandOnBank.getCommand() == Command::Precharge)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.memSpec.tRP);
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::ReadA)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.memSpec.tRTP + config.memSpec.tRP);
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRTP + config.memSpec.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::WriteA)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.memSpec.tRFC);
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRFC);
}
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.memSpec.tXP);
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXP);
}
else if (lastCommandOnBank.getCommand() == Command::SREFX)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.memSpec.tXSR);
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXSR);
}
else
reportFatal("Activate Checker", "Activate can not follow " + commandToString(lastCommandOnBank.getCommand()));
@@ -67,7 +65,7 @@ void ActivateChecker::delay_to_satisfy_activateToActivate_sameBank(ScheduledComm
ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate, command.getBank());
if (lastActivateOnBank.isValidCommand())
{
command.delayToMeetConstraint(lastActivateOnBank.getStart(), config.memSpec.tRC);
command.establishMinDistanceFromStart(lastActivateOnBank.getStart(), config.memSpec.tRC);
}
}
@@ -111,5 +109,3 @@ bool ActivateChecker::satisfies_nActivateWindow(ScheduledCommand& command) const
return true;
}
} /* namespace controller */

View File

@@ -11,9 +11,7 @@
#include <map>
#include "ICommandChecker.h"
#include "../../configuration/Configuration.h"
#include "../../ControllerState.h"
namespace core {
#include "../../../ControllerState.h"
class ActivateChecker: public ICommandChecker
{
@@ -31,6 +29,4 @@ private:
bool satisfies_nActivateWindow(ScheduledCommand& command) const;
};
} /* namespace controller */
#endif /* ACTIVATESCHEDULER_H_ */

View File

@@ -11,7 +11,6 @@
#include <systemc.h>
#include "../ScheduledCommand.h"
namespace core {
class ICommandChecker
{
@@ -20,7 +19,6 @@ public:
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const = 0;
};
} /* namespace controller */
#endif /* ICOMMANDSCHEDULER_H_ */

View File

@@ -8,7 +8,6 @@
#include "PowerDownChecker.h"
#include "../../TimingCalculation.h"
namespace core {
void PowerDownChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
sc_assert(
@@ -23,31 +22,31 @@ void PowerDownChecker::delayToSatisfyConstraints(ScheduledCommand& command) cons
{
if (lastCommandOnBank.getCommand() == Command::Read || lastCommandOnBank.getCommand() == Command::ReadA)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tRL + getReadAccessTime() + config.memSpec.clk);
}
else if (lastCommandOnBank.getCommand() == Command::Write)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR);
}
else if (lastCommandOnBank.getCommand() == Command::WriteA)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.clk);
}
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.memSpec.tRFC);
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRFC);
}
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.memSpec.tXP);
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXP);
}
else if (lastCommandOnBank.getCommand() == Command::SREFX)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.memSpec.tXSR);
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXSR);
}
else
@@ -59,19 +58,17 @@ void PowerDownChecker::delayToSatisfyConstraints(ScheduledCommand& command) cons
else if (command.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(state.getLastCommand(Command::PDNA).getStart(), config.memSpec.tCKE);
command.establishMinDistanceFromStart(state.getLastCommand(Command::PDNA).getStart(), config.memSpec.tCKE);
}
else if (command.getCommand() == Command::PDNPX)
{
command.delayToMeetConstraint(state.getLastCommand(Command::PDNP).getStart(), config.memSpec.tCKE);
command.establishMinDistanceFromStart(state.getLastCommand(Command::PDNP).getStart(), config.memSpec.tCKE);
}
else if (command.getCommand() == Command::SREFX)
{
command.delayToMeetConstraint(state.getLastCommand(Command::SREF).getStart(), config.memSpec.tCKESR);
command.establishMinDistanceFromStart(state.getLastCommand(Command::SREF).getStart(), config.memSpec.tCKESR);
}
state.bus.moveCommandToNextFreeSlot(command);
}
} /* namespace core */

View File

@@ -8,12 +8,11 @@
#ifndef POWERDOWNCHECKER_H_
#define POWERDOWNCHECKER_H_
#include "../../ControllerState.h"
#include "../../../ControllerState.h"
#include "../../configuration/Configuration.h"
#include "ICommandChecker.h"
#include <systemc>
namespace core {
class PowerDownChecker : public ICommandChecker
{
@@ -33,6 +32,5 @@ private:
ControllerState& state;
};
} /* namespace core */
#endif /* POWERDOWNCHECKER_H_ */

View File

@@ -8,44 +8,52 @@
#include "PrechargeAllChecker.h"
#include "../../TimingCalculation.h"
namespace core {
void PrechargeAllChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
sc_assert(command.getCommand() == Command::PrechargeAll);
// Consider all banks for the constraints, since precharge all command is supposed to happen at the same time on all banks
for (unsigned int bank = 0; bank < config.memSpec.NumberOfBanks; ++bank)
{
ScheduledCommand lastCommand = state.getLastScheduledCommand(Bank(bank));
if (lastCommand.isValidCommand())
{
if (lastCommand.getCommand() == Command::Read)
if(lastCommand.getCommand() == Command::Precharge)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.memSpec.tRTP);
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRP);
}
else if(lastCommand.getCommand() == Command::Activate)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRCD);
}
else if (lastCommand.getCommand() == Command::Read)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRTP);
}
else if (lastCommand.getCommand() == Command::ReadA)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.memSpec.tRTP + config.memSpec.tRP);
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRTP + config.memSpec.tRP);
}
else if (lastCommand.getCommand() == Command::Write)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR);
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR);
}
else if(lastCommand.getCommand() == Command::WriteA)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.tRP);
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.tRP);
}
else if (lastCommand.getCommand() == Command::AutoRefresh)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.memSpec.tRFC);
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRFC);
}
else if (lastCommand.getCommand() == Command::PDNAX || lastCommand.getCommand() == Command::PDNPX)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.memSpec.tXP);
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tXP);
}
else if (lastCommand.getCommand() == Command::SREFX)
{
command.delayToMeetConstraint(lastCommand.getEnd(), config.memSpec.tXSR);
command.establishMinDistanceFromStart(lastCommand.getEnd(), config.memSpec.tXSR);
}
else
reportFatal("Precharge All Checker",
@@ -56,10 +64,9 @@ void PrechargeAllChecker::delayToSatisfyConstraints(ScheduledCommand& command) c
ScheduledCommand lastActivate = state.getLastCommand(Command::Activate, command.getBank());
if (lastActivate.isValidCommand())
{
command.delayToMeetConstraint(lastActivate.getStart(), config.memSpec.tRAS);
command.establishMinDistanceFromStart(lastActivate.getStart(), config.memSpec.tRAS);
}
state.bus.moveCommandToNextFreeSlot(command);
}
} /* namespace core */

View File

@@ -10,11 +10,10 @@
#include "ICommandChecker.h"
#include "../../configuration/Configuration.h"
#include "../../ControllerState.h"
#include "../../../ControllerState.h"
namespace core {
class PrechargeAllChecker: public core::ICommandChecker
class PrechargeAllChecker: public ICommandChecker
{
public:
PrechargeAllChecker(const Configuration& config, ControllerState& state) :
@@ -32,6 +31,5 @@ private:
ControllerState& state;
};
} /* namespace core */
#endif /* PRECHARGEALLCHECKER_H_ */

View File

@@ -8,7 +8,6 @@
#include "PrechargeChecker.h"
#include "../../TimingCalculation.h"
namespace core {
void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
@@ -19,18 +18,29 @@ void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand& command) cons
if (lastCommand.isValidCommand())
{
if (lastCommand.getCommand() == Command::Read)
// the first two cases happen when a resfresh interrups the command sequence of a transaction
// (e.g. commands to process transaction are PRE-ACT-RD and refresh happens after the PRE or after the ACT)
if(lastCommand.getCommand() == Command::Precharge)
{
command.delayToMeetConstraint(lastCommand.getStart(),config.memSpec.tRTP);
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRP);
}
else if(lastCommand.getCommand() == Command::Activate)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRCD);
}
else if (lastCommand.getCommand() == Command::Read)
{
command.establishMinDistanceFromStart(lastCommand.getStart(),config.memSpec.tRTP);
}
else if (lastCommand.getCommand() == Command::Write)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR);
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR);
}
else if (lastCommand.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.memSpec.tXP);
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tXP);
}
else
reportFatal("Precharge Checker", "Precharge can not follow " + commandToString(lastCommand.getCommand()));
@@ -39,11 +49,9 @@ void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand& command) cons
ScheduledCommand lastActivate = state.getLastCommand(Command::Activate, command.getBank());
if (lastActivate.isValidCommand())
{
command.delayToMeetConstraint(lastActivate.getStart(), config.memSpec.tRAS);
command.establishMinDistanceFromStart(lastActivate.getStart(), config.memSpec.tRAS);
}
state.bus.moveCommandToNextFreeSlot(command);
}
} /* namespace controller */

View File

@@ -10,11 +10,10 @@
#include "ICommandChecker.h"
#include "../../configuration/Configuration.h"
#include "../../ControllerState.h"
#include "../../../ControllerState.h"
namespace core {
class PrechargeChecker: public core::ICommandChecker
class PrechargeChecker: public ICommandChecker
{
public:
PrechargeChecker(const Configuration& config, ControllerState& state) : config(config), state(state) {}
@@ -26,6 +25,5 @@ private:
ControllerState& state;
};
} /* namespace controller */
#endif /* PRECHARGECHECKER_H_ */

View File

@@ -10,49 +10,29 @@
#include "../../../../common/Utils.h"
#include "WriteChecker.h"
namespace core {
void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
sc_assert(command.getCommand() == Command::Read || command.getCommand() == Command::ReadA);
delayToSatisfyDLL(command);
ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank());
//fifo patch
if(config.Scheduler == "FIFO")
{
//no access can accelerate other access
ScheduledCommand lastread = state.getLastCommand(Command::Read);
ScheduledCommand lastwrite = state.getLastCommand(Command::Write);
ScheduledCommand lastreada = state.getLastCommand(Command::ReadA);
ScheduledCommand lastwritea = state.getLastCommand(Command::WriteA);
command.delayToMeetConstraint(lastread.getStart(), SC_ZERO_TIME);
command.delayToMeetConstraint(lastreada.getStart(), SC_ZERO_TIME);
command.delayToMeetConstraint(lastwrite.getStart(), SC_ZERO_TIME);
command.delayToMeetConstraint(lastwritea.getStart(), SC_ZERO_TIME);
}
if (lastCommand.isValidCommand())
{
if (lastCommand.getCommand() == Command::Activate)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.memSpec.tRCD);
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRCD);
}
else if (lastCommand.getCommand() == Command::Read)
{
command.delayToMeetConstraint(lastCommand.getStart(), ReadChecker::readToRead(lastCommand,command));
command.establishMinDistanceFromStart(lastCommand.getStart(), ReadChecker::readToRead(lastCommand,command));
}
else if (lastCommand.getCommand() == Command::Write)
{
command.delayToMeetConstraint(lastCommand.getStart(), ReadChecker::writeToRead(lastCommand, command));
command.establishMinDistanceFromStart(lastCommand.getStart(), ReadChecker::writeToRead(lastCommand, command));
}
else if (lastCommand.getCommand() == Command::PDNPX || lastCommand.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.memSpec.tXP);
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tXP);
}
else
reportFatal("Read Checker", "Read can not follow " + commandToString(lastCommand.getCommand()));
@@ -100,7 +80,7 @@ void ReadChecker::delayToSatisfyDLL(ScheduledCommand& read) const
{
ScheduledCommand lastSREFX = state.getLastCommand(Command::SREFX, read.getBank());
if (lastSREFX.isValidCommand())
read.delayToMeetConstraint(lastSREFX.getStart(), config.memSpec.tXSRDLL);
read.establishMinDistanceFromStart(lastSREFX.getStart(), config.memSpec.tXSRDLL);
}
sc_time ReadChecker::readToRead(ScheduledCommand& firstRead, ScheduledCommand& secondRead)
@@ -123,5 +103,4 @@ sc_time ReadChecker::writeToRead(ScheduledCommand& write, ScheduledCommand& read
return config.tWL + getWriteAccessTime() + tWTR;
}
} /* namespace controller */

View File

@@ -10,11 +10,10 @@
#include "ICommandChecker.h"
#include "../../configuration/Configuration.h"
#include "../../ControllerState.h"
#include "../../../ControllerState.h"
namespace core {
class ReadChecker: public core::ICommandChecker
class ReadChecker: public ICommandChecker
{
public:
ReadChecker(Configuration& config, ControllerState& state) : config(config), state(state) {}
@@ -34,6 +33,5 @@ private:
bool collidesWithStrobeCommand(ScheduledCommand& read, ScheduledCommand& strobeCommand) const;
};
} /* namespace controller */
#endif /* READCHECKER_H_ */

View File

@@ -9,7 +9,6 @@
#include "../../TimingCalculation.h"
namespace core {
void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
@@ -21,24 +20,24 @@ void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
if (lastCommandOnBank.getCommand() == Command::Precharge || lastCommandOnBank.getCommand() == Command::PrechargeAll)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.memSpec.tRP);
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::ReadA)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.memSpec.tRTP + config.memSpec.tRP);
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRTP + config.memSpec.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::WriteA)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.memSpec.tXP);
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXP);
}
else if (lastCommandOnBank.getCommand() == Command::SREFX)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.memSpec.tXSR);
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXSR);
}
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
{
@@ -50,5 +49,4 @@ void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
state.bus.moveCommandToNextFreeSlot(command);
}
} /* namespace core */

View File

@@ -9,11 +9,10 @@
#define REFRESHCHECKER_H_
#include "ICommandChecker.h"
#include "../../ControllerState.h"
#include "../../../ControllerState.h"
#include "../../configuration/Configuration.h"
#include <systemc>
namespace core {
class RefreshChecker: public ICommandChecker
{
@@ -34,6 +33,5 @@ private:
};
} /* namespace core */
#endif /* REFRESHCHECKER_H_ */

View File

@@ -10,7 +10,6 @@
#include "../../../../common/Utils.h"
#include "ReadChecker.h"
namespace core {
void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
@@ -18,39 +17,23 @@ void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank());
//fifo patch
if(config.Scheduler == "FIFO")
{
//no access can accelerate other access
ScheduledCommand lastread = state.getLastCommand(Command::Read);
ScheduledCommand lastwrite = state.getLastCommand(Command::Write);
ScheduledCommand lastreada = state.getLastCommand(Command::ReadA);
ScheduledCommand lastwritea = state.getLastCommand(Command::WriteA);
command.delayToMeetConstraint(lastread.getStart(), SC_ZERO_TIME);
command.delayToMeetConstraint(lastreada.getStart(), SC_ZERO_TIME);
command.delayToMeetConstraint(lastwrite.getStart(), SC_ZERO_TIME);
command.delayToMeetConstraint(lastwritea.getStart(), SC_ZERO_TIME);
}
if (lastCommand.isValidCommand())
{
if (lastCommand.getCommand() == Command::Activate)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.memSpec.tRCD);
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRCD);
}
else if (lastCommand.getCommand() == Command::Read)
{
command.delayToMeetConstraint(lastCommand.getStart(), WriteChecker::readToWrite(lastCommand, command));
command.establishMinDistanceFromStart(lastCommand.getStart(), WriteChecker::readToWrite(lastCommand, command));
}
else if (lastCommand.getCommand() == Command::Write)
{
command.delayToMeetConstraint(lastCommand.getStart(), WriteChecker::writeToWrite(lastCommand, command));
command.establishMinDistanceFromStart(lastCommand.getStart(), WriteChecker::writeToWrite(lastCommand, command));
}
else if (lastCommand.getCommand() == Command::PDNPX || lastCommand.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.memSpec.tXP);
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tXP);
}
else
reportFatal("Write Checker", "Write can not follow " + commandToString(lastCommand.getCommand()));
@@ -113,4 +96,3 @@ sc_time WriteChecker::readToWrite(ScheduledCommand& read, ScheduledCommand& writ
return config.tRL + getReadAccessTime() - config.tWL + config.clk * 2;
}
} /* namespace controller */

View File

@@ -10,11 +10,10 @@
#include "ICommandChecker.h"
#include "../../configuration/Configuration.h"
#include "../../ControllerState.h"
#include "../../../ControllerState.h"
namespace core {
class WriteChecker: public core::ICommandChecker
class WriteChecker: public ICommandChecker
{
public:
WriteChecker(const Configuration& config, ControllerState& state) : config(config), state(state) {}
@@ -31,6 +30,5 @@ private:
ControllerState& state;
};
} /* namespace controller */
#endif /* WRITECHECKER_H_ */

View File

@@ -7,43 +7,28 @@
#include "Fifo.h"
namespace scheduler {
bool Fifo::hasPayloads()
{
return getNumberOfQueuedPayloads() > 0;
}
using namespace std;
void Fifo::schedule(gp* payload)
{
buffer.push_back(payload);
buffer[DramExtension::getExtension(payload).getBank()].emplace_back(payload);
}
gp* Fifo::getNextPayload()
pair<Command, tlm::tlm_generic_payload*> Fifo::getNextRequest(Bank bank)
{
if(!buffer.empty())
if(!buffer[bank].empty())
{
DramExtension& frontRequest = DramExtension::getExtension(buffer.front());
vector<Bank> freeBanks = controllerCore.getFreeBanks();
if(std::find(freeBanks.begin(),freeBanks.end(),frontRequest.getBank()) != freeBanks.end())
gp* payload = buffer[bank].front();
Command command = IScheduler::getNextCommand(*payload);
if(command == Command::Read || command == Command::ReadA || command == Command::Write || command == Command::WriteA)
{
return buffer.front();
buffer[bank].pop_front();
}
return pair<Command, tlm::tlm_generic_payload*>(command, payload);
}
return NULL;
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
}
void Fifo::removePayload(gp* /*payload*/)
{
buffer.pop_front();
}
unsigned int Fifo::getNumberOfQueuedPayloads()
{
return buffer.size();
}
} /* namespace scheduler */

View File

@@ -8,33 +8,26 @@
#ifndef FIFO_H_
#define FIFO_H_
#include "Scheduler.h"
#include "../core/ControllerCore.h"
#include "../Command.h"
#include "IScheduler.h"
#include <deque>
#include <map>
#include <utility>
namespace scheduler {
class Fifo : public Scheduler
class Fifo : public IScheduler
{
public:
Fifo(core::ControllerCore &controllerCore) : controllerCore(controllerCore)
Fifo(ControllerCore &controllerCore) : IScheduler(controllerCore)
{}
virtual ~Fifo()
{}
virtual bool hasPayloads() override;
virtual void schedule(gp* payload) override;
virtual gp* getNextPayload() override;
virtual void removePayload(gp* payload) override;
void schedule(gp* payload) override;
std::pair<Command, tlm::tlm_generic_payload*> getNextRequest(Bank bank) override;
private:
std::deque<gp*> buffer;
core::ControllerCore &controllerCore;
unsigned int getNumberOfQueuedPayloads();
std::map<Bank, std::deque<gp*>> buffer;
};
} /* namespace scheduler */
#endif /* FIFO_H_ */

View File

@@ -0,0 +1,89 @@
#include "FifoStrict.h"
void FifoStrict::schedule(gp *payload)
{
buffer.push_back(payload);
printDebugMessage("New payload scheduled. Total number " + std::to_string(buffer.size()) + "\n");
}
void FifoStrict::printFrontElementState()
{
if(buffer.size() > 0)
{
printDebugMessage("Front element state - Bank: " + DramExtension::getBank(buffer.front()).toString() + " Operation: " +
commandToString(getNextCommand(*buffer.front())) + "\n");
}
else
{
printDebugMessage("No fron element. Buffer is empty \n ");
}
}
void FifoStrict::NotifyBeginRD()
{
Bank oldFrontElementBank = DramExtension::getBank(buffer.front());
buffer.erase(buffer.begin());
printDebugMessage("Front element finished. New front Element: ");
printFrontElementState();
if(buffer.size() > 0)
{
// If the new front element was orginally blocked, because it had to wait on the preceeding fron element, we have to unblock it.
// We only have to unblock if the new fron element is waiting for a RD/WR operation
if(commandIsIn(getNextCommand(*buffer.front()), {Command::Read, Command::Write, Command::ReadA, Command::WriteA})
&& !controllerCore.bankIsBusy(DramExtension::getBank(buffer.front())))
{
printDebugMessage("Unblocking front element.\n");
controller.scheduleNextFromScheduler(DramExtension::getBank(buffer.front()));
}
// If the new front element is on the same bank as the old one, we have let it make progress, even when the next command is not a RD/WR
// because we are not calling scheduleNextFromScheduler from the calling side
else if(oldFrontElementBank == DramExtension::getBank(*buffer.front()))
{
controller.scheduleNextFromScheduler(DramExtension::getBank(buffer.front()));
}
}
}
std::pair<Command, tlm::tlm_generic_payload *> FifoStrict::getNextRequest(Bank bank)
{
if(buffer.empty())
{
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
}
else if(DramExtension::getBank(buffer.front()) == bank)
{
Command command = getNextCommand(*buffer.front());
pair<Command, tlm::tlm_generic_payload*> result(command, buffer.front());
printDebugMessage("Operation for front Element scheduled. ");
printFrontElementState();
return result;
}
else
{
for(unsigned int i = 1; i < buffer.size(); ++i)
{
if(DramExtension::getBank(buffer[i]) == bank)
{
Command command = getNextCommand(*buffer[i]);
// RD/WR operations have to be strictly in order across banks, so only allow progress on commands
// other than RD/WR commands.
if(commandIsIn(command, {Command::Read, Command::Write, Command::ReadA, Command::WriteA}))
{
printDebugMessage("Current queue element " + std::to_string(i) + " blocked. Waiting for earlier rd/wr to finish\n");
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
}
else
{
return pair<Command, tlm::tlm_generic_payload*>(command, buffer[i]);
}
}
}
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
}
}

View File

@@ -0,0 +1,32 @@
#ifndef FIFOSTRICT_H
#define FIFOSTRICT_H
#include "../core/ControllerCore.h"
#include "../Command.h"
#include "../../common/dramExtension.h"
#include "IScheduler.h"
#include <deque>
#include <map>
#include <utility>
class FifoStrict : public IScheduler
{
public:
FifoStrict(IController &controller,ControllerCore &controllerCore) :
IScheduler(controllerCore), controller(controller)
{}
virtual ~FifoStrict()
{}
void schedule(gp* payload) override;
std::pair<Command, tlm::tlm_generic_payload*> getNextRequest(Bank bank) override;
void NotifyBeginRD();
private:
std::vector<gp*> buffer;
IController &controller;
void printFrontElementState();
};
#endif // FIFOSTRICT_H

View File

@@ -4,133 +4,47 @@
#include <algorithm>
using namespace std;
using namespace core;
namespace scheduler {
FR_FCFS::FR_FCFS(core::ControllerCore& controllerCore, bool useExternalStates, bool adaptiveOpenPage) :
controllerCore(controllerCore), useExternalStates(useExternalStates), adaptiveOpenPage(
adaptiveOpenPage)
{
}
FR_FCFS::~FR_FCFS()
{
}
bool FR_FCFS::hasPayloads()
{
return getNumberOfQueuedPayloads() > 0;
}
void FR_FCFS::schedule(gp* payload)
void FR_FCFS::schedule(gp *payload)
{
buffer[DramExtension::getExtension(payload).getBank()].emplace_back(payload);
}
void FR_FCFS::schedule(std::vector<gp*> payloads)
{
for(gp* payload: payloads)
schedule(payload);
}
gp* FR_FCFS::getNextPayload()
{
for(Bank bank: controllerCore.getFreeBanks())
{
if(!buffer[bank].empty())
{
Row openRowOnBank = (useExternalStates) ? controllerCore.getRowBufferStates().getRowInRowBuffer(bank) : internalBankstates.getRowInRowBuffer(bank);
auto rowHits = findRowHits(bank, openRowOnBank);
gp* result = rowHits.empty() ? buffer[bank].front() : rowHits.front();
if (!adaptiveOpenPage)
{
return result;
}
else
{
rowHits = findRowHits(bank, DramExtension::getExtension(result).getRow());
//other row hits are still in buffer, leave page open
if (rowHits.size() > 1)
Configuration::getInstance().OpenPagePolicy = true;
else
Configuration::getInstance().OpenPagePolicy = false;
//other row hits are still in buffer, leave page open
if(findRowHits(bank,DramExtension::getExtension(result).getRow()).size() > 1)
Configuration::getInstance().OpenPagePolicy = true;
else
Configuration::getInstance().OpenPagePolicy = false;
//no other hit in buffer, but row miss is waiting
if(findRowHits(bank,DramExtension::getExtension(result).getRow()).size() == 1 && buffer[bank].size() > 2 )
Configuration::getInstance().OpenPagePolicy = false;
else
Configuration::getInstance().OpenPagePolicy = true;
return result;
}
}
}
return NULL;
}
gp* FR_FCFS::popOldest(Bank bank)
std::pair<Command, gp*> FR_FCFS::getNextRequest(Bank bank)
{
if(buffer[bank].empty())
return NULL;
gp* result = buffer[bank].front();
buffer[bank].pop_front();
return result;
}
unsigned int FR_FCFS::getNumberOfQueuedPayloads()
{
unsigned int numberOfQueuedPaylods = 0;
for(auto& bufferElement : buffer)
{
numberOfQueuedPaylods += bufferElement.second.size();
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
}
return numberOfQueuedPaylods;
}
bool FR_FCFS::containsPayloadTragetingSameAddress(gp *payload)
{
Bank bank = DramExtension::getExtension(payload).getBank();
Row row = DramExtension::getExtension(payload).getRow();
for(gp* bufferedPayload: buffer[bank])
deque<gp*>::iterator it = FindRowHit(bank);
if(it != buffer[bank].end())
{
if(DramExtension::getExtension(bufferedPayload).getRow() == row)
return true;
gp* payload = *it;
buffer[bank].erase(it);
return pair<Command, gp*>(getReadWriteCommand(*payload), payload);
}
return false;
return pair<Command, gp*>(getNextCommand(buffer[bank].front()), buffer[bank].front());
}
std::vector<gp*> FR_FCFS::findRowHits(Bank bank, Row row)
deque<gp*>::iterator FR_FCFS::FindRowHit(Bank bank)
{
vector<gp*> found;
for (gp* payload : buffer[bank])
deque<gp*> &queue = buffer[bank];
if(!controllerCore.getRowBufferStates().rowBufferIsOpen(bank))
return queue.end();
for(auto it = queue.begin(); it!=queue.end(); it++)
{
if (DramExtension::getExtension(payload).getRow() == row)
found.push_back(payload);
gp* payload = *it;
//Found row-hit
if(DramExtension::getRow(payload) == controllerCore.getRowBufferStates().getRowInRowBuffer(bank))
{
return it;
}
}
return found;
return queue.end();
}
void FR_FCFS::removePayload(gp* payload)
{
Bank bank = DramExtension::getExtension(payload).getBank();
buffer[bank].remove(payload);
if (!useExternalStates)
{
internalBankstates.openRowInRowBuffer(bank, DramExtension::getExtension(payload).getRow());
}
}
}

View File

@@ -1,41 +1,27 @@
#ifndef FR_FCFS_H_
#define FR_FCFS_H_
#include "Scheduler.h"
#include "IScheduler.h"
#include "../core/ControllerCore.h"
#include <list>
#include <map>
#include <vector>
namespace scheduler {
class FR_FCFS : public Scheduler
class FR_FCFS : public IScheduler
{
public:
FR_FCFS(core::ControllerCore& controllerCore, bool refreshAware, bool adaptiveOpenPage);
virtual ~FR_FCFS();
FR_FCFS(ControllerCore &controllerCore) : IScheduler(controllerCore){}
virtual ~FR_FCFS(){}
virtual bool hasPayloads() override;
virtual void schedule(gp* payload) override;
virtual gp* getNextPayload() override;
virtual void removePayload(gp* payload) override;
void schedule(gp* payload) override;
std::pair<Command, tlm::tlm_generic_payload*> getNextRequest(Bank bank) override;
//used by PAR_BS
void schedule(std::vector<gp*> payloads);
gp* popOldest(Bank bank);
unsigned int getNumberOfQueuedPayloads();
//used by read/write grouper
bool containsPayloadTragetingSameAddress(gp* payload);
private:
std::vector<gp*> findRowHits(Bank bank, Row row);
std::map<Bank,std::list<gp*>> buffer;
core::ControllerCore& controllerCore;
core::RowBufferState internalBankstates;
bool useExternalStates;
bool adaptiveOpenPage;
std::map<Bank, std::deque<gp*>> buffer;
std::deque<gp*>::iterator FindRowHit(Bank bank);
};
} /* namespace scheduler */
#endif

View File

@@ -0,0 +1,58 @@
#include "IScheduler.h"
#include "../../common/DebugManager.h"
#include "../core/configuration/Configuration.h"
std::string IScheduler::sendername = "scheduler";
void IScheduler::printDebugMessage(std::string message)
{
DebugManager::getInstance().printDebugMessage(IScheduler::sendername, message);
}
// Get the next command that is necessary to process the request representend by the payload
Command IScheduler::getNextCommand(gp& payload)
{
Bank bank = DramExtension::getBank(payload);
if(!controllerCore.getRowBufferStates().rowBufferIsOpen(bank))
{
return Command::Activate;
}
else if(controllerCore.getRowBufferStates().rowBufferIsOpen(bank) &&
controllerCore.getRowBufferStates().getRowInRowBuffer(bank) != DramExtension::getRow(payload))
{
return Command::Precharge;
}
else
{
return getReadWriteCommand(payload);
}
}
Command IScheduler::getNextCommand(gp *payload)
{
return getNextCommand(*payload);
}
Command IScheduler::getReadWriteCommand(gp& payload)
{
if (payload.get_command() == tlm::TLM_READ_COMMAND)
{
if(Configuration::getInstance().OpenPagePolicy)
return Command::Read;
else
return Command::ReadA;
}
else
{
if(Configuration::getInstance().OpenPagePolicy)
return Command::Write;
else
return Command::WriteA;
}
}
Command IScheduler::getReadWriteCommand(gp *payload)
{
return getReadWriteCommand(*payload);
}

View File

@@ -0,0 +1,33 @@
#ifndef ISCHEDULER_H
#define ISCHEDULER_H
#include <tlm.h>
#include "../../common/dramExtension.h"
#include "../Command.h"
#include "../core/ControllerCore.h"
typedef tlm::tlm_generic_payload gp;
class IScheduler
{
public:
virtual ~IScheduler(){}
IScheduler(ControllerCore &controllerCore) : controllerCore(controllerCore){}
virtual void schedule(gp* payload) = 0;
virtual std::pair<Command, gp*> getNextRequest(Bank bank) = 0;
static std::string sendername;
protected:
void printDebugMessage(std::string message);
Command getNextCommand(gp &payload);
Command getNextCommand(gp *payload);
Command getReadWriteCommand(gp &payload);
Command getReadWriteCommand(gp *payload);
ControllerCore &controllerCore;
};
#endif // ISCHEDULER_H

View File

@@ -1,113 +1,112 @@
// * PARBS.cpp
// *
// * Created on: Apr 9, 2014
// * Author: robert
// */
//// * PARBS.cpp
//// *
//// * Created on: Apr 9, 2014
//// * Author: robert
//// */
#include "PARBS.h"
#include "../core/configuration/Configuration.h"
#include "../../common/dramExtension.h"
#include "map"
#include "ThreadLoad.h"
#include <algorithm>
//#include "PARBS.h"
//#include "../core/configuration/Configuration.h"
//#include "../../common/dramExtension.h"
//#include "map"
//#include "ThreadLoad.h"
//#include <algorithm>
namespace scheduler {
//namespace scheduler {
using namespace std;
using namespace core;
//using namespace std;
PAR_BS::PAR_BS(core::ControllerCore& controllerCore, bool useExternalBankstates, unsigned int capsize) :
controllerCore(controllerCore), useExternalBankstates(useExternalBankstates), capsize(capsize)
{
if (useExternalBankstates)
{
batch = new FR_FCFS(controllerCore, true, false);
buffer = new FR_FCFS(controllerCore, true, false);
}
else
{
batch = new FR_FCFS(controllerCore, true, false);
buffer = new FR_FCFS(controllerCore, true, false);
}
}
//PAR_BS::PAR_BS(ControllerCore& controllerCore, bool useExternalBankstates, unsigned int capsize) :
// controllerCore(controllerCore), useExternalBankstates(useExternalBankstates), capsize(capsize)
//{
// if (useExternalBankstates)
// {
// batch = new FR_FCFS(controllerCore, true, false);
// buffer = new FR_FCFS(controllerCore, true, false);
// }
// else
// {
// batch = new FR_FCFS(controllerCore, true, false);
// buffer = new FR_FCFS(controllerCore, true, false);
// }
//}
PAR_BS::~PAR_BS()
{
//PAR_BS::~PAR_BS()
//{
}
//}
bool PAR_BS::hasPayloads()
{
return batch->hasPayloads() || buffer->hasPayloads();
}
//bool PAR_BS::hasPayloads()
//{
// return batch->hasPayloads() || buffer->hasPayloads();
//}
void PAR_BS::schedule(gp* payload)
{
printDebugMessage("hello!");
buffer->schedule(payload);
}
//void PAR_BS::schedule(gp* payload)
//{
// printDebugMessage("hello!");
// buffer->schedule(payload);
//}
gp* PAR_BS::getNextPayload()
{
if (!batch->hasPayloads())
{
stringstream s;
s << "In batch: " << batch->getNumberOfQueuedPayloads() << "\t" << "in buffer: " << buffer->getNumberOfQueuedPayloads() << endl;
formBatch();
s<< "Formed new batch" << endl;
s << "In batch: " << batch->getNumberOfQueuedPayloads() << "\t" << "in buffer: " << buffer->getNumberOfQueuedPayloads() << endl;
printDebugMessage(s.str());
sc_assert(batch->hasPayloads());
}
//gp* PAR_BS::getNextPayload()
//{
// if (!batch->hasPayloads())
// {
// stringstream s;
// s << "In batch: " << batch->getNumberOfQueuedPayloads() << "\t" << "in buffer: " << buffer->getNumberOfQueuedPayloads() << endl;
// formBatch();
// s<< "Formed new batch" << endl;
// s << "In batch: " << batch->getNumberOfQueuedPayloads() << "\t" << "in buffer: " << buffer->getNumberOfQueuedPayloads() << endl;
// printDebugMessage(s.str());
// sc_assert(batch->hasPayloads());
// }
gp* result = batch->getNextPayload();
if(result == NULL)
result = buffer->getNextPayload();
return result;
}
// gp* result = batch->getNextPayload();
// if(result == NULL)
// result = buffer->getNextPayload();
// return result;
//}
void PAR_BS::removePayload(gp* payload)
{
buffer->removePayload(payload);
batch->removePayload(payload);
//void PAR_BS::removePayload(gp* payload)
//{
// buffer->removePayload(payload);
// batch->removePayload(payload);
if (!useExternalBankstates)
{
DramExtension& extension = DramExtension::getExtension(payload);
internalBankstates.openRowInRowBuffer(extension.getBank(), extension.getRow());
}
// if (!useExternalBankstates)
// {
// DramExtension& extension = DramExtension::getExtension(payload);
// internalBankstates.openRowInRowBuffer(extension.getBank(), extension.getRow());
// }
}
//}
void PAR_BS::formBatch()
{
map<Thread, ThreadLoad> loads;
//void PAR_BS::formBatch()
//{
// map<Thread, ThreadLoad> loads;
for (Bank bank : controllerCore.getBanks())
{
for (unsigned int i = 0; i < capsize; i++)
{
gp* payload = buffer->popOldest(bank);
if(payload == NULL)
break;
loads[DramExtension::getExtension(payload).getThread()].addTransaction(payload);
}
}
// for (Bank bank : controllerCore.getBanks())
// {
// for (unsigned int i = 0; i < capsize; i++)
// {
// gp* payload = buffer->popOldest(bank);
// if(payload == NULL)
// break;
// loads[DramExtension::getExtension(payload).getThread()].addTransaction(payload);
// }
// }
vector<ThreadLoad*> sortedLoads;
for (auto& threadLoadPair : loads)
{
sortedLoads.push_back(&threadLoadPair.second);
}
// vector<ThreadLoad*> sortedLoads;
// for (auto& threadLoadPair : loads)
// {
// sortedLoads.push_back(&threadLoadPair.second);
// }
sort(sortedLoads.begin(), sortedLoads.end(), LoadPointerComparer());
// sort(sortedLoads.begin(), sortedLoads.end(), LoadPointerComparer());
for (auto& load : sortedLoads)
{
batch->schedule(load->getTransactions());
}
// for (auto& load : sortedLoads)
// {
// batch->schedule(load->getTransactions());
// }
}
//}
}
//}

View File

@@ -1,40 +1,40 @@
// * PARBS.h
// *
// * Created on: Apr 9, 2014
// * Author: robert
// *
//// * PARBS.h
//// *
//// * Created on: Apr 9, 2014
//// * Author: robert
//// *
#ifndef PARBS_H_
#define PARBS_H_
#include "Scheduler.h"
#include "../core/ControllerCore.h"
#include "Fr_Fcfs.h"
//#ifndef PARBS_H_
//#define PARBS_H_
//#include "Scheduler.h"
//#include "../core/ControllerCore.h"
//#include "Fr_Fcfs.h"
namespace scheduler {
//namespace scheduler {
class PAR_BS : public Scheduler
{
public:
PAR_BS(core::ControllerCore& controllerCore, bool useExternalBankstates, unsigned int capsize);
virtual ~PAR_BS();
//class PAR_BS : public Scheduler
//{
//public:
// PAR_BS(ControllerCore& controllerCore, bool useExternalBankstates, unsigned int capsize);
// virtual ~PAR_BS();
virtual bool hasPayloads() override;
virtual void schedule(gp* payload) override;
virtual gp* getNextPayload() override;
virtual void removePayload(gp* payload) override;
// virtual bool hasPayloads() override;
// virtual void schedule(gp* payload) override;
// virtual gp* getNextPayload() override;
// virtual void removePayload(gp* payload) override;
private:
void formBatch();
//private:
// void formBatch();
core::ControllerCore& controllerCore;
bool useExternalBankstates;
core::RowBufferState internalBankstates;
FR_FCFS *batch;
FR_FCFS *buffer;
unsigned int capsize;
};
// ControllerCore& controllerCore;
// bool useExternalBankstates;
// RowBufferState internalBankstates;
// FR_FCFS *batch;
// FR_FCFS *buffer;
// unsigned int capsize;
//};
} /* scheduler core */
//} /* scheduler core */
#endif
//#endif

View File

@@ -1,16 +0,0 @@
#include "Scheduler.h"
#include "../../common/DebugManager.h"
#include <iostream>
using namespace std;
using namespace scheduler;
std::string Scheduler::sendername = "scheduler";
void Scheduler::printDebugMessage(std::string message)
{
//cout << "scheduler: " << message << std::endl;
DebugManager::getInstance().printDebugMessage(Scheduler::sendername, message);
}

View File

@@ -1,28 +0,0 @@
#ifndef SCHEDULER_H
#define SCHEDULER_H
#include <tlm.h>
#include "../../common/dramExtension.h"
namespace scheduler {
typedef tlm::tlm_generic_payload gp;
class Scheduler
{
public:
virtual ~Scheduler(){}
virtual void schedule(gp* payload) = 0;
virtual bool hasPayloads() = 0;
virtual gp* getNextPayload() = 0;
virtual void removePayload(gp* payload) = 0;
static std::string sendername;
protected:
void printDebugMessage(std::string message);
};
}
#endif // SCHEDULER_H

View File

@@ -1,71 +1,71 @@
/*
* ThreadLoad.cpp
*
* Created on: Apr 9, 2014
* Author: robert
*/
#include "ThreadLoad.h"
// * ThreadLoad.cpp
// *
// * Created on: Apr 9, 2014
// * Author: robert
// */
namespace scheduler {
//#include "ThreadLoad.h"
using namespace std;
//namespace scheduler {
ThreadLoad::ThreadLoad()
{
// TODO Auto-generated constructor stub
//using namespace std;
}
//ThreadLoad::ThreadLoad()
//{
// // TODO Auto-generated constructor stub
ThreadLoad::~ThreadLoad()
{
// TODO Auto-generated destructor stub
}
//}
unsigned int ThreadLoad::getMaxBankLoad() const
{
unsigned int maxLoad = 0;
for (auto& bankVectorPair : load)
{
if (bankVectorPair.second.size() > maxLoad)
maxLoad = bankVectorPair.second.size();
}
return maxLoad;
}
//ThreadLoad::~ThreadLoad()
//{
// // TODO Auto-generated destructor stub
//}
unsigned int ThreadLoad::getTotalLoad() const
{
unsigned int totalLoad = 0;
for (auto& bankVectorPair : load)
{
totalLoad += bankVectorPair.second.size();
}
return totalLoad;
}
//unsigned int ThreadLoad::getMaxBankLoad() const
//{
// unsigned int maxLoad = 0;
// for (auto& bankVectorPair : load)
// {
// if (bankVectorPair.second.size() > maxLoad)
// maxLoad = bankVectorPair.second.size();
// }
// return maxLoad;
//}
void ThreadLoad::addTransaction(gp* payload)
{
load[DramExtension::getExtension(payload).getBank()].push_back(payload);
}
//unsigned int ThreadLoad::getTotalLoad() const
//{
// unsigned int totalLoad = 0;
// for (auto& bankVectorPair : load)
// {
// totalLoad += bankVectorPair.second.size();
// }
// return totalLoad;
//}
bool operator<(const ThreadLoad& lhs, const ThreadLoad& rhs)
{
if (lhs.getMaxBankLoad() < rhs.getMaxBankLoad())
return true;
else if (lhs.getMaxBankLoad() == rhs.getMaxBankLoad())
return lhs.getTotalLoad() < rhs.getTotalLoad();
else
return false;
}
//void ThreadLoad::addTransaction(gp* payload)
//{
// load[DramExtension::getExtension(payload).getBank()].push_back(payload);
//}
vector<gp*> ThreadLoad::getTransactions()
{
vector<gp*> result;
for (auto& bankVectorPair : load)
{
result.insert(result.end(), bankVectorPair.second.begin(), bankVectorPair.second.end());
}
return result;
}
//bool operator<(const ThreadLoad& lhs, const ThreadLoad& rhs)
//{
// if (lhs.getMaxBankLoad() < rhs.getMaxBankLoad())
// return true;
// else if (lhs.getMaxBankLoad() == rhs.getMaxBankLoad())
// return lhs.getTotalLoad() < rhs.getTotalLoad();
// else
// return false;
//}
} /* namespace scheduler */
//vector<gp*> ThreadLoad::getTransactions()
//{
// vector<gp*> result;
// for (auto& bankVectorPair : load)
// {
// result.insert(result.end(), bankVectorPair.second.begin(), bankVectorPair.second.end());
// }
// return result;
//}
//} /* namespace scheduler

View File

@@ -1,44 +1,44 @@
/*
* ThreadLoad.h
*
* Created on: Apr 9, 2014
* Author: robert
*/
#ifndef THREADLOAD_H_
#define THREADLOAD_H_
#include <map>
#include <tlm.h>
#include "../../common/dramExtension.h"
//// * ThreadLoad.h
//// *
//// * Created on: Apr 9, 2014
//// * Author: robert
//// */
namespace scheduler {
//#ifndef THREADLOAD_H_
//#define THREADLOAD_H_
//#include <map>
//#include <tlm.h>
//#include "../../common/dramExtension.h"
typedef tlm::tlm_generic_payload gp;
//namespace scheduler {
class ThreadLoad
{
public:
ThreadLoad();
virtual ~ThreadLoad();
//typedef tlm::tlm_generic_payload gp;
unsigned int getMaxBankLoad() const;
unsigned int getTotalLoad() const;
//class ThreadLoad
//{
//public:
// ThreadLoad();d
// virtual ~ThreadLoad();
void addTransaction(gp* payload);
std::vector<gp*> getTransactions();
// unsigned int getMaxBankLoad() const;
// unsigned int getTotalLoad() const;
private:
std::map<Bank,std::vector<gp*>> load;
};
// void addTransaction(gp* payload);
// std::vector<gp*> getTransactions();
bool operator< (const ThreadLoad &lhs, const ThreadLoad &rhs);
//private:
// std::map<Bank,std::vector<gp*>> load;
//};
struct LoadPointerComparer {
bool operator()(const ThreadLoad* l, const ThreadLoad* r) {
return *l < *r;
}
};
//bool operator< (const ThreadLoad &lhs, const ThreadLoad &rhs);
} /* namespace scheduler */
//struct LoadPointerComparer {
// bool operator()(const ThreadLoad* l, const ThreadLoad* r) {
// return *l < *r;
// }
//};
#endif /* THREADLOAD_H_ */
//} /* namespace scheduler */
//#endif /* THREADLOAD_H_

View File

@@ -1,154 +1,154 @@
#include "readwritegrouper.h"
#include "../../common/DebugManager.h"
//#include "readwritegrouper.h"
//#include "../../common/DebugManager.h"
namespace scheduler{
//namespace scheduler{
using namespace tlm;
using namespace std;
//using namespace tlm;
//using namespace std;
ReadWriteGrouper::ReadWriteGrouper(core::ControllerCore& controllerCore): controllerCore(controllerCore)
{
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
}
//ReadWriteGrouper::ReadWriteGrouper(ControllerCore& controllerCore): controllerCore(controllerCore)
//{
// batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
// batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
//}
ReadWriteGrouper::~ReadWriteGrouper()
{
//ReadWriteGrouper::~ReadWriteGrouper()
//{
}
//}
void ReadWriteGrouper::schedule(gp *payload)
{
tlm_command command = payload->get_command();
//void ReadWriteGrouper::schedule(gp *payload)
//{
// tlm_command command = payload->get_command();
if(batches.size() > 2)
{
if(command == TLM_READ_COMMAND)
{
//printDebugMessage("Scheduling read");
// if(batches.size() > 2)
// {
// if(command == TLM_READ_COMMAND)
// {
// //printDebugMessage("Scheduling read");
if(schedulingReadCausesHazardWithQueuedWrite(payload))
{
printDebugMessage("Scheduling read causes hazard with queued write");
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
}
// if(schedulingReadCausesHazardWithQueuedWrite(payload))
// {
// printDebugMessage("Scheduling read causes hazard with queued write");
// batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
// batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
// }
getLatestReadBatch().schedule(payload);
}
else if(command == TLM_WRITE_COMMAND)
{
//printDebugMessage("Scheduling write");
getLatestWriteBatch().schedule(payload);
}
}
else if(batches.size() == 2)
{
if(command == TLM_READ_COMMAND)
{
//printDebugMessage("Scheduling read");
// getLatestReadBatch().schedule(payload);
// }
// else if(command == TLM_WRITE_COMMAND)
// {
// //printDebugMessage("Scheduling write");
// getLatestWriteBatch().schedule(payload);
// }
// }
// else if(batches.size() == 2)
// {
// if(command == TLM_READ_COMMAND)
// {
// //printDebugMessage("Scheduling read");
if(getLatestReadBatch().hasPayloads() && schedulingReadCausesHazardWithQueuedWrite(payload))
{
printDebugMessage("Scheduling read causes hazard with queued write");
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
}
else if(!getLatestReadBatch().hasPayloads() && getLatestWriteBatch().hasPayloads())
{
printDebugMessage("Scheduling read, but there are writes to be processed first");
batches.erase(batches.begin());
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
}
getLatestReadBatch().schedule(payload);
// if(getLatestReadBatch().hasPayloads() && schedulingReadCausesHazardWithQueuedWrite(payload))
// {
// printDebugMessage("Scheduling read causes hazard with queued write");
// batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
// batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
// }
// else if(!getLatestReadBatch().hasPayloads() && getLatestWriteBatch().hasPayloads())
// {
// printDebugMessage("Scheduling read, but there are writes to be processed first");
// batches.erase(batches.begin());
// batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
// batches.push_back(shared_ptr<FR_FCFS>(new FR_FCFS(controllerCore,true,false)));
// }
// getLatestReadBatch().schedule(payload);
}
else if(command == TLM_WRITE_COMMAND)
{
//printDebugMessage("Scheduling write");
getLatestWriteBatch().schedule(payload);
}
}
else
{
sc_assert(false);
}
}
// }
// else if(command == TLM_WRITE_COMMAND)
// {
// //printDebugMessage("Scheduling write");
// getLatestWriteBatch().schedule(payload);
// }
// }
// else
// {
// sc_assert(false);
// }
//}
gp *ReadWriteGrouper::getNextPayload()
{
if(batches.size() > 2)
{
return batches.front()->getNextPayload();
}
else if(batches.size() == 2)
{
if(getLatestReadBatch().hasPayloads())
return getLatestReadBatch().getNextPayload();
else if(getLatestWriteBatch().hasPayloads())
return getLatestWriteBatch().getNextPayload();
else
return NULL;
}
else
{
sc_assert(false);
return NULL;
}
}
//gp *ReadWriteGrouper::getNextPayload()
//{
// if(batches.size() > 2)
// {
// return batches.front()->getNextPayload();
// }
// else if(batches.size() == 2)
// {
// if(getLatestReadBatch().hasPayloads())
// return getLatestReadBatch().getNextPayload();
// else if(getLatestWriteBatch().hasPayloads())
// return getLatestWriteBatch().getNextPayload();
// else
// return NULL;
// }
// else
// {
// sc_assert(false);
// return NULL;
// }
//}
void ReadWriteGrouper::removePayload(gp *payload)
{
if(batches.size() > 2)
{
batches.front()->removePayload(payload);
if(!batches.front()->hasPayloads())
batches.erase(batches.begin());
}
else if(batches.size() == 2)
{
if(payload->is_read())
getLatestReadBatch().removePayload(payload);
else
getLatestWriteBatch().removePayload(payload);
}
else
{
sc_assert(false);
}
}
//void ReadWriteGrouper::removePayload(gp *payload)
//{
// if(batches.size() > 2)
// {
// batches.front()->removePayload(payload);
// if(!batches.front()->hasPayloads())
// batches.erase(batches.begin());
// }
// else if(batches.size() == 2)
// {
// if(payload->is_read())
// getLatestReadBatch().removePayload(payload);
// else
// getLatestWriteBatch().removePayload(payload);
// }
// else
// {
// sc_assert(false);
// }
//}
bool ReadWriteGrouper::hasPayloads()
{
if(batches.size() > 2)
return true;
else if(batches.size() == 2)
return (getLatestReadBatch().hasPayloads() || getLatestWriteBatch().hasPayloads());
else
{
sc_assert(false);
return NULL;
}
}
//bool ReadWriteGrouper::hasPayloads()
//{
// if(batches.size() > 2)
// return true;
// else if(batches.size() == 2)
// return (getLatestReadBatch().hasPayloads() || getLatestWriteBatch().hasPayloads());
// else
// {
// sc_assert(false);
// return NULL;
// }
//}
bool ReadWriteGrouper::schedulingReadCausesHazardWithQueuedWrite(gp *payload)
{
sc_assert(payload->is_read());
return getLatestWriteBatch().containsPayloadTragetingSameAddress(payload);
}
//bool ReadWriteGrouper::schedulingReadCausesHazardWithQueuedWrite(gp *payload)
//{
// sc_assert(payload->is_read());
// return getLatestWriteBatch().containsPayloadTragetingSameAddress(payload);
//}
FR_FCFS &ReadWriteGrouper::getLatestWriteBatch()
{
return *batches[batches.size()-1];
}
//FR_FCFS &ReadWriteGrouper::getLatestWriteBatch()
//{
// return *batches[batches.size()-1];
//}
FR_FCFS &ReadWriteGrouper::getLatestReadBatch()
{
return *batches[batches.size()-2];
}
//FR_FCFS &ReadWriteGrouper::getLatestReadBatch()
//{
// return *batches[batches.size()-2];
//}
}
//}

View File

@@ -1,41 +1,41 @@
#ifndef READWRITEGROUPER_H
#define READWRITEGROUPER_H
#include "Scheduler.h"
#include "Fr_Fcfs.h"
#include "../core/ControllerCore.h"
#include <memory>
#include <vector>
//#ifndef READWRITEGROUPER_H
//#define READWRITEGROUPER_H
//#include "Scheduler.h"
//#include "Fr_Fcfs.h"
//#include "../core/ControllerCore.h"
//#include <memory>
//#include <vector>
namespace scheduler{
//namespace scheduler{
class ReadWriteGrouper : public Scheduler
{
public:
ReadWriteGrouper(core::ControllerCore& controllerCore);
~ReadWriteGrouper();
virtual void schedule(gp* payload) override;
virtual bool hasPayloads() override;
virtual gp* getNextPayload() override;
virtual void removePayload(gp* payload) override;
//class ReadWriteGrouper : public Scheduler
//{
//public:
// ReadWriteGrouper(ControllerCore& controllerCore);
// ~ReadWriteGrouper();
// virtual void schedule(gp* payload) override;
// virtual bool hasPayloads() override;
// virtual gp* getNextPayload() override;
// virtual void removePayload(gp* payload) override;
private:
// contains batches of requests
// last element always contains writes
// next-to-last element always contains reads
// there are always at least two batches
// if there are more than two batches, batches[0] is never empty and
// getNextPayload and removePayload are forwarded to batches[0]
std::vector<std::shared_ptr<FR_FCFS>> batches;
core::ControllerCore& controllerCore;
//private:
// // contains batches of requests
// // last element always contains writes
// // next-to-last element always contains reads
// // there are always at least two batches
// // if there are more than two batches, batches[0] is never empty and
// // getNextPayload and removePayload are forwarded to batches[0]
// std::vector<std::shared_ptr<FR_FCFS>> batches;
// ControllerCore& controllerCore;
bool schedulingReadCausesHazardWithQueuedWrite(gp* payload);
FR_FCFS& getLatestWriteBatch();
FR_FCFS& getLatestReadBatch();
// bool schedulingReadCausesHazardWithQueuedWrite(gp* payload);
// FR_FCFS& getLatestWriteBatch();
// FR_FCFS& getLatestReadBatch();
};
//};
}
//}
#endif // READWRITEGROUPER_H
//#endif // READWRITEGROUPER_H

View File

@@ -26,11 +26,12 @@
using namespace std;
using namespace tlm;
using namespace core;
;
using namespace Data;
#define POWER //not better to define in simulation xml? also flag for storage simulation
//#define POWER
//not better to define in simulation xml? also flag for storage simulation
//configuration->PowerAnalysys
//configuration->ModelStorage
//configuration->ModelErrotInjection

View File

@@ -23,8 +23,10 @@ MemoryManager::~MemoryManager()
delete payload;
numberOfFrees++;
}
DebugManager::getInstance().printDebugMessage("MemomryManager","Number of allocated payloads: " + to_string(numberOfAllocations));
DebugManager::getInstance().printDebugMessage("MemomryManager","Number of freed payloads: " + to_string(numberOfFrees));
//Comment in if you are suspecting a memory leak in the manager
//DebugManager::getInstance().printDebugMessage("MemoryManager","Number of allocated payloads: " + to_string(numberOfAllocations));
//DebugManager::getInstance().printDebugMessage("MemoryManager","Number of freed payloads: " + to_string(numberOfFrees));
}
gp* MemoryManager::allocate()

View File

@@ -44,18 +44,6 @@ Simulation::Simulation(sc_module_name /*name*/, string pathToResources, string t
void Simulation::setupDebugManager(const string& traceName)
{
auto& dbg = DebugManager::getInstance();
dbg.addToWhiteList(controller->name());
dbg.addToWhiteList(player1->name());
dbg.addToWhiteList(player2->name());
dbg.addToWhiteList(player3->name());
dbg.addToWhiteList(player4->name());
dbg.addToWhiteList(this->name());
dbg.addToWhiteList(Scheduler::sendername);
dbg.addToWhiteList(TlmRecorder::senderName);
dbg.addToWhiteList(ControllerCore::senderName);
dbg.addToWhiteList(PowerDownManagerBankwise::senderName);
dbg.writeToConsole = true;
dbg.writeToFile = true;
if(dbg.writeToFile)
@@ -77,7 +65,6 @@ void Simulation::setupTlmRecorder(const string &traceName, const string &pathToR
{
TlmRecorder::recordingEnabled = false;
}
}
void Simulation::instantiateModules(const string &pathToResources, const std::vector<Device>& devices)
@@ -85,10 +72,8 @@ void Simulation::instantiateModules(const string &pathToResources, const std::ve
dram = new Dram<>("dram");
arbiter = new Arbiter<NumberOfTracePlayers, 128>("arbiter");
controller = new Controller<>("controller");
//reorder = new ReorderBuffer<>("reorder");
player1 = new StlPlayer<>("player1", pathToResources + string("traces/") + devices[0].trace, devices[0].clkMhz, this);
//player1 = new TraceGenerator<>("player1", 0, this);
player2 = new StlPlayer<>("player2", pathToResources + string("traces/") + devices[1].trace, devices[1].clkMhz, this);
player3 = new StlPlayer<>("player3", pathToResources + string("traces/") + devices[2].trace, devices[2].clkMhz, this);
player4 = new StlPlayer<>("player4", pathToResources + string("traces/") + devices[3].trace, devices[3].clkMhz, this);
@@ -97,9 +82,6 @@ void Simulation::instantiateModules(const string &pathToResources, const std::ve
void Simulation::bindSockets()
{
player1->iSocket.bind(arbiter->tSockets[0]);
//player1->iSocket.bind(reorder->tSocket);
//reorder->iSocket.bind(arbiter->tSockets[0]);
player2->iSocket.bind(arbiter->tSockets[1]);
player3->iSocket.bind(arbiter->tSockets[2]);
player4->iSocket.bind(arbiter->tSockets[3]);

View File

@@ -27,9 +27,6 @@ void SimulationManager::loadSimulationsFromXML(string uri)
cout << headline << endl;
exportPath = getFileName(uri);
//basePath = boost::filesystem::path(uri).parent_path();
loadXML(uri, simulationdoc);
cout << "\t-> parsing simulation objects .." << endl;
@@ -52,7 +49,7 @@ void SimulationManager::runSimulations()
{
for (auto& batch : simulationBatches)
{
boost::filesystem::path dir(exportPath);// + "/" + batch.simulationName);
boost::filesystem::path dir(exportPath);
boost::filesystem::create_directories(dir);
for (auto& dramSetup : batch.dramSetups)
@@ -81,8 +78,6 @@ void SimulationManager::parseSimulationBatch(XMLElement* simulation)
XMLElement* memconfigs = simulation->FirstChildElement("memconfigs");
if(memconfigs == NULL) memconfigs = simulation;
for (XMLElement* memspec = memspecs->FirstChildElement("memspec"); memspec != NULL;
memspec = memspec->NextSiblingElement("memspec"))
{
@@ -131,11 +126,6 @@ void SimulationManager::startTraceAnalyzer()
{
string p = getenv("trace");
string run_tpr = p + " -f ";
for (auto batch : simulationBatches)
{
// run_tpr += exportPath + "/" + batch.simulationName + " ";
}
run_tpr += "&";
system(run_tpr.c_str());
}
@@ -157,8 +147,6 @@ void SimulationManager::addTraceSetup(SimulationBatch& batch, tinyxml2::XMLEleme
void SimulationManager::report(string message)
{
//DebugManager::getInstance().printDebugMessage("Simulation Manager", message);
//if (DebugManager::getInstance().writeToConsole == false)
cout << message << endl;
}

View File

@@ -104,11 +104,11 @@ StlPlayer<BUSWIDTH>::StlPlayer(sc_module_name /*name*/, string pathToTrace, unsi
SC_REPORT_FATAL(0, (string("Could not open trace ") + pathToTrace).c_str());
if(clkMhz == 0)
clk = core::Configuration::getInstance().memSpec.clk;
clk = Configuration::getInstance().memSpec.clk;
else
clk = core::FrequencyToClk(clkMhz);
clk = FrequencyToClk(clkMhz);
this->burstlenght = core::Configuration::getInstance().memSpec.BurstLength;
this->burstlenght = Configuration::getInstance().memSpec.BurstLength;
}
#endif // STLPLAYER_H

Some files were not shown because too many files have changed in this diff Show More