Changed constraints in all checkers to be generic for wideIO and ddr4

This commit is contained in:
robert
2014-04-14 02:41:04 +02:00
parent 6583a661d2
commit 0a7829d0ad
26 changed files with 516 additions and 377 deletions

View File

@@ -4,7 +4,7 @@
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-2055719358" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} -E -P -v -dD &quot;${INPUTS}&quot; -std=c++11">
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-60060699001507781" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} -E -P -v -dD &quot;${INPUTS}&quot; -std=c++11">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -14,7 +14,7 @@
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-2055719358" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} -E -P -v -dD &quot;${INPUTS}&quot; -std=c++11">
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-60060699001507781" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} -E -P -v -dD &quot;${INPUTS}&quot; -std=c++11">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>

View File

@@ -13,8 +13,8 @@
<dramconfig>
<addressmap length="29">
<channel from="27" to="28" />
<row from="14" to="26" />
<bank from="11" to="13" />
<row from="15" to="26" />
<bank from="11" to="14" />
<colum from="4" to="10" />
<bytes from="0" to="3" />
<!-- <channel from="27" to="28" />

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!--
<dramconfig>
<addressmap length="29">
<channel from="27" to="28" />
<bank from="24" to="26" />
<row from="11" to="23" />
<colum from="4" to="10" />
<bytes from="0" to="3" />
</addressmap>
</dramconfig>
-->
<dramconfig>
<addressmap length="29">
<channel from="27" to="28" />
<row from="13" to="26" />
<bank from="11" to="12" />
<colum from="4" to="10" />
<bytes from="0" to="3" />
<!-- <channel from="27" to="28" />
<row from="14" to="26" />
<bytes from="10" to="13" />
<colum from="3" to="9" />
<bank from="0" to="2" /> -->
</addressmap>
</dramconfig>

View File

@@ -21,8 +21,8 @@
<parameter id="RAS" type="uint" value="6" />
<parameter id="WL" type="uint" value="1" />
<parameter id="AL" type="uint" value="0" />
<!--<parameter id="DQSCK" type="uint" value="1" />
<parameter id="RTP" type="uint" value="4" />-->
<!--<parameter id="DQSCK" type="uint" value="1" />-->
<parameter id="RTP" type="uint" value="4" />
<parameter id="WR" type="uint" value="2" />
<parameter id="XP" type="uint" value="2" />
<!--<parameter id="XPDLL" type="uint" value="2" />-->

View File

@@ -21,8 +21,8 @@
<parameter id="RAS" type="uint" value="6" />
<parameter id="WL" type="uint" value="1" />
<parameter id="AL" type="uint" value="0" />
<!--<parameter id="DQSCK" type="uint" value="1" />
<parameter id="RTP" type="uint" value="4" />-->
<!--<parameter id="DQSCK" type="uint" value="1" />-->
<parameter id="RTP" type="uint" value="4" />
<parameter id="WR" type="uint" value="2" />
<parameter id="XP" type="uint" value="2" />
<!--<parameter id="XPDLL" type="uint" value="2" />-->

View File

