diff --git a/dram/resources/scripts/tests.py b/dram/resources/scripts/tests.py
index 8d827256..781a4ed8 100644
--- a/dram/resources/scripts/tests.py
+++ b/dram/resources/scripts/tests.py
@@ -1,56 +1,154 @@
import sys
import sqlite3
import math
+import os
+import xml.etree.ElementTree as ET
-class DramConfig(object):
- """Holds the timing constraints in the standard and the configuration of the DRAM"""
-
- unitOfTime = "ns"
- nActivateWindow = 0
- clk = numberOfBanks = 0
- tRP = tRAS = tRC = tRRD = tRCD = tTAW = tRL = tWL = tWTR = tRFC = tWR = 0
- tReadLength = tWriteLength = 0
+def getPathToConfigs():
+ return os.path.dirname(__file__).replace("/scripts","/configs")
+
+def getValueFromConfigXML(root, id):
+ return root.findall(".//parameter[@id='{0}']".format(id))[0].attrib['value']
+
+def getMemconfig(connection):
+ cursor = connection.cursor()
+ cursor.execute("SELECT Memconfig FROM GeneralInfo")
+ result = cursor.fetchone()
+ memconfig = getPathToConfigs() + "/memconfigs/" + result[0]
+ return ET.parse(memconfig)
+
+def getMemspec(connection):
+ cursor = connection.cursor()
+ cursor.execute("SELECT Memspec FROM GeneralInfo")
+ result = cursor.fetchone()
+ memspec = getPathToConfigs() + "/memspecs/" + result[0]
+ return ET.parse(memspec)
+
+def getClock(connection):
+ cursor = connection.cursor()
+ cursor.execute("SELECT clk, UnitOfTime FROM GeneralInfo")
+ result = cursor.fetchone()
+ return (result[0],result[1])
+
+class DramConfig(object):
+ memoryType = ""
bankwiseRefresh = False
bankwisePowerdown = False
+ clk = 0
+ unitOfTime = ""
+ dataRate = 0
+ nActivateWindow = numberOfBanks = 0
+
+ clk = 0
+ tRP = 0 #precharge-time (pre -> act same bank)
+ tRAS = 0 #active-time (act -> pre same bank)
+ tRC = 0 #RAS-cycle-time (min time bw 2 succesive ACT to same bank)
+ tCCD_S = 0 #TODO: relevant? max(bl, tCCD)
+ tCCD_L = 0
+ tRTP = 0 #Read to precharge
+ tRRD_S = 0 #min time bw 2 succesive ACT to different banks (different bank group)
+ tRRD_L = 0 #.. (same bank group)
+ tRCD = 0 #act -> read/write
+ tNAW = 0 #n activate window
+ tRL = 0 #read latency (read command start to data strobe)
+ tWL = 0 #write latency
+ tWR = 0 #write recovery (write to precharge)
+ tWTR_S = 0 #write to read (different bank group)
+ tWTR_L = 0 #.. (same bank group)
+ tCKESR = 0 #min time in sref
+ tCKE = 0 #min time in pdna or pdnp
+ tXP = 0 #min delay to row access command after pdnpx pdnax
+ tXPDLL = 0 #min delay to row access command after pdnpx pdnax for dll commands
+ tXSR = 0 #min delay to row access command after srefx
+ tXSRDLL = 0 #min delay to row access command after srefx for dll commands
+ tAL = 0 #additive delay (delayed execution in dram)
+ tRFC = 0 #min ref->act delay
+
+
+ def readConfigFromFiles(self, connection):
+ print("parsing stuff and stuff")
+ memspec = getMemspec(connection)
+
+ bankwisePowerdown = bankwiseRefresh = getValueFromConfigXML(getMemconfig(connection), "bankwiseLogic")
+ clk = getClock(connection)
+ self.clk = clk[0]
+ self.unitOfTime = clk[1].lower()
+
+ self.numberOfBanks = getValueFromConfigXML(memspec, "nbrOfBanks")
+ self.burstLength = getValueFromConfigXML(memspec, "burstLength")
+ self.memoryType = getValueFromConfigXML(memspec, "memoryType")
+ self.dataRate = getValueFromConfigXML(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.tRRD_L = self.tRRD_S
+ self.tCCD_S = self.clk * getValueFromConfigXML(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.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.tXPDLL = self.tXP
+ self.tXSR = self.clk * getValueFromConfigXML(memspec, "XS")
+ self.tXSRDLL = self.tXSR
+ self.tAL = self.clk * getValueFromConfigXML(memspec, "AL")
+ self.tRFC = self.clk * getValueFromConfigXML(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");
+ 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 parseFromXml(self):
- self.clk = 6
- self.numberOfBanks = 8
- self.nActivateWindow = 2
- self.burstLength = 2
-
- self.tRP = 3*self.clk
- self.tRAS = 6*self.clk
- self.tRRD = 2*self.clk
- self.tRC = self.tRP + self.tRAS
- self.tRCD = 3*self.clk
- self.tRL = 3*self.clk
- self.tWL = 1*self.clk
- self.tWTR = 3*self.clk
- self.tWR = 2*self.clk
- self.tTAW = self.clkAlign(50)
- self.tRFC = self.clkAlign(130)
- self.tCKESR = self.clkAlign(max(3*self.clk, 15))
-
def __init__(self):
- self.parseFromXml()
+ pass
dramconfig = DramConfig()
-
def calculateReadLength(burstLength):
return dramconfig.tRL + burstLength * dramconfig.clk
def calculateWriteLength(burstLength):
return dramconfig.tWL + burstLength * dramconfig.clk
-
# ----------- test utils ---------------------------------------
-
tests = []
def test(function):
@@ -73,12 +171,11 @@ def TestFailed(message):
def formatTime(time):
return ('{0} {1}'.format(time, dramconfig.unitOfTime))
-# ----------- command bus checks ---------------------------------------
+# ----------- checks ---------------------------------------
@test
def commands_are_clockaligned(connection):
"""Checks that all commands on the command bus are aligned to the system clock"""
- passedTest = True
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})
@@ -88,272 +185,272 @@ def commands_are_clockaligned(connection):
if(result != None):
return TestFailed("Command with PhaseID {0} starts at {1} and ends at, which is not aligned to system clock ({2})".format(
result[0], formatTime(result[1]), formatTime(result[2]), formatTime(dramconfig.clk)))
-
return TestSuceeded()
-@test
-def commandbus_slots_are_used_once(connection):
- """Checks that no two phases on the command bus start at the same time"""
- cursor = connection.cursor()
+# @test
+# def commandbus_slots_are_used_once(connection):
+# """Checks that no two phases on the command bus start at the same time"""
+# cursor = connection.cursor()
- if dramconfig.bankwisePowerdown and dramconfig.bankwiseRefresh:
- excludedPhases = "('REQ','RESP','PRE_ALL')"
- elif (not dramconfig.bankwisePowerdown and dramconfig.bankwiseRefresh):
- excludedPhases = "('REQ','RESP','PRE_ALL','PDNA','PDNP','SREF')"
- elif dramconfig.bankwisePowerdown and not dramconfig.bankwiseRefresh:
- excludedPhases = "('REQ','RESP','PRE_ALL','AUTO_REFRESH')"
- else:
- excludedPhases = "('REQ','RESP','PRE_ALL','PDNA','PDNP','SREF','AUTO_REFRESH')"
+# if dramconfig.bankwisePowerdown and dramconfig.bankwiseRefresh:
+# excludedPhases = "('REQ','RESP','PRE_ALL')"
+# elif (not dramconfig.bankwisePowerdown and dramconfig.bankwiseRefresh):
+# excludedPhases = "('REQ','RESP','PRE_ALL','PDNA','PDNP','SREF')"
+# elif dramconfig.bankwisePowerdown and not dramconfig.bankwiseRefresh:
+# excludedPhases = "('REQ','RESP','PRE_ALL','AUTO_REFRESH')"
+# else:
+# excludedPhases = "('REQ','RESP','PRE_ALL','PDNA','PDNP','SREF','AUTO_REFRESH')"
- query = """SELECT PhaseBegin,count FROM (SELECT phaseBegin,count(phasebegin) AS count
- FROM Phases WHERE PhaseName NOT IN """ + excludedPhases + """ AND phasebegin>0 GROUP BY phaseBegin) WHERE count>1"""
- cursor.execute(query)
- result = cursor.fetchone()
- if(result != None):
- return TestFailed("Slot on commandbus at time {0} is used multiple times".format(formatTime(result[0])))
+# query = """SELECT PhaseBegin,count FROM (SELECT phaseBegin,count(phasebegin) AS count
+# FROM Phases WHERE PhaseName NOT IN """ + excludedPhases + """ AND phasebegin>0 GROUP BY phaseBegin) WHERE count>1"""
+# cursor.execute(query)
+# result = cursor.fetchone()
+# if(result != None):
+# return TestFailed("Slot on commandbus at time {0} is used multiple times".format(formatTime(result[0])))
- return TestSuceeded()
+# return TestSuceeded()
-@test
-def command_sequences_are_valid(connection):
- cursor = connection.cursor()
- cursor.execute("SELECT group_concat(phaseName),transact FROM phases GROUP BY transact")
+# @test
+# def command_sequences_are_valid(connection):
+# cursor = connection.cursor()
+# cursor.execute("SELECT group_concat(phaseName),transact FROM phases GROUP BY transact")
- 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'
- ])
+# 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'
+# ])
- 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))
+# 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()
+# 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
- AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin"""
+# @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
+# AND PhaseName NOT IN ('REQ','RESP') ORDER BY PhaseBegin"""
- for bankNumber in range(dramconfig.numberOfBanks):
- cursor.execute(query,{"bank": bankNumber})
+# for bankNumber in range(dramconfig.numberOfBanks):
+# cursor.execute(query,{"bank": bankNumber})
- rowBufferIsClosed = True
- #phases that precharge the bank
- prechargingPhases = set(['PRE','PRE_ALL','RDA','WRA'])
- #phases that require the bank to be precharged
- accessingPhases = set(['RD,RDA,WR,WRA,SREF,AUTO_REFRESH'])
+# rowBufferIsClosed = True
+# #phases that precharge the bank
+# prechargingPhases = set(['PRE','PRE_ALL','RDA','WRA'])
+# #phases that require the bank to be precharged
+# accessingPhases = set(['RD,RDA,WR,WRA,SREF,AUTO_REFRESH'])
- for currentRow in cursor:
+# for currentRow in cursor:
- if(currentRow[0] in accessingPhases and rowBufferIsClosed == True):
- return TestFailed("Phase {0}({1}) acesses a closed rowbuffer".format(currentRow[1], currentRow[0]))
+# if(currentRow[0] in accessingPhases and rowBufferIsClosed == True):
+# return TestFailed("Phase {0}({1}) acesses a closed rowbuffer".format(currentRow[1], currentRow[0]))
- if(currentRow[0] == 'ACT'):
- if(rowBufferIsClosed == True):
- rowBufferIsClosed = False
- else:
- return TestFailed("Phase {0}({1}) activates an already activated rowbuffer".format(currentRow[1],currentRow[0]))
+# if(currentRow[0] == 'ACT'):
+# if(rowBufferIsClosed == True):
+# rowBufferIsClosed = False
+# else:
+# return TestFailed("Phase {0}({1}) activates an already activated rowbuffer".format(currentRow[1],currentRow[0]))
- if(currentRow[0] in prechargingPhases):
- 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
+# if(currentRow[0] in prechargingPhases):
+# 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()
+# 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')"""
+# @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 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"))):
+# 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 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()
+# 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 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)
- 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()
+# 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 ---------------------------------------
+# #----------- 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()
+# @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()
+# 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"
+# @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.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()
-# ----------- read/write checks ---------------------------------------
+# # ----------- read/write checks ---------------------------------------
-@test
-def read_to_read(connection):
- """Checks minimal time between two reads(JEDEC 229, P. 29)"""
- cursor = connection.cursor()
- cursor.execute("SELECT Phases.ID, PhaseBegin, PhaseName from Phases WHERE PhaseName IN ('RD','RDA') ORDER BY PhaseBegin")
- lastRow = cursor.fetchone()
+# @test
+# def read_to_read(connection):
+# """Checks minimal time between two reads(JEDEC 229, P. 29)"""
+# cursor = connection.cursor()
+# cursor.execute("SELECT Phases.ID, PhaseBegin, PhaseName from Phases WHERE PhaseName IN ('RD','RDA') ORDER BY PhaseBegin")
+# lastRow = cursor.fetchone()
- for currentRow in cursor:
- if(currentRow[1] < lastRow[1] + dramconfig.tReadLength):
- timeBetweenReads = currentRow[1] - lastRow[1];
- clocksBetweenReads = round(timeBetweenReads/dramconfig.clk)
- if(clocksBetweenReads % 2 == 1):
- return TestFailed("{0} with PhaseID {1} interrupts data acess of {2} {3}. They are {4} clocks ({5}) apart. Numbers of clock between interrupting reads must be even.".
- format(currentRow[2], currentRow[0], lastRow[2], lastRow[0], clocksBetweenReads, formatTime(timeBetweenReads)))
- lastRow = currentRow
+# for currentRow in cursor:
+# if(currentRow[1] < lastRow[1] + dramconfig.tReadLength):
+# timeBetweenReads = currentRow[1] - lastRow[1];
+# clocksBetweenReads = round(timeBetweenReads/dramconfig.clk)
+# if(clocksBetweenReads % 2 == 1):
+# return TestFailed("{0} with PhaseID {1} interrupts data acess of {2} {3}. They are {4} clocks ({5}) apart. Numbers of clock between interrupting reads must be even.".
+# format(currentRow[2], currentRow[0], lastRow[2], lastRow[0], clocksBetweenReads, formatTime(timeBetweenReads)))
+# lastRow = currentRow
- return TestSuceeded()
+# return TestSuceeded()
-@test
-def write_to_read_and_read_to_write(connection):
- """Checks minimal time between write and read/read and write (JEDEC 229, P. 33/34)"""
- cursor = connection.cursor()
- query = """SELECT Phases.ID,PhaseBegin,PhaseName from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID
- WHERE PhaseName IN ('RD','WR','RDA','WRA') ORDER BY PhaseBegin"""
+# @test
+# def write_to_read_and_read_to_write(connection):
+# """Checks minimal time between write and read/read and write (JEDEC 229, P. 33/34)"""
+# cursor = connection.cursor()
+# query = """SELECT Phases.ID,PhaseBegin,PhaseName from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID
+# WHERE PhaseName IN ('RD','WR','RDA','WRA') ORDER BY PhaseBegin"""
- cursor.execute(query)
- lastRow = cursor.fetchone()
+# cursor.execute(query)
+# lastRow = cursor.fetchone()
- for currentRow in cursor:
- if(currentRow[2] in ["RD","RDA"] and lastRow[2] in ["WR","WRA"]):
- writeEndToReadBegin = currentRow[1] - (lastRow[1] + dramconfig.tWriteLength);
- if(writeEndToReadBegin < dramconfig.tWTR ):
- return TestFailed("Read with PhaseID {0} starts {1} after end of data access of write {2}. Minimum time between end of write and start of read is {3}".
- format(currentRow[0],formatTime(writeEndToReadBegin),lastRow[0], formatTime(dramconfig.tWTR )))
- elif(currentRow[2] in ["WR","WRA"] and lastRow[2] in ["RD","RDA"]):
- if(currentRow[1] < (lastRow[1]+dramconfig.tReadLength)):
- return TestFailed("WR with PhaseID {0} starts before end of data acess of read {1}".
- format(currentRow[0], lastRow[0]))
- lastRow = currentRow
+# for currentRow in cursor:
+# if(currentRow[2] in ["RD","RDA"] and lastRow[2] in ["WR","WRA"]):
+# writeEndToReadBegin = currentRow[1] - (lastRow[1] + dramconfig.tWriteLength);
+# if(writeEndToReadBegin < dramconfig.tWTR ):
+# return TestFailed("Read with PhaseID {0} starts {1} after end of data access of write {2}. Minimum time between end of write and start of read is {3}".
+# format(currentRow[0],formatTime(writeEndToReadBegin),lastRow[0], formatTime(dramconfig.tWTR )))
+# elif(currentRow[2] in ["WR","WRA"] and lastRow[2] in ["RD","RDA"]):
+# if(currentRow[1] < (lastRow[1]+dramconfig.tReadLength)):
+# return TestFailed("WR with PhaseID {0} starts before end of data acess of read {1}".
+# format(currentRow[0], lastRow[0]))
+# lastRow = currentRow
- return TestSuceeded()
+# 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"""
+# @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
+# minReadStartToPrecharge = dramconfig.burstLength * dramconfig.clk
+# minWriteEndToPreStart = dramconfig.tWR
- for bankNumber in range(dramconfig.numberOfBanks):
+# for bankNumber in range(dramconfig.numberOfBanks):
- cursor.execute(query,{"bank": bankNumber})
- lastRow = cursor.fetchone()
+# cursor.execute(query,{"bank": bankNumber})
+# lastRow = cursor.fetchone()
- 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)))
+# 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)))
+# 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()
+# 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()
+# @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):
connection = sqlite3.connect(pathToTrace)
+ dramconfig.readConfigFromFiles(connection)
testResults = []
numberOfFailedTest = 0
diff --git a/dram/resources/simulations/first.xml b/dram/resources/simulations/first.xml
deleted file mode 100644
index 91776355..00000000
--- a/dram/resources/simulations/first.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
- MICRON_4Gb_DDR4-1866_8bit_A.xml
-
- memconfig.xml
-
-
-
-
- chstone-mips_32.stl
- empty.stl
-
-
-
diff --git a/dram/src/core/configuration/TimingConfiguration.h b/dram/src/core/configuration/TimingConfiguration.h
index 7bac0d9a..79602d5d 100644
--- a/dram/src/core/configuration/TimingConfiguration.h
+++ b/dram/src/core/configuration/TimingConfiguration.h
@@ -31,7 +31,7 @@ struct TimingConfiguration
sc_time tRP; //precharge-time (pre -> act same bank)
sc_time tRAS; //active-time (act -> pre same bank)
sc_time tRC; //RAS-cycle-time (min time bw 2 succesive ACT to same bank)
- sc_time tCCD_S; //TODO: relevant? max(bl, tCCD)
+ sc_time tCCD_S; //max(bl, tCCD) is relevant for rd->rd
sc_time tCCD_L;
sc_time tRTP; //Read to precharge
sc_time tRRD_S; //min time bw 2 succesive ACT to different banks (different bank group)
diff --git a/dram/src/simulation/Simulation.cpp b/dram/src/simulation/Simulation.cpp
index f2f6f7ab..2d85b4ab 100644
--- a/dram/src/simulation/Simulation.cpp
+++ b/dram/src/simulation/Simulation.cpp
@@ -30,15 +30,16 @@ Simulation::Simulation(string name, string pathToResources, string traceName, Dr
TlmRecorder::sqlScriptURI = pathToResources + string("scripts/createTraceDB.sql");
Configuration::memconfigUri = pathToResources + string("configs/memconfigs/") + setup.memconfig;
Configuration::memspecUri = pathToResources + string("configs/memspecs/") + setup.memspec;
+ TlmRecorder::getInstance().recordMemconfig(setup.memconfig);
+ TlmRecorder::getInstance().recordMemspec(setup.memspec);
- //setup dram
dram = new Dram<>("dram");
arbiter = new Arbiter("arbiter");
controller = new Controller<>("controller");
player1 = new TracePlayer<>("player1", pathToResources + string("traces/") + devices[0].trace, devices[0].burstLength, this);
player2 = new TracePlayer<>("player2", pathToResources + string("traces/") + devices[1].trace, devices[1].burstLength, this);
-
+ TlmRecorder::getInstance().recordTracenames(devices[0].trace + "," + devices[1].trace);
player1->iSocket.bind(arbiter->tSockets[0]);
player2->iSocket.bind(arbiter->tSockets[1]);