corrected two act window

This commit is contained in:
robert
2014-03-31 12:05:05 +02:00
parent 9f97e77db4
commit e930002e5c
7 changed files with 222 additions and 169 deletions

View File

@@ -1,23 +1,42 @@
import sys
import sqlite3
def the_answer_to_life_the_universe_and_everything(connection):
return 42
def number_of_precharges(connection):
return 21
metrics = []
def metric(function):
metrics.append(function)
return function
@metric
def average_response_latency(connection):
cursor = connection.cursor()
cursor.execute("SELECT avg(end-begin) FROM ranges")
result = cursor.fetchone()
return round(result[0],1)
@metric
def number_of_activates(connection):
cursor = connection.cursor()
cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName = 'ACT'")
result = cursor.fetchone()
return result[0]
def calculateMetrics(pathToTrace):
connection = sqlite3.connect(pathToTrace)
metrics = [the_answer_to_life_the_universe_and_everything, number_of_precharges]
result = []
calculatedMetrics = []
print("================================")
print("Calculating metrics for {0}".format(pathToTrace))
for metric in metrics:
result.append((metric.__name__.replace("_"," "), metric(connection)))
res = (metric.__name__.replace("_"," "), metric(connection))
print("{0}: {1}".format(res[0],res[1]))
calculatedMetrics.append(res)
connection.close()
print(result)
return result
return calculatedMetrics
if __name__ == "__main__":
path = sys.argv[1]

View File