@@ -3,6 +3,7 @@ import sqlite3
import math
import os
import xml.etree.ElementTree as ET
from sets import Set
def getPathToConfigs():
return os.path.dirname(__file__).replace("/scripts","/configs")
@@ -10,6 +11,9 @@ def getPathToConfigs():
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")
@@ -32,7 +36,7 @@ def getClock(connection):
class DramConfig(object):
memoryType = ""
bankwiseLogic = False
bankwiseLogic = 0
clk = 0
unitOfTime = ""
dataRate = 0
@@ -68,73 +72,83 @@ class DramConfig(object):
print("Parsing dram configuration")
memspec = getMemspec(connection)
bankwiseLogic = getValueFromConfigXML(getMemconfig(connection), "bankwiseLogic")
clk = getClock(connection)
self.clk = clk[0]
self.unitOfTime = clk[1].lower()
clkWithUnit = getClock(connection)
self.clk = clkWithUnit[0]
self.unitOfTime = clkWithUnit[1].lower()
self.numberOfBanks = getValueFromConfigXML(memspec, "nbrOfBanks")
self.burstLength = getValueFromConfigXML(memspec, "burstLength")
self.bankwiseLogic = getIntValueFromConfigXML(getMemconfig(connection), "bankwiseLogic")
self.numberOfBanks = getIntValueFromConfigXML(memspec, "nbrOfBanks")
self.burstLength = getIntValueFromConfigXML(memspec, "burstLength")
self.memoryType = getValueFromConfigXML(memspec, "memoryType")
self.dataRate = getValueFromConfigXML(memspec, "dataRate")
self.dataRate = getIntValueFromConfigXML(memspec, "dataRate")
if(self.memoryType == "WIDEIO_SDR"):
self.nActivateWindow = 2;
self.tRP = self.clk * getValueFromConfigXML(memspec, "RP")
self.tRAS = self.clk * getValueFromConfigXML(memspec, "RAS")
self.tRC = self.clk * getValueFromConfigXML(memspec, "RC")
self.tRRD_S = self.clk * getValueFromConfigXML(memspec, "RRD")
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 * getValueFromConfigXML(memspec, "CCD")
self.tCCD_S = self.clk * getIntValueFromConfigXML(memspec, "CCD")
self.tCCD_L = self.tCCD_S
self.tRCD = self.clk * getValueFromConfigXML(memspec, "RCD")
self.tNAW = self.clk * getValueFromConfigXML(memspec, "TAW")
self.tRL = self.clk * getValueFromConfigXML(memspec, "RL")
self.tWL = self.clk * getValueFromConfigXML(memspec, "WL")
self.tWR = self.clk * getValueFromConfigXML(memspec, "WR")
self.tWTR_S = self.clk * getValueFromConfigXML(memspec, "WTR")
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 = 0
self.tCKESR = self.clk * getValueFromConfigXML(memspec, "CKESR")
self.tCKE = self.clk * getValueFromConfigXML(memspec, "CKE")
self.tXP = self.clk * getValueFromConfigXML(memspec, "XP")
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 * getValueFromConfigXML(memspec, "XS")
self.tXSR = self.clk * getIntValueFromConfigXML(memspec, "XS")
self.tXSRDLL = self.tXSR
self.tAL = self.clk * getValueFromConfigXML(memspec, "AL")
self.tRFC = self.clk * getValueFromConfigXML(memspec, "RFC")
self.tAL = self.clk * getIntValueFromConfigXML(memspec, "AL")
self.tRFC = self.clk * getIntValueFromConfigXML(memspec, "RFC")
elif(self. memoryType == "DDR4"):
self.tRP = clk * getValueFromConfigXML(memspec, "RP");
self.tRAS = clk * getValueFromConfigXML(memspec, "RAS");
self.tRC = clk * getValueFromConfigXML(memspec, "RC");
self.tRTP = clk * getValueFromConfigXML(memspec, "RTP");
self.tRRD_S = clk * getValueFromConfigXML(memspec, "RRD_S");
self.tRRD_L = clk * getValueFromConfigXML(memspec, "RRD_L");
self.tCCD_S = clk * getValueFromConfigXML(memspec, "CCD_S");
self.tCCD_L = clk * getValueFromConfigXML(memspec, "CCD_L");
self.tRCD = clk * getValueFromConfigXML(memspec, "RCD");
self.tNAW = clk * getValueFromConfigXML(memspec, "FAW");
self.tRL = clk * getValueFromConfigXML(memspec, "RL");
self.tWL = clk * getValueFromConfigXML(memspec, "WL");
self.tWR = clk * getValueFromConfigXML(memspec, "WR");
self.tWTR_S = clk * getValueFromConfigXML(memspec, "WTR_S");
self.tWTR_L = clk * getValueFromConfigXML(memspec, "WTR_L");
self.tCKESR = clk * getValueFromConfigXML(memspec, "CKESR");
self.tCKE = clk * getValueFromConfigXML(memspec, "CKE");
self.tXP = clk * getValueFromConfigXML(memspec, "XP");
self.tXPDLL = clk * getValueFromConfigXML(memspec, "XPDLL");
self.tXSR = clk * getValueFromConfigXML(memspec, "XS");
self.tXSRDLL = clk * getValueFromConfigXML(memspec, "XSDLL");
self.tAL = clk * getValueFromConfigXML(memspec, "AL");
self.tRFC = clk * getValueFromConfigXML(memspec, "RFC");
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 some coins and try again")
def clkAlign(self, value):
return math.ceil(1.0*value/self.clk)*self.clk
def getWriteAcessTime(self):
if(self.dataRate == 1):
return self.clk*(self.burstLength - 1)
elif (self.memoryType == "DDR4"):
return self.clk*self.burstLength/self.dataRate
def getReadAcessTime(self):
return self.burstLength/self.dataRate * dramconfig.clk
def __init__(self):
pass
@@ -172,12 +186,12 @@ def formatTime(time):
# ----------- checks ---------------------------------------
@test
#@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": 6})
cursor.execute(query, {"clk": dramconfig.clk})
result = cursor.fetchone()
@@ -186,7 +200,7 @@ def commands_are_clockaligned(connection):
result[0], formatTime(result[1]), formatTime(result[2]), formatTime(dramconfig.clk)))
return TestSuceeded()
@test
#@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()
@@ -207,27 +221,132 @@ def commandbus_slots_are_used_once(connection):
return TestSuceeded()
@test
def command_sequences_are_valid(connection):
#@test
def phase_transitions_are_valid(connection):
"""Checks if the transition of two consequtive phases is valid"""
cursor = connection.cursor()
cursor.execute("SELECT group_concat(phaseName),transact FROM phases GROUP BY transact")
validTransitions = {}
validSequences = set(['AUTO_REFRESH','PDNA','PDNP','SREF',
'PRE,AUTO_REFRESH', 'PRE_ALL,AUTO_REFRESH',
'REQ,RD,RESP', 'REQ,WR,RESP', 'REQ,RDA,RESP', 'REQ,WRA,RESP',
'REQ,ACT,RD,RESP', 'REQ,ACT,WR,RESP', 'REQ,ACT,RDA,RESP', 'REQ,ACT,WRA,RESP',
'REQ,PRE,ACT,RD,RESP', 'REQ,PRE,ACT,WR,RESP', 'REQ,PRE,ACT,RDA,RESP', 'REQ,PRE,ACT,WRA,RESP'
])
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
for currentRow in cursor:
commandSequence = currentRow[0]
if(commandSequence not in validSequences):
return TestFailed("Transaction {0} generated invalid command sequence {1}".format(currentRow[1], commandSequence))
return TestSuceeded()
@test
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, getReadAcessTime())
elif(SecondPhase in ["WR","WRA"]):
return dramconfig.tRL + getReadAcessTime() - dramconfig.tWL + 2*dramconfig.clk
elif(SecondPhase == "PDNA" ):
return dramconfig.tRL + getReadAcessTime() + dramconfig.clk
elif(FirstPhaseName == "WR"):
if(SecondPhaseName in ["PRE, PRE_ALL", "PDNA"]):
return dramconfig.tWL + dramconfig.getWriteAcessTime() + dramconfig.tWR
elif(SecondPhaseName in ["RD, RDA"]):
return dramconfig.tWL + dramconfig.getWriteAcessTime() + 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 + getReadAcessTime() + dramconfig.clk
elif(FirstPhaseName == "WRA"):
if(SecondPhaseName in ["ACT", "PRE_ALL", "AUTO_REFRESH"]):
return dramconfig.tWL + getWriteAcessTime() + dramconfig.tWR + dramconfig.tRP
elif(SecondPhaseName in ["PDNA","PDNP"]):
return dramconfig.tWL + dramconfig.getWriteAcessTime() + 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_same_bank(connection):
"""Checks that two consecutive phases on the same bank satisfy timing constraint"""
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):
cursor = connection.cursor()
query = """SELECT PhaseName, phases.ID FROM phases INNER JOIN transactions ON phases.transact=transactions.ID WHERE TBank=:bank
@@ -237,10 +356,11 @@ def row_buffer_is_used_correctly(connection):
cursor.execute(query,{"bank": bankNumber})
rowBufferIsClosed = True
#phases that precharge the bank
prechargingPhases = set(['PRE','PRE_ALL','RDA','WRA'])
closingPhases = set(['PRE','PRE_ALL','RDA','WRA'])
#phases that require the bank to be precharged
accessingPhases = set(['RD,RDA,WR,WRA,SREF,AUTO_REFRESH'])
accessingPhases = set(['RD, RDA, WR, WRA, SREF, AUTO_REFRESH'])
for currentRow in cursor:
@@ -253,106 +373,69 @@ def row_buffer_is_used_correctly(connection):
else:
return TestFailed("Phase {0}({1}) activates an already activated rowbuffer".format(currentRow[1],currentRow[0]))
if(currentRow[0] in prechargingPhases):
if(currentRow[0] in closingPhases):
if(rowBufferIsClosed == True and currentRow[0] != 'PRE_ALL'):
return TestFailed("Phase {0}({1}) closes an already closed rowbuffer".format(currentRow[1],currentRow[0]))
else:
rowBufferIsClosed = True
return TestSuceeded()
#----------- activate checks ---------------------------------------
@test
def activate_to_activate(connection):
"""Checks minimal time between two activates (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), minTime))
lastRow = currentRow
return TestSuceeded()
# @test
# def phases_on_bank_are_sequential(connection):
# cursor = connection.cursor()
# query = """SELECT PhaseBegin,PhaseEnd,phases.ID,PhaseName FROM phases INNER JOIN transactions on transactions.ID = phases.transact WHERE Tbank=:bank AND phaseName not IN ('REQ','RESP')"""
# for bankNumber in range(dramconfig.numberOfBanks):
# cursor.execute(query,{"bank": bankNumber})
# lastRow = cursor.fetchone()
# for currentRow in cursor:
# if(currentRow[0] < lastRow[1] and not ((currentRow[3]=="RD" and lastRow[3]=="RD")
# or (currentRow[3]=="PRE" and lastRow[3]=="RD") or (currentRow[3] == "WR" and lastRow[3] == "WR"))):
# return TestFailed("Phases with PhaseIDs {0}({1}) and {2}({3}) should not interleave".format(
# currentRow[2], currentRow[3],lastRow[2],lastRow[3]))
# lastRow = currentRow
# return TestSuceeded()
# #@test
# def phase_lengths_are_correct(connection):
# query = """SELECT phases.ID,PhaseName, PhaseEnd-PhaseBegin,Burstlength FROM Phases INNER JOIN transactions ON transactions.ID = phases.transact """
# cursor = connection.cursor()
# cursor.execute(query)
@test
def activate_to_activate_on_same_bank(connection):
"""Checks minimal time between two activates on the same bank (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 currentRow in cursor:
# command = currentRow[1]
# commandLength = currentRow[2]
# burstlength = currentRow[3]
# if(command == "RD" and commandLength != calculateReadLength(burstlength) or
# command == "WR" and commandLength != calculateWriteLength(burstLength) or
# command == "RDA" and commandLength != calculateReadLength(burstlength)+dramconfig.tRP or
# command == "WRA" and commandLength != calculateReadLength(burstlength)+dramconfig.tRP or
# (command == "PRE" or command=="PRE_ALL") and commandLength != dramconfig.tRP or
# command == "AUTO_REFRESH" and commandLength != dramconfig.tRFC):
# return TestFailed("Phase with ID {0}({1}) has invalid length of {2}".format(currentRow[0],command,formatTime(commandLength)))
# return TestSuceeded()
# #----------- activate checks ---------------------------------------
# @test
# def activate_to_activate(connection):
# """Checks minimal time between two activates (JEDEC 229, P. 27)"""
# cursor = connection.cursor()
# cursor.execute("SELECT ID,PhaseBegin from Phases WHERE PhaseName = 'ACT' ORDER BY PhaseBegin")
# lastRow = cursor.fetchone()
# for currentRow in cursor:
# timeBetweenActivates = currentRow[1] - lastRow[1];
# if(timeBetweenActivates < dramconfig.tRRD):
# 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), dramconfig.tRRD))
# else:
# lastRow = currentRow
# return TestSuceeded()
# @test
# def activate_to_activate_on_same_bank(connection):
# """Checks minimal time between two activates on the same bank (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 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
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()
return TestSuceeded()
# @test
# def n_activate_window(connection):
# """Checks n-Activate constraint (JEDEC 229, P. 27)"""
# cursor = connection.cursor()
# cursor.execute("SELECT ID,PhaseBegin from Phases WHERE PhaseName = 'ACT' ORDER BY PhaseBegin")
# activateWindow = []
@test
def n_activate_window(connection):
"""Checks n-Activate constraint (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.tTAW):
# 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.tTAW)))
# return TestSuceeded()
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 ---------------------------------------
@@ -400,50 +483,30 @@ def row_buffer_is_used_correctly(connection):
# return TestSuceeded()
# @test
# def write_or_read_to_precharge(connection):
# """Checks minimal time between write/read and precharge (JEDEC 229, P. 37)"""
# cursor = connection.cursor()
# query = """SELECT Phases.ID,PhaseBegin,PhaseEnd,PhaseName from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID
# WHERE PhaseName IN ('RD','WR', 'PRE', 'PRE_ALL') AND TBANK = :bank ORDER BY PhaseBegin"""
# minReadStartToPrecharge = dramconfig.burstLength * dramconfig.clk
# minWriteEndToPreStart = dramconfig.tWR
@test
def sref_active_for_minimal_time(connection):
"""Checks that SREF 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()
# for bankNumber in range(dramconfig.numberOfBanks):
# cursor.execute(query,{"bank": bankNumber})
# lastRow = cursor.fetchone()
@test
def pdna_pdnp_active_for_minimal_time(connection):
"""Checks that PDNA,PDNP are 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()
# for currentRow in cursor:
# if(currentRow[3] in ["PRE","PRE_ALL"] and lastRow[3] == "RD"):
# readStartToPrecharge = currentRow[1] - lastRow[1]
# if(readStartToPrecharge < minReadStartToPrecharge):
# return TestFailed("Precharge with PhaseID {0} starts {1} after start of RD {2}. Minimum time between end of read and start of precharge is {3}".
# format(currentRow[0],formatTime(readStartToPrecharge),lastRow[0], formatTime(minReadStartToPrecharge)))
# elif(currentRow[3] in ["PRE","PRE_ALL"] and lastRow[3] == "WR"):
# writeEndToPrecharge = currentRow[1] - lastRow[2]
# if(writeEndToPrecharge < minWriteEndToPreStart):
# return TestFailed("Precharge with PhaseID {0} starts {1} after end of WR {2}. Minimum time between end of write and start of precharge is {3}".
# format(currentRow[0],formatTime(writeEndToPrecharge),lastRow[0], formatTime(minWriteEndToPreStart)))
# lastRow = currentRow
# return TestSuceeded()
# @test
# def sref_active_for_minimal_time(connection):
# """Checks if SREF is active for at least a minimal time (JEDEC 229, P. 41)"""
# cursor = connection.cursor()
# cursor.execute("SELECT ID, PhaseEnd-PhaseBegin FROM Phases WHERE PhaseName = 'SREF'")
# for currentRow in cursor:
# if(currentRow[1] < dramconfig.tCKESR):
# return TestFailed("SREF with ID {0} is {1} long. Minimal time in SREF is {2}".format(currentRow[0], formatTime(currentRow[1]), dramconfig.tCKESR))
# return TestSuceeded()
# -------------------------- interface methods --------------------
def runTests(pathToTrace):
print(pathToTrace)
connection = sqlite3.connect(pathToTrace)
dramconfig.readConfigFromFiles(connection)
@@ -460,9 +523,9 @@ def runTests(pathToTrace):
testResults.append((testName, testResult.passed,testResult.message))
if(testResult.passed):
print("{0} passed".format(testName))
print("[passed] {0}".format(testName))
else:
print(">>>>>>{0} failed. Message: {1}".format(testName, testResult.message))
print("[failed] {0} failed. Message: {1}".format(testName, testResult.message))
numberOfFailedTest = numberOfFailedTest + 1
print("\n-----------------------------")
@@ -477,6 +540,7 @@ def runTests(pathToTrace):
return testResults
if __name__ == "__main__":
path = sys.argv[1]
runTests(path)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
for i in range(1,len(sys.argv)):
runTests(sys.argv[i])

View File

@@ -1,13 +1,13 @@
<simulation>
<memspec>MICRON_4Gb_DDR4-1866_8bit_A.xml</memspec>
<addressmapping>am_wideio.xml</addressmapping>
<memspec>JEDEC_256Mb_WIDEIO_SDR-266_128bit.xml</memspec>
<addressmapping>am_wideioFourBanks.xml</addressmapping>
<memconfigs>
<memconfig>fr_fcfs.xml</memconfig>
<memconfig>fr_fcfs_bankwise.xml</memconfig>
</memconfigs>
<trace-setups>
<trace-setup id="1">
<device >chstone-jpeg_32.stl</device>
<device >mediabench-fractal_32.stl</device>
</trace-setup>
</trace-setups>
</simulation>

View File

@@ -1,26 +1,27 @@
<simulation id="matzesWideIO">
<memspec>MatzesWideIO.xml</memspec>
<addressmapping>am_wideio.xml</addressmapping>
<simulation id="wideio">
<memspec>JEDEC_256Mb_WIDEIO_SDR-266_128bit.xml</memspec>
<addressmapping>am_wideioFourBanks.xml</addressmapping>
<memconfigs>
<memconfig>fr_fcfs.xml</memconfig>
<memconfig>fr_fcfs_bankwise.xml</memconfig>
</memconfigs>
<trace-setups>
<trace-setup id="1">
<device >mediabench-adpcmencode_32.stl</device>
<device >mediabench-c-ray-1.1_32.stl</device>
</trace-setup>
</trace-setups>
</simulation>
<simulation id="matzesWideIO2">
<memspec>MatzesWideIO.xml</memspec>
<addressmapping>am_wideio.xml</addressmapping>
<simulation id="dd4">
<memspec>MICRON_4Gb_DDR4-1866_8bit_A.xml</memspec>
<addressmapping>am_ddr4.xml</addressmapping>
<memconfigs>
<memconfig>fr_fcfs.xml</memconfig>
<memconfig>fr_fcfs_bankwise.xml</memconfig>
</memconfigs>
<trace-setups>
<trace-setup id="1">
<device >mediabench-adpcmencode_32.stl</device>
<device >mediabench-c-ray-1.1_32.stl</device>
</trace-setup>
</trace-setups>
</simulation>

View File

@@ -53,31 +53,19 @@ sc_time getExecutionTime(Command command, tlm::tlm_generic_payload& payload)
}
else if (command == Command::Read)
{
return config.tRL + getBurstLengthOnDataStrobe(payload.get_streaming_width());
return config.tRL + getReadAcessTime();
}
else if (command == Command::ReadA)
{
return getBurstLengthOnDataStrobe(payload.get_streaming_width()) + max(config.tRP, config.tRL);
return config.tRTP + config.tRP;
}
else if (command == Command::Write || command == Command::WriteA)
else if (command == Command::Write)
{
sc_time lockTime;
Configuration& config = Configuration::getInstance();
if(config.DataRate == 1)
lockTime = getBurstLengthOnDataStrobe(payload.get_streaming_width()) - config.Timings.clk;
else //special case DDR4 -> always 4 clocks
{
lockTime = config.Timings.clk * config.BurstLength / config.DataRate;
}
if (command == Command::Write)
{
return config.Timings.tWL + lockTime;
}
else
{
return config.Timings.tWL + lockTime + config.Timings.tWR;
}
return config.tWL + getWriteAcessTime();
}
else if (command == Command::WriteA)
{
return config.tWL + getWriteAcessTime() + config.tWR + config.tRP;
}
else if (command == Command::PrechargeAll)
{
@@ -117,28 +105,39 @@ sc_time getMinimalExecutionTime(Command command, tlm::tlm_generic_payload& paylo
}
}
bool isClkAligned(sc_time time, sc_time clk)
{
return !((time / clk) - ceil(time / clk));
return !((time / clk) - ceil(time / clk));
}
bool TimeInterval::timeIsInInterval(sc_time time)
{
return (start < time && time < end);
return (start < time && time < end);
}
bool TimeInterval::intersects(TimeInterval other)
{
return other.timeIsInInterval(this->start) || this->timeIsInInterval(other.start);
return other.timeIsInInterval(this->start) || this->timeIsInInterval(other.start);
}
sc_time getBurstLengthOnDataStrobe(unsigned int burstlength)
sc_time getReadAcessTime()
{
Configuration& config = Configuration::getInstance();
sc_assert((burstlength / config.DataRate) > 0);
Configuration& config = Configuration::getInstance();
return config.BurstLength/config.DataRate*config.Timings.clk;
}
return config.Timings.clk * (burstlength / config.DataRate);
sc_time getWriteAcessTime()
{
Configuration& config = Configuration::getInstance();
if (config.DataRate == 1)
{
return config.Timings.clk * (config.BurstLength-1) ;
}
else
{
return config.Timings.clk * config.BurstLength / config.DataRate;
}
}
}

