Changed constraints in all checkers to be generic for wideIO and ddr4
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-2055719358" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} -E -P -v -dD "${INPUTS}" -std=c++11">
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-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 "${INPUTS}" -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 "${INPUTS}" -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 "${INPUTS}" -std=c++11">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
27
dram/resources/configs/amconfigs/am_wideioFourBanks.xml
Executable file
27
dram/resources/configs/amconfigs/am_wideioFourBanks.xml
Executable 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>
|
||||
@@ -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" />-->
|
||||
|
||||
@@ -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" />-->
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user