@@ -19,6 +19,7 @@ class DramConfig(object):
self.numberOfBanks = 8
self.nActivateWindow = 2
self.burstLength = 2
self.tRP = 3*self.clk
self.tRAS = 6*self.clk
self.tRRD = 2*self.clk
@@ -99,138 +100,138 @@ def commandbus_slots_are_used_once(connection):
# ----------- activate checks ---------------------------------------
@test
def precharge_before_activate(connection):
"""Checks that all activate commands are preceeded by a precharge or a refresh or a powerdown"""
cursor = connection.cursor()
query = """SELECT Phases.ID, PhaseName, PhaseBegin FROM Transactions INNER JOIN Phases ON Phases.Transact = Transactions.ID
WHERE (TBank = :bank AND PhaseName IN ('ACT','PRE','REFB')) OR PhaseName IN ('REFA','SREF','PDNP','PDNA') ORDER BY PhaseBegin"""
# @test
# def precharge_before_activate(connection):
# """Checks that all activate commands are preceeded by a precharge or a refresh or a powerdown"""
# cursor = connection.cursor()
# query = """SELECT Phases.ID, PhaseName, PhaseBegin FROM Transactions INNER JOIN Phases ON Phases.Transact = Transactions.ID
# WHERE (TBank = :bank AND PhaseName IN ('ACT','PRE','REFB')) OR PhaseName IN ('REFA','SREF','PDNP','PDNA') 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:
if(lastRow[1] != currentRow[1] or currentRow[1] != 'ACT'):
lastRow = currentRow
else:
return TestFailed("No precharge between activates with PhaseID {0} and {1}".format(lastRow[0], currentRow[0]))
return TestSuceeded()
# for currentRow in cursor:
# if(lastRow[1] != currentRow[1] or currentRow[1] != 'ACT'):
# lastRow = currentRow
# else:
# return TestFailed("No precharge between activates with PhaseID {0} and {1}".format(lastRow[0], currentRow[0]))
# return TestSuceeded()
@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 checks ---------------------------------------
# # ----------- read checks ---------------------------------------
@test
def activate_to_read(connection):
"""Checks minimal time bewteen activate and following read (JEDEC 229, P. 29)"""
cursor = connection.cursor()
query = "SELECT Phases.ID,PhaseBegin,PhaseName from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID WHERE PhaseName IN ('ACT','RD') AND TBANK = :bank ORDER BY PhaseBegin"
# @test
# def activate_to_read(connection):
# """Checks minimal time bewteen activate and following read (JEDEC 229, P. 29)"""
# cursor = connection.cursor()
# query = "SELECT Phases.ID,PhaseBegin,PhaseName from Phases INNER JOIN Transactions ON Phases.Transact = Transactions.ID WHERE PhaseName IN ('ACT','RD') AND TBANK = :bank ORDER BY PhaseBegin"
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[2] == "RD" and lastRow[2] == "ACT"):
actToReadTime = currentRow[1] - lastRow[1];
if(actToReadTime < dramconfig.tRCD):
return TestFailed("Read with PhaseID {0} starts {1} after activate {2}. Minimum activate to read time is {3}".
format(currentRow[0],formatTime(actToReadTime),lastRow[0], formatTime(dramconfig.tRCD)))
lastRow = currentRow
# for currentRow in cursor:
# if(currentRow[2] == "RD" and lastRow[2] == "ACT"):
# actToReadTime = currentRow[1] - lastRow[1];
# if(actToReadTime < dramconfig.tRCD):
# return TestFailed("Read with PhaseID {0} starts {1} after activate {2}. Minimum activate to read time is {3}".
# format(currentRow[0],formatTime(actToReadTime),lastRow[0], formatTime(dramconfig.tRCD)))
# lastRow = currentRow
return TestSuceeded()
# return TestSuceeded()
@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, PhaseEnd from Phases WHERE PhaseName = 'RD' 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, PhaseEnd from Phases WHERE PhaseName = 'RD' ORDER BY PhaseBegin")
# lastRow = cursor.fetchone()
for currentRow in cursor:
if(currentRow[1] < lastRow[2]):
timeBetweenReads = currentRow[1] - lastRow[1];
clocksBetweenReads = round(timeBetweenReads/dramconfig.clk)
if(clocksBetweenReads % 2 == 1):
return TestFailed("Read with PhaseID {0} interrupts read {1}. They are {2} clocks ({3}) apart. Numbers of clock between interrupting reads must be even.".
format(currentRow[0], lastRow[0], clocksBetweenReads, formatTime(timeBetweenReads)))
lastRow = currentRow
# for currentRow in cursor:
# if(currentRow[1] < lastRow[2]):
# timeBetweenReads = currentRow[1] - lastRow[1];
# clocksBetweenReads = round(timeBetweenReads/dramconfig.clk)
# if(clocksBetweenReads % 2 == 1):
# return TestFailed("Read with PhaseID {0} interrupts read {1}. They are {2} clocks ({3}) apart. Numbers of clock between interrupting reads must be even.".
# format(currentRow[0], lastRow[0], clocksBetweenReads, formatTime(timeBetweenReads)))
# lastRow = currentRow
return TestSuceeded()
# return TestSuceeded()
@test
def write_to_read(connection):
"""Checks minimal time between write and following read (JEDEC 229, P. 34)"""
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') AND TBANK = :bank ORDER BY PhaseBegin"
# @test
# def write_to_read(connection):
# """Checks minimal time between write and following read (JEDEC 229, P. 34)"""
# 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') AND TBANK = :bank ORDER BY PhaseBegin"
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] == "RD" and lastRow[3] == "WR"):
writeEndToReadBegin = currentRow[1] - lastRow[2];
if(writeEndToReadBegin < dramconfig.tWTR ):
return TestFailed("Read with PhaseID {0} starts {1} after end 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 )))
lastRow = currentRow
# for currentRow in cursor:
# if(currentRow[3] == "RD" and lastRow[3] == "WR"):
# writeEndToReadBegin = currentRow[1] - lastRow[2];
# if(writeEndToReadBegin < dramconfig.tWTR ):
# return TestFailed("Read with PhaseID {0} starts {1} after end 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 )))
# lastRow = currentRow
return TestSuceeded()
# return TestSuceeded()

View File

@@ -29,6 +29,8 @@ public:
void closeRowBuffer(const Bank &bank);
void closeAllRowBuffers();
private:
std::vector<Bank> banks;
std::vector<Row> rowsInRowBuffers;

View File

@@ -46,7 +46,7 @@ struct TimingConfiguration
tRL = 3*clk; //read latency (read command start to data strobe)
tWL = 1*clk; //write latency
tTAW = 48*clk; //two activate window
tTAW = clkAlign(sc_time(50,SC_NS), clk); //two activate window
tRR = 2*clk; //min read to read on same rank
tWW = 1*clk; //min write to write on same rank
tWTR = 3*clk;//write to read

View File

@@ -1,26 +1,51 @@
//#include "Fr_Fcfs.h"
//#include "assert.h"
//#include "../common/dramExtension.h"
//
//using namespace tlm;
//using namespace std;
//
//namespace scheduler {
//
//bool FR_FCFS::hasScheduledTransactions(Bank bank)
//{
// return rowHitBuffer.hasBufferedTransaction(bank);
//}
//
//gp* FR_FCFS::getNextScheduledTransaction(Bank bank)
//{
// gp* result = rowHitBuffer.getRowHitOrOldest(bank);
// return result;
//}
//
//void FR_FCFS::schedule(gp* payload)
//{
// rowHitBuffer.bufferTransaction(payload);
//}
//
//}
#include "Fr_Fcfs.h"
#include "../common/dramExtension.h"
#include <algorithm>
using namespace std;
namespace scheduler {
bool scheduler::FR_FCFS::hasTransactionForBank(Bank bank)
{
return (buffer.at(bank.ID()).size() > 0);
}
void scheduler::FR_FCFS::schedule(gp* payload)
{
buffer.at(DramExtension::getExtension(payload).getBank().ID()).emplace_back(payload);
}
gp* scheduler::FR_FCFS::getTransactionForBank(Bank bank)
{
sc_assert(hasTransactionForBank(bank));
list<gp*>& payloads = buffer.at(bank.ID());
auto found =
find_if(payloads.begin(), payloads.end(),
[&](gp* payload)
{ return DramExtension::getExtension(payload).getRow() == bankstates.getRowInRowBuffer(bank);});
if (found != payloads.end())
return *found;
else
return payloads.front();
}
void scheduler::FR_FCFS::popTransactionForBank(Bank bank)
{
sc_assert(hasTransactionForBank(bank));
list<gp*>& payloads = buffer.at(bank.ID());
auto found =
find_if(payloads.begin(), payloads.end(),
[&](gp* payload)
{ return DramExtension::getExtension(payload).getRow() == bankstates.getRowInRowBuffer(bank);});
if (found != payloads.end())
payloads.erase(found);
else
payloads.erase(payloads.begin());
}
}

View File

@@ -1,26 +1,31 @@
//#ifndef FR_FCFS_H
//#define FR_FCFS_H
//#include <list>
//#include <vector>
//#include "Scheduler.h"
//#include "RowHitBuffer.h"
//#include "../core/BankStates.h"
//
//namespace scheduler{
//
//class FR_FCFS : public Scheduler
//{
//public:
// FR_FCFS(const core::BankStates& bankstates): rowHitBuffer(bankstates){}
// virtual ~FR_FCFS(){}
// virtual bool hasScheduledTransactions(Bank bank) override;
// virtual void schedule(gp* payload) override;
// virtual gp* getNextScheduledTransaction(Bank bank) override;
//
//private:
// RowHitBuffer rowHitBuffer;
//};
//
//}
//
//#endif // FR_FCFS_H
#ifndef FR_FCFS_H_
#define FR_FCFS_H_
#include "Scheduler.h"
#include "../core/BankStates.h"
#include <list>
#include <vector>
namespace scheduler {
class FR_FCFS : public Scheduler
{
public:
FR_FCFS(const core::BankStates& bankstates) : bankstates(bankstates), buffer(bankstates.getNumberOfBanks())
{}
virtual ~FR_FCFS()
{}
virtual bool hasTransactionForBank(Bank bank) override;
virtual void schedule(gp* payload) override;
virtual gp* getTransactionForBank(Bank bank) override;
virtual void popTransactionForBank(Bank bank) override;
private:
std::vector<std::list<gp*>> buffer;
const core::BankStates& bankstates;
};
} /* namespace scheduler */
#endif

View File

@@ -24,6 +24,7 @@
#include "../core/Controller.h"
#include "../scheduler/Scheduler.h"
#include "../scheduler/Fifo.h"
#include "../scheduler/Fr_Fcfs.h"
using namespace std;
using namespace tlm;
@@ -44,7 +45,7 @@ public:
&ControllerWrapper::controllerPEQCallback), recorder(recorder), debugManager(DebugManager::getInstance())
{
controller = new Controller(*this, recorder);
scheduler = new Fifo(controller->getBankStates());
scheduler = new FR_FCFS(controller->getBankStates());
inputBufferDelay = controller->config.Timings.clk;
iSocket.register_nb_transport_bw(this, &ControllerWrapper::nb_transport_bw);
tSocket.register_nb_transport_fw(this, &ControllerWrapper::nb_transport_fw);