View File

@@ -31,7 +31,8 @@ struct TimeInterval
sc_time getMinimalExecutionTime(Command command, tlm::tlm_generic_payload& payload);
sc_time getExecutionTime(Command command, tlm::tlm_generic_payload& payload);
sc_time getBurstLengthOnDataStrobe(unsigned int burstlength);
sc_time getReadAcessTime();
sc_time getWriteAcessTime();
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint);
enum Alignment {UP, DOWN};

View File

@@ -138,7 +138,7 @@ void MemSpecLoader::loadWideIO(Configuration& config, XMLElement* memspec)
config.Timings.tWR = clk * queryUIntParameter(timings, "WR");
config.Timings.tWTR_S = clk * queryUIntParameter(timings, "WTR");
config.Timings.tWTR_L = config.Timings.tWTR_S;
config.Timings.tRTP = SC_ZERO_TIME; //TODO .. not defined in jedec. bl on datastrobe used
config.Timings.tRTP = clk * queryUIntParameter(timings, "RTP");
config.Timings.tCKESR = clk * queryUIntParameter(timings, "CKESR");
config.Timings.tCKE = clk * queryUIntParameter(timings, "CKE");
config.Timings.tXP = clk * queryUIntParameter(timings, "XP");

View File

@@ -27,12 +27,13 @@ RefreshManager::~RefreshManager()
bool RefreshManager::hasCollision(const CommandSchedule& schedule)
{
return schedule.getEnd() > nextPlannedRefresh;
return schedule.getStart() < controller.state.getLastCommand(Command::AutoRefresh).getEnd() || schedule.getEnd() > nextPlannedRefresh;
}
bool RefreshManager::hasCollision(const ScheduledCommand& command)
{
return command.getEnd() > nextPlannedRefresh;
return command.getStart() < controller.state.getLastCommand(Command::AutoRefresh).getEnd() || command.getEnd() > nextPlannedRefresh;
}
void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time)

View File

@@ -17,7 +17,7 @@ namespace core {
RefreshManagerBankwise::RefreshManagerBankwise(ControllerCore& controller) :
controller(controller)
{
for(Bank bank : controller.getBanks())
for (Bank bank : controller.getBanks())
{
setUpDummy(refreshPayloads[bank], bank);
planNextRefresh(bank);
@@ -30,13 +30,14 @@ RefreshManagerBankwise::~RefreshManagerBankwise()
bool RefreshManagerBankwise::hasCollision(const CommandSchedule& schedule)
{
return schedule.getEnd() > nextPlannedRefreshs[schedule.getBank()];
return schedule.getStart() < controller.state.getLastCommand(Command::AutoRefresh, schedule.getBank()).getEnd()
|| schedule.getEnd() > nextPlannedRefreshs[schedule.getBank()];
}
bool RefreshManagerBankwise::hasCollision(const ScheduledCommand& command)
{
return command.getEnd() > nextPlannedRefreshs[command.getBank()];
}
return command.getStart() < controller.state.getLastCommand(Command::AutoRefresh, command.getBank()).getEnd()
|| command.getEnd() > nextPlannedRefreshs[command.getBank()];}
void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time)
{
@@ -81,7 +82,5 @@ bool RefreshManagerBankwise::isInvalidated(tlm::tlm_generic_payload& payload, sc
return nextPlannedRefreshs[DramExtension::getExtension(payload).getBank()] > time;
}
} /* namespace core */

View File

@@ -97,23 +97,16 @@ TimeInterval ScheduledCommand::getIntervalOnDataStrobe() const
TimingConfiguration& timings = Configuration::getInstance().Timings;
sc_time burstLengthOnDataStrobe = getBurstLengthOnDataStrobe(getBurstLength());
if (getCommand() == Command::Read || getCommand() == Command::ReadA)
{
return TimeInterval(getStart() + timings.tRL,
getStart() + timings.tRL + burstLengthOnDataStrobe);
return TimeInterval(getStart() + timings.tRL,getStart() + timings.tRL + getReadAcessTime());
}
else
{
return TimeInterval(getStart() + timings.tWL - timings.clk / 2,
getStart() + timings.tWL + burstLengthOnDataStrobe - timings.clk / 2);
return TimeInterval(getStart() + timings.tWL - timings.clk / 2, getStart() + timings.tWL + getWriteAcessTime() - timings.clk / 2);
}
}
bool ScheduledCommand::collidesOnDataStrobe(const ScheduledCommand& cmd) const
{
return cmd.getIntervalOnDataStrobe().intersects(getIntervalOnDataStrobe());
}
}

View File

@@ -51,12 +51,10 @@ public:
unsigned int getBurstLength() const;
bool operator ==(const ScheduledCommand& b) const;
bool commandIsIn(const std::vector<Command>& commandSet) const;
TimeInterval getIntervalOnDataStrobe() const;
bool collidesOnDataStrobe(const ScheduledCommand& command) const;
private:
Command command;

View File

@@ -23,13 +23,24 @@ void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
if (lastCommandOnBank.isValidCommand())
{
if (isIn(lastCommandOnBank.getCommand(), { Command::Precharge, Command::AutoRefresh,
Command::ReadA, Command::WriteA }))
if (lastCommandOnBank.getCommand() == Command::Precharge)
{
command.delayToMeetConstraint(lastCommandOnBank.getEnd(), SC_ZERO_TIME);
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::PDNPX
|| lastCommandOnBank.getCommand() == Command::PDNAX)
else if (lastCommandOnBank.getCommand() == Command::ReadA)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRTP + config.Timings.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::WriteA)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
config.Timings.tWL + getWriteAcessTime() + config.Timings.tWR + config.Timings.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRFC);
}
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXP);
}
@@ -38,14 +49,12 @@ void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXSR);
}
else
reportFatal("Activate Checker",
"Activate can not follow " + commandToString(lastCommandOnBank.getCommand()));
reportFatal("Activate Checker", "Activate can not follow " + commandToString(lastCommandOnBank.getCommand()));
}
delay_to_satisfy_activateToActivate_sameBank(command);
while (!(state.bus.isFree(command.getStart())
&& satsfies_activateToActivate_differentBank(command)
while (!(state.bus.isFree(command.getStart()) && satsfies_activateToActivate_differentBank(command)
&& satisfies_nActivateWindow(command)))
{
command.delayStart(config.Timings.clk);
@@ -55,8 +64,7 @@ void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
void ActivateChecker::delay_to_satisfy_activateToActivate_sameBank(ScheduledCommand& command) const
{
ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate,
command.getBank());
ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate, command.getBank());
if (lastActivateOnBank.isValidCommand())
{
command.delayToMeetConstraint(lastActivateOnBank.getStart(), config.Timings.tRC);
@@ -68,9 +76,7 @@ bool ActivateChecker::satsfies_activateToActivate_differentBank(ScheduledCommand
for (auto act : state.lastActivates)
{
sc_time time = act.first;
sc_time tRRD =
(command.getBankGroup() == act.second.getBankGroup()) ?
config.Timings.tRRD_L : config.Timings.tRRD_S;
sc_time tRRD = (command.getBankGroup() == act.second.getBankGroup()) ? config.Timings.tRRD_L : config.Timings.tRRD_S;
if ((time < command.getStart() && command.getStart() - time < tRRD)
|| (command.getStart() <= time && time - command.getStart() < tRRD))

View File

@@ -6,6 +6,7 @@
*/
#include "PowerDownChecker.h"
#include "../../../common/Utils.h"
namespace core {
void PowerDownChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
@@ -18,12 +19,38 @@ void PowerDownChecker::delayToSatisfyConstraints(ScheduledCommand& command) cons
{
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
if (lastCommandOnBank.isValidCommand()
&& lastCommandOnBank.commandIsIn( { Command::Read, Command::ReadA, Command::WriteA }))
if (lastCommandOnBank.isValidCommand())
{
command.delayToMeetConstraint(lastCommandOnBank.getEnd(), config.Timings.clk);
if (lastCommandOnBank.getCommand() == Command::Read || lastCommandOnBank.getCommand() == Command::ReadA)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
config.Timings.tRL + getReadAcessTime() + config.Timings.clk);
}
else if (lastCommandOnBank.getCommand() == Command::Write)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
config.Timings.tWL + getWriteAcessTime() + config.Timings.tWR);
}
else if (lastCommandOnBank.getCommand() == Command::WriteA)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
config.Timings.tWL + getWriteAcessTime() + config.Timings.tWR + config.Timings.clk);
}
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRFC);
}
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXP);
}
else
{
reportFatal("Powerdown checker", commandToString(command.getCommand()) + " can not follow " + commandToString(lastCommandOnBank.getCommand()));
}
}
}
else if (command.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(state.getLastCommand(Command::PDNA).getStart(), config.Timings.tCKE);

View File

@@ -21,30 +21,32 @@ void PrechargeAllChecker::delayToSatisfyConstraints(ScheduledCommand& command) c
{
if (lastCommand.getCommand() == Command::Read)
{
command.delayToMeetConstraint(lastCommand.getStart(), lastCommand.getBurstLength() * config.Timings.clk);
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRTP);
}
else if (lastCommand.getCommand() == Command::ReadA)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRTP + config.Timings.tRP);
}
else if (lastCommand.getCommand() == Command::Write)
{
command.delayToMeetConstraint(lastCommand.getEnd(), config.Timings.tWR);
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tWL + getWriteAcessTime() + config.Timings.tWR);
}
else if (lastCommand.getCommand() == Command::WriteA)
else if(lastCommand.getCommand() == Command::WriteA)
{
command.delayToMeetConstraint(lastCommand.getEnd(), SC_ZERO_TIME);
if (config.Timings.tWR > config.Timings.tRP)
command.delayToMeetConstraint(lastCommand.getEnd(), config.Timings.tWR - config.Timings.tRP);
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tWL + getWriteAcessTime() + config.Timings.tWR + config.Timings.tRP);
}
else if (lastCommand.commandIsIn( { Command::PDNAX, Command::PDNPX }))
else if (lastCommand.getCommand() == Command::AutoRefresh)
{
command.delayToMeetConstraint(lastCommand.getEnd(), config.Timings.tXP);
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRFC);
}
else if (lastCommand.getCommand() == Command::PDNAX || lastCommand.getCommand() == Command::PDNPX)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);
}
else if (lastCommand.getCommand() == Command::SREFX)
{
command.delayToMeetConstraint(lastCommand.getEnd(), config.Timings.tXSR);
}
else if (lastCommand.commandIsIn( { Command::ReadA, Command::AutoRefresh }))
{
command.delayToMeetConstraint(lastCommand.getEnd(), SC_ZERO_TIME);
}
else
reportFatal("Precharge All Checker",
"Precharge All can not follow " + commandToString(lastCommand.getCommand()));

View File

@@ -20,16 +20,15 @@ void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand& command) cons
{
if (lastCommand.getCommand() == Command::Read)
{
command.delayToMeetConstraint(lastCommand.getStart(),
max(config.Timings.tRTP, lastCommand.getIntervalOnDataStrobe().getLength()));
command.delayToMeetConstraint(lastCommand.getStart(),config.Timings.tRTP);
}
else if (lastCommand.getCommand() == Command::Write)
{
command.delayToMeetConstraint(lastCommand.getEnd(), config.Timings.tWR);
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tWL + getWriteAcessTime() + config.Timings.tWR);
}
else if (lastCommand.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(lastCommand.getEnd(), config.Timings.tXP);
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);
}
else
reportFatal("Precharge Checker", "Precharge can not follow " + commandToString(lastCommand.getCommand()));

View File

@@ -8,6 +8,7 @@
#include "ReadChecker.h"
#include "../../TimingCalculation.h"
#include "../../../common/Utils.h"
#include "WriteChecker.h"
namespace core {
@@ -23,19 +24,22 @@ void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
if (lastCommand.getCommand() == Command::Activate)
{
command.delayToMeetConstraint(lastCommand.getEnd(), SC_ZERO_TIME);
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRCD);
}
else if (lastCommand.getCommand() == Command::Read
|| lastCommand.getCommand() == Command::Write)
else if (lastCommand.getCommand() == Command::Read)
{
command.delayToMeetConstraint(lastCommand.getStart(), ReadChecker::readToRead(lastCommand,command));
}
else if (lastCommand.getCommand() == Command::PDNAX || lastCommand.getCommand() == Command::PDNPX)
else if (lastCommand.getCommand() == Command::Write)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);//TODO DLL ??
command.delayToMeetConstraint(lastCommand.getStart(), ReadChecker::writeToRead(lastCommand, command));
}
else if (lastCommand.getCommand() == Command::PDNPX || lastCommand.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);
}
else
reportFatal("Read Checker",
"Read can not follow " + commandToString(lastCommand.getCommand()));
reportFatal("Read Checker", "Read can not follow " + commandToString(lastCommand.getCommand()));
}
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command))
@@ -44,7 +48,6 @@ void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
}
}
bool ReadChecker::collidesOnDataStrobe(ScheduledCommand& read) const
{
for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands)
@@ -56,46 +59,23 @@ bool ReadChecker::collidesOnDataStrobe(ScheduledCommand& read) const
return false;
}
bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read,
ScheduledCommand& strobeCommand) const
bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read, ScheduledCommand& strobeCommand) const
{
//read to read
if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA)
{
bool collision = read.collidesOnDataStrobe(strobeCommand);
sc_time tCCD =
(read.getBankGroup() == strobeCommand.getBankGroup()) ?
config.Timings.tCCD_L : config.Timings.tCCD_S;
bool casToCas =
(getDistance(read.getStart(), strobeCommand.getStart()) < tCCD) ? true : false;
return collision || casToCas;
return getDistance(read.getStart(),strobeCommand.getStart()) < ReadChecker::readToRead(strobeCommand,read);
}
else if (strobeCommand.getCommand() == Command::Write
|| strobeCommand.getCommand() == Command::WriteA)
else if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA)
{
//read to write
if (strobeCommand.getStart() >= read.getStart())
{
return strobeCommand.getStart() < read.getIntervalOnDataStrobe().end;
}
//write to read
return getDistance(read.getStart(), strobeCommand.getStart()) < WriteChecker::readToWrite(read,strobeCommand);
else
{
sc_time tWTR =
(read.getBankGroup() == strobeCommand.getBankGroup()) ?
config.Timings.tWTR_L : config.Timings.tWTR_S;
return read.getStart()
< clkAlign(strobeCommand.getIntervalOnDataStrobe().end, Alignment::DOWN) + tWTR;
}
return getDistance(strobeCommand.getStart(), read.getStart()) < ReadChecker::writeToRead(strobeCommand, read);
}
else
{
reportFatal("Read Checker",
"Invalid strobeCommand in data strobe commands "
+ commandToString(strobeCommand.getCommand()));
"Invalid strobeCommand in data strobe commands " + commandToString(strobeCommand.getCommand()));
return true;
}
}
@@ -103,9 +83,29 @@ bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read,
void ReadChecker::delayToSatisfyDLL(ScheduledCommand& read) const
{
ScheduledCommand lastSREFX = state.getLastCommand(Command::SREFX, read.getBank());
if(lastSREFX.isValidCommand())
if (lastSREFX.isValidCommand())
read.delayToMeetConstraint(lastSREFX.getStart(), config.Timings.tXSRDLL);
}
sc_time ReadChecker::readToRead(ScheduledCommand& firstRead, ScheduledCommand& secondRead)
{
sc_assert(firstRead.getCommand() == Command::Read || firstRead.getCommand() == Command::ReadA);
sc_assert(secondRead.getCommand() == Command::Read || secondRead.getCommand() == Command::ReadA);
TimingConfiguration& config = Configuration::getInstance().Timings;
sc_time tCCD = (firstRead.getBankGroup() == secondRead.getBankGroup()) ? config.tCCD_L : config.tCCD_S;
return max(tCCD, getReadAcessTime());
}
sc_time ReadChecker::writeToRead(ScheduledCommand& write, ScheduledCommand& read)
{
sc_assert(read.getCommand() == Command::Read || read.getCommand() == Command::ReadA);
sc_assert(write.getCommand() == Command::Write || write.getCommand() == Command::WriteA);
TimingConfiguration& config = Configuration::getInstance().Timings;
sc_time tWTR = (write.getBankGroup() == read.getBankGroup()) ? config.tWTR_L : config.tWTR_S;
return config.tWL + getWriteAcessTime() + tWTR;
}
} /* namespace controller */

View File

@@ -22,6 +22,9 @@ public:
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
static sc_time readToRead(ScheduledCommand& firstRead, ScheduledCommand& secondRead);
static sc_time writeToRead(ScheduledCommand& write, ScheduledCommand& read);
private:
const Configuration& config;
ControllerState& state;

View File

@@ -18,23 +18,32 @@ void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
if (lastCommandOnBank.isValidCommand())
{
if (lastCommandOnBank.getCommand() == Command::Precharge || lastCommandOnBank.getCommand() == Command::PrechargeAll )
if (lastCommandOnBank.getCommand() == Command::Precharge || lastCommandOnBank.getCommand() == Command::PrechargeAll)
{
command.delayToMeetConstraint(lastCommandOnBank.getEnd(), SC_ZERO_TIME);
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::PDNPX)
else if (lastCommandOnBank.getCommand() == Command::ReadA)
{
command.delayToMeetConstraint(lastCommandOnBank.getEnd(), config.Timings.tXP);
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tRTP + config.Timings.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::SREFX)
else if (lastCommandOnBank.getCommand() == Command::WriteA)
{
command.delayToMeetConstraint(lastCommandOnBank.getEnd(), config.Timings.tXSR);
command.delayToMeetConstraint(lastCommandOnBank.getStart(),
config.Timings.tWL + getWriteAcessTime() + config.Timings.tWR + config.Timings.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(lastCommandOnBank.getStart(), config.Timings.tXP);
}
else
reportFatal("Refresh Checker", "Refresh can not follow " + commandToString(lastCommandOnBank.getCommand()));
// else if (lastCommandOnBank.getCommand() == Command::SREFX)
// {
// command.delayToMeetConstraint(lastCommandOnBank.getEnd(), config.Timings.tXSR);
// }
// else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
// {
// }
// else
// reportFatal("Refresh Checker", "Refresh can not follow " + commandToString(lastCommandOnBank.getCommand()));
}
state.bus.moveCommandToNextFreeSlot(command);

View File

@@ -8,6 +8,7 @@
#include "WriteChecker.h"
#include "../../TimingCalculation.h"
#include "../../../common/Utils.h"
#include "ReadChecker.h"
namespace core {
@@ -21,13 +22,17 @@ void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
{
if (lastCommand.getCommand() == Command::Activate)
{
command.delayToMeetConstraint(lastCommand.getEnd(), SC_ZERO_TIME);
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tRCD);
}
else if (lastCommand.getCommand() == Command::Read || lastCommand.getCommand() == Command::Write)
else if (lastCommand.getCommand() == Command::Read)
{
command.delayToMeetConstraint(lastCommand.getStart(), WriteChecker::readToWrite(lastCommand, command));
}
else if (lastCommand.getCommand() == Command::PDNAX)
else if (lastCommand.getCommand() == Command::Write)
{
command.delayToMeetConstraint(lastCommand.getStart(), WriteChecker::writeToWrite(lastCommand, command));
}
else if (lastCommand.getCommand() == Command::PDNPX || lastCommand.getCommand() == Command::PDNAX)
{
command.delayToMeetConstraint(lastCommand.getStart(), config.Timings.tXP);
}
@@ -54,34 +59,16 @@ bool WriteChecker::collidesOnDataStrobe(ScheduledCommand& write) const
bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write, ScheduledCommand& strobeCommand) const
{
//write to write
if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA)
{
bool collision = write.collidesOnDataStrobe(strobeCommand);
sc_time tCCD =
(write.getBank().getBankGroup() == strobeCommand.getBank().getBankGroup()) ?
config.Timings.tCCD_L : config.Timings.tCCD_S;
bool casToCas = (getDistance(write.getStart(), strobeCommand.getStart()) < tCCD) ? true : false;
return collision || casToCas;
return getDistance(write.getStart(),strobeCommand.getStart()) < WriteChecker::writeToWrite(strobeCommand,write);
}
else if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA)
{
//write to read
if (strobeCommand.getStart() >= write.getStart())
{
sc_time tWTR =
(write.getBank().getBankGroup() == strobeCommand.getBank().getBankGroup()) ?
config.Timings.tWTR_L : config.Timings.tWTR_S;
return strobeCommand.getStart() < clkAlign(write.getIntervalOnDataStrobe().end, Alignment::DOWN) + tWTR;
}
//read to write
return getDistance(write.getStart(),strobeCommand.getStart()) < ReadChecker::writeToRead(write, strobeCommand);
else
{
return write.getStart() < strobeCommand.getIntervalOnDataStrobe().end;
}
return getDistance(strobeCommand.getStart(), write.getStart()) < WriteChecker::readToWrite(strobeCommand, write);
}
else
{
@@ -91,4 +78,23 @@ bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write, ScheduledC
}
}
sc_time WriteChecker::writeToWrite(ScheduledCommand& firstWrite, ScheduledCommand& secondWrite)
{
sc_assert(firstWrite.getCommand() == Command::Write || firstWrite.getCommand() == Command::WriteA);
sc_assert(secondWrite.getCommand() == Command::Write || secondWrite.getCommand() == Command::WriteA);
TimingConfiguration& config = Configuration::getInstance().Timings;
sc_time tCCD = (firstWrite.getBankGroup() == secondWrite.getBankGroup()) ? config.tCCD_L : config.tCCD_S;
return max(tCCD, getWriteAcessTime());
}
sc_time WriteChecker::readToWrite(ScheduledCommand& read, ScheduledCommand& write)
{
sc_assert(read.getCommand() == Command::Read || read.getCommand() == Command::ReadA);
sc_assert(write.getCommand() == Command::Write || write.getCommand() == Command::WriteA);
TimingConfiguration& config = Configuration::getInstance().Timings;
return config.tRL + getReadAcessTime() - config.tWL + config.clk * 2;
}
} /* namespace controller */

View File

@@ -21,11 +21,16 @@ public:
virtual ~WriteChecker() {}
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
static sc_time writeToWrite(ScheduledCommand& firstWrite, ScheduledCommand& secondWrite);
static sc_time readToWrite(ScheduledCommand& read, ScheduledCommand& write);
private:
bool collidesOnDataStrobe(ScheduledCommand& write) const;
bool collidesWithStrobeCommand(ScheduledCommand& write, ScheduledCommand& strobeCommand) const;
const Configuration& config;
ControllerState& state;
};
} /* namespace controller */

View File

@@ -129,6 +129,7 @@ void Simulation::stop()
{
wait(terminateSimulation);
report("\nTerminating simulation");
wait(sc_time(50, SC_NS));
controller->terminateSimulation();
wait(sc_time(50, SC_NS));
TlmRecorder::getInstance().closeConnection();

View File

@@ -39,9 +39,7 @@ public:
if (!file.is_open())
SC_REPORT_FATAL(0, (string("Could not open trace ") + pathToTrace).c_str());
if(burstLength == 0)
this->burstlenght = core::Configuration::getInstance().BurstLength;
this->burstlenght = core::Configuration::getInstance().BurstLength;
iSocket.register_nb_transport_bw(this, &TracePlayer::nb_transport_bw);
}