Merge branch 'master' of git.rhrk.uni-kl.de:EIT-Wehn/dram.vp.system

This commit is contained in:
Matthias Jung
2018-06-08 20:18:49 +02:00
201 changed files with 7030 additions and 5689 deletions

3
.gitmodules vendored
View File

@@ -5,3 +5,6 @@
path = DRAMSys/library/src/common/third_party/DRAMPower
url = https://github.com/tukl-msd/DRAMPower.git
branch = master
[submodule "DRAMSys/library/src/common/third_party/json"]
path = DRAMSys/library/src/common/third_party/json
url = https://github.com/nlohmann/json.git

View File

@@ -39,3 +39,5 @@ simulator.depends = library
# Additional Files:
# tests folder (DRAMSys/tests)
include(tests/tests.pri)
DISTFILES += ../README.md

View File

@@ -55,7 +55,7 @@ class Gem5SimControlDRAMsys: public Gem5SystemC::Gem5SimControl
{
public:
Gem5SimControlDRAMsys(string configFile) :
Gem5SystemC::Gem5SimControl("gem5",configFile,0,"MemoryAccess")
Gem5SystemC::Gem5SimControl("gem5", configFile, 0, "MemoryAccess")
{
}
@@ -66,37 +66,38 @@ public:
};
struct AddressOffset: sc_module
{
private:
struct AddressOffset: sc_module {
private:
unsigned long long int offset;
public:
public:
tlm_utils::simple_target_socket<AddressOffset> t_socket;
tlm_utils::simple_initiator_socket<AddressOffset> i_socket;
AddressOffset(sc_module_name, unsigned long long int o) : offset(o),t_socket("t_socket"),i_socket("i_socket")
AddressOffset(sc_module_name, unsigned long long int o) : offset(o),
t_socket("t_socket"), i_socket("i_socket")
{
t_socket.register_nb_transport_fw(this,&AddressOffset::nb_transport_fw);
t_socket.register_transport_dbg(this,&AddressOffset::transport_dbg);
t_socket.register_b_transport(this,&AddressOffset::b_transport);
i_socket.register_nb_transport_bw(this,&AddressOffset::nb_transport_bw);
t_socket.register_nb_transport_fw(this, &AddressOffset::nb_transport_fw);
t_socket.register_transport_dbg(this, &AddressOffset::transport_dbg);
t_socket.register_b_transport(this, &AddressOffset::b_transport);
i_socket.register_nb_transport_bw(this, &AddressOffset::nb_transport_bw);
}
//Forward Interface
tlm::tlm_sync_enum nb_transport_fw(tlm_generic_payload &trans, tlm_phase &phase, sc_time &delay)
tlm::tlm_sync_enum nb_transport_fw(tlm_generic_payload &trans, tlm_phase &phase,
sc_time &delay)
{
//std::cout << "NB "<< this->name() <<": " << trans.get_address() << " -" << offset;
trans.set_address(trans.get_address()-offset);
trans.set_address(trans.get_address() - offset);
//std::cout << " = " << trans.get_address() << std::endl;
return i_socket->nb_transport_fw(trans,phase,delay);
return i_socket->nb_transport_fw(trans, phase, delay);
}
unsigned int transport_dbg(tlm::tlm_generic_payload &trans)
{
// adjust address offset:
//std::cout << "Debug "<< this->name() <<": " << trans.get_address() << " -" << offset;
trans.set_address(trans.get_address()-offset);
trans.set_address(trans.get_address() - offset);
//std::cout << " = " << trans.get_address() << std::endl;
return i_socket->transport_dbg(trans);
}
@@ -105,16 +106,17 @@ struct AddressOffset: sc_module
{
// adjust address offset:
//std::cout << "B "<< this->name() <<": " << trans.get_address() << " -" << offset;
trans.set_address(trans.get_address()-offset);
trans.set_address(trans.get_address() - offset);
//std::cout << " = " << trans.get_address() << std::endl;
i_socket->b_transport(trans, delay);
}
//Backward Interface
tlm::tlm_sync_enum nb_transport_bw(tlm_generic_payload &trans, tlm_phase &phase, sc_time &delay)
tlm::tlm_sync_enum nb_transport_bw(tlm_generic_payload &trans, tlm_phase &phase,
sc_time &delay)
{
//trans.set_address(trans.get_address()+offset);
return t_socket->nb_transport_bw(trans,phase,delay);
return t_socket->nb_transport_bw(trans, phase, delay);
}
};
@@ -132,18 +134,15 @@ int sc_main(int argc, char **argv)
string gem5ConfigFile;
string resources;
if(argc > 1)
{
if (argc > 1) {
// Get path of resources:
resources = pathOfFile(argv[0])
+ string("/../../DRAMSys/library/resources/");
+ string("/../../DRAMSys/library/resources/");
SimulationXML = argv[1];
gem5ConfigFile = argv[2];
}
else
{
SC_REPORT_FATAL("sc_main","Please provide configuration files");
} else {
SC_REPORT_FATAL("sc_main", "Please provide configuration files");
}
// Instantiate DRAMSys:
@@ -177,8 +176,8 @@ int sc_main(int argc, char **argv)
Gem5SystemC::Gem5SlaveTransactor dramInterface("transactor1", "transactor1");
Gem5SystemC::Gem5SlaveTransactor nvmInterface("transactor2", "transactor2");
AddressOffset nvmOffset("nvmOffset",0);
AddressOffset dramOffset("dramOffset", (2147483648-67108863));//+67108863);
AddressOffset nvmOffset("nvmOffset", 0);
AddressOffset dramOffset("dramOffset", (2147483648 - 67108863)); //+67108863);
dramInterface.socket.bind(dramOffset.t_socket);
dramOffset.i_socket.bind(dramSys.tSocket); // ID0
@@ -194,9 +193,8 @@ int sc_main(int argc, char **argv)
sc_core::sc_set_stop_mode(SC_STOP_FINISH_DELTA);
sc_core::sc_start();
if (!sc_core::sc_end_of_simulation_invoked())
{
SC_REPORT_INFO("sc_main","Simulation stopped without explicit sc_stop()");
if (!sc_core::sc_end_of_simulation_invoked()) {
SC_REPORT_INFO("sc_main", "Simulation stopped without explicit sc_stop()");
sc_core::sc_stop();
}

View File

@@ -51,6 +51,7 @@ INCLUDEPATH += $${systemc_home}/include
INCLUDEPATH += src/common/third_party/DRAMPower/src
INCLUDEPATH += src/common/third_party/DRAMPower/src/libdrampower
INCLUDEPATH += src/common/third_party/json/include
DEFINES += TIXML_USE_STL
DEFINES += SC_INCLUDE_DYNAMIC_PROCESSES
@@ -119,7 +120,9 @@ SOURCES += \
src/error/eccbaseclass.cpp \
src/error/ecchamming.cpp \
src/controller/scheduler/Fr_Fcfs_read_priority.cpp \
src/controller/scheduler/Fr_Fcfs_grouper.cpp
src/controller/scheduler/Fr_Fcfs_grouper.cpp \
src/common/AddressDecoder.cpp \
src/common/jsonAddressDecoder.cpp
HEADERS += \
src/common/third_party/tinyxml2/tinyxml2.h \
@@ -192,7 +195,10 @@ HEADERS += \
src/controller/scheduler/Fr_Fcfs_read_priority.h \
src/controller/scheduler/Fr_Fcfs_grouper.h \
src/simulation/IArbiter.h \
src/simulation/SimpleArbiter.h
src/simulation/SimpleArbiter.h \
src/common/AddressDecoder.h \
src/common/jsonAddressDecoder.h
#src/common/third_party/json/include/nlohmann/json.hpp \
thermalsim = $$(THERMALSIM)
isEmpty(thermalsim) {

View File

@@ -0,0 +1,45 @@
{
"Config": {
"numberOfBankBits": 3,
"numberOfRowBits": 14,
"numberOfColumnBits": 10,
"numberOfByteBits": 3,
"numberOfBLBits": 3
},
"Name": "merged_sorted",
"Solutions": [
{
"XOR": [
],
"Banks Rows": [
{
"bank_bits": [
27,
28,
29
],
"rows": {
"row_bits": [
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26
],
"costs": 477468
},
"costs": 477468
}
]
}
]
}

View File

@@ -32,6 +32,7 @@ OTHER_FILES += resources/scripts/DRAMSylva/README
OTHER_FILES += resources/scripts/DRAMSylva/DRAMSylva.patch
OTHER_FILES += resources/scripts/DRAMSylva/DRAMSylva.sh
OTHER_FILES += resources/scripts/DRAMSylva/DRAMSylvaCSVPlot.py
OTHER_FILES += resources/scripts/trace_gen.py
# Trace Files
OTHER_FILES += resources/traces/chstone-aes_32.stl
@@ -173,4 +174,5 @@ DISTFILES += \
$$PWD/simulations/lpddr4-single-device.xml \
$$PWD/configs/amconfigs/am_lpddr4.xml \
$$PWD/configs/memspecs/MICRON_6Gb_LPDDR4-3200_NDA_NDA_NDA.xml \
$$PWD/scripts/traceGenerationForNNTraining.pl
$$PWD/scripts/traceGenerationForNNTraining.pl \
$$PWD/configs/amconfigs/am_test_congen_output.json

View File

@@ -0,0 +1,137 @@
#! /usr/bin/env python3
# vim: set fileencoding=utf-8
# Copyright (c) 2018, University of Kaiserslautern
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Author: Éder F. Zulian
import ctypes
# A trace file is a pre-recorded file containing memory transactions. Each
# memory transaction has a timestamp that tells the simulator when it shall
# happen, a transaction type (read or write) and a memory address given in
# hexadecimal.
#
# Here is an example syntax:
#
# ```
# # Comment lines begin with #
# # [clock-cyle]: [write|read] [hex-address]
# 31: read 0x400140
# 33: read 0x400160
# 56: write 0x7fff8000
# 81: read 0x400180
# ```
#
# The timestamp corresponds to the time the request is to be issued and it is
# given in cycles of the bus master device. Example: the device is a FPGA with
# frequency 200 MHz (clock period of 5 ns). If the timestamp is 10 it means
# that the request is to be issued when time is 50 ns.
#
# The default values given as example assume the following address mapping:
#
# DIMM Characteristics:
# Byte Offset (Y): 8 [0:2] (8-byte-wide memory module, i.e., 64-bit-wide data bus) -> 3 bit
# Cols (C): 1K [3:12] (A0 - A9) -> 10 bit
# Rows (R): 128K [13:29] (A0 - A16) -> 17 bit
# Bank (B): 8 [30:32] (BA0 - BA2) -> 3 bit
#
# 3 3 3 | 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 | 1 1 1
# 2 1 0 | 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 | 2 1 0 9 8 7 6 5 4 3 | 2 1 0
# B B B | R R R R R R R R R R R R R R R R R | C C C C C C C C C C | Y Y Y
#
# Transaction type (read or write)
transaction = 'read'
# Channel information. If your address mapping does not have channel bits keep
# it equal to 1 and set the shift to the extreme left of the address.
num_ch = 1 # Number of channels
ch_shift = 34 # Shift to reach the frist bit reserved for channels in the address
ch_mask = 0x1 # Mask for all channel bits in the address
# Bank group information. If your address mapping does not have bank groups
# keep it equal to 1 and set the shift to the extreme left of the address.
num_bank_groups = 1 # Number of bank groups
bgroup_shift = 33 # Shift to reach the frist bit reserved for bank groups in the address
bgroup_mask = 0x1 # Mask for all bits in the address related to bank groups
# Bank information
num_banks = 8 # Number of banks
bank_shift = 30 # Shift to reach the frist bit reserved for banks in the address
bank_mask = 0x7 # Mask for all bank bits in the address
# Row information
num_rows = 128 * 1024 # Number of rows
row_shift = 13 # Shift to reach the frist bit reserved for rows in the address
row_mask = 0x1ffff # Mask for all row bits in the address
# Column information
num_col = 1 * 1024 # Number of columns
col_shift = 3 # Shift to reach the frist bit reserved for columns in the address
col_mask = 0x3ff # Mask for all column bits in the address
# Burst length of 8 columns. 8 columns written/read per access (in 4 full
# clock cycles of the memory bus).
burst_len = 8
# Initial clock cycle
clock_cycle = 0
# Clock cycle increment between two accesses
clock_increment = 10
def clear_bits(mask, shift, val):
m = ctypes.c_uint64(~(mask << shift)).value
return ctypes.c_uint64(val & m).value
def set_bits(mask, shift, val, v):
val = clear_bits(mask, shift, val)
return ctypes.c_uint64(val | (v << shift)).value
address = 0
for ch in range(0, num_ch):
address = set_bits(ch_mask, ch_shift, address, ch)
for bg in range(0, num_bank_groups):
address = set_bits(bgroup_mask, bgroup_shift, address, bg)
for b in range(0, num_banks):
address = set_bits(bank_mask, bank_shift, address, b)
for row in range(0, num_rows):
address = set_bits(row_mask, row_shift, address, row)
for col in range(0, num_col, burst_len):
address = set_bits(col_mask, col_shift, address, col)
print('# clock cycle: {0:d} | {1} | address: 0x{2:010X} | channel: {3} | bank group: {4} | bank: {5} | row: {6} | column: {7}'.format(clock_cycle, transaction, address, ch, bg, b, row, col))
print('{0:d}:\t{1}\t0x{2:010X}'.format(clock_cycle, transaction, address))
clock_cycle = clock_cycle + clock_increment

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2018, University of Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Johannes Feldmann
*/
#include "AddressDecoder.h"
#include "xmlAddressdecoder.h"
#include "jsonAddressDecoder.h"
AddressDecoder *AddressDecoder::m_pInstance = nullptr;
AddressDecoder &AddressDecoder::getInstance()
{
assert(m_pInstance != nullptr);
return *m_pInstance;
}
void AddressDecoder::createInstance(Type t)
{
assert(m_pInstance == nullptr);
switch (t) {
case Type::XML:
m_pInstance = new xmlAddressDecoder;
break;
case Type::JSON:
m_pInstance = new JSONAddressDecoder;
break;
default:
throw std::logic_error("Instance type not supported.");
break;
}
}
AddressDecoder::AddressDecoder()
{
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2018, University of Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Johannes Feldmann
*/
#ifndef ADDRESSDECODER_H
#define ADDRESSDECODER_H
#include <tlm.h>
#include <iostream>
#include <sstream>
#include <string>
#include <map>
struct DecodedAddress {
DecodedAddress() : channel(0),
rank(0),
bankgroup(0),
row(0),
bank(0),
column(0),
bytes(0)
{
}
unsigned int channel;
unsigned int rank;
unsigned int bankgroup;
unsigned int row;
unsigned int bank;
unsigned int column;
unsigned int bytes;
};
class AddressDecoder
{
public:
enum class Type {
XML,
JSON
};
protected:
AddressDecoder();
static AddressDecoder *m_pInstance;
public:
static AddressDecoder &getInstance();
static void createInstance(Type t);
virtual void setConfiguration(std::string url) = 0;
virtual DecodedAddress decodeAddress(sc_dt::uint64 addr) = 0;
virtual sc_dt::uint64 encodeAddress(DecodedAddress n) = 0;
virtual void print() = 0;
std::map<std::string, unsigned int> amount;
};
#endif // ADDRESSDECODER_H

View File

@@ -40,37 +40,38 @@ using namespace std;
void DebugManager::printDebugMessage(string sender, string message)
{
if(Configuration::getInstance().Debug)
{
if (Configuration::getInstance().Debug) {
if (writeToConsole)
cout << " at " << sc_time_stamp() << "\t in " << sender << "\t: " << message << endl;
cout << " at " << sc_time_stamp() << "\t in " << sender << "\t: " << message <<
endl;
if (writeToFile && debugFile)
debugFile << " at " << sc_time_stamp() << " in " << sender << "\t: " << message << "\n";
debugFile << " at " << sc_time_stamp() << " in " << sender << "\t: " << message
<< "\n";
}
}
void DebugManager::printMessage(string sender, string message)
{
cout << " at " << sc_time_stamp() << "\t in " << sender << "\t: " << message << endl;
cout << " at " << sc_time_stamp() << "\t in " << sender << "\t: " << message <<
endl;
}
void DebugManager::openDebugFile(string filename)
{
if(debugFile)
if (debugFile)
debugFile.close();
debugFile.open(filename);
}
DebugManager::DebugManager() :
writeToConsole(true), writeToFile(true)
writeToConsole(true), writeToFile(true)
{
}
DebugManager::~DebugManager()
{
if (writeToFile)
{
if (writeToFile) {
debugFile.flush();
debugFile.close();
}

View File

@@ -58,7 +58,7 @@ public:
private:
DebugManager();
DebugManager(const DebugManager&){}
DebugManager(const DebugManager &) {}
ofstream debugFile;
};

View File

@@ -48,13 +48,16 @@
using namespace std;
TlmRecorder::TlmRecorder(sc_module_name /*name*/, string uri, string dbname, bool recenable) : sqlScriptURI(uri), dbName(dbname), recordingEnabled(recenable), totalNumTransactions(1), simulationTimeCoveredByRecording(SC_ZERO_TIME)
TlmRecorder::TlmRecorder(sc_module_name /*name*/, string uri, string dbname,
bool recenable) : sqlScriptURI(uri), dbName(dbname),
recordingEnabled(recenable), totalNumTransactions(1),
simulationTimeCoveredByRecording(SC_ZERO_TIME)
{
if (TlmRecorder::recordingEnabled == true) {
recordedData.reserve(transactionCommitRate);
setUpTransactionTerminatingPhases();
openDB(TlmRecorder::dbName.c_str());
char * sErrMsg;
char *sErrMsg;
sqlite3_exec(db, "PRAGMA main.page_size = 4096", NULL, NULL, &sErrMsg);
sqlite3_exec(db, "PRAGMA main.cache_size=10000", NULL, NULL, &sErrMsg);
sqlite3_exec(db, "PRAGMA main.locking_mode=EXCLUSIVE", NULL, NULL, &sErrMsg);
@@ -72,16 +75,6 @@ TlmRecorder::~TlmRecorder()
{
if (db)
closeConnection();
sqlite3_finalize(insertTransactionStatement);
sqlite3_finalize(insertRangeStatement);
sqlite3_finalize(updateRangeStatement);
sqlite3_finalize(insertPhaseStatement);
sqlite3_finalize(updatePhaseStatement);
sqlite3_finalize(insertGeneralInfoStatement);
sqlite3_finalize(insertDebugMessageStatement);
sqlite3_finalize(updateDataStrobeStatement);
sqlite3_finalize(insertPowerStatement);
}
void TlmRecorder::recordPower(double timeInSeconds, double averagePower)
@@ -93,10 +86,10 @@ void TlmRecorder::recordPower(double timeInSeconds, double averagePower)
}
}
void TlmRecorder::recordPhase(tlm::tlm_generic_payload& trans, tlm::tlm_phase phase, sc_time time)
void TlmRecorder::recordPhase(tlm::tlm_generic_payload &trans,
tlm::tlm_phase phase, sc_time time)
{
if(TlmRecorder::recordingEnabled)
{
if (TlmRecorder::recordingEnabled) {
if (currentTransactionsInSystem.count(&trans) == 0)
introduceTransactionSystem(trans);
@@ -104,17 +97,14 @@ void TlmRecorder::recordPhase(tlm::tlm_generic_payload& trans, tlm::tlm_phase ph
string phaseBeginPrefix = "BEGIN_";
string phaseEndPrefix = "END_";
if (phaseName.find(phaseBeginPrefix) != string::npos)
{
if (phaseName.find(phaseBeginPrefix) != string::npos) {
phaseName.erase(0, phaseBeginPrefix.length());
assert(currentTransactionsInSystem.count(&trans) != 0);
currentTransactionsInSystem[&trans].insertPhase(phaseName,time);
}
else
{
currentTransactionsInSystem[&trans].insertPhase(phaseName, time);
} else {
phaseName.erase(0, phaseEndPrefix.length());
assert(currentTransactionsInSystem.count(&trans) != 0);
currentTransactionsInSystem[&trans].setPhaseEnd(phaseName,time);
currentTransactionsInSystem[&trans].setPhaseEnd(phaseName, time);
}
bool phaseTerminatesTransaction = count(transactionTerminatingPhases.begin(),
@@ -127,10 +117,10 @@ void TlmRecorder::recordPhase(tlm::tlm_generic_payload& trans, tlm::tlm_phase ph
}
void TlmRecorder::updateDataStrobe(const sc_time& begin,const sc_time& end, tlm::tlm_generic_payload& trans)
void TlmRecorder::updateDataStrobe(const sc_time &begin, const sc_time &end,
tlm::tlm_generic_payload &trans)
{
if(TlmRecorder::recordingEnabled)
{
if (TlmRecorder::recordingEnabled) {
assert(currentTransactionsInSystem.count(&trans) != 0);
currentTransactionsInSystem[&trans].timeOnDataStrobe.start = begin;
currentTransactionsInSystem[&trans].timeOnDataStrobe.end = end;
@@ -140,44 +130,48 @@ void TlmRecorder::updateDataStrobe(const sc_time& begin,const sc_time& end, tlm:
void TlmRecorder::recordDebugMessage(std::string message, sc_time time)
{
if(TlmRecorder::recordingEnabled)
if (TlmRecorder::recordingEnabled)
insertDebugMessageInDB(message, time);
}
// ------------- internal -----------------------
void TlmRecorder::introduceTransactionSystem(tlm::tlm_generic_payload& trans)
void TlmRecorder::introduceTransactionSystem(tlm::tlm_generic_payload &trans)
{
unsigned int id = totalNumTransactions++;
currentTransactionsInSystem[&trans].id = id;
currentTransactionsInSystem[&trans].address = trans.get_address();
currentTransactionsInSystem[&trans].burstlength = trans.get_streaming_width();
currentTransactionsInSystem[&trans].dramExtension = DramExtension::getExtension(trans);
currentTransactionsInSystem[&trans].dramExtension = DramExtension::getExtension(
trans);
if(DramExtension::getExtension(trans).getThread().ID() == Controller::ControllerThreadId())
if (DramExtension::getExtension(trans).getThread().ID() ==
Controller::ControllerThreadId())
currentTransactionsInSystem[&trans].timeOfGeneration = SC_ZERO_TIME;
else
currentTransactionsInSystem[&trans].timeOfGeneration = GenerationExtension::getExtension(&trans).TimeOfGeneration();
currentTransactionsInSystem[&trans].timeOfGeneration =
GenerationExtension::getExtension(&trans).TimeOfGeneration();
printDebugMessage("New transaction #" + to_string(id) + " generation time " + currentTransactionsInSystem[&trans].timeOfGeneration.to_string());
printDebugMessage("New transaction #" + to_string(id) + " generation time " +
currentTransactionsInSystem[&trans].timeOfGeneration.to_string());
if (id % transactionCommitRate == 0)
{
if (id % transactionCommitRate == 0) {
printDebugMessage(
"Committing transactions " + to_string(id - transactionCommitRate + 1) + " - "
+ to_string(id));
"Committing transactions " + to_string(id - transactionCommitRate + 1) + " - "
+ to_string(id));
commitRecordedDataToDB();
}
}
void TlmRecorder::removeTransactionFromSystem(tlm::tlm_generic_payload& trans)
void TlmRecorder::removeTransactionFromSystem(tlm::tlm_generic_payload &trans)
{
assert(currentTransactionsInSystem.count(&trans) != 0);
printDebugMessage("Removing transaction #" + to_string(currentTransactionsInSystem[&trans].id));
printDebugMessage("Removing transaction #" + to_string(
currentTransactionsInSystem[&trans].id));
Transaction& recordingData = currentTransactionsInSystem[&trans];
Transaction &recordingData = currentTransactionsInSystem[&trans];
recordedData.push_back(recordingData);
currentTransactionsInSystem.erase(&trans);
}
@@ -185,18 +179,17 @@ void TlmRecorder::removeTransactionFromSystem(tlm::tlm_generic_payload& trans)
void TlmRecorder::commitRecordedDataToDB()
{
sqlite3_exec(db, "BEGIN;", 0, 0, 0);
for(Transaction& recordingData: recordedData)
{
for (Transaction &recordingData : recordedData) {
assert(recordingData.recordedPhases.size() > 0);
insertTransactionInDB(recordingData);
for(Transaction::Phase& phaseData: recordingData.recordedPhases)
{
insertPhaseInDB(phaseData.name,phaseData.interval.start,phaseData.interval.end,recordingData.id);
for (Transaction::Phase &phaseData : recordingData.recordedPhases) {
insertPhaseInDB(phaseData.name, phaseData.interval.start,
phaseData.interval.end, recordingData.id);
}
sc_time rangeBegin = recordingData.recordedPhases.front().interval.start;
sc_time rangeEnd = recordingData.recordedPhases.back().interval.end;
insertRangeInDB(recordingData.id,rangeBegin,rangeEnd);
insertRangeInDB(recordingData.id, rangeBegin, rangeEnd);
}
sqlite3_exec(db, "COMMIT;", 0, 0, 0);
@@ -206,7 +199,7 @@ void TlmRecorder::commitRecordedDataToDB()
void TlmRecorder::Transaction::insertPhase(string name, sc_time begin)
{
recordedPhases.push_back(Phase(name,begin));
recordedPhases.push_back(Phase(name, begin));
}
void TlmRecorder::Transaction::setPhaseEnd(string name, sc_time end)
@@ -214,32 +207,28 @@ void TlmRecorder::Transaction::setPhaseEnd(string name, sc_time end)
// Find the latest recorder phase for that transaction with a matching name and update it
// Note: Transaction have the same phase multiple times (e.g. PRE->ACT->REF->ACT->RD) only update the latest
// one that has been recorder
for(int i = recordedPhases.size() - 1; i >= 0;i--)
{
Phase& data = recordedPhases[i];
if(data.name == name)
{
for (int i = recordedPhases.size() - 1; i >= 0; i--) {
Phase &data = recordedPhases[i];
if (data.name == name) {
data.interval.end = end;
return;
}
}
SC_REPORT_FATAL("Recording Error", "While trying to set phase end: phaseBegin has not been recorded");
SC_REPORT_FATAL("Recording Error",
"While trying to set phase end: phaseBegin has not been recorded");
}
void TlmRecorder::openDB(std::string name)
{
ifstream f(name.c_str());
if(f.good())
{
if(remove(name.c_str()) != 0)
{
SC_REPORT_FATAL("TlmRecorder", "Error deleting file" );
if (f.good()) {
if (remove(name.c_str()) != 0) {
SC_REPORT_FATAL("TlmRecorder", "Error deleting file" );
}
}
if (sqlite3_open(name.c_str(), &db) != SQLITE_OK)
{
if (sqlite3_open(name.c_str(), &db) != SQLITE_OK) {
SC_REPORT_FATAL("Error in TraceRecorder", "Error cannot open database");
sqlite3_close(db);
}
@@ -257,117 +246,152 @@ void TlmRecorder::setUpTransactionTerminatingPhases()
transactionTerminatingPhases.push_back(tlm::END_RESP);
// Refresh All
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>(END_REFA));
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>
(END_REFA));
// Refresh Bank
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>(END_REFB));
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>
(END_REFB));
// Phases for Power Down
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>(END_PDNA));
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>(END_PDNP));
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>(END_SREF));
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>
(END_PDNA));
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>
(END_PDNP));
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>
(END_SREF));
// Phases for Power Down Bankwise
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>(END_PDNAB));
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>(END_PDNPB));
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>(END_SREFB));
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>
(END_PDNAB));
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>
(END_PDNPB));
transactionTerminatingPhases.push_back(static_cast<const tlm::tlm_phase>
(END_SREFB));
}
void TlmRecorder::prepareSqlStatements()
{
insertTransactionString =
"INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:bank,:bankgroup,:row,:column,:dataStrobeBegin,:dataStrobeEnd, :timeOfGeneration,:command)";
"INSERT INTO Transactions VALUES (:id,:rangeID,:address,:burstlength,:thread,:channel,:bank,:bankgroup,:row,:column,:dataStrobeBegin,:dataStrobeEnd, :timeOfGeneration,:command)";
insertRangeString = "INSERT INTO Ranges VALUES (:id,:begin,:end)";
updateRangeString = "UPDATE Ranges SET End = :end WHERE ID = :id";
updateDataStrobeString = "UPDATE Transactions SET DataStrobeBegin = :begin, DataStrobeEnd = :end WHERE ID = :id";
updateDataStrobeString =
"UPDATE Transactions SET DataStrobeBegin = :begin, DataStrobeEnd = :end WHERE ID = :id";
insertPhaseString =
"INSERT INTO Phases (PhaseName,PhaseBegin,PhaseEnd,Transact) VALUES (:name,:begin,:end,:transaction)";
"INSERT INTO Phases (PhaseName,PhaseBegin,PhaseEnd,Transact) VALUES (:name,:begin,:end,:transaction)";
updatePhaseString =
"UPDATE Phases SET PhaseEnd = :end WHERE Transact = :trans AND PhaseName = :name";
"UPDATE Phases SET PhaseEnd = :end WHERE Transact = :trans AND PhaseName = :name";
insertGeneralInfoString =
"INSERT INTO GeneralInfo (NumberOfTransactions,TraceEnd,NumberOfBanks,clk,UnitOfTime,MCconfig,Memspec,Traces, WindowSize, FlexibleRefresh, MaxRefBurst, ControllerThread) VALUES"
"(:numberOfTransactions,:end,:numberOfBanks,:clk,:unitOfTime,:mcconfig,:memspec,:traces,:windowSize, :flexibleRefresh, :maxRefBurst, :controllerThread)";
insertDebugMessageString = "INSERT INTO DebugMessages (Time,Message) Values (:time,:message)";
"INSERT INTO GeneralInfo (NumberOfTransactions,TraceEnd,NumberOfBanks,clk,UnitOfTime,MCconfig,Memspec,Traces, WindowSize, FlexibleRefresh, MaxRefBurst, ControllerThread) VALUES"
"(:numberOfTransactions,:end,:numberOfBanks,:clk,:unitOfTime,:mcconfig,:memspec,:traces,:windowSize, :flexibleRefresh, :maxRefBurst, :controllerThread)";
insertDebugMessageString =
"INSERT INTO DebugMessages (Time,Message) Values (:time,:message)";
insertPowerString = "INSERT INTO Power VALUES (:time,:averagePower)";
sqlite3_prepare_v2(db, insertTransactionString.c_str(), -1, &insertTransactionStatement, 0);
sqlite3_prepare_v2(db, insertTransactionString.c_str(), -1,
&insertTransactionStatement, 0);
sqlite3_prepare_v2(db, insertRangeString.c_str(), -1, &insertRangeStatement, 0);
sqlite3_prepare_v2(db, updateRangeString.c_str(), -1, &updateRangeStatement, 0);
sqlite3_prepare_v2(db, insertPhaseString.c_str(), -1, &insertPhaseStatement, 0);
sqlite3_prepare_v2(db, updatePhaseString.c_str(), -1, &updatePhaseStatement, 0);
sqlite3_prepare_v2(db, updateDataStrobeString.c_str(), -1, &updateDataStrobeStatement, 0);
sqlite3_prepare_v2(db, insertGeneralInfoString.c_str(), -1, &insertGeneralInfoStatement, 0);
sqlite3_prepare_v2(db, insertDebugMessageString.c_str(), -1, &insertDebugMessageStatement, 0);
sqlite3_prepare_v2(db, updateDataStrobeString.c_str(), -1,
&updateDataStrobeStatement, 0);
sqlite3_prepare_v2(db, insertGeneralInfoString.c_str(), -1,
&insertGeneralInfoStatement, 0);
sqlite3_prepare_v2(db, insertDebugMessageString.c_str(), -1,
&insertDebugMessageStatement, 0);
sqlite3_prepare_v2(db, insertPowerString.c_str(), -1, &insertPowerStatement, 0);
}
void TlmRecorder::insertDebugMessageInDB(string message, const sc_time& time)
void TlmRecorder::insertDebugMessageInDB(string message, const sc_time &time)
{
sqlite3_bind_int64(insertDebugMessageStatement, 1, time.value());
sqlite3_bind_text(insertDebugMessageStatement, 2, message.c_str(), message.length(), 0);
sqlite3_bind_text(insertDebugMessageStatement, 2, message.c_str(),
message.length(), 0);
executeSqlStatement(insertDebugMessageStatement);
}
void TlmRecorder::insertGeneralInfo()
{
sqlite3_bind_int64(insertGeneralInfoStatement, 1, totalNumTransactions - 1);
sqlite3_bind_int64(insertGeneralInfoStatement, 2, simulationTimeCoveredByRecording.value());
sqlite3_bind_int64(insertGeneralInfoStatement, 2,
simulationTimeCoveredByRecording.value());
sqlite3_bind_int(insertGeneralInfoStatement, 3,
Configuration::getInstance().memSpec.NumberOfBanks);
sqlite3_bind_int(insertGeneralInfoStatement, 4, Configuration::getInstance().memSpec.clk.value());
sqlite3_bind_int(insertGeneralInfoStatement, 4,
Configuration::getInstance().memSpec.clk.value());
sqlite3_bind_text(insertGeneralInfoStatement, 5, "PS", 2, NULL);
sqlite3_bind_text(insertGeneralInfoStatement, 6, mcconfig.c_str(), mcconfig.length(), NULL);
sqlite3_bind_text(insertGeneralInfoStatement, 7, memspec.c_str(), memspec.length(), NULL);
sqlite3_bind_text(insertGeneralInfoStatement, 8, traces.c_str(), traces.length(), NULL);
sqlite3_bind_text(insertGeneralInfoStatement, 6, mcconfig.c_str(),
mcconfig.length(), NULL);
sqlite3_bind_text(insertGeneralInfoStatement, 7, memspec.c_str(),
memspec.length(), NULL);
sqlite3_bind_text(insertGeneralInfoStatement, 8, traces.c_str(),
traces.length(), NULL);
if (!Configuration::getInstance().EnableWindowing)
sqlite3_bind_int64(insertGeneralInfoStatement, 9, 0);
else
sqlite3_bind_int64(insertGeneralInfoStatement, 9, (Configuration::getInstance().memSpec.clk*Configuration::getInstance().WindowSize).value());
if (Configuration::getInstance().ControllerCoreEnableRefPostpone || Configuration::getInstance().ControllerCoreEnableRefPullIn)
{
sqlite3_bind_int(insertGeneralInfoStatement, 10, 1);
sqlite3_bind_int(insertGeneralInfoStatement, 11, std::max(Configuration::getInstance().ControllerCoreMaxPulledInARCmd, Configuration::getInstance().ControllerCoreMaxPostponedARCmd));
sqlite3_bind_int64(insertGeneralInfoStatement, 9,
(Configuration::getInstance().memSpec.clk *
Configuration::getInstance().WindowSize).value());
if (Configuration::getInstance().ControllerCoreEnableRefPostpone
|| Configuration::getInstance().ControllerCoreEnableRefPullIn) {
sqlite3_bind_int(insertGeneralInfoStatement, 10, 1);
sqlite3_bind_int(insertGeneralInfoStatement, 11,
std::max(Configuration::getInstance().ControllerCoreMaxPulledInARCmd,
Configuration::getInstance().ControllerCoreMaxPostponedARCmd));
} else {
sqlite3_bind_int(insertGeneralInfoStatement, 10, 0);
sqlite3_bind_int(insertGeneralInfoStatement, 11, 0);
}
else
{
sqlite3_bind_int(insertGeneralInfoStatement, 10, 0);
sqlite3_bind_int(insertGeneralInfoStatement, 11, 0);
}
sqlite3_bind_int(insertGeneralInfoStatement, 12, Controller::ControllerThreadId()); ;
sqlite3_bind_int(insertGeneralInfoStatement, 12,
Controller::ControllerThreadId()); ;
executeSqlStatement(insertGeneralInfoStatement);
}
void TlmRecorder::insertTransactionInDB(Transaction& recordingData)
void TlmRecorder::insertTransactionInDB(Transaction &recordingData)
{
sqlite3_bind_int(insertTransactionStatement, 1, recordingData.id);
sqlite3_bind_int(insertTransactionStatement, 2, recordingData.id);
sqlite3_bind_int(insertTransactionStatement, 3, recordingData.address);
sqlite3_bind_int(insertTransactionStatement, 4, recordingData.burstlength);
sqlite3_bind_int(insertTransactionStatement, 5, recordingData.dramExtension.getThread().ID());
sqlite3_bind_int(insertTransactionStatement, 6, recordingData.dramExtension.getChannel().ID());
sqlite3_bind_int(insertTransactionStatement, 7, recordingData.dramExtension.getBank().ID());
sqlite3_bind_int(insertTransactionStatement, 8, recordingData.dramExtension.getBankGroup().ID());
sqlite3_bind_int(insertTransactionStatement, 9, recordingData.dramExtension.getRow().ID());
sqlite3_bind_int(insertTransactionStatement, 10, recordingData.dramExtension.getColumn().ID());
sqlite3_bind_int64(insertTransactionStatement, 11, recordingData.timeOnDataStrobe.start.value());
sqlite3_bind_int64(insertTransactionStatement, 12, recordingData.timeOnDataStrobe.end.value());
sqlite3_bind_int64(insertTransactionStatement, 13, recordingData.timeOfGeneration.value());
sqlite3_bind_int(insertTransactionStatement, 5,
recordingData.dramExtension.getThread().ID());
sqlite3_bind_int(insertTransactionStatement, 6,
recordingData.dramExtension.getChannel().ID());
sqlite3_bind_int(insertTransactionStatement, 7,
recordingData.dramExtension.getBank().ID());
sqlite3_bind_int(insertTransactionStatement, 8,
recordingData.dramExtension.getBankGroup().ID());
sqlite3_bind_int(insertTransactionStatement, 9,
recordingData.dramExtension.getRow().ID());
sqlite3_bind_int(insertTransactionStatement, 10,
recordingData.dramExtension.getColumn().ID());
sqlite3_bind_int64(insertTransactionStatement, 11,
recordingData.timeOnDataStrobe.start.value());
sqlite3_bind_int64(insertTransactionStatement, 12,
recordingData.timeOnDataStrobe.end.value());
sqlite3_bind_int64(insertTransactionStatement, 13,
recordingData.timeOfGeneration.value());
executeSqlStatement(insertTransactionStatement);
}
void TlmRecorder::insertRangeInDB(unsigned int id, const sc_time& begin, const sc_time& end)
void TlmRecorder::insertRangeInDB(unsigned int id, const sc_time &begin,
const sc_time &end)
{
sqlite3_bind_int(insertRangeStatement, 1, id);
sqlite3_bind_int64(insertRangeStatement, 2, begin.value());
sqlite3_bind_int64(insertRangeStatement, 3, end.value());
executeSqlStatement(insertRangeStatement);
}
void TlmRecorder::insertPhaseInDB(string phaseName, const sc_time& begin, const sc_time& end,
void TlmRecorder::insertPhaseInDB(string phaseName, const sc_time &begin,
const sc_time &end,
unsigned int transactionID)
{
sqlite3_bind_text(insertPhaseStatement, 1, phaseName.c_str(), phaseName.length(), 0);
sqlite3_bind_text(insertPhaseStatement, 1, phaseName.c_str(),
phaseName.length(), 0);
sqlite3_bind_int64(insertPhaseStatement, 2, begin.value());
sqlite3_bind_int64(insertPhaseStatement, 3, end.value());
sqlite3_bind_int(insertPhaseStatement, 4, transactionID);
@@ -375,12 +399,12 @@ void TlmRecorder::insertPhaseInDB(string phaseName, const sc_time& begin, const
}
void TlmRecorder::executeSqlStatement(sqlite3_stmt* statement)
void TlmRecorder::executeSqlStatement(sqlite3_stmt *statement)
{
int errorCode = sqlite3_step(statement);
if (errorCode != SQLITE_DONE)
{
reportFatal("Error in TraceRecorder", string("Could not execute statement. Error code: ") + to_string(errorCode));
if (errorCode != SQLITE_DONE) {
reportFatal("Error in TraceRecorder",
string("Could not execute statement. Error code: ") + to_string(errorCode));
}
sqlite3_reset(statement);
}
@@ -389,10 +413,9 @@ void TlmRecorder::executeSqlCommand(string command)
{
printDebugMessage("Creating database by running provided sql script");
char * errMsg = 0;
char *errMsg = 0;
int rc = sqlite3_exec(db, command.c_str(), NULL, 0, &errMsg);
if (rc != SQLITE_OK)
{
if (rc != SQLITE_OK) {
SC_REPORT_FATAL("SQLITE Error", errMsg);
sqlite3_free(errMsg);
}
@@ -407,13 +430,22 @@ void TlmRecorder::printDebugMessage(std::string message)
void TlmRecorder::closeConnection()
{
if(TlmRecorder::recordingEnabled)
{
if (TlmRecorder::recordingEnabled) {
commitRecordedDataToDB();
insertGeneralInfo();
printDebugMessage(
"Number of transactions written to DB: " + std::to_string(totalNumTransactions - 1));
"Number of transactions written to DB: " + std::to_string(
totalNumTransactions - 1));
printDebugMessage("tlmPhaseRecorder:\tEnd Recording");
sqlite3_finalize(insertTransactionStatement);
sqlite3_finalize(insertRangeStatement);
sqlite3_finalize(updateRangeStatement);
sqlite3_finalize(insertPhaseStatement);
sqlite3_finalize(updatePhaseStatement);
sqlite3_finalize(insertGeneralInfoStatement);
sqlite3_finalize(insertDebugMessageStatement);
sqlite3_finalize(updateDataStrobeStatement);
sqlite3_finalize(insertPowerStatement);
sqlite3_close(db);
db = NULL;
}

View File

@@ -55,7 +55,8 @@
using namespace std;
class TlmRecorder : public sc_module {
class TlmRecorder : public sc_module
{
public:
std::string sqlScriptURI;
std::string dbName;
@@ -64,22 +65,32 @@ public:
TlmRecorder(sc_module_name /*name*/, string uri, string dbname, bool recenable);
~TlmRecorder();
void recordMCconfig(string mcconfig){this->mcconfig = mcconfig;}
void recordMemspec(string memspec){this->memspec = memspec;}
void recordTracenames(string traces){this->traces = traces;}
void recordMCconfig(string mcconfig)
{
this->mcconfig = mcconfig;
}
void recordMemspec(string memspec)
{
this->memspec = memspec;
}
void recordTracenames(string traces)
{
this->traces = traces;
}
void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase, sc_time time);
void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase,
sc_time time);
void recordPower(double timeInSeconds, double averagePower);
void recordDebugMessage(std::string message, sc_time time);
void updateDataStrobe(const sc_time& begin, const sc_time& end, tlm::tlm_generic_payload& trans);
void updateDataStrobe(const sc_time &begin, const sc_time &end,
tlm::tlm_generic_payload &trans);
void closeConnection();
private:
struct Transaction
{
Transaction(){}
Transaction(unsigned int id):id(id){}
struct Transaction {
Transaction() {}
Transaction(unsigned int id): id(id) {}
unsigned int id;
unsigned int address;
@@ -88,53 +99,56 @@ private:
sc_time timeOfGeneration;
TimeInterval timeOnDataStrobe;
struct Phase
{
Phase(string name,sc_time begin): name(name), interval(begin,SC_ZERO_TIME){}
struct Phase {
Phase(string name, sc_time begin): name(name), interval(begin, SC_ZERO_TIME) {}
string name;
TimeInterval interval;
};
std::vector<Phase> recordedPhases;
void insertPhase(string name,sc_time begin);
void setPhaseEnd(string name,sc_time end);
void insertPhase(string name, sc_time begin);
void setPhaseEnd(string name, sc_time end);
};
std::string mcconfig,memspec,traces;
std::string mcconfig, memspec, traces;
void prepareSqlStatements();
void executeSqlCommand(std::string command);
void executeSqlStatement(sqlite3_stmt* statement);
void executeSqlStatement(sqlite3_stmt *statement);
void openDB(std::string name);
void createTables(std::string pathToURI);
void setUpTransactionTerminatingPhases();
void introduceTransactionSystem(tlm::tlm_generic_payload& trans);
void removeTransactionFromSystem(tlm::tlm_generic_payload& trans);
void introduceTransactionSystem(tlm::tlm_generic_payload &trans);
void removeTransactionFromSystem(tlm::tlm_generic_payload &trans);
void commitRecordedDataToDB();
void insertGeneralInfo();
void insertTransactionInDB(Transaction& recordingData);
void insertRangeInDB(unsigned int id, const sc_time& begin, const sc_time& end);
void insertPhaseInDB(string phaseName, const sc_time& begin, const sc_time& end, unsigned int transactionID);
void insertDebugMessageInDB(string message, const sc_time& time);
void insertTransactionInDB(Transaction &recordingData);
void insertRangeInDB(unsigned int id, const sc_time &begin, const sc_time &end);
void insertPhaseInDB(string phaseName, const sc_time &begin, const sc_time &end,
unsigned int transactionID);
void insertDebugMessageInDB(string message, const sc_time &time);
void printDebugMessage(std::string message);
static const int transactionCommitRate = 1000;
vector<Transaction> recordedData;
map<tlm::tlm_generic_payload*, Transaction> currentTransactionsInSystem;
map<tlm::tlm_generic_payload *, Transaction> currentTransactionsInSystem;
unsigned int totalNumTransactions;
sc_time simulationTimeCoveredByRecording;
std::vector<tlm::tlm_phase> transactionTerminatingPhases;
sqlite3 *db = NULL;
sqlite3_stmt *insertTransactionStatement, *insertRangeStatement, *updateRangeStatement,
*insertPhaseStatement, *updatePhaseStatement, *insertGeneralInfoStatement, *insertDebugMessageStatement, *updateDataStrobeStatement, *insertPowerStatement;
std::string insertTransactionString, insertRangeString, updateRangeString, insertPhaseString, updatePhaseString, insertGeneralInfoString,
insertDebugMessageString, updateDataStrobeString, insertPowerString;
sqlite3_stmt *insertTransactionStatement, *insertRangeStatement,
*updateRangeStatement,
*insertPhaseStatement, *updatePhaseStatement, *insertGeneralInfoStatement,
*insertDebugMessageStatement, *updateDataStrobeStatement, *insertPowerStatement;
std::string insertTransactionString, insertRangeString, updateRangeString,
insertPhaseString, updatePhaseString, insertGeneralInfoString,
insertDebugMessageString, updateDataStrobeString, insertPowerString;
};
#endif

View File

@@ -52,7 +52,8 @@ bool TimeInterval::timeIsInInterval(sc_time time)
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 getDistance(sc_time a, sc_time b)
@@ -76,17 +77,16 @@ std::string phaseNameToString(tlm::tlm_phase phase)
return str;
}
unsigned int queryUIntParameter(XMLElement* node, string name)
unsigned int queryUIntParameter(XMLElement *node, string name)
{
int result = 0;
XMLElement* element;
XMLElement *element;
for (element = node->FirstChildElement("parameter"); element != NULL;
element = element->NextSiblingElement("parameter"))
{
if (element->Attribute("id") == name)
{
element = element->NextSiblingElement("parameter")) {
if (element->Attribute("id") == name) {
sc_assert(!strcmp(element->Attribute("type"), "uint"));
XMLError __attribute__((unused)) error = element->QueryIntAttribute("value", &result);
XMLError __attribute__((unused)) error = element->QueryIntAttribute("value",
&result);
sc_assert(!error);
return result;
}
@@ -96,31 +96,28 @@ unsigned int queryUIntParameter(XMLElement* node, string name)
return 0;
}
bool parameterExists(tinyxml2::XMLElement* node, std::string name)
bool parameterExists(tinyxml2::XMLElement *node, std::string name)
{
XMLElement* element;
XMLElement *element;
for (element = node->FirstChildElement("parameter"); element != NULL;
element = element->NextSiblingElement("parameter"))
{
if (element->Attribute("id") == name)
{
element = element->NextSiblingElement("parameter")) {
if (element->Attribute("id") == name) {
return true;
}
}
return false;
}
double queryDoubleParameter(XMLElement* node, string name)
double queryDoubleParameter(XMLElement *node, string name)
{
double result = 0;
XMLElement* element;
XMLElement *element;
for (element = node->FirstChildElement("parameter"); element != NULL;
element = element->NextSiblingElement("parameter"))
{
if (element->Attribute("id") == name)
{
element = element->NextSiblingElement("parameter")) {
if (element->Attribute("id") == name) {
sc_assert(!strcmp(element->Attribute("type"), "double"));
XMLError __attribute__((unused)) error = element->QueryDoubleAttribute("value", &result);
XMLError __attribute__((unused)) error = element->QueryDoubleAttribute("value",
&result);
sc_assert(!error);
return result;
}
@@ -130,17 +127,16 @@ double queryDoubleParameter(XMLElement* node, string name)
return 0;
}
bool queryBoolParameter(XMLElement* node, string name)
bool queryBoolParameter(XMLElement *node, string name)
{
bool result = false;
XMLElement* element;// = node->FirstChildElement("parameter");
XMLElement *element;// = node->FirstChildElement("parameter");
for (element = node->FirstChildElement("parameter"); element != NULL;
element = element->NextSiblingElement("parameter"))
{
if (element->Attribute("id") == name)
{
element = element->NextSiblingElement("parameter")) {
if (element->Attribute("id") == name) {
sc_assert(!strcmp(element->Attribute("type"), "bool"));
XMLError __attribute__((unused)) error = element->QueryBoolAttribute("value", &result);
XMLError __attribute__((unused)) error = element->QueryBoolAttribute("value",
&result);
sc_assert(!error);
return result;
}
@@ -150,14 +146,12 @@ bool queryBoolParameter(XMLElement* node, string name)
return 0;
}
string queryStringParameter(XMLElement* node, string name)
string queryStringParameter(XMLElement *node, string name)
{
XMLElement* element;
XMLElement *element;
for (element = node->FirstChildElement("parameter"); element != NULL;
element = element->NextSiblingElement("parameter"))
{
if (element->Attribute("id") == name)
{
element = element->NextSiblingElement("parameter")) {
if (element->Attribute("id") == name) {
return element->Attribute("value");
}
}
@@ -168,36 +162,57 @@ string queryStringParameter(XMLElement* node, string name)
string errorToString(XMLError error)
{
switch(error){
case XML_NO_ERROR: return "no error"; case XML_NO_ATTRIBUTE: return "NO_ATTRIBUTE";
case XML_WRONG_ATTRIBUTE_TYPE: return "WRONG_ATTRIBUTE_TYPE";
case XML_ERROR_FILE_NOT_FOUND: return "FILE_NOT_FOUND";
case XML_ERROR_FILE_COULD_NOT_BE_OPENED: return "FILE_COULD_NOT_BE_OPENED";
case XML_ERROR_FILE_READ_ERROR: return "FILE_READ_ERROR";
case XML_ERROR_ELEMENT_MISMATCH: return "ERROR_ELEMENT_MISMATCH";
case XML_ERROR_PARSING_ELEMENT: return "ERROR_PARSING_ELEMENT";
case XML_ERROR_PARSING_ATTRIBUTE: return "ERROR_PARSING_ATTRIBUTE";
case XML_ERROR_IDENTIFYING_TAG: return "ERROR_IDENTIFYING_TAG";
case XML_ERROR_PARSING_TEXT: return "ERROR_PARSING_TEXT";
case XML_ERROR_PARSING_CDATA: return "ERROR_PARSING_CDATA";
case XML_ERROR_PARSING_COMMENT: return "ERROR_PARSING_COMMENT";
case XML_ERROR_PARSING_DECLARATION: return "ERROR_PARSING_DECLARATION";
case XML_ERROR_PARSING_UNKNOWN: return "ERROR_PARSING_UNKNOWN";
case XML_ERROR_EMPTY_DOCUMENT: return "ERROR_EMPTY_DOCUMENT";
case XML_ERROR_MISMATCHED_ELEMENT: return "ERROR_MISMATCHED_ELEMENT";
case XML_ERROR_PARSING: return "ERROR_PARSING";
case XML_CAN_NOT_CONVERT_TEXT: return "CAN_NOT_CONVERT_TEXT";
case XML_NO_TEXT_NODE: return "NO_TEXT_NODE";
default: return "";
switch (error) {
case XML_NO_ERROR:
return "no error";
case XML_NO_ATTRIBUTE:
return "NO_ATTRIBUTE";
case XML_WRONG_ATTRIBUTE_TYPE:
return "WRONG_ATTRIBUTE_TYPE";
case XML_ERROR_FILE_NOT_FOUND:
return "FILE_NOT_FOUND";
case XML_ERROR_FILE_COULD_NOT_BE_OPENED:
return "FILE_COULD_NOT_BE_OPENED";
case XML_ERROR_FILE_READ_ERROR:
return "FILE_READ_ERROR";
case XML_ERROR_ELEMENT_MISMATCH:
return "ERROR_ELEMENT_MISMATCH";
case XML_ERROR_PARSING_ELEMENT:
return "ERROR_PARSING_ELEMENT";
case XML_ERROR_PARSING_ATTRIBUTE:
return "ERROR_PARSING_ATTRIBUTE";
case XML_ERROR_IDENTIFYING_TAG:
return "ERROR_IDENTIFYING_TAG";
case XML_ERROR_PARSING_TEXT:
return "ERROR_PARSING_TEXT";
case XML_ERROR_PARSING_CDATA:
return "ERROR_PARSING_CDATA";
case XML_ERROR_PARSING_COMMENT:
return "ERROR_PARSING_COMMENT";
case XML_ERROR_PARSING_DECLARATION:
return "ERROR_PARSING_DECLARATION";
case XML_ERROR_PARSING_UNKNOWN:
return "ERROR_PARSING_UNKNOWN";
case XML_ERROR_EMPTY_DOCUMENT:
return "ERROR_EMPTY_DOCUMENT";
case XML_ERROR_MISMATCHED_ELEMENT:
return "ERROR_MISMATCHED_ELEMENT";
case XML_ERROR_PARSING:
return "ERROR_PARSING";
case XML_CAN_NOT_CONVERT_TEXT:
return "CAN_NOT_CONVERT_TEXT";
case XML_NO_TEXT_NODE:
return "NO_TEXT_NODE";
default:
return "";
}
}
void loadXML(string uri, XMLDocument& doc)
void loadXML(string uri, XMLDocument &doc)
{
XMLError error = doc.LoadFile(uri.c_str());
if (error)
{
if (error) {
reportFatal("Configuration", "Error loading xml from: " + uri + " "
+ errorToString(error));
}
@@ -207,8 +222,7 @@ string loadTextFileContents(string filename)
{
ifstream in(filename.c_str(), ios::in | ios::binary);
if (in)
{
if (in) {
string contents;
in.seekg(0, ios::end);
contents.resize(in.tellg());
@@ -216,15 +230,13 @@ string loadTextFileContents(string filename)
in.read(&contents[0], contents.size());
in.close();
return (contents);
}
else
{
} else {
reportFatal("Error loading file", "Could not load textfile from " + filename);
return "";
}
}
void setUpDummy(tlm::tlm_generic_payload& payload, Bank& bank)
void setUpDummy(tlm::tlm_generic_payload &payload, Bank &bank)
{
payload.set_address(bank.getStartAddress());
payload.set_command(tlm::TLM_READ_COMMAND);
@@ -233,7 +245,9 @@ void setUpDummy(tlm::tlm_generic_payload& payload, Bank& bank)
payload.set_dmi_allowed(false);
payload.set_byte_enable_length(0);
payload.set_streaming_width(0);
payload.set_extension(new DramExtension(Thread(Controller::ControllerThreadId()), bank, BankGroup(0), Row(0), Column(0))); //payload takes ownership
payload.set_extension(new DramExtension(Thread(
Controller::ControllerThreadId()), bank, BankGroup(0), Row(0),
Column(0))); //payload takes ownership
//TODO .. Dummies muessen noch banggruppe und rank sauber bekommen .. noch was ueberlegen!!!
}
@@ -242,15 +256,13 @@ std::string getFileName(std::string uri)
// Remove directory if present.
// Do this before extension removal incase directory has a period character.
const size_t last_slash_idx = uri.find_last_of("\\/");
if (std::string::npos != last_slash_idx)
{
if (std::string::npos != last_slash_idx) {
uri.erase(0, last_slash_idx + 1);
}
// Remove extension if present.
const size_t period_idx = uri.rfind('.');
if (std::string::npos != period_idx)
{
if (std::string::npos != period_idx) {
uri.erase(period_idx);
}
return uri;

View File

@@ -58,22 +58,23 @@ public: \
//TODO : move to timing specific header
sc_time getDistance(sc_time a, sc_time b);
struct TimeInterval
{
sc_time start,end;
TimeInterval() : start(SC_ZERO_TIME), end(SC_ZERO_TIME){}
TimeInterval(sc_time start,sc_time end) : start(start), end(end){}
struct TimeInterval {
sc_time start, end;
TimeInterval() : start(SC_ZERO_TIME), end(SC_ZERO_TIME) {}
TimeInterval(sc_time start, sc_time end) : start(start), end(end) {}
sc_time getLength() {return getDistance(start,end);}
sc_time getLength()
{
return getDistance(start, end);
}
bool timeIsInInterval(sc_time time);
bool intersects(TimeInterval other);
};
template<typename Key, typename Val>
inline Val getElementFromMap(const std::map<Key, Val>& m, Key key)
inline Val getElementFromMap(const std::map<Key, Val> &m, Key key)
{
if (m.count(key) == 0)
{
if (m.count(key) == 0) {
SC_REPORT_FATAL("Map", "Element not in map");
}
@@ -81,17 +82,17 @@ inline Val getElementFromMap(const std::map<Key, Val>& m, Key key)
}
template<typename T>
bool isIn(const T& value, const std::vector<T>& collection)
bool isIn(const T &value, const std::vector<T> &collection)
{
for (T t : collection)
{
for (T t : collection) {
if (t == value)
return true;
}
return false;
}
constexpr const char headline[] = "=========================================================";
constexpr const char headline[] =
"=========================================================";
static inline void loadbar(unsigned int x,
unsigned int n,
@@ -108,24 +109,24 @@ static inline void loadbar(unsigned int x,
for (unsigned int x = 0; x < c; x++)
std::cout << "";
if(rest >= 0 && rest < 0.125 && c != w)
if (rest >= 0 && rest < 0.125 && c != w)
std::cout << " ";
if(rest >= 0.125 && rest < 2*0.125)
if (rest >= 0.125 && rest < 2 * 0.125)
std::cout << "";
if(rest >= 2*0.125 && rest < 3*0.125)
if (rest >= 2 * 0.125 && rest < 3 * 0.125)
std::cout << "";
if(rest >= 3*0.125 && rest < 4*0.125)
if (rest >= 3 * 0.125 && rest < 4 * 0.125)
std::cout << "";
if(rest >= 4*0.125 && rest < 5*0.125)
if (rest >= 4 * 0.125 && rest < 5 * 0.125)
std::cout << "";
if(rest >= 5*0.125 && rest < 6*0.125)
if (rest >= 5 * 0.125 && rest < 6 * 0.125)
std::cout << "";
if(rest >= 6*0.125 && rest < 7*0.125)
if (rest >= 6 * 0.125 && rest < 7 * 0.125)
std::cout << "";
if(rest >= 7*0.125 && rest < 8*0.125)
if (rest >= 7 * 0.125 && rest < 8 * 0.125)
std::cout << "";
for (unsigned int x = c; x < (w-1); x++)
for (unsigned int x = c; x < (w - 1); x++)
std::cout << " ";
std::cout << "|\r" << std::flush;
}
@@ -137,15 +138,15 @@ std::string phaseNameToString(tlm::tlm_phase phase);
//TODO : Move to other source specific to xml
std::string getFileName(std::string uri);
bool parameterExists(tinyxml2::XMLElement* node, std::string name);
bool parameterExists(tinyxml2::XMLElement *node, std::string name);
std::string loadTextFileContents(std::string filename);
void loadXML(std::string uri, tinyxml2::XMLDocument& doc);
unsigned int queryUIntParameter(tinyxml2::XMLElement* node, std::string name);
std::string queryStringParameter(tinyxml2::XMLElement* node, std::string name);
bool queryBoolParameter(tinyxml2::XMLElement* node, std::string name);
double queryDoubleParameter(tinyxml2::XMLElement* node, std::string name);
void loadXML(std::string uri, tinyxml2::XMLDocument &doc);
unsigned int queryUIntParameter(tinyxml2::XMLElement *node, std::string name);
std::string queryStringParameter(tinyxml2::XMLElement *node, std::string name);
bool queryBoolParameter(tinyxml2::XMLElement *node, std::string name);
double queryDoubleParameter(tinyxml2::XMLElement *node, std::string name);
void setUpDummy(tlm::tlm_generic_payload& payload, Bank& bank);
void setUpDummy(tlm::tlm_generic_payload &payload, Bank &bank);
#endif /* UTILS_COMMON_H_ */

View File

@@ -48,26 +48,32 @@ DramExtension::DramExtension() :
{
}
DramExtension::DramExtension(const Thread &thread, const Bank &bank, const BankGroup &bankgroup, const Row &row, const Column &column, unsigned int burstlength) :
thread(thread), channel(0), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
DramExtension::DramExtension(const Thread &thread, const Bank &bank,
const BankGroup &bankgroup, const Row &row, const Column &column,
unsigned int burstlength) :
thread(thread), channel(0), bank(bank), bankgroup(bankgroup), row(row),
column(column), burstlength(burstlength)
{
}
DramExtension::DramExtension(const Thread &thread, const Channel &channel, const Bank &bank, const BankGroup &bankgroup, const Row &row, const Column &column, unsigned int burstlength) :
thread(thread), channel(channel), bank(bank), bankgroup(bankgroup), row(row), column(column), burstlength(burstlength)
DramExtension::DramExtension(const Thread &thread, const Channel &channel,
const Bank &bank, const BankGroup &bankgroup, const Row &row,
const Column &column, unsigned int burstlength) :
thread(thread), channel(channel), bank(bank), bankgroup(bankgroup), row(row),
column(column), burstlength(burstlength)
{
}
DramExtension& DramExtension::getExtension(const tlm_generic_payload *payload)
DramExtension &DramExtension::getExtension(const tlm_generic_payload *payload)
{
DramExtension *result = NULL;
payload->get_extension(result);
sc_assert(result!=NULL);
sc_assert(result != NULL);
return *result;
}
DramExtension& DramExtension::getExtension(const tlm_generic_payload &payload)
DramExtension &DramExtension::getExtension(const tlm_generic_payload &payload)
{
return DramExtension::getExtension(&payload);
}
@@ -113,14 +119,14 @@ Row DramExtension::getRow(const tlm_generic_payload &payload)
}
tlm_extension_base* DramExtension::clone() const
tlm_extension_base *DramExtension::clone() const
{
return new DramExtension(thread, bank, bankgroup, row, column, burstlength);
}
void DramExtension::copy_from(const tlm_extension_base& ext)
void DramExtension::copy_from(const tlm_extension_base &ext)
{
const DramExtension& cpyFrom = static_cast<const DramExtension&>(ext);
const DramExtension &cpyFrom = static_cast<const DramExtension &>(ext);
thread = cpyFrom.thread;
bank = cpyFrom.bank;
bankgroup = cpyFrom.bankgroup;
@@ -169,87 +175,91 @@ void DramExtension::incrementRow()
++row;
}
tlm_extension_base* GenerationExtension::clone() const
tlm_extension_base *GenerationExtension::clone() const
{
return new GenerationExtension(timeOfGeneration);
}
void GenerationExtension::copy_from(const tlm_extension_base& ext)
void GenerationExtension::copy_from(const tlm_extension_base &ext)
{
const GenerationExtension& cpyFrom = static_cast<const GenerationExtension&>(ext);
const GenerationExtension &cpyFrom = static_cast<const GenerationExtension &>
(ext);
timeOfGeneration = cpyFrom.timeOfGeneration;
}
GenerationExtension& GenerationExtension::getExtension(const tlm::tlm_generic_payload* payload)
GenerationExtension &GenerationExtension::getExtension(const
tlm::tlm_generic_payload *payload)
{
GenerationExtension *result = NULL;
payload->get_extension(result);
sc_assert(result!=NULL);
sc_assert(result != NULL);
return *result;
}
sc_time GenerationExtension::getTimeOfGeneration(const tlm::tlm_generic_payload *payload)
sc_time GenerationExtension::getTimeOfGeneration(const tlm::tlm_generic_payload
*payload)
{
return GenerationExtension::getExtension(payload).TimeOfGeneration();
}
sc_time GenerationExtension::getTimeOfGeneration(const tlm::tlm_generic_payload &payload)
sc_time GenerationExtension::getTimeOfGeneration(const tlm::tlm_generic_payload
&payload)
{
return GenerationExtension::getTimeOfGeneration(&payload);
}
//THREAD
bool operator ==(const Thread& lhs, const Thread& rhs)
bool operator ==(const Thread &lhs, const Thread &rhs)
{
return lhs.ID() == rhs.ID();
}
bool operator !=(const Thread& lhs, const Thread& rhs)
bool operator !=(const Thread &lhs, const Thread &rhs)
{
return !(lhs == rhs);
}
bool operator <(const Thread& lhs, const Thread& rhs)
bool operator <(const Thread &lhs, const Thread &rhs)
{
return lhs.ID() < rhs.ID();
}
//CHANNEL
bool operator ==(const Channel& lhs, const Channel& rhs)
bool operator ==(const Channel &lhs, const Channel &rhs)
{
return lhs.ID() == rhs.ID();
}
bool operator !=(const Channel& lhs, const Channel& rhs)
bool operator !=(const Channel &lhs, const Channel &rhs)
{
return !(lhs == rhs);
}
//BANKGROUP
bool operator ==(const BankGroup& lhs, const BankGroup& rhs)
bool operator ==(const BankGroup &lhs, const BankGroup &rhs)
{
return lhs.ID() == rhs.ID();
}
bool operator !=(const BankGroup& lhs, const BankGroup& rhs)
bool operator !=(const BankGroup &lhs, const BankGroup &rhs)
{
return !(lhs == rhs);
}
//BANK
bool operator ==(const Bank& lhs, const Bank& rhs)
bool operator ==(const Bank &lhs, const Bank &rhs)
{
return lhs.ID() == rhs.ID();
}
bool operator !=(const Bank& lhs, const Bank& rhs)
bool operator !=(const Bank &lhs, const Bank &rhs)
{
return !(lhs == rhs);
}
bool operator <(const Bank& lhs, const Bank& rhs)
bool operator <(const Bank &lhs, const Bank &rhs)
{
return lhs.ID() < rhs.ID();
}
@@ -257,14 +267,14 @@ bool operator <(const Bank& lhs, const Bank& rhs)
//ROW
const Row Row::NO_ROW;
bool operator ==(const Row& lhs, const Row& rhs)
bool operator ==(const Row &lhs, const Row &rhs)
{
if (lhs.isNoRow != rhs.isNoRow)
return false;
return lhs.ID() == rhs.ID();
}
bool operator !=(const Row& lhs, const Row& rhs)
bool operator !=(const Row &lhs, const Row &rhs)
{
return !(lhs == rhs);
}
@@ -277,12 +287,12 @@ const Row Row::operator ++()
//COLUMN
bool operator ==(const Column& lhs, const Column& rhs)
bool operator ==(const Column &lhs, const Column &rhs)
{
return lhs.ID() == rhs.ID();
}
bool operator !=(const Column& lhs, const Column& rhs)
bool operator !=(const Column &lhs, const Column &rhs)
{
return !(lhs == rhs);
}

View File

@@ -46,7 +46,7 @@ class Thread
{
public:
explicit Thread(unsigned int id) :
id(id)
id(id)
{
}
@@ -62,7 +62,7 @@ class Channel
{
public:
explicit Channel(unsigned int id) :
id(id)
id(id)
{
}
unsigned int ID() const
@@ -77,7 +77,7 @@ class BankGroup
{
public:
explicit BankGroup(unsigned int id) :
id(id)
id(id)
{
}
unsigned int ID() const
@@ -92,7 +92,7 @@ class Bank
{
public:
Bank(unsigned int id) :
id(id)
id(id)
{
}
unsigned int ID() const
@@ -121,11 +121,11 @@ public:
static const Row NO_ROW;
Row() :
id(0), isNoRow(true)
id(0), isNoRow(true)
{
}
explicit Row(unsigned int id) :
id(id), isNoRow(false)
id(id), isNoRow(false)
{
}
@@ -146,7 +146,7 @@ class Column
{
public:
explicit Column(unsigned int id) :
id(id)
id(id)
{
}
@@ -163,16 +163,18 @@ class DramExtension: public tlm::tlm_extension<DramExtension>
{
public:
DramExtension();
DramExtension(const Thread& thread, const Bank& bank, const BankGroup& bankgroup, const Row& row, const Column& column,
unsigned int burstlength = 0);
DramExtension(const Thread& thread, const Channel& channel, const Bank& bank, const BankGroup& bankgroup, const Row& row,
const Column& column, unsigned int burstlength = 0);
DramExtension(const Thread &thread, const Bank &bank,
const BankGroup &bankgroup, const Row &row, const Column &column,
unsigned int burstlength = 0);
DramExtension(const Thread &thread, const Channel &channel, const Bank &bank,
const BankGroup &bankgroup, const Row &row,
const Column &column, unsigned int burstlength = 0);
virtual tlm_extension_base* clone() const;
virtual void copy_from(const tlm_extension_base& ext);
virtual tlm_extension_base *clone() const;
virtual void copy_from(const tlm_extension_base &ext);
static DramExtension& getExtension(const tlm::tlm_generic_payload *payload);
static DramExtension& getExtension(const tlm::tlm_generic_payload &payload);
static DramExtension &getExtension(const tlm::tlm_generic_payload *payload);
static DramExtension &getExtension(const tlm::tlm_generic_payload &payload);
// Used for convience, caller could also use getExtension(..) to access these field
static Bank getBank(const tlm::tlm_generic_payload *payload);
@@ -211,11 +213,16 @@ private:
class GenerationExtension : public tlm::tlm_extension<GenerationExtension>
{
public:
GenerationExtension(sc_time timeOfGeneration) : timeOfGeneration(timeOfGeneration) {}
virtual tlm_extension_base* clone() const;
virtual void copy_from(const tlm_extension_base& ext);
static GenerationExtension& getExtension(const tlm::tlm_generic_payload *payload);
sc_time TimeOfGeneration() const {return timeOfGeneration;}
GenerationExtension(sc_time timeOfGeneration) : timeOfGeneration(
timeOfGeneration) {}
virtual tlm_extension_base *clone() const;
virtual void copy_from(const tlm_extension_base &ext);
static GenerationExtension &getExtension(const tlm::tlm_generic_payload
*payload);
sc_time TimeOfGeneration() const
{
return timeOfGeneration;
}
static sc_time getTimeOfGeneration(const tlm::tlm_generic_payload *payload);
static sc_time getTimeOfGeneration(const tlm::tlm_generic_payload &payload);

View File

@@ -0,0 +1,272 @@
/*
* Copyright (c) 2018, University of Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Johannes Feldmann
*/
#include "jsonAddressDecoder.h"
#include "Utils.h"
#include <fstream>
using std::ifstream;
using std::cout;
using std::endl;
#if 0 // Problems with gcc version on KOA for more details refer to pull-request #190 and issue #198
#include <nlohmann/json.hpp>
using json = nlohmann::json;
#endif
#include <set>
using std::set;
JSONAddressDecoder::JSONAddressDecoder()
{
}
void JSONAddressDecoder::setConfiguration(std::string url)
{
ifstream file;
file.open(url);
if (!file.is_open()) {
cout << "Unable to open file " << url << endl;
return;
}
#if 0 //XXX: Problems with gcc version on KOA for more details refer to pull-request #190 and issue #198
// parse json file
json data;
file >> data;
file.close();
// extract data
// For simplicity take the first solution of one or more available ones.
auto sol = data["Solutions"].begin();
assert(sol != data["Solutions"].end());
// Set for connected bits. Used to find the remaining bits, which are not part of the json file = column bits.
set<unsigned> sUsed;
// get XOR connections
// An XOR connection needs two parameters: A bank bit and a Row bit.
// These parameters are all stored in one array with the following pattern: bank0, bank1, ..., row0, row1, ...
unsigned num = (*sol)["XOR"].size() >> 1;
for (unsigned i = 0; i < num; i++) {
m_vXor.push_back(pair<unsigned, unsigned> ((*sol)["XOR"].at(i),
(*sol)["XOR"].at(i + num)));
}
// get all bank bits
// Each bank bit of the address will be stored with a counter value which assigns the bit position DecodedAddress struct.
unsigned counter = 0;
for (auto it = (*sol)["Banks Rows"][0]["bank_bits"].begin();
it != (*sol)["Banks Rows"][0]["bank_bits"].end(); it++) {
m_vBankBits.push_back(pair<unsigned, unsigned>(counter++, (*it)));
sUsed.insert((unsigned)(*it));
}
// get all row bits bits
// Each Row bit of the address will be stored with a counter value which assigns the bit position DecodedAddress struct.
counter = 0;
for (auto it = (*sol)["Banks Rows"][0]["rows"]["row_bits"].begin();
it != (*sol)["Banks Rows"][0]["rows"]["row_bits"].end(); it++) {
m_vRowBits.push_back(pair<unsigned, unsigned>(counter++, (*it)));
sUsed.insert((unsigned)(*it));
}
// Add byte bits (fixed)
sUsed.insert(0);
sUsed.insert(1);
sUsed.insert(2);
// Theset bits are ignored
sUsed.insert(30);
sUsed.insert(31);
// Create Column mapping
// These bits are not stored in the JSON file, but can be generated. All bits, which are until now not used for any other purpose are column bits.
// Each column bit of the address will be stored with a counter value which assigns the bit position DecodedAddress struct.
counter = 0;
for (unsigned i = 0; i < 32; i++) {
if (sUsed.find(i) != sUsed.end())
continue; // Already mapped
m_vColumnBits.push_back(pair<unsigned, unsigned>(counter++, i));
}
// Fill the amount map. This is copied from xmlAddressDecoder without further investigation
amount["channel"] = 1;
amount["bank"] = pow(2.0, m_vBankBits.size());
amount["row"] = pow(2.0, m_vRowBits.size());
amount["column"] = pow(2.0, m_vColumnBits.size());
amount["bytes"] = pow(2.0, 3);
#endif
}
DecodedAddress JSONAddressDecoder::decodeAddress(sc_dt::uint64 addr)
{
DecodedAddress result;
// Apply XOR
// For each used xor:
// Get the bank bit and row bit. Apply a bitwise xor operator and save it back to the bank bit.
for (auto it = m_vXor.begin(); it != m_vXor.end(); it++) {
unsigned new_bank_bit;
// Bank Row
new_bank_bit = (((addr >> it->first) & 1) ^ ((addr >> it->second) & 1));
addr &= ~(1 << it->first);
addr |= new_bank_bit << it->first;
}
// Unsed
result.bankgroup = 0;
result.channel = 0;
result.rank = 0;
// Pass through of the three byte bits
result.bytes = addr & 0x7;
// Bank
// it->second: position of the target bit in the address
// it->first: target position of the bit in the variable
// For each bank bit:
// shift address bit to position 0. Clear all other bits. shift it the right bank bit. Add it to the set of bank bits.
result.bank = 0;
for (auto it = m_vBankBits.begin(); it != m_vBankBits.end(); it++) {
result.bank |= ((addr >> it->second) & 1) << it->first;
}
// Row
// it->second: position of the target bit in the address
// it->first: target position of the bit in the variable
// For each row bit:
// shift address bit to position 0. Clear all other bits. shift it the right row bit. Add it to the set of row bits.
result.row = 0;
for (auto it = m_vRowBits.begin(); it != m_vRowBits.end(); it++) {
result.row |= ((addr >> it->second) & 1) << it->first;
}
// Column
// it->second: position of the target bit in the address
// it->first: target position of the bit in the variable
// For each column bit:
// shift address bit to position 0. Clear all other bits. shift it the right column bit. Add it to the set of column bits.
result.column = 0;
for (auto it = m_vColumnBits.begin(); it != m_vColumnBits.end(); it++) {
result.column |= ((addr >> it->second) & 1) << it->first;
}
return result;
}
sc_dt::uint64 JSONAddressDecoder::encodeAddress(DecodedAddress n)
{
sc_dt::uint64 address = 0;
// Bank
// it->first: position of the target bit in the DecodedAddress struct field
// it->second: target position of the bit in the address
// For each bank bit:
// shift bank bit to position 0. Clear all other bits. shift it the right address bit. Add it to the set of address bits.
for (auto it = m_vBankBits.begin(); it != m_vBankBits.end(); it++) {
address |= ((n.bank >> it->first) & 1) << it->second;
}
// Row
// it->first: position of the target bit in the DecodedAddress struct field
// it->second: target position of the bit in the address
// For each row bit:
// shift row bit to position 0. Clear all other bits. shift it the right address bit. Add it to the set of address bits.
for (auto it = m_vRowBits.begin(); it != m_vRowBits.end(); it++) {
address |= ((n.row >> it->first) & 1) << it->second;
}
// Column
// it->first: position of the target bit in the DecodedAddress struct field
// it->second: target position of the bit in the address
// For each column bit:
// shift column bit to position 0. Clear all other bits. shift it the right address bit. Add it to the set of address bits.
for (auto it = m_vColumnBits.begin(); it != m_vColumnBits.end(); it++) {
address |= ((n.column >> it->first) & 1) << it->second;
}
// Add the unchanged byte bits
address |= n.bytes;
// Apply XOR
// For each used xor:
// Get the bank bit and row bit. Apply a bitwise xor operator and save it back to the bank bit.
for (auto it = m_vXor.begin(); it != m_vXor.end(); it++) {
unsigned new_bank_bit;
new_bank_bit = (((address >> it->first) & 1) ^ ((address >> it->second) & 1));
address &= ~(1 << it->first);
address |= new_bank_bit << it->first;
}
return address;
}
void JSONAddressDecoder::print()
{
map<unsigned, pair<unsigned, char>> output;
for (auto it = m_vBankBits.begin(); it != m_vBankBits.end(); it++) {
output[it->second] = pair<unsigned, char>(it->first , 'B');
}
for (auto it = m_vRowBits.begin(); it != m_vRowBits.end(); it++) {
output[it->second] = pair<unsigned, char>(it->first , 'R');
}
for (auto it = m_vColumnBits.begin(); it != m_vColumnBits.end(); it++) {
output[it->second] = pair<unsigned, char>(it->first , 'C');
}
// add byte bits
output[0] = pair<unsigned, char>(0 , 'b');
output[1] = pair<unsigned, char>(1 , 'b');
output[2] = pair<unsigned, char>(2 , 'b');
cout << "Used addressmapping:" << endl;
cout << headline << endl;
for (unsigned i = 0; i < 32; i++) {
cout << " " << i << " ";
}
cout << endl;
for (unsigned i = 0; i < 32; i++) {
cout << " " << output[i].second << "(" << output[i].first << ") ";
}
cout << endl;
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2018, University of Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Johannes Feldmann
*/
#ifndef JSONADDRESSDECODER_H
#define JSONADDRESSDECODER_H
#include "AddressDecoder.h"
#include <vector>
#include <map>
using std::vector;
using std::pair;
using std::map;
class JSONAddressDecoder
: public AddressDecoder
{
// Friendship needed so that the AddressDecoder can access the
// constructor of this class to create the object in CreateInstance.
friend class AddressDecoder;
private:
JSONAddressDecoder();
vector<pair<unsigned, unsigned>>
m_vXor; // This container stores for each used xor gate a pair which consists of "First/Number of an address bit which corresponds to a bank"
// and "Second/Number of an address bit which corresponds to a row"
vector<pair<unsigned, unsigned>>
m_vBankBits; // This container stores for each bank bit a pair which consists of "First/Number of the bank bit" and "Second/Number of the address bit"
vector<pair<unsigned, unsigned>>
m_vRowBits; // This container stores for each row bit a pair which consists of "First/Number of the row bit" and "Second/Number of the address bit"
vector<pair<unsigned, unsigned>>
m_vColumnBits; // This container stores for each column bit a pair which consists of "First/Number of the column bit" and "Second/Number of the address bit"
public:
virtual void setConfiguration(std::string url);
virtual DecodedAddress decodeAddress(sc_dt::uint64 addr);
virtual sc_dt::uint64 encodeAddress(DecodedAddress n);
virtual void print();
};
#endif // JSONADDRESSDECODER_H

File diff suppressed because it is too large Load Diff

View File

@@ -49,37 +49,20 @@ xmlAddressDecoder::xmlAddressDecoder()
addressmapping = NULL;
}
xmlAddressDecoder::xmlAddressDecoder(string addressConfigURI)
{
setConfiguration(addressConfigURI);
}
xmlAddressDecoder::xmlAddressDecoder(XMLElement* addressmap)
{
setConfiguration(addressmap);
}
void xmlAddressDecoder::setConfiguration(std::string addressConfigURI)
{
tinyxml2::XMLDocument doc;
loadXML(addressConfigURI, doc);
setConfiguration(doc.RootElement());
}
void xmlAddressDecoder::setConfiguration(tinyxml2::XMLElement* addressMap)
{
tinyxml2::XMLDocument doc;
tinyxml2::XMLElement *addressMap = doc.RootElement();
string xmlNodeName(addressMap->Name());
if( xmlNodeName != "addressmapping")
{
if ( xmlNodeName != "addressmapping") {
reportFatal("AddressDecorder", "addressmap node expected");
}
for(XMLElement* child = addressMap->FirstChildElement();
child != NULL;
child = child->NextSiblingElement())
{
for (XMLElement *child = addressMap->FirstChildElement();
child != NULL;
child = child->NextSiblingElement()) {
int from;
int to;
@@ -100,7 +83,8 @@ DecodedAddress xmlAddressDecoder::decodeAddress(sc_dt::uint64 addr)
//result.rank = (addr & masks["rank"]) >> shifts["rank"];
//result.bankgroup = (addr & masks["bankgroup"]) >> shifts["bankgroup"];
result.bank = (addr & masks["bank"]) >> shifts["bank"];
result.bankgroup = result.bank % Configuration::getInstance().memSpec.NumberOfBankGroups;
result.bankgroup = result.bank %
Configuration::getInstance().memSpec.NumberOfBankGroups;
result.rank = result.bank % Configuration::getInstance().memSpec.NumberOfRanks;
result.row = (addr & masks["row"]) >> shifts["row"];
result.column = (addr & masks["column"]) >> shifts["column"];
@@ -111,21 +95,20 @@ DecodedAddress xmlAddressDecoder::decodeAddress(sc_dt::uint64 addr)
sc_dt::uint64 xmlAddressDecoder::encodeAddress(DecodedAddress n)
{
return n.channel << shifts["channel"] |
n.rank << shifts["rank"] |
n.bankgroup << shifts["bankgroup"] |
n.row << shifts["row"] |
n.bank << shifts["bank"] |
n.column << shifts["column"] |
n.bytes << shifts["bytes"];
n.rank << shifts["rank"] |
n.bankgroup << shifts["bankgroup"] |
n.row << shifts["row"] |
n.bank << shifts["bank"] |
n.column << shifts["column"] |
n.bytes << shifts["bytes"];
}
void xmlAddressDecoder::print()
{
cout << "Used addressmapping:" << endl;
cout << headline << endl;
for(auto& pair : masks)
{
cout<<pair.first<<"\t:\t" << bitset<32>(pair.second)<<endl;
for (auto &pair : masks) {
cout << pair.first << "\t:\t" << bitset<32>(pair.second) << endl;
}
cout<<"\n"<<endl;
cout << "\n" << endl;
}

View File

@@ -38,62 +38,35 @@
#ifndef _XMLADDRESSDECODER_H
#define _XMLADDRESSDECODER_H
#include <tlm.h>
#include <iostream>
#include <sstream>
#include <string>
#include <math.h>
#include <map>
#include "Utils.h"
#include "third_party/tinyxml2/tinyxml2.h"
struct DecodedAddress
{
DecodedAddress() : channel(0),
rank(0),
bankgroup(0),
row(0),
bank(0),
column(0),
bytes(0)
{
}
unsigned int channel;
unsigned int rank;
unsigned int bankgroup;
unsigned int row;
unsigned int bank;
unsigned int column;
unsigned int bytes;
};
#include "AddressDecoder.h"
class xmlAddressDecoder
: public AddressDecoder
{
// Friendship needed so that the AddressDecoder can access the
// constructor of this class to create the object in CreateInstance.
friend class AddressDecoder;
private:
private:
xmlAddressDecoder();
xmlAddressDecoder(std::string URI);
xmlAddressDecoder(tinyxml2::XMLElement* addressMap);
std::map<std::string, sc_dt::uint64> masks;
std::map<std::string, unsigned int> shifts;
tinyxml2::XMLElement* addressmapping;
tinyxml2::XMLElement *addressmapping;
public:
DEF_SINGLETON(xmlAddressDecoder);
DecodedAddress decodeAddress(sc_dt::uint64 addr);
sc_dt::uint64 encodeAddress(DecodedAddress n);
public:
virtual DecodedAddress decodeAddress(sc_dt::uint64 addr);
virtual sc_dt::uint64 encodeAddress(DecodedAddress n);
void setConfiguration(std::string url);
void setConfiguration(tinyxml2::XMLElement* addressMap);
void print();
std::map<std::string, unsigned int> amount;
public:
virtual void print();
};
#endif

View File

@@ -41,8 +41,7 @@
std::string commandToString(Command command)
{
switch (command)
{
switch (command) {
case Command::Read:
return "RD";
break;
@@ -99,19 +98,19 @@ std::string commandToString(Command command)
return "";
}
const std::vector<Command>& getAllCommands()
const std::vector<Command> &getAllCommands()
{
static std::vector<Command> allCommands( { Command::Precharge, Command::PrechargeAll,
Command::Activate, Command::Read, Command::Write, Command::ReadA, Command::WriteA,
Command::AutoRefresh, Command::PDNA, Command::PDNAX, Command::PDNP, Command::PDNPX,
Command::SREF, Command::SREFX });
Command::SREF, Command::SREFX
});
return allCommands;
}
bool commandIsIn(Command command, std::vector<Command> commands)
{
for (Command c : commands)
{
for (Command c : commands) {
if (c == command)
return true;
}

View File

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

View File

@@ -43,29 +43,19 @@ void Controller::buildScheduler()
string selectedScheduler = Configuration::getInstance().Scheduler;
std::cout << "Selected Scheduler: " << selectedScheduler << std::endl;
if (selectedScheduler == "FIFO")
{
if (selectedScheduler == "FIFO") {
scheduler = new Fifo(*controllerCore);
}
else if (selectedScheduler == "FIFO_STRICT")
{
} else if (selectedScheduler == "FIFO_STRICT") {
scheduler = new FifoStrict(*this, *controllerCore);
}
else if (selectedScheduler == "FR_FCFS")
{
} else if (selectedScheduler == "FR_FCFS") {
scheduler = new FR_FCFS(*controllerCore);
}
else if (selectedScheduler == "FR_FCFS_RP")
{
} else if (selectedScheduler == "FR_FCFS_RP") {
scheduler = new FR_FCFS_RP(*controllerCore);
}
else if (selectedScheduler == "FR_FCFS_GRP")
{
scheduler = new FR_FCFS_GRP(*controllerCore,this);
}
else if (selectedScheduler == "SMS")
{
scheduler = new SMS("SMS", *controllerCore, Configuration::getInstance().SJFProbability);
} else if (selectedScheduler == "FR_FCFS_GRP") {
scheduler = new FR_FCFS_GRP(*controllerCore, this);
} else if (selectedScheduler == "SMS") {
scheduler = new SMS("SMS", *controllerCore,
Configuration::getInstance().SJFProbability);
}
//else if (selectedScheduler == "PAR_BS")
//{
@@ -81,98 +71,105 @@ void Controller::buildScheduler()
}
//Send the next scheduled command to the DRAM
void Controller::send(const ScheduledCommand &command, tlm_generic_payload &payload)
void Controller::send(const ScheduledCommand &command,
tlm_generic_payload &payload)
{
sc_assert(command.getStart() >= sc_time_stamp());
TimeInterval dataStrobe;
switch (command.getCommand())
{
switch (command.getCommand()) {
//TODO: refactor tlm recorder
case Command::Read:
dataStrobe = command.getIntervalOnDataStrobe();
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_RD, command.getStart() - sc_time_stamp());
controllerCorePEQ.notify(payload, BEGIN_RD,
command.getStart() - sc_time_stamp());
break;
case Command::ReadA:
dataStrobe = command.getIntervalOnDataStrobe();
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_RDA, command.getStart() - sc_time_stamp());
controllerCorePEQ.notify(payload, BEGIN_RDA,
command.getStart() - sc_time_stamp());
break;
case Command::Write:
dataStrobe = command.getIntervalOnDataStrobe();
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_WR, command.getStart() - sc_time_stamp());
controllerCorePEQ.notify(payload, BEGIN_WR,
command.getStart() - sc_time_stamp());
break;
case Command::WriteA:
dataStrobe = command.getIntervalOnDataStrobe();
tlmRecorder->updateDataStrobe(dataStrobe.start, dataStrobe.end, payload);
controllerCorePEQ.notify(payload, BEGIN_WRA, command.getStart() - sc_time_stamp());
controllerCorePEQ.notify(payload, BEGIN_WRA,
command.getStart() - sc_time_stamp());
break;
case Command::AutoRefresh:
if(!Configuration::getInstance().BankwiseLogic)
{
controllerCorePEQ.notify(payload, BEGIN_REFA, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, BEGIN_REFB, command.getStart() - sc_time_stamp());
if (!Configuration::getInstance().BankwiseLogic) {
controllerCorePEQ.notify(payload, BEGIN_REFA,
command.getStart() - sc_time_stamp());
} else
controllerCorePEQ.notify(payload, BEGIN_REFB,
command.getStart() - sc_time_stamp());
break;
case Command::Activate:
controllerCorePEQ.notify(payload, BEGIN_ACT, command.getStart() - sc_time_stamp());
controllerCorePEQ.notify(payload, BEGIN_ACT,
command.getStart() - sc_time_stamp());
break;
case Command::Precharge:
controllerCorePEQ.notify(payload, BEGIN_PRE, command.getStart() - sc_time_stamp());
controllerCorePEQ.notify(payload, BEGIN_PRE,
command.getStart() - sc_time_stamp());
break;
case Command::PrechargeAll:
controllerCorePEQ.notify(payload, BEGIN_PRE_ALL, command.getStart() - sc_time_stamp());
controllerCorePEQ.notify(payload, BEGIN_PRE_ALL,
command.getStart() - sc_time_stamp());
break;
case Command::PDNA:
if(!Configuration::getInstance().BankwiseLogic)
{
controllerCorePEQ.notify(payload, BEGIN_PDNA, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, BEGIN_PDNAB, command.getStart() - sc_time_stamp());
if (!Configuration::getInstance().BankwiseLogic) {
controllerCorePEQ.notify(payload, BEGIN_PDNA,
command.getStart() - sc_time_stamp());
} else
controllerCorePEQ.notify(payload, BEGIN_PDNAB,
command.getStart() - sc_time_stamp());
break;
case Command::PDNAX:
if(!Configuration::getInstance().BankwiseLogic)
{
controllerCorePEQ.notify(payload, END_PDNA, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, END_PDNAB, command.getStart() - sc_time_stamp());
if (!Configuration::getInstance().BankwiseLogic) {
controllerCorePEQ.notify(payload, END_PDNA,
command.getStart() - sc_time_stamp());
} else
controllerCorePEQ.notify(payload, END_PDNAB,
command.getStart() - sc_time_stamp());
break;
case Command::PDNP:
if(!Configuration::getInstance().BankwiseLogic)
{
controllerCorePEQ.notify(payload, BEGIN_PDNP, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, BEGIN_PDNPB, command.getStart() - sc_time_stamp());
if (!Configuration::getInstance().BankwiseLogic) {
controllerCorePEQ.notify(payload, BEGIN_PDNP,
command.getStart() - sc_time_stamp());
} else
controllerCorePEQ.notify(payload, BEGIN_PDNPB,
command.getStart() - sc_time_stamp());
break;
case Command::PDNPX:
if(!Configuration::getInstance().BankwiseLogic)
{
controllerCorePEQ.notify(payload, END_PDNP, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, END_PDNPB, command.getStart() - sc_time_stamp());
if (!Configuration::getInstance().BankwiseLogic) {
controllerCorePEQ.notify(payload, END_PDNP,
command.getStart() - sc_time_stamp());
} else
controllerCorePEQ.notify(payload, END_PDNPB,
command.getStart() - sc_time_stamp());
break;
case Command::SREF:
if(!Configuration::getInstance().BankwiseLogic)
{
controllerCorePEQ.notify(payload, BEGIN_SREF, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, BEGIN_SREFB, command.getStart() - sc_time_stamp());
if (!Configuration::getInstance().BankwiseLogic) {
controllerCorePEQ.notify(payload, BEGIN_SREF,
command.getStart() - sc_time_stamp());
} else
controllerCorePEQ.notify(payload, BEGIN_SREFB,
command.getStart() - sc_time_stamp());
break;
case Command::SREFX:
if(!Configuration::getInstance().BankwiseLogic)
{
controllerCorePEQ.notify(payload, END_SREF, command.getStart() - sc_time_stamp());
}
else
controllerCorePEQ.notify(payload, END_SREFB, command.getStart() - sc_time_stamp());
if (!Configuration::getInstance().BankwiseLogic) {
controllerCorePEQ.notify(payload, END_SREF,
command.getStart() - sc_time_stamp());
} else
controllerCorePEQ.notify(payload, END_SREFB,
command.getStart() - sc_time_stamp());
break;
default:
SC_REPORT_FATAL(0, "unsupported command was sent by controller");
@@ -181,65 +178,61 @@ void Controller::send(const ScheduledCommand &command, tlm_generic_payload &payl
}
//Trigger the next planned refresh or the power down mode on the DRAM
void Controller::send(Trigger trigger, sc_time time, tlm_generic_payload &payload)
void Controller::send(Trigger trigger, sc_time time,
tlm_generic_payload &payload)
{
sc_assert(time >= sc_time_stamp());
sc_time delay = time - sc_time_stamp();
if (trigger == Trigger::REFTrigger)
{
if (trigger == Trigger::REFTrigger) {
controllerCorePEQ.notify(payload, REF_TRIGGER, delay);
}
else if (trigger == Trigger::PDNTrigger)
{
} else if (trigger == Trigger::PDNTrigger) {
controllerCorePEQ.notify(payload, PDN_TRIGGER, delay);
}
else
{
} else {
SC_REPORT_FATAL("controller wrapper", "unknown trigger");
}
}
void Controller::controllerCorePEQCallback(tlm_generic_payload &payload, const tlm_phase &phase)
void Controller::controllerCorePEQCallback(tlm_generic_payload &payload,
const tlm_phase &phase)
{
if (phase == REF_TRIGGER)
{
if (phase == REF_TRIGGER) {
controllerCore->triggerRefresh(payload);
}
else if (phase == PDN_TRIGGER)
{
controllerCore->powerDownManager->sleep(DramExtension::getExtension(payload).getBank(),sc_time_stamp());
}
else
{
} else if (phase == PDN_TRIGGER) {
controllerCore->powerDownManager->sleep(DramExtension::getExtension(
payload).getBank(), sc_time_stamp());
} else {
Bank bank = DramExtension::getBank(payload);
sendToDram(payload, phase, SC_ZERO_TIME);
if (phase == BEGIN_RD || phase == BEGIN_WR)
{
if (phase == BEGIN_RD || phase == BEGIN_WR) {
scheduleNextFromScheduler(DramExtension::getBank(payload));
}
else if (phase == BEGIN_REFB)
} else if (phase == BEGIN_REFB)
printDebugMessage("Entering REFB on bank " + to_string(bank.ID()));
else if (phase == BEGIN_REFA)
printDebugMessage("Entering REFA");
else if (containsPhase(phase, { BEGIN_PDNAB, BEGIN_PDNPB, BEGIN_SREFB }))
printDebugMessage("Entering PowerDown " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()));
printDebugMessage("Entering PowerDown " + phaseNameToString(
phase) + " on bank " + to_string(bank.ID()));
else if (containsPhase(phase, { END_PDNAB, END_PDNPB, END_SREFB }))
printDebugMessage("Leaving PowerDown " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()));
printDebugMessage("Leaving PowerDown " + phaseNameToString(
phase) + " on bank " + to_string(bank.ID()));
else if (containsPhase(phase, { BEGIN_PDNA, BEGIN_PDNP, BEGIN_SREF }))
printDebugMessage("Entering PowerDown " + phaseNameToString(phase) + " on all banks");
printDebugMessage("Entering PowerDown " + phaseNameToString(
phase) + " on all banks");
else if (containsPhase(phase, { END_PDNA, END_PDNP, END_SREF }))
printDebugMessage("Leaving PowerDown " + phaseNameToString(phase) + " on all banks" );
else if (containsPhase(phase, { BEGIN_RD, BEGIN_WR, BEGIN_ACT, BEGIN_PRE, BEGIN_PRE_ALL, BEGIN_RDA, BEGIN_WRA }))
{
printDebugMessage("Leaving PowerDown " + phaseNameToString(
phase) + " on all banks" );
else if (containsPhase(phase, { BEGIN_RD, BEGIN_WR, BEGIN_ACT, BEGIN_PRE, BEGIN_PRE_ALL, BEGIN_RDA, BEGIN_WRA })) {
}
else
SC_REPORT_FATAL(0, "refreshTriggerPEQCallback queue in controller wrapper was triggered with unsupported phase");
SC_REPORT_FATAL(0,
"refreshTriggerPEQCallback queue in controller wrapper was triggered with unsupported phase");
}
}
tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &fwDelay)
tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &payload,
tlm_phase &phase, sc_time &fwDelay)
{
sc_time recTime;
sc_time notDelay;
@@ -251,31 +244,39 @@ tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &payload, tlm_phas
unsigned int row = DramExtension::getExtension(payload).getRow().ID();
unsigned int col = DramExtension::getExtension(payload).getColumn().ID();
if (phase == BEGIN_REQ)
{
if (phase == BEGIN_REQ) {
recTime = fwDelay + sc_time_stamp();
notDelay = clkAlign(sc_time_stamp() + fwDelay) - (sc_time_stamp() + fwDelay) + Configuration::getInstance().memSpec.clk;
notDelay = clkAlign(sc_time_stamp() + fwDelay) - (sc_time_stamp() + fwDelay) +
Configuration::getInstance().memSpec.clk;
printDebugMessage("[fw] Recording " + phaseNameToString(phase) + " thread " + to_string(thr) + " channel " + to_string(ch) + " bank group " + to_string(bg) + " bank " + to_string(bank) + " row " + to_string(row) + " column " + to_string(col) + " at " + recTime.to_string() + " notification in " + notDelay.to_string());
printDebugMessage("[fw] Recording " + phaseNameToString(
phase) + " thread " + to_string(thr) + " channel " + to_string(
ch) + " bank group " + to_string(bg) + " bank " + to_string(
bank) + " row " + to_string(row) + " column " + to_string(
col) + " at " + recTime.to_string() + " notification in " +
notDelay.to_string());
tlmRecorder->recordPhase(payload, phase, recTime);
frontendPEQ.notify(payload, phase, notDelay);
//Bandwidth IDLE
if ((getTotalNumberOfPayloadsInSystem()== 0)&& idleState){
if ((getTotalNumberOfPayloadsInSystem() == 0) && idleState) {
endBandwidthIdleCollector();
}
}
else if (phase == END_RESP)
{
} else if (phase == END_RESP) {
recTime = fwDelay + sc_time_stamp() + Configuration::getInstance().memSpec.clk;
notDelay = clkAlign(sc_time_stamp() + fwDelay) - (sc_time_stamp() + fwDelay);
printDebugMessage("[fw] Recording " + phaseNameToString(phase) + " thread " + to_string(thr) + " channel " + to_string(ch) + " bank group " + to_string(bg) + " bank " + to_string(bank) + " row " + to_string(row) + " column " + to_string(col) + " at " + recTime.to_string() + " notification in " + notDelay.to_string());
printDebugMessage("[fw] Recording " + phaseNameToString(
phase) + " thread " + to_string(thr) + " channel " + to_string(
ch) + " bank group " + to_string(bg) + " bank " + to_string(
bank) + " row " + to_string(row) + " column " + to_string(
col) + " at " + recTime.to_string() + " notification in " +
notDelay.to_string());
// Badnwith IDLE
if (getTotalNumberOfPayloadsInSystem()==1){
if (getTotalNumberOfPayloadsInSystem() == 1) {
startBandwidthIdleCollector();
}
@@ -286,20 +287,21 @@ tlm_sync_enum Controller::nb_transport_fw(tlm_generic_payload &payload, tlm_phas
return TLM_ACCEPTED;
}
unsigned int Controller::transport_dbg(tlm::tlm_generic_payload& trans)
unsigned int Controller::transport_dbg(tlm::tlm_generic_payload &trans)
{
return iSocket->transport_dbg(trans);
}
void Controller::frontendPEQCallback(tlm_generic_payload &payload, const tlm_phase &phase)
void Controller::frontendPEQCallback(tlm_generic_payload &payload,
const tlm_phase &phase)
{
if (phase == BEGIN_REQ)
{
printDebugMessage(string("Payload in system: ") + to_string(getTotalNumberOfPayloadsInSystem()));
if (phase == BEGIN_REQ) {
printDebugMessage(string("Payload in system: ") + to_string(
getTotalNumberOfPayloadsInSystem()));
payload.acquire();
payloadEntersSystem(payload);
if (getTotalNumberOfPayloadsInSystem() > controllerCore->config.MaxNrOfTransactions)
{
if (getTotalNumberOfPayloadsInSystem() >
controllerCore->config.MaxNrOfTransactions) {
printDebugMessage("##Backpressure: Max number of transactions in system reached");
backpressure = &payload;
return;
@@ -309,16 +311,11 @@ void Controller::frontendPEQCallback(tlm_generic_payload &payload, const tlm_pha
scheduler->schedule(&payload);
scheduleNextFromScheduler(DramExtension::getExtension(payload).getBank());
}
else if (phase == PendingRequest)
{
// Schedule a pending request.
scheduleNextFromScheduler(DramExtension::getExtension(payload).getBank());
}
else if (phase == END_RESP)
{
if (backpressure != NULL)
{
} else if (phase == PendingRequest) {
// Schedule a pending request.
scheduleNextFromScheduler(DramExtension::getExtension(payload).getBank());
} else if (phase == END_RESP) {
if (backpressure != NULL) {
printDebugMessage("##Backpressure released");
backpressure->set_response_status(tlm::TLM_OK_RESPONSE);
sendToFrontend(*backpressure, END_REQ, SC_ZERO_TIME);
@@ -330,10 +327,9 @@ void Controller::frontendPEQCallback(tlm_generic_payload &payload, const tlm_pha
payloadLeavesSystem(payload);
payload.release();
}
else
{
SC_REPORT_FATAL(0, "Frontend PEQ event queue in controller wrapper was triggered with unknown phase");
} else {
SC_REPORT_FATAL(0,
"Frontend PEQ event queue in controller wrapper was triggered with unknown phase");
}
}
@@ -341,13 +337,14 @@ void Controller::payloadEntersSystem(tlm_generic_payload &payload)
{
Bank bank = DramExtension::getExtension(payload).getBank();
printDebugMessage(
"Payload enters system on bank " + to_string(bank.ID()) + ". Total number of payloads in Controller: "
+ to_string(getTotalNumberOfPayloadsInSystem()));
"Payload enters system on bank " + to_string(bank.ID()) +
". Total number of payloads in Controller: "
+ to_string(getTotalNumberOfPayloadsInSystem()));
numberOfPayloadsInSystem[bank]++;
// Set Start Time for Simulation
if (startTimeSet == false){
if (startTimeSet == false) {
printDebugMessage("Simulation Timer Start");
startTime = sc_time_stamp()-Configuration::getInstance().memSpec.clk;
startTime = sc_time_stamp() - Configuration::getInstance().memSpec.clk;
startTimeSet = true;
}
}
@@ -357,16 +354,16 @@ void Controller::payloadLeavesSystem(tlm_generic_payload &payload)
Bank bank = DramExtension::getExtension(payload).getBank();
numberOfPayloadsInSystem[bank]--;
printDebugMessage(
"Payload left system on bank " + to_string(bank.ID()) + ". Total number of payloads in Controller: "
+ to_string(getTotalNumberOfPayloadsInSystem()));
"Payload left system on bank " + to_string(bank.ID()) +
". Total number of payloads in Controller: "
+ to_string(getTotalNumberOfPayloadsInSystem()));
controllerCore->powerDownManager->triggerSleep(bank, sc_time_stamp());
}
unsigned int Controller::getTotalNumberOfPayloadsInSystem()
{
unsigned int sum = 0;
for (Bank bank : controllerCore->getBanks())
{
for (Bank bank : controllerCore->getBanks()) {
sum += numberOfPayloadsInSystem[bank];
}
return sum;
@@ -375,27 +372,26 @@ unsigned int Controller::getTotalNumberOfPayloadsInSystem()
void Controller::scheduleNextFromScheduler(Bank bank)
{
if(controllerCore->bankIsBusy(bank))
{
if (controllerCore->bankIsBusy(bank)) {
return;
}
bool rescheduled = true;
pair<Command, tlm::tlm_generic_payload*> nextRequest = scheduler->getNextRequest(bank);
if(nextRequest.second != NULL)
{
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(nextRequest.second).getBank(), sc_time_stamp());
pair<Command, tlm::tlm_generic_payload *> nextRequest =
scheduler->getNextRequest(bank);
if (nextRequest.second != NULL) {
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(
nextRequest.second).getBank(), sc_time_stamp());
controllerCore->scheduleRequest(nextRequest.first, *nextRequest.second);
printDebugMessage("\t-> Next payload was scheduled by core [" + commandToString(nextRequest.first) + "]");
}
else
{
gp* pendingRequest = scheduler->getPendingRequest(bank);
if (pendingRequest != NULL)
{
rescheduled = true;
frontendPEQ.notify(*(pendingRequest), PendingRequest, Configuration::getInstance().memSpec.clk);
}
printDebugMessage("\t-> Next payload was scheduled by core [" + commandToString(
nextRequest.first) + "]");
} else {
gp *pendingRequest = scheduler->getPendingRequest(bank);
if (pendingRequest != NULL) {
rescheduled = true;
frontendPEQ.notify(*(pendingRequest), PendingRequest,
Configuration::getInstance().memSpec.clk);
}
}
queue<Bank> blocked;
@@ -403,24 +399,23 @@ void Controller::scheduleNextFromScheduler(Bank bank)
bank = blockedRequests.front();
blockedRequests.pop();
pair<Command, tlm::tlm_generic_payload*> nextRequest = scheduler->getNextRequest(bank);
pair<Command, tlm::tlm_generic_payload *> nextRequest =
scheduler->getNextRequest(bank);
if (nextRequest.second != NULL) {
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(nextRequest.second).getBank(), sc_time_stamp());
controllerCore->powerDownManager->wakeUp(DramExtension::getExtension(
nextRequest.second).getBank(), sc_time_stamp());
controllerCore->scheduleRequest(nextRequest.first, *nextRequest.second);
printDebugMessage("\t-> Next payload was scheduled by core [" + commandToString(nextRequest.first) + "] (unblocked)");
}
else
{
gp* pendingRequest = scheduler->getPendingRequest(bank);
if(pendingRequest != NULL)
{
printDebugMessage("\t-> Next payload was scheduled by core [" + commandToString(
nextRequest.first) + "] (unblocked)");
} else {
gp *pendingRequest = scheduler->getPendingRequest(bank);
if (pendingRequest != NULL) {
//Pending request
if(!rescheduled)
{
if (!rescheduled) {
rescheduled = true;
frontendPEQ.notify(*(pendingRequest), PendingRequest, Configuration::getInstance().memSpec.clk);
}
else
frontendPEQ.notify(*(pendingRequest), PendingRequest,
Configuration::getInstance().memSpec.clk);
} else
blocked.push(bank);
}
}
@@ -428,14 +423,16 @@ void Controller::scheduleNextFromScheduler(Bank bank)
blockedRequests = blocked;
}
void Controller::sendToFrontend(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay)
void Controller::sendToFrontend(tlm_generic_payload &payload,
const tlm_phase &phase, const sc_time &delay)
{
tlm_phase TPhase = phase;
sc_time TDelay = delay;
tSocket->nb_transport_bw(payload, TPhase, TDelay);
}
tlm_sync_enum Controller::nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase, sc_time &bwDelay)
tlm_sync_enum Controller::nb_transport_bw(tlm_generic_payload &payload,
tlm_phase &phase, sc_time &bwDelay)
{
sc_time recTime = bwDelay + sc_time_stamp();
sc_time notDelay = bwDelay;
@@ -447,7 +444,12 @@ tlm_sync_enum Controller::nb_transport_bw(tlm_generic_payload &payload, tlm_phas
unsigned int row = DramExtension::getExtension(payload).getRow().ID();
unsigned int col = DramExtension::getExtension(payload).getColumn().ID();
printDebugMessage("[bw] Recording " + phaseNameToString(phase) + " thread " + to_string(thr) + " channel " + to_string(ch) + " bank group " + to_string(bg) + " bank " + to_string(bank) + " row " + to_string(row) + " column " + to_string(col) + " at " + recTime.to_string() + " notification in " + notDelay.to_string());
printDebugMessage("[bw] Recording " + phaseNameToString(
phase) + " thread " + to_string(thr) + " channel " + to_string(
ch) + " bank group " + to_string(bg) + " bank " + to_string(
bank) + " row " + to_string(row) + " column " + to_string(
col) + " at " + recTime.to_string() + " notification in " +
notDelay.to_string());
dramPEQ.notify(payload, phase, notDelay);
tlmRecorder->recordPhase(payload, phase, recTime);
@@ -455,71 +457,57 @@ tlm_sync_enum Controller::nb_transport_bw(tlm_generic_payload &payload, tlm_phas
return TLM_ACCEPTED;
}
void Controller::dramPEQCallback(tlm_generic_payload &payload, const tlm_phase &phase)
void Controller::dramPEQCallback(tlm_generic_payload &payload,
const tlm_phase &phase)
{
Bank bank = DramExtension::getExtension(payload).getBank();
printDebugMessage("Received " + phaseNameToString(phase) + " on bank " + to_string(bank.ID()) + " from DRAM");
printDebugMessage("Received " + phaseNameToString(phase) + " on bank " +
to_string(bank.ID()) + " from DRAM");
if (phase == END_RD || phase == END_WR)
{
if (phase == END_RD || phase == END_WR) {
sendToFrontend(payload, BEGIN_RESP, SC_ZERO_TIME);
}
else if (phase == END_RDA || phase == END_WRA)
{
} else if (phase == END_RDA || phase == END_WRA) {
sendToFrontend(payload, BEGIN_RESP, SC_ZERO_TIME);
scheduleNextFromScheduler(bank);
}
else if (phase == END_REFA)
{
} else if (phase == END_REFA) {
printDebugMessage("Finished auto refresh on all banks ");
bool sleepy = true;
for(Bank bank : controllerCore->getBanks())
{
if(numberOfPayloadsInSystem[bank] != 0)
{
for (Bank bank : controllerCore->getBanks()) {
if (numberOfPayloadsInSystem[bank] != 0) {
sleepy = false;
scheduleNextFromScheduler(bank);
}
}
if(sleepy == true)
{
controllerCore->powerDownManager->sleep(0,sc_time_stamp());
if (sleepy == true) {
controllerCore->powerDownManager->sleep(0, sc_time_stamp());
}
}
else if(phase == END_REFB)
{
} else if (phase == END_REFB) {
printDebugMessage("Finished auto refresh on bank " + to_string(bank.ID()));
if(numberOfPayloadsInSystem[bank] == 0)
{
controllerCore->powerDownManager->sleep(bank,sc_time_stamp());
}
else
{
if (numberOfPayloadsInSystem[bank] == 0) {
controllerCore->powerDownManager->sleep(bank, sc_time_stamp());
} else {
scheduleNextFromScheduler(bank);
}
scheduleNextFromScheduler(bank);
}
else if (containsPhase(phase, { END_PRE, END_ACT }))
{
} else if (containsPhase(phase, { END_PRE, END_ACT })) {
scheduleNextFromScheduler(bank);
}
else if(phase == END_PRE_ALL)
{
else if (phase == END_PRE_ALL) {
// No need to trigger anything for a END_PRE_ALL. It is followed by a AUTO_REFRESH anyway (in our current
// scheduler implementation)
}
else
{
string str = string("dramPEQCallback queue in controller wrapper was triggered with unsupported phase ")
+ phaseNameToString(phase);
} else {
string str =
string("dramPEQCallback queue in controller wrapper was triggered with unsupported phase ")
+ phaseNameToString(phase);
SC_REPORT_FATAL(0, str.c_str());
}
}
void Controller::sendToDram(tlm_generic_payload &payload, const tlm_phase &phase, const sc_time &delay)
void Controller::sendToDram(tlm_generic_payload &payload,
const tlm_phase &phase, const sc_time &delay)
{
tlm_phase TPhase = phase;
sc_time TDelay = delay;
@@ -533,8 +521,7 @@ void Controller::printDebugMessage(string message)
bool Controller::containsPhase(tlm_phase phase, std::vector<tlm_phase> phases)
{
for (tlm_phase p : phases)
{
for (tlm_phase p : phases) {
if (p == phase)
return true;
}
@@ -548,15 +535,11 @@ void Controller::end_of_simulation()
void Controller::terminateSimulation()
{
if(Configuration::getInstance().BankwiseLogic)
{
for (Bank bank : controllerCore->getBanks())
{
if (Configuration::getInstance().BankwiseLogic) {
for (Bank bank : controllerCore->getBanks()) {
controllerCore->powerDownManager->wakeUp(bank, clkAlign(sc_time_stamp()));
}
}
else
{
} else {
controllerCore->powerDownManager->wakeUp(0, clkAlign(sc_time_stamp()));
}
@@ -574,24 +557,25 @@ void Controller::startBandwidthIdleCollector()
void Controller::endBandwidthIdleCollector()
{
printDebugMessage("IDLE End");
idleTime += sc_time_stamp()-idleStart+ Configuration::getInstance().memSpec.clk;
idleTime += sc_time_stamp() - idleStart +
Configuration::getInstance().memSpec.clk;
idleState = false;
}
sc_time Controller::getIdleTime()
{
printDebugMessage("IDLE Time: "+idleTime.to_string());
printDebugMessage("IDLE Time: " + idleTime.to_string());
return idleTime;
}
sc_time Controller::getEndTime()
{
printDebugMessage("End Time: "+endTime.to_string());
printDebugMessage("End Time: " + endTime.to_string());
return endTime;
}
sc_time Controller::getStartTime()
{
printDebugMessage("Start Time: "+startTime.to_string());
printDebugMessage("Start Time: " + startTime.to_string());
return startTime;
}

View File

@@ -81,7 +81,10 @@ class Controller: public sc_module, public IController
{
public:
Controller(sc_module_name /*name*/, TlmRecorder *rec) :
frontendPEQ(this, &Controller::frontendPEQCallback), dramPEQ(this, &Controller::dramPEQCallback), controllerCorePEQ(this, &Controller::controllerCorePEQCallback), debugManager(DebugManager::getInstance()), tlmRecorder(rec)
frontendPEQ(this, &Controller::frontendPEQCallback), dramPEQ(this,
&Controller::dramPEQCallback), controllerCorePEQ(this,
&Controller::controllerCorePEQCallback),
debugManager(DebugManager::getInstance()), tlmRecorder(rec)
{
controllerCore = new ControllerCore("core", *this, numberOfPayloadsInSystem);
buildScheduler();
@@ -103,51 +106,61 @@ public:
sc_time getStartTime();
// ------- CONTROLLER CORE ---------
virtual void send(const ScheduledCommand& command, tlm_generic_payload& payload) override;
virtual void send(Trigger trigger, sc_time time, tlm_generic_payload& payload) override;
virtual void send(const ScheduledCommand &command,
tlm_generic_payload &payload) override;
virtual void send(Trigger trigger, sc_time time,
tlm_generic_payload &payload) override;
tlm_utils::simple_initiator_socket<Controller> iSocket;
tlm_utils::simple_target_socket<Controller> tSocket;
unsigned int getTotalNumberOfPayloadsInSystem();
void scheduleNextFromScheduler(Bank bank) override;
static unsigned int ControllerThreadId() {return controllerThreadId;}
static unsigned int ControllerThreadId()
{
return controllerThreadId;
}
private:
void buildScheduler();
void payloadEntersSystem(tlm_generic_payload& payload);
void payloadLeavesSystem(tlm_generic_payload& payload);
void payloadEntersSystem(tlm_generic_payload &payload);
void payloadLeavesSystem(tlm_generic_payload &payload);
// --- FRONTEND ------
tlm_sync_enum nb_transport_fw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& fwDelay);
virtual unsigned int transport_dbg(tlm::tlm_generic_payload& trans);
void frontendPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase);
void sendToFrontend(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay);
tlm_sync_enum nb_transport_fw(tlm_generic_payload &payload, tlm_phase &phase,
sc_time &fwDelay);
virtual unsigned int transport_dbg(tlm::tlm_generic_payload &trans);
void frontendPEQCallback(tlm_generic_payload &payload, const tlm_phase &phase);
void sendToFrontend(tlm_generic_payload &payload, const tlm_phase &phase,
const sc_time &delay);
// --- DRAM ------
tlm_sync_enum nb_transport_bw(tlm_generic_payload& payload, tlm_phase& phase, sc_time& bwDelay);
void dramPEQCallback(tlm_generic_payload& payload, const tlm_phase& phase);
void sendToDram(tlm_generic_payload& payload, const tlm_phase& phase, const sc_time& delay);
tlm_sync_enum nb_transport_bw(tlm_generic_payload &payload, tlm_phase &phase,
sc_time &bwDelay);
void dramPEQCallback(tlm_generic_payload &payload, const tlm_phase &phase);
void sendToDram(tlm_generic_payload &payload, const tlm_phase &phase,
const sc_time &delay);
// ------- CONTROLLER CORE ---------
void controllerCorePEQCallback(tlm_generic_payload& payload, const tlm_phase& phase);
void controllerCorePEQCallback(tlm_generic_payload &payload,
const tlm_phase &phase);
// Helpers TODO move them
void printDebugMessage(string message);
bool containsPhase(tlm_phase phase, std::vector<tlm_phase> phases);
ControllerCore* controllerCore;
ControllerCore *controllerCore;
//Scheduler* scheduler;
IScheduler* scheduler;
IScheduler *scheduler;
std::map<Bank, int> numberOfPayloadsInSystem;
std::vector<gp* > refreshCollisionRequets;
tlm::tlm_generic_payload* backpressure = NULL;
std::vector<gp * > refreshCollisionRequets;
tlm::tlm_generic_payload *backpressure = NULL;
tlm_utils::peq_with_cb_and_phase<Controller> frontendPEQ;
tlm_utils::peq_with_cb_and_phase<Controller> dramPEQ;
tlm_utils::peq_with_cb_and_phase<Controller> controllerCorePEQ;
DebugManager& debugManager;
DebugManager &debugManager;
TlmRecorder *tlmRecorder;
// Bandwidth realted:

View File

@@ -41,7 +41,8 @@
using namespace std;
const ScheduledCommand ControllerState::getLastCommand(Command command, Bank bank) //TODO const reference? and make const
const ScheduledCommand ControllerState::getLastCommand(Command command,
Bank bank) //TODO const reference? and make const
{
return lastScheduledByCommandAndBank[command][bank];
}
@@ -50,8 +51,7 @@ const ScheduledCommand ControllerState::getLastCommand(Command command)
{
ScheduledCommand max;
for (unsigned int i = 0; i < config->memSpec.NumberOfBanks; ++i)
{
for (unsigned int i = 0; i < config->memSpec.NumberOfBanks; ++i) {
ScheduledCommand current = getLastCommand(command, Bank(i));
if (current.getStart() > max.getStart())
max = current;
@@ -64,17 +64,16 @@ const ScheduledCommand ControllerState::getLastScheduledCommand()
{
ScheduledCommand lastCommand;
for(Command cmd : getAllCommands())
{
for(Bank bank : Configuration::getInstance().memSpec.getBanks())
{
ScheduledCommand& current = lastScheduledByCommandAndBank[cmd][bank];
for (Command cmd : getAllCommands()) {
for (Bank bank : Configuration::getInstance().memSpec.getBanks()) {
ScheduledCommand &current = lastScheduledByCommandAndBank[cmd][bank];
if (current.getStart() > lastCommand.getStart())
lastCommand = current;
}
}
printDebugMessage("Last scheduled command was " + commandToString(lastCommand.getCommand()));
printDebugMessage("Last scheduled command was " + commandToString(
lastCommand.getCommand()));
return lastCommand;
}
@@ -83,27 +82,29 @@ const ScheduledCommand ControllerState::getLastScheduledCommand(Bank bank)
{
ScheduledCommand lastCommand;
for(Command cmd : getAllCommands())
{
ScheduledCommand& current = lastScheduledByCommandAndBank[cmd][bank];
for (Command cmd : getAllCommands()) {
ScheduledCommand &current = lastScheduledByCommandAndBank[cmd][bank];
if (current.getStart() > lastCommand.getStart())
lastCommand = current;
}
printDebugMessage("Last scheduled command on bank " + to_string(bank.ID()) + " was " + commandToString(lastCommand.getCommand()));
printDebugMessage("Last scheduled command on bank " + to_string(
bank.ID()) + " was " + commandToString(lastCommand.getCommand()));
return lastCommand;
}
void ControllerState::change(const ScheduledCommand& scheduledCommand)
void ControllerState::change(const ScheduledCommand &scheduledCommand)
{
bus.blockSlot(scheduledCommand.getStart());
printDebugMessage("Changing state on bank " + to_string(scheduledCommand.getBank().ID()) + " command is " + commandToString(scheduledCommand.getCommand()));
lastScheduledByCommandAndBank[scheduledCommand.getCommand()][scheduledCommand.getBank()] = scheduledCommand;
printDebugMessage("Changing state on bank " + to_string(
scheduledCommand.getBank().ID()) + " command is " + commandToString(
scheduledCommand.getCommand()));
lastScheduledByCommandAndBank[scheduledCommand.getCommand()][scheduledCommand.getBank()]
= scheduledCommand;
switch (scheduledCommand.getCommand())
{
switch (scheduledCommand.getCommand()) {
case Command::Read:
lastDataStrobeCommands.emplace_back(scheduledCommand);
break;
@@ -121,7 +122,8 @@ void ControllerState::change(const ScheduledCommand& scheduledCommand)
case Command::AutoRefresh:
break;
case Command::Activate:
rowBufferStates->openRowInRowBuffer(scheduledCommand.getBank(), scheduledCommand.getRow());
rowBufferStates->openRowInRowBuffer(scheduledCommand.getBank(),
scheduledCommand.getRow());
lastActivates.emplace(scheduledCommand.getStart(), scheduledCommand);
break;
case Command::Precharge:
@@ -142,18 +144,19 @@ void ControllerState::cleanUp(sc_time time)
{
bus.cleanUpSlots(time);
vector<ScheduledCommand> tmp;
for(ScheduledCommand& command: lastDataStrobeCommands)
{
if(command.getEnd() >= time || getDistance(command.getEnd(), time) <= config->memSpec.tDataStrobeHistory())
for (ScheduledCommand &command : lastDataStrobeCommands) {
if (command.getEnd() >= time
|| getDistance(command.getEnd(), time) <= config->memSpec.tDataStrobeHistory())
tmp.push_back(command);
}
lastDataStrobeCommands = tmp;
if(time >= config->memSpec.tActHistory())
lastActivates.erase(lastActivates.begin(), lastActivates.lower_bound(time - config->memSpec.tActHistory()));
if (time >= config->memSpec.tActHistory())
lastActivates.erase(lastActivates.begin(),
lastActivates.lower_bound(time - config->memSpec.tActHistory()));
}
void ControllerState::printDebugMessage(std::string message)
{
DebugManager::getInstance().printDebugMessage(ownerName, message);
DebugManager::getInstance().printDebugMessage(ownerName, message);
}

View File

@@ -48,24 +48,27 @@
class ControllerState
{
public:
ControllerState(std::string ownerName, Configuration *config) : bus(config->memSpec.clk), ownerName(ownerName), config(config)
ControllerState(std::string ownerName,
Configuration *config) : bus(config->memSpec.clk), ownerName(ownerName),
config(config)
{
rowBufferStates = new RowBufferState(ownerName);
rowBufferStates = new RowBufferState(ownerName);
}
virtual ~ControllerState(){}
virtual ~ControllerState() {}
const ScheduledCommand getLastCommand(Command command, Bank bank);
const ScheduledCommand getLastCommand(Command command);
const ScheduledCommand getLastScheduledCommand(Bank bank);
const ScheduledCommand getLastScheduledCommand();
void change(const ScheduledCommand& scheduledCommand);
void change(const ScheduledCommand &scheduledCommand);
void cleanUp(sc_time time);
RowBufferState *rowBufferStates;
//used by the various checkers
std::map<Command, std::map<Bank, ScheduledCommand> > lastScheduledByCommandAndBank;
std::map<Command, std::map<Bank, ScheduledCommand> >
lastScheduledByCommandAndBank;
std::map<Command, ScheduledCommand> lastScheduledByCommand;
std::map<Bank, ScheduledCommand> lastScheduledByBank;
ScheduledCommand lastScheduled;
@@ -76,7 +79,7 @@ public:
private:
std::string ownerName;
Configuration* config;
Configuration *config;
void printDebugMessage(std::string message);
};

View File

@@ -51,8 +51,10 @@ class IController
{
public:
virtual ~IController() {}
virtual void send(const ScheduledCommand& command,tlm::tlm_generic_payload& payload) = 0;
virtual void send(Trigger trigger, sc_time time, tlm::tlm_generic_payload& payload) = 0;
virtual void send(const ScheduledCommand &command,
tlm::tlm_generic_payload &payload) = 0;
virtual void send(Trigger trigger, sc_time time,
tlm::tlm_generic_payload &payload) = 0;
virtual void scheduleNextFromScheduler(Bank bank) = 0;
std::queue<Bank> blockedRequests;

View File

@@ -43,7 +43,7 @@ using namespace std;
RowBufferState::RowBufferState(std::string ownerName) : ownerName(ownerName)
{
closeAllRowBuffers();
closeAllRowBuffers();
}
RowBufferState::~RowBufferState()
@@ -52,31 +52,33 @@ RowBufferState::~RowBufferState()
bool RowBufferState::rowBufferIsOpen(Bank bank) const
{
return getElementFromMap(rowsInRowBuffers,bank) != Row::NO_ROW;
return getElementFromMap(rowsInRowBuffers, bank) != Row::NO_ROW;
}
Row RowBufferState::getRowInRowBuffer(Bank bank) const
{
return getElementFromMap(rowsInRowBuffers,bank);
return getElementFromMap(rowsInRowBuffers, bank);
}
void RowBufferState::openRowInRowBuffer(Bank bank,Row row)
void RowBufferState::openRowInRowBuffer(Bank bank, Row row)
{
printDebugMessage("Row buffer for bank " + to_string(bank.ID()) + " is now open");
printDebugMessage("Row buffer for bank " + to_string(bank.ID()) +
" is now open");
rowsInRowBuffers[bank] = row;
}
void RowBufferState::closeRowBuffer(Bank bank)
{
printDebugMessage("Row buffer for bank " + to_string(bank.ID()) + " is now closed");
printDebugMessage("Row buffer for bank " + to_string(bank.ID()) +
" is now closed");
rowsInRowBuffers[bank] = Row::NO_ROW;
}
bool RowBufferState::allRowBuffersAreClosed() const
{
for(unsigned int i=0; i<Configuration::getInstance().memSpec.NumberOfBanks;++i)
{
if(rowBufferIsOpen(Bank(i)))
for (unsigned int i = 0; i < Configuration::getInstance().memSpec.NumberOfBanks;
++i) {
if (rowBufferIsOpen(Bank(i)))
return false;
}
return true;
@@ -84,14 +86,14 @@ bool RowBufferState::allRowBuffersAreClosed() const
void RowBufferState::closeAllRowBuffers()
{
for(unsigned int i=0; i<Configuration::getInstance().memSpec.NumberOfBanks;++i)
{
for (unsigned int i = 0; i < Configuration::getInstance().memSpec.NumberOfBanks;
++i) {
rowsInRowBuffers[Bank(i)] = Row::NO_ROW;
}
}
void RowBufferState::printDebugMessage(std::string message)
{
DebugManager::getInstance().printDebugMessage(ownerName, message);
DebugManager::getInstance().printDebugMessage(ownerName, message);
}

View File

@@ -40,7 +40,8 @@
#include <map>
#include "../common/dramExtension.h"
class RowBufferState {
class RowBufferState
{
public:
RowBufferState(std::string ownerName);
virtual ~RowBufferState();
@@ -55,7 +56,7 @@ public:
private:
std::string ownerName;
std::map<Bank,Row> rowsInRowBuffers;
std::map<Bank, Row> rowsInRowBuffers;
void printDebugMessage(std::string message);
};

View File

@@ -57,8 +57,10 @@
#include "powerdown/NoPowerDown.h"
#include "../../common/DebugManager.h"
ControllerCore::ControllerCore(sc_module_name /*name*/, IController& wrapperConnector, std::map<Bank, int>& numberOfPayloads) :
config(Configuration::getInstance()), controller(wrapperConnector), numberOfPayloads(numberOfPayloads), commandChecker()
ControllerCore::ControllerCore(sc_module_name /*name*/,
IController &wrapperConnector, std::map<Bank, int> &numberOfPayloads) :
config(Configuration::getInstance()), controller(wrapperConnector),
numberOfPayloads(numberOfPayloads), commandChecker()
{
state = new ControllerState(name(), &config);
@@ -78,36 +80,28 @@ ControllerCore::ControllerCore(sc_module_name /*name*/, IController& wrapperConn
commandChecker[Command::PDNPX] = commandChecker[Command::PDNA];
commandChecker[Command::SREFX] = commandChecker[Command::PDNA];
if (config.BankwiseLogic)
{
if (config.BankwiseLogic) {
refreshManager = new RefreshManagerBankwise("refManagerBw", *this);
}
else
{
} else {
refreshManager = new RefreshManager("refManager", *this);
}
if(config.PowerDownMode == EPowerDownMode::Staggered)
{
if (config.PowerDownMode == EPowerDownMode::Staggered) {
if (config.BankwiseLogic)
powerDownManager = new PowerDownManagerBankwise("pdnManagerBw", *this);
else
powerDownManager = new PowerDownManager("pdnManager", *this);
}
else if(config.PowerDownMode == EPowerDownMode::TimeoutPDN || config.PowerDownMode == EPowerDownMode::TimeoutSREF)
{
} else if (config.PowerDownMode == EPowerDownMode::TimeoutPDN
|| config.PowerDownMode == EPowerDownMode::TimeoutSREF) {
if (config.BankwiseLogic)
powerDownManager = new PowerDownManagerTimeoutBankwise("pdnManagerBw", *this);
else
powerDownManager = new PowerDownManagerTimeout("pdnManager", *this);
}
else if(config.PowerDownMode == EPowerDownMode::NoPowerDown)
{
} else if (config.PowerDownMode == EPowerDownMode::NoPowerDown) {
powerDownManager = new NoPowerDown();
}
else
{
SC_REPORT_FATAL(0, "Unsupported powerdown mode in constructor of controller core");
} else {
SC_REPORT_FATAL(0,
"Unsupported powerdown mode in constructor of controller core");
}
}
@@ -125,7 +119,7 @@ ControllerCore::~ControllerCore()
delete state;
}
void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload)
void ControllerCore::triggerRefresh(tlm::tlm_generic_payload &payload)
{
/* Refresh can be disabled for tests purpose */
if (config.ControllerCoreDisableRefresh == false) {
@@ -134,28 +128,27 @@ void ControllerCore::triggerRefresh(tlm::tlm_generic_payload& payload)
state->cleanUp(time);
if (!refreshManager->isInvalidated(payload, time) && !powerDownManager->isInSelfRefresh(bank))
{
if (!refreshManager->isInvalidated(payload, time)
&& !powerDownManager->isInSelfRefresh(bank)) {
printDebugMessage("Triggering refresh on bank " + to_string(bank.ID()));
powerDownManager->wakeUpForRefresh(bank, time); //expects PDNA and PDNP to exit without delay
powerDownManager->wakeUpForRefresh(bank,
time); //expects PDNA and PDNP to exit without delay
bool pdnpToSrefTransition = false;
if (config.PowerDownMode == EPowerDownMode::Staggered)
{
pdnpToSrefTransition = state->getLastCommand(Command::PDNPX,bank).getStart() >= time;
if (config.PowerDownMode == EPowerDownMode::Staggered) {
pdnpToSrefTransition = state->getLastCommand(Command::PDNPX,
bank).getStart() >= time;
}
if (pdnpToSrefTransition)
{
powerDownManager->sleep(bank,time);
}
else
{
if (pdnpToSrefTransition) {
powerDownManager->sleep(bank, time);
} else {
refreshManager->scheduleRefresh(payload, time);
}
}
}
}
void ControllerCore::scheduleRequest(Command command, tlm::tlm_generic_payload &payload)
void ControllerCore::scheduleRequest(Command command,
tlm::tlm_generic_payload &payload)
{
sc_time start = clkAlign(sc_time_stamp());
state->cleanUp(start);
@@ -164,9 +157,8 @@ void ControllerCore::scheduleRequest(Command command, tlm::tlm_generic_payload &
state->change(scheduledCommand);
controller.send(scheduledCommand, payload);
} else {
if(!((command == Command::Precharge || command == Command::Activate)
&& refreshManager->hasCollision(scheduledCommand)))
{
if (!((command == Command::Precharge || command == Command::Activate)
&& refreshManager->hasCollision(scheduledCommand))) {
state->change(scheduledCommand);
controller.send(scheduledCommand, payload);
}
@@ -174,20 +166,21 @@ void ControllerCore::scheduleRequest(Command command, tlm::tlm_generic_payload &
}
ScheduledCommand ControllerCore::schedule(Command command, sc_time start,
tlm::tlm_generic_payload& payload)
tlm::tlm_generic_payload &payload)
{
ControllerCore::printDebugMessage("Scheduling command " + commandToString(command) + " on " + DramExtension::getBank(payload).toString());
ICommandChecker& checker = getCommandChecker(command);
sc_time executionTime = getExecutionTime(command, payload);
ScheduledCommand scheduledCommand(command, start, executionTime, DramExtension::getExtension(payload));
checker.delayToSatisfyConstraints(scheduledCommand);
return scheduledCommand;
ControllerCore::printDebugMessage("Scheduling command " + commandToString(
command) + " on " + DramExtension::getBank(payload).toString());
ICommandChecker &checker = getCommandChecker(command);
sc_time executionTime = getExecutionTime(command, payload);
ScheduledCommand scheduledCommand(command, start, executionTime,
DramExtension::getExtension(payload));
checker.delayToSatisfyConstraints(scheduledCommand);
return scheduledCommand;
}
bool ControllerCore::hasPendingRequests()
{
for (Bank bank : getBanks())
{
for (Bank bank : getBanks()) {
if (numberOfPayloads[bank] != 0)
return true;
}
@@ -202,40 +195,33 @@ bool ControllerCore::bankIsBusy(Bank bank)
if (lastScheduledCommand.isNoCommand())
return false;
else if (lastScheduledCommand.commandIsIn( { Command::Write, Command::Read }))
{
else if (lastScheduledCommand.commandIsIn( { Command::Write, Command::Read })) {
// Read and writes can overlap, so the bank should not be busy during a rd/wr
return (time < lastScheduledCommand.getStart());
}
else if (lastScheduledCommand.commandIsIn( { Command::WriteA, Command::ReadA, Command::Precharge, Command::PrechargeAll, Command::Activate }))
{
else if (lastScheduledCommand.commandIsIn( { Command::WriteA, Command::ReadA, Command::Precharge, Command::PrechargeAll, Command::Activate })) {
return (time < lastScheduledCommand.getEnd());
}
else if (lastScheduledCommand.getCommand() == Command::AutoRefresh)
{
else if (lastScheduledCommand.getCommand() == Command::AutoRefresh) {
return (time < lastScheduledCommand.getEnd());
}
else if (lastScheduledCommand.commandIsIn( { Command::SREFX, Command::PDNPX, Command::PDNAX, Command::SREF, Command::PDNP,
Command::PDNA }))
{
} else if (lastScheduledCommand.commandIsIn( { Command::SREFX, Command::PDNPX, Command::PDNAX, Command::SREF, Command::PDNP,
Command::PDNA
})) {
return false;
}
else
{
else {
SC_REPORT_FATAL("Core", "Last command unkown");
return false;
}
}
const std::vector<Bank>& ControllerCore::getBanks()
const std::vector<Bank> &ControllerCore::getBanks()
{
static std::vector<Bank> banks;
if (banks.size() == 0)
{
for (unsigned int i = 0; i < config.memSpec.NumberOfBanks; i++)
{
if (banks.size() == 0) {
for (unsigned int i = 0; i < config.memSpec.NumberOfBanks; i++) {
banks.push_back(Bank(i));
}
}
@@ -246,15 +232,14 @@ const std::vector<Bank>& ControllerCore::getBanks()
std::vector<Bank> ControllerCore::getFreeBanks()
{
std::vector<Bank> freeBanks;
for(Bank bank: getBanks())
{
if(!bankIsBusy(bank))
for (Bank bank : getBanks()) {
if (!bankIsBusy(bank))
freeBanks.push_back(bank);
}
return freeBanks;
}
ICommandChecker& ControllerCore::getCommandChecker(Command command)
ICommandChecker &ControllerCore::getCommandChecker(Command command)
{
return *getElementFromMap(commandChecker, command);
}

View File

@@ -54,31 +54,36 @@ using namespace std;
class ControllerCore : public sc_module
{
public:
ControllerCore(sc_module_name /*name*/, IController& controller, std::map<Bank, int>& numberOfPayloads);
ControllerCore(sc_module_name /*name*/, IController &controller,
std::map<Bank, int> &numberOfPayloads);
virtual ~ControllerCore();
void scheduleRequest(Command command, tlm::tlm_generic_payload& payload);
void triggerRefresh(tlm::tlm_generic_payload& payload);
void scheduleRequest(Command command, tlm::tlm_generic_payload &payload);
void triggerRefresh(tlm::tlm_generic_payload &payload);
const std::vector<Bank>& getBanks();
const std::vector<Bank> &getBanks();
std::vector<Bank> getFreeBanks();
const RowBufferState& getRowBufferStates(){return *(state->rowBufferStates);}
const RowBufferState &getRowBufferStates()
{
return *(state->rowBufferStates);
}
bool hasPendingRequests();
bool bankIsBusy(Bank bank);
ICommandChecker& getCommandChecker(Command command);
ICommandChecker &getCommandChecker(Command command);
Configuration config;
ControllerState *state;
IController& controller;
IPowerDownManager* powerDownManager;
IRefreshManager* refreshManager;
std::map<Bank,int>& numberOfPayloads;
IController &controller;
IPowerDownManager *powerDownManager;
IRefreshManager *refreshManager;
std::map<Bank, int> &numberOfPayloads;
private:
ScheduledCommand schedule(Command command, sc_time start, tlm::tlm_generic_payload &payload);
std::map<Command, ICommandChecker*> commandChecker;
ScheduledCommand schedule(Command command, sc_time start,
tlm::tlm_generic_payload &payload);
std::map<Command, ICommandChecker *> commandChecker;
void printDebugMessage(string message);
};

View File

@@ -39,7 +39,7 @@
Slots::Slots(sc_time clk) :
clk(clk)
clk(clk)
{
}
@@ -48,41 +48,40 @@ Slots::~Slots()
{
}
void Slots::moveCommandToNextFreeSlot(ScheduledCommand& command)
void Slots::moveCommandToNextFreeSlot(ScheduledCommand &command)
{
while(!isFree(command.getStart()))
command.delayStart(clk);
while (!isFree(command.getStart()))
command.delayStart(clk);
}
void Slots::cleanUpSlots(sc_time time)
{
slotSet.erase(slotSet.begin(), slotSet.lower_bound(time));
slotSet.erase(slotSet.begin(), slotSet.lower_bound(time));
}
void Slots::blockSlot(sc_time time)
{
sc_assert(isClkAligned(time, clk));
slotSet.insert(time);
sc_assert(isClkAligned(time, clk));
slotSet.insert(time);
}
bool Slots::isFree(sc_time time)
{
return (slotSet.count(time) == 0);
return (slotSet.count(time) == 0);
}
void Slots::blockSlots(sc_time begin, sc_time end, bool excludeBorders)
{
sc_assert(isClkAligned(begin, clk));
sc_assert(isClkAligned(end, clk));
sc_assert(isClkAligned(begin, clk));
sc_assert(isClkAligned(end, clk));
if (excludeBorders)
{
begin += clk;
end -= clk;
}
if (excludeBorders) {
begin += clk;
end -= clk;
}
for (sc_time time = begin; time <= end; time += clk) {
blockSlot(time);
}
for (sc_time time = begin; time <= end; time += clk) {
blockSlot(time);
}
}

View File

@@ -47,7 +47,7 @@ public:
Slots(sc_time clk);
virtual ~Slots();
void moveCommandToNextFreeSlot(ScheduledCommand& command);
void moveCommandToNextFreeSlot(ScheduledCommand &command);
void cleanUpSlots(sc_time time);
void blockSlot(sc_time time);
bool isFree(sc_time);

View File

@@ -43,7 +43,8 @@
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint)
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start,
sc_time constraint)
{
if (previous + constraint > start)
return previous + constraint - start;
@@ -66,49 +67,33 @@ const sc_time clkAlign(sc_time time, Alignment alignment)
}
// Returns the execution time for commands that have a fixed execution time
sc_time getExecutionTime(Command command, tlm::tlm_generic_payload& payload)
sc_time getExecutionTime(Command command, tlm::tlm_generic_payload &payload)
{
MemSpec& config = Configuration::getInstance().memSpec;
MemSpec &config = Configuration::getInstance().memSpec;
if (command == Command::Precharge || command == Command::PrechargeAll)
{
if (command == Command::Precharge || command == Command::PrechargeAll) {
return config.tRP;
}
else if (command == Command::Activate)
{
} else if (command == Command::Activate) {
return config.tRCD;
}
else if (command == Command::Read)
{
} else if (command == Command::Read) {
return config.tRL + getReadAccessTime();
}
else if (command == Command::ReadA)
{
} else if (command == Command::ReadA) {
return config.tRTP + config.tRP;
}
else if (command == Command::Write)
{
} else if (command == Command::Write) {
return config.tWL + getWriteAccessTime();
}
else if (command == Command::WriteA)
{
} else if (command == Command::WriteA) {
return config.tWL + getWriteAccessTime() + config.tWR + config.tRP;
}
else if (command == Command::PrechargeAll)
{
} else if (command == Command::PrechargeAll) {
return config.tRP;
}
else if (command == Command::AutoRefresh)
{
return getElementFromMap(config.refreshTimings, DramExtension::getExtension(payload).getBank()).tRFC;
}
else if (command == Command::PDNAX || command == Command::PDNPX || command == Command::SREFX)
{
} else if (command == Command::AutoRefresh) {
return getElementFromMap(config.refreshTimings,
DramExtension::getExtension(payload).getBank()).tRFC;
} else if (command == Command::PDNAX || command == Command::PDNPX
|| command == Command::SREFX) {
return config.clk;
}
else
{
SC_REPORT_FATAL("getExecutionTime", "command not known or command doesn't have a fixed execution time");
} else {
SC_REPORT_FATAL("getExecutionTime",
"command not known or command doesn't have a fixed execution time");
return SC_ZERO_TIME;
}
}
@@ -116,18 +101,14 @@ sc_time getExecutionTime(Command command, tlm::tlm_generic_payload& payload)
// Returns the minimum execution time for commands that have a variable execution time
sc_time getMinExecutionTimeForPowerDownCmd(Command command)
{
MemSpec& config = Configuration::getInstance().memSpec;
if (command == Command::PDNA || command == Command::PDNP)
{
MemSpec &config = Configuration::getInstance().memSpec;
if (command == Command::PDNA || command == Command::PDNP) {
return config.tCKE;
}
else if (command == Command::SREF)
{
} else if (command == Command::SREF) {
return config.tCKESR;
}
else
{
SC_REPORT_FATAL("getMinimalExecutionTime", "command is not know or command has a fixed execution time");
} else {
SC_REPORT_FATAL("getMinimalExecutionTime",
"command is not know or command has a fixed execution time");
return SC_ZERO_TIME;
}
}
@@ -140,21 +121,20 @@ bool isClkAligned(sc_time time, sc_time clk)
sc_time getReadAccessTime()
{
Configuration& config = Configuration::getInstance();
return (config.memSpec.BurstLength / config.memSpec.DataRate)*config.memSpec.clk;
Configuration &config = Configuration::getInstance();
return (config.memSpec.BurstLength / config.memSpec.DataRate) *
config.memSpec.clk;
}
sc_time getWriteAccessTime()
{
Configuration& config = Configuration::getInstance();
Configuration &config = Configuration::getInstance();
if (config.memSpec.DataRate == 1)
{
if (config.memSpec.DataRate == 1) {
return config.memSpec.clk * (config.memSpec.BurstLength);
}
else
{
return config.memSpec.clk * (config.memSpec.BurstLength / config.memSpec.DataRate);
} else {
return config.memSpec.clk * (config.memSpec.BurstLength /
config.memSpec.DataRate);
}
}

View File

@@ -44,11 +44,12 @@
sc_time getMinExecutionTimeForPowerDownCmd(Command command);
sc_time getExecutionTime(Command command, tlm::tlm_generic_payload& payload);
sc_time getExecutionTime(Command command, tlm::tlm_generic_payload &payload);
sc_time getReadAccessTime();
sc_time getWriteAccessTime();
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start, sc_time constraint);
sc_time getDelayToMeetConstraint(sc_time previous, sc_time start,
sc_time constraint);
enum Alignment {UP, DOWN};
const sc_time clkAlign(sc_time time, Alignment alignment = UP);

View File

@@ -53,16 +53,11 @@ Configuration::Configuration()
bool string2bool(string s)
{
if(s.compare("0") == 0)
{
if (s.compare("0") == 0) {
return false;
}
else if(s.compare("1") == 0)
{
} else if (s.compare("1") == 0) {
return true;
}
else
{
} else {
SC_REPORT_FATAL("Configuration", ("Could not convert to bool: " + s).c_str());
return false;
}
@@ -80,14 +75,13 @@ unsigned long long string2ull(string s)
StorageMode string2StoreMode(string s)
{
if(s == "NoStorage")
if (s == "NoStorage")
return StorageMode::NoStorage;
else if(s == "Store")
else if (s == "Store")
return StorageMode::Store;
else if (s == "ErrorModel")
return StorageMode::ErrorModel;
else
{
else {
SC_REPORT_FATAL("Configuration", ("Unknown StorageMode: " + s).c_str());
throw;
}
@@ -95,16 +89,15 @@ StorageMode string2StoreMode(string s)
EPowerDownMode string2PDNMode(string s)
{
if(s == "NoPowerDown")
if (s == "NoPowerDown")
return EPowerDownMode::NoPowerDown;
else if(s == "Staggered")
else if (s == "Staggered")
return EPowerDownMode::Staggered;
else if (s == "TimeoutPDN")
return EPowerDownMode::TimeoutPDN;
else if (s == "TimeoutSREF")
return EPowerDownMode::TimeoutSREF;
else
{
else {
SC_REPORT_FATAL("Configuration", ("Unknown PowerDownMode: " + s).c_str());
throw;
}
@@ -112,15 +105,14 @@ EPowerDownMode string2PDNMode(string s)
ECCControllerMode string2ECCControllerMode(string s)
{
if(s == "Disabled")
return ECCControllerMode::Disabled;
else if(s == "Hamming")
return ECCControllerMode::Hamming;
else
{
SC_REPORT_FATAL("Configuration", ("Unknown ECCControllerMode: " + s).c_str());
throw;
}
if (s == "Disabled")
return ECCControllerMode::Disabled;
else if (s == "Hamming")
return ECCControllerMode::Hamming;
else {
SC_REPORT_FATAL("Configuration", ("Unknown ECCControllerMode: " + s).c_str());
throw;
}
}
enum sc_time_unit string2TimeUnit(string s)
@@ -138,131 +130,133 @@ enum sc_time_unit string2TimeUnit(string s)
else if (s == "fs")
return SC_FS;
else {
SC_REPORT_FATAL("Configuration", ("Could not convert to enum sc_time_unit: " + s).c_str());
SC_REPORT_FATAL("Configuration",
("Could not convert to enum sc_time_unit: " + s).c_str());
throw;
}
}
void Configuration::setParameter(std::string name, std::string value)
{
if(name == "BankwiseLogic")
if (name == "BankwiseLogic")
BankwiseLogic = string2bool(value);
else if(name == "OpenPagePolicy")
else if (name == "OpenPagePolicy")
OpenPagePolicy = string2bool(value);
else if(name == "MaxNrOfTransactions")
else if (name == "MaxNrOfTransactions")
MaxNrOfTransactions = string2int(value);
else if(name == "Scheduler")
else if (name == "Scheduler")
Scheduler = value;
else if(name == "SJFProbability")
if (string2int(value) > 100 || string2int(value) < 0) {
SC_REPORT_FATAL("Configuration", ("Invalid value for parameter " + name + ". This parameter must be between 0 and 100.").c_str());
} else {
SJFProbability = string2int(value);
}
else if (name == "SJFProbability")
if (string2int(value) > 100 || string2int(value) < 0) {
SC_REPORT_FATAL("Configuration",
("Invalid value for parameter " + name +
". This parameter must be between 0 and 100.").c_str());
} else {
SJFProbability = string2int(value);
}
else if (name == "RequestBufferSize")
RequestBufferSize = string2int(value);
else if(name == "Capsize")
RequestBufferSize = string2int(value);
else if (name == "Capsize")
Capsize = string2int(value);
else if(name == "PowerDownTimeout")
else if (name == "PowerDownTimeout")
powerDownTimeoutInClk = string2int(value);
else if(name == "PowerDownMode")
else if (name == "PowerDownMode")
PowerDownMode = string2PDNMode(value);
else if(name == "ReadWriteGrouping")
else if (name == "ReadWriteGrouping")
ReadWriteGrouping = string2bool(value);
else if(name == "ReorderBuffer")
else if (name == "ReorderBuffer")
ReorderBuffer = string2bool(value);
//SimConfig------------------------------------------------
else if(name == "SimulationName")
else if (name == "SimulationName")
SimulationName = value;
else if(name == "DatabaseRecording")
else if (name == "DatabaseRecording")
DatabaseRecording = string2bool(value);
else if(name == "PowerAnalysis")
else if (name == "PowerAnalysis")
PowerAnalysis = string2bool(value);
else if (name == "EnableWindowing")
EnableWindowing = string2bool(value);
else if(name == "WindowSize")
if(string2int(value) < 1) {
SC_REPORT_FATAL("Configuration", ("Invalid value for parameter " + name + ". This parameter must be at least one.").c_str());
}
else
else if (name == "WindowSize")
if (string2int(value) < 1) {
SC_REPORT_FATAL("Configuration",
("Invalid value for parameter " + name +
". This parameter must be at least one.").c_str());
} else
WindowSize = string2int(value);
else if(name == "Debug")
else if (name == "Debug")
Debug = string2bool(value);
else if (name == "NumberOfMemChannels") {
NumberOfMemChannels = string2int(value);
unsigned int maxNumberofMemChannels = xmlAddressDecoder::getInstance().amount["channel"];
if (NumberOfMemChannels > maxNumberofMemChannels) {
unsigned int maxNumberofMemChannels =
AddressDecoder::getInstance().amount["channel"];
if (NumberOfMemChannels > maxNumberofMemChannels) {
SC_REPORT_FATAL("Configuration", ("Invalid value for parameter "
+ name
+ ". Value is out of range. The maximum value according to "
+ "the address mapping configuration file is "
+ std::to_string(maxNumberofMemChannels) + ".").c_str());
}
}
else if (name == "ControllerCoreDisableRefresh")
}
} else if (name == "ControllerCoreDisableRefresh")
ControllerCoreDisableRefresh = string2bool(value);
else if (name == "ControllerCoreForceMaxRefBurst")
ControllerCoreForceMaxRefBurst = string2bool(value);
else if (name == "ControllerCoreEnableRefPostpone")
{
else if (name == "ControllerCoreEnableRefPostpone") {
ControllerCoreEnableRefPostpone = string2bool(value);
// Refresh postpone feature available for DDR3 only in the current
// version of DRAMsys.
if (ControllerCoreEnableRefPostpone && memSpec.MemoryType != "DDR3") {
SC_REPORT_FATAL("Configuration", (name + " requires memory type DDR3.").c_str());
SC_REPORT_FATAL("Configuration",
(name + " requires memory type DDR3.").c_str());
}
}
else if (name == "ControllerCoreEnableRefPullIn")
{
} else if (name == "ControllerCoreEnableRefPullIn") {
ControllerCoreEnableRefPullIn = string2bool(value);
// Refresh pull-in feature available for DDR3 only in the current
// version of DRAMsys.
if (ControllerCoreEnableRefPullIn && memSpec.MemoryType != "DDR3") {
SC_REPORT_FATAL("Configuration", (name + " requires memory type DDR3.").c_str());
SC_REPORT_FATAL("Configuration",
(name + " requires memory type DDR3.").c_str());
}
}
else if (name == "ControllerCoreMaxPostponedARCmd")
} else if (name == "ControllerCoreMaxPostponedARCmd")
ControllerCoreMaxPostponedARCmd = string2int(value);
else if (name == "ControllerCoreMaxPulledInARCmd")
ControllerCoreMaxPulledInARCmd = string2int(value);
else if (name == "ThermalSimulation")
ThermalSimulation = string2bool(value);
else if(name == "SimulationProgressBar")
else if (name == "SimulationProgressBar")
SimulationProgressBar = string2bool(value);
else if(name == "NumberOfDevicesOnDIMM")
if (string2int(value) < 1) {
SC_REPORT_FATAL("Configuration", ("Invalid value for parameter " + name + ". This parameter must be at least one.").c_str());
} else
NumberOfDevicesOnDIMM = string2int(value);
else if(name == "AddressOffset")
{
else if (name == "NumberOfDevicesOnDIMM")
if (string2int(value) < 1) {
SC_REPORT_FATAL("Configuration",
("Invalid value for parameter " + name +
". This parameter must be at least one.").c_str());
} else
NumberOfDevicesOnDIMM = string2int(value);
else if (name == "AddressOffset") {
#ifdef DRAMSYS_GEM5
AddressOffset = string2ull(value);
#else
AddressOffset = 0;
#endif
cout << "Address Offset: " << AddressOffset << endl;
}
else if(name == "CheckTLM2Protocol")
} else if (name == "CheckTLM2Protocol")
CheckTLM2Protocol = string2bool(value);
else if(name == "ECCControllerMode")
ECCMode = string2ECCControllerMode(value);
else if (name == "ECCControllerMode")
ECCMode = string2ECCControllerMode(value);
// Specification for ErrorChipSeed, ErrorCSVFile path and StoreMode
else if(name == "ErrorChipSeed")
else if (name == "ErrorChipSeed")
ErrorChipSeed = string2int(value);
else if(name == "ErrorCSVFile")
else if (name == "ErrorCSVFile")
ErrorCSVFile = value;
else if(name == "StoreMode")
else if (name == "StoreMode")
StoreMode = string2StoreMode(value);
// Temperature Simulation related
else if (name == "TemperatureScale") {
if (value != "Celsius" && value != "Fahrenheit" && value != "Kelvin") {
SC_REPORT_FATAL("Configuration", ("Invalid value for parameter " + name + ".").c_str());
SC_REPORT_FATAL("Configuration",
("Invalid value for parameter " + name + ".").c_str());
}
temperatureSim.TemperatureScale = value;
}
else if (name == "StaticTemperatureDefaultValue")
} else if (name == "StaticTemperatureDefaultValue")
temperatureSim.StaticTemperatureDefaultValue = string2int(value);
else if (name == "ThermalSimPeriod")
temperatureSim.ThermalSimPeriod = std::stod(value.c_str());
@@ -271,8 +265,7 @@ void Configuration::setParameter(std::string name, std::string value)
else if (name == "PowerInfoFile") {
temperatureSim.powerInfoFile = value;
temperatureSim.parsePowerInfoFile();
}
else if (name == "IceServerIp")
} else if (name == "IceServerIp")
temperatureSim.IceServerIp = value;
else if (name == "IceServerPort")
temperatureSim.IceServerPort = string2int(value);
@@ -284,9 +277,9 @@ void Configuration::setParameter(std::string name, std::string value)
temperatureSim.GenerateTemperatureMap = string2bool(value);
else if (name == "GeneratePowerMap")
temperatureSim.GeneratePowerMap = string2bool(value);
else
{
SC_REPORT_FATAL("Configuration", ("Parameter " + name + " not defined in Configuration").c_str());
else {
SC_REPORT_FATAL("Configuration",
("Parameter " + name + " not defined in Configuration").c_str());
}
}
@@ -301,10 +294,10 @@ std::string Configuration::getPathToResources()
return pathToResources;
}
void Configuration::setParameters(std::map<std::string, std::string> parameterMap)
void Configuration::setParameters(std::map<std::string, std::string>
parameterMap)
{
for(auto item : parameterMap)
{
for (auto item : parameterMap) {
setParameter(item.first, item.second);
}
}
@@ -349,7 +342,8 @@ unsigned int Configuration::getBytesPerBurst()
// The least significant bits of the physical address are the byte
// offset of the N-byte-wide memory module (DIMM) (a single data word
// or burst element has N bytes. N = 2^(# bits for byte offset)).
unsigned int burstElementSizeInBytes = xmlAddressDecoder::getInstance().amount["bytes"];
unsigned int burstElementSizeInBytes =
AddressDecoder::getInstance().amount["bytes"];
assert(bytesPerBurst == (burstElementSizeInBytes * memSpec.BurstLength));
}
@@ -359,12 +353,11 @@ unsigned int Configuration::getBytesPerBurst()
// Changes the number of bytes depeding on the ECC Controller. This function is needed for modules which get data directly or indirectly from the ECC Controller
unsigned int Configuration::adjustNumBytesAfterECC(unsigned nBytes)
{
// Manipulate the number of bytes only if there is an ECC Controller selected
if(ECCMode == ECCControllerMode::Disabled)
return nBytes;
else
{
assert(pECC != nullptr);
return pECC->AllocationSize(nBytes);
}
// Manipulate the number of bytes only if there is an ECC Controller selected
if (ECCMode == ECCControllerMode::Disabled)
return nBytes;
else {
assert(pECC != nullptr);
return pECC->AllocationSize(nBytes);
}
}

View File

@@ -47,14 +47,13 @@
#include "../../../error/eccbaseclass.h"
enum class StorageMode{NoStorage, Store, ErrorModel};
enum class StorageMode {NoStorage, Store, ErrorModel};
enum class EPowerDownMode{NoPowerDown, Staggered, TimeoutPDN, TimeoutSREF};
enum class EPowerDownMode {NoPowerDown, Staggered, TimeoutPDN, TimeoutSREF};
enum class ECCControllerMode{Disabled, Hamming};
enum class ECCControllerMode {Disabled, Hamming};
struct Configuration
{
struct Configuration {
static std::string memspecUri;
static std::string mcconfigUri;
std::string pathToResources;
@@ -69,7 +68,10 @@ struct Configuration
unsigned int SJFProbability;
unsigned int RequestBufferSize;
unsigned int Capsize = 5;
sc_time getPowerDownTimeout(){return powerDownTimeoutInClk*memSpec.clk;}
sc_time getPowerDownTimeout()
{
return powerDownTimeoutInClk * memSpec.clk;
}
EPowerDownMode PowerDownMode = EPowerDownMode::Staggered;
bool ReadWriteGrouping = false;
bool ReorderBuffer = false;
@@ -92,8 +94,8 @@ struct Configuration
bool SimulationProgressBar = false;
unsigned int NumberOfDevicesOnDIMM = 1;
bool CheckTLM2Protocol = false;
ECCControllerMode ECCMode = ECCControllerMode::Disabled;
ECCBaseClass* pECC = nullptr;
ECCControllerMode ECCMode = ECCControllerMode::Disabled;
ECCBaseClass *pECC = nullptr;
bool gem5 = false;
unsigned long long int AddressOffset = 0;
@@ -105,7 +107,7 @@ struct Configuration
//Configs for Seed, csv file and StorageMode
unsigned int ErrorChipSeed;
std::string ErrorCSVFile ="not defined.";
std::string ErrorCSVFile = "not defined.";
StorageMode StoreMode;
// Temperature Simulation related
@@ -114,7 +116,7 @@ struct Configuration
std::uint64_t getSimMemSizeInBytes();
unsigned int getDataBusWidth();
unsigned int getBytesPerBurst();
unsigned int adjustNumBytesAfterECC(unsigned bytes);
unsigned int adjustNumBytesAfterECC(unsigned bytes);
void setPathToResources(std::string path);
std::string getPathToResources();

View File

@@ -41,19 +41,20 @@
using namespace tinyxml2;
using namespace std;
void ConfigurationLoader::loadSimConfig(Configuration& config, string simconfigUri)
void ConfigurationLoader::loadSimConfig(Configuration &config,
string simconfigUri)
{
tinyxml2::XMLDocument doc;
loadXML(simconfigUri, doc);
XMLElement* simconfig = doc.FirstChildElement("simconfig");
XMLElement *simconfig = doc.FirstChildElement("simconfig");
loadConfig(config, simconfig);
}
void ConfigurationLoader::loadSimConfig(Configuration& config, XMLElement* simconfig)
void ConfigurationLoader::loadSimConfig(Configuration &config,
XMLElement *simconfig)
{
if(simconfig->Attribute("src"))
{
if (simconfig->Attribute("src")) {
XMLDocument doc;
string src(simconfig->Attribute("src"));
loadXML(src, doc);
@@ -62,12 +63,14 @@ void ConfigurationLoader::loadSimConfig(Configuration& config, XMLElement* simco
loadConfig(config, simconfig);
}
void ConfigurationLoader::loadTemperatureSimConfig(Configuration &config, std::string thermalsimconfigUri)
void ConfigurationLoader::loadTemperatureSimConfig(Configuration &config,
std::string thermalsimconfigUri)
{
loadConfigFromUri(config, thermalsimconfigUri, "thermalsimconfig");
}
void ConfigurationLoader::loadTemperatureSimConfig(Configuration &config, XMLElement *thermalsimconfig)
void ConfigurationLoader::loadTemperatureSimConfig(Configuration &config,
XMLElement *thermalsimconfig)
{
if (thermalsimconfig->Attribute("src")) {
// Configuration is inside another a file
@@ -78,18 +81,19 @@ void ConfigurationLoader::loadTemperatureSimConfig(Configuration &config, XMLEle
}
}
void ConfigurationLoader::loadConfig(Configuration& config, XMLElement* configNode)
void ConfigurationLoader::loadConfig(Configuration &config,
XMLElement *configNode)
{
XMLElement* element;
XMLElement *element;
for (element = configNode->FirstChildElement(); element != NULL;
element = element->NextSiblingElement())
{
element = element->NextSiblingElement()) {
config.setParameter(element->Name(), element->Attribute("value"));
}
}
void ConfigurationLoader::loadConfigFromUri(Configuration &config, std::string uri, std::string first_element)
void ConfigurationLoader::loadConfigFromUri(Configuration &config,
std::string uri, std::string first_element)
{
tinyxml2::XMLDocument doc;
loadXML(uri, doc);
@@ -97,75 +101,66 @@ void ConfigurationLoader::loadConfigFromUri(Configuration &config, std::string u
loadConfig(config, e);
}
void ConfigurationLoader::loadMemSpec(Configuration& config, string memspecUri)
void ConfigurationLoader::loadMemSpec(Configuration &config, string memspecUri)
{
tinyxml2::XMLDocument doc;
config.memspecUri = memspecUri;
loadXML(memspecUri, doc);
XMLElement* memspec = doc.FirstChildElement("memspec");
XMLElement *memspec = doc.FirstChildElement("memspec");
loadMemSpec(config, memspec);
}
void ConfigurationLoader::loadMemSpec(Configuration& config, XMLElement* memspec)
void ConfigurationLoader::loadMemSpec(Configuration &config,
XMLElement *memspec)
{
config.memSpec.MemoryId = queryStringParameter(memspec, "memoryId");
config.memSpec.MemoryType = queryStringParameter(memspec, "memoryType");
std::cout << "Memtype: " << config.memSpec.MemoryType << std::endl;
if (config.memSpec.MemoryType == "DDR4")
{
if (config.memSpec.MemoryType == "DDR4") {
loadDDR4(config, memspec);
}
else if (config.memSpec.MemoryType == "DDR3")
{
} else if (config.memSpec.MemoryType == "DDR3") {
loadDDR3(config, memspec);
}
else if (config.memSpec.MemoryType == "LPDDR4")
{
} else if (config.memSpec.MemoryType == "LPDDR4") {
loadLPDDR4(config, memspec);
}
else if (config.memSpec.MemoryType == "WIDEIO_SDR")
{
} else if (config.memSpec.MemoryType == "WIDEIO_SDR") {
loadWideIO(config, memspec);
}
else
{
} else {
reportFatal("ConfigurationLoader", "Unsupported DRAM type");
}
}
void ConfigurationLoader::loadMCConfig(Configuration& config, string mcconfigUri)
void ConfigurationLoader::loadMCConfig(Configuration &config,
string mcconfigUri)
{
tinyxml2::XMLDocument doc;
config.mcconfigUri = mcconfigUri;
loadXML(mcconfigUri, doc);
XMLElement* mcconfig = doc.FirstChildElement("mcconfig");
XMLElement *mcconfig = doc.FirstChildElement("mcconfig");
loadConfig(config, mcconfig);
}
void ConfigurationLoader::loadMCConfig(Configuration& config, XMLElement* mcconfig)
void ConfigurationLoader::loadMCConfig(Configuration &config,
XMLElement *mcconfig)
{
if(mcconfig->Attribute("src"))
{
if (mcconfig->Attribute("src")) {
XMLDocument doc;
string src(mcconfig->Attribute("src"));
config.mcconfigUri = src;
loadXML(src, doc);
loadMCConfig(config, doc.FirstChildElement("mcconfig"));
}
else
{
} else {
loadConfig(config, mcconfig);
}
}
void ConfigurationLoader::loadDDR3(Configuration& config, XMLElement* memspec)
void ConfigurationLoader::loadDDR3(Configuration &config, XMLElement *memspec)
{
//MemArchitecture
XMLElement* architecture = memspec->FirstChildElement("memarchitecturespec");
XMLElement *architecture = memspec->FirstChildElement("memarchitecturespec");
config.memSpec.NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks");
config.memSpec.NumberOfBankGroups = 1;
@@ -174,13 +169,14 @@ void ConfigurationLoader::loadDDR3(Configuration& config, XMLElement* memspec)
config.memSpec.nActivate = 4;
config.memSpec.DataRate = queryUIntParameter(architecture, "dataRate");
config.memSpec.NumberOfRows = queryUIntParameter(architecture, "nbrOfRows");
config.memSpec.NumberOfColumns = queryUIntParameter(architecture, "nbrOfColumns");
config.memSpec.NumberOfColumns = queryUIntParameter(architecture,
"nbrOfColumns");
config.memSpec.bitWidth = queryUIntParameter(architecture, "width");
config.memSpec.DLL = true;
config.memSpec.termination = true;
//MemTimings
XMLElement* timings = memspec->FirstChildElement("memtimingspec");
XMLElement *timings = memspec->FirstChildElement("memtimingspec");
double clkMhz = queryDoubleParameter(timings, "clkMhz");
config.memSpec.clk = FrequencyToClk(clkMhz);
sc_time clk = config.memSpec.clk;
@@ -211,13 +207,13 @@ void ConfigurationLoader::loadDDR3(Configuration& config, XMLElement* memspec)
config.memSpec.tDQSCK = clk * queryUIntParameter(timings, "DQSCK");
config.memSpec.refreshTimings.clear();
for (unsigned int i = 0; i < config.memSpec.NumberOfBanks; ++i)
{
config.memSpec.refreshTimings[Bank(i)] = RefreshTiming(config.memSpec.tRFC, config.memSpec.tREFI);
for (unsigned int i = 0; i < config.memSpec.NumberOfBanks; ++i) {
config.memSpec.refreshTimings[Bank(i)] = RefreshTiming(config.memSpec.tRFC,
config.memSpec.tREFI);
}
// Currents and Volatages: TODO Check if this is correct.
XMLElement* powers = memspec->FirstChildElement("mempowerspec");
XMLElement *powers = memspec->FirstChildElement("mempowerspec");
config.memSpec.iDD0 = queryDoubleParameter(powers, "idd0");
config.memSpec.iDD02 = queryDoubleParameter(powers, "idd0");
config.memSpec.iDD2P0 = queryDoubleParameter(powers, "idd2p0");
@@ -236,25 +232,27 @@ void ConfigurationLoader::loadDDR3(Configuration& config, XMLElement* memspec)
}
void ConfigurationLoader::loadDDR4(Configuration& config, XMLElement* memspec)
void ConfigurationLoader::loadDDR4(Configuration &config, XMLElement *memspec)
{
//MemArchitecture
XMLElement* architecture = memspec->FirstChildElement("memarchitecturespec");
XMLElement *architecture = memspec->FirstChildElement("memarchitecturespec");
config.memSpec.NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks");
config.memSpec.NumberOfBankGroups = queryUIntParameter(architecture, "nbrOfBankGroups");
config.memSpec.NumberOfBankGroups = queryUIntParameter(architecture,
"nbrOfBankGroups");
config.memSpec.NumberOfRanks = queryUIntParameter(architecture, "nbrOfRanks");
config.memSpec.BurstLength = queryUIntParameter(architecture, "burstLength");
config.memSpec.nActivate = 4;
config.memSpec.DataRate = queryUIntParameter(architecture, "dataRate");
config.memSpec.NumberOfRows = queryUIntParameter(architecture, "nbrOfRows");
config.memSpec.NumberOfColumns = queryUIntParameter(architecture, "nbrOfColumns");
config.memSpec.NumberOfColumns = queryUIntParameter(architecture,
"nbrOfColumns");
config.memSpec.bitWidth = queryUIntParameter(architecture, "width");
config.memSpec.DLL = true;
config.memSpec.termination = true;
//MemTimings
XMLElement* timings = memspec->FirstChildElement("memtimingspec");
XMLElement *timings = memspec->FirstChildElement("memtimingspec");
double clkMhz = queryDoubleParameter(timings, "clkMhz");
config.memSpec.clk = FrequencyToClk(clkMhz);
sc_time clk = config.memSpec.clk;
@@ -285,13 +283,13 @@ void ConfigurationLoader::loadDDR4(Configuration& config, XMLElement* memspec)
config.memSpec.tDQSCK = clk * queryUIntParameter(timings, "DQSCK");
config.memSpec.refreshTimings.clear();
for (unsigned int i = 0; i < config.memSpec.NumberOfBanks; ++i)
{
config.memSpec.refreshTimings[Bank(i)] = RefreshTiming(config.memSpec.tRFC, config.memSpec.tREFI);
for (unsigned int i = 0; i < config.memSpec.NumberOfBanks; ++i) {
config.memSpec.refreshTimings[Bank(i)] = RefreshTiming(config.memSpec.tRFC,
config.memSpec.tREFI);
}
// Currents and Volatages:
XMLElement* powers = memspec->FirstChildElement("mempowerspec");
XMLElement *powers = memspec->FirstChildElement("mempowerspec");
config.memSpec.iDD0 = queryDoubleParameter(powers, "idd0");
config.memSpec.iDD02 = queryDoubleParameter(powers, "idd02");
config.memSpec.iDD2P0 = queryDoubleParameter(powers, "idd2p0");
@@ -310,10 +308,10 @@ void ConfigurationLoader::loadDDR4(Configuration& config, XMLElement* memspec)
}
// TODO: fix this for LPDDR4
void ConfigurationLoader::loadLPDDR4(Configuration& config, XMLElement* memspec)
void ConfigurationLoader::loadLPDDR4(Configuration &config, XMLElement *memspec)
{
//MemArchitecture:
XMLElement* architecture = memspec->FirstChildElement("memarchitecturespec");
XMLElement *architecture = memspec->FirstChildElement("memarchitecturespec");
config.memSpec.NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks");
config.memSpec.NumberOfBankGroups = 1;
@@ -322,13 +320,14 @@ void ConfigurationLoader::loadLPDDR4(Configuration& config, XMLElement* memspec)
config.memSpec.nActivate = 4;
config.memSpec.DataRate = queryUIntParameter(architecture, "dataRate");
config.memSpec.NumberOfRows = queryUIntParameter(architecture, "nbrOfRows");
config.memSpec.NumberOfColumns = queryUIntParameter(architecture, "nbrOfColumns");
config.memSpec.NumberOfColumns = queryUIntParameter(architecture,
"nbrOfColumns");
config.memSpec.bitWidth = queryUIntParameter(architecture, "width");
config.memSpec.DLL = false; // TODO: Correct?
config.memSpec.termination = true; // TODO: Correct?
//MemTimings
XMLElement* timings = memspec->FirstChildElement("memtimingspec");
XMLElement *timings = memspec->FirstChildElement("memtimingspec");
double clkMhz = queryDoubleParameter(timings, "clkMhz");
config.memSpec.clk = FrequencyToClk(clkMhz);
sc_time clk = config.memSpec.clk;
@@ -362,13 +361,13 @@ void ConfigurationLoader::loadLPDDR4(Configuration& config, XMLElement* memspec)
config.memSpec.tDQSCK = clk * queryUIntParameter(timings, "DQSCK");
config.memSpec.refreshTimings.clear();
for (unsigned int i = 0; i < config.memSpec.NumberOfBanks; ++i)
{
config.memSpec.refreshTimings[Bank(i)] = RefreshTiming(config.memSpec.tRFC, config.memSpec.tREFI);
for (unsigned int i = 0; i < config.memSpec.NumberOfBanks; ++i) {
config.memSpec.refreshTimings[Bank(i)] = RefreshTiming(config.memSpec.tRFC,
config.memSpec.tREFI);
}
// Currents and Volatages:
XMLElement* powers = memspec->FirstChildElement("mempowerspec");
XMLElement *powers = memspec->FirstChildElement("mempowerspec");
config.memSpec.iDD0 = queryDoubleParameter(powers, "idd0");
config.memSpec.iDD02 = queryDoubleParameter(powers, "idd02");
config.memSpec.iDD2P0 = queryDoubleParameter(powers, "idd2p");
@@ -386,10 +385,10 @@ void ConfigurationLoader::loadLPDDR4(Configuration& config, XMLElement* memspec)
config.memSpec.vDD2 = queryDoubleParameter(powers, "vdd2");
}
void ConfigurationLoader::loadWideIO(Configuration& config, XMLElement* memspec)
void ConfigurationLoader::loadWideIO(Configuration &config, XMLElement *memspec)
{
//MemSpecification
XMLElement* architecture = memspec->FirstChildElement("memarchitecturespec");
XMLElement *architecture = memspec->FirstChildElement("memarchitecturespec");
config.memSpec.NumberOfBanks = queryUIntParameter(architecture, "nbrOfBanks");
config.memSpec.NumberOfBankGroups = 1;
@@ -398,13 +397,14 @@ void ConfigurationLoader::loadWideIO(Configuration& config, XMLElement* memspec)
config.memSpec.nActivate = 2;
config.memSpec.DataRate = queryUIntParameter(architecture, "dataRate");
config.memSpec.NumberOfRows = queryUIntParameter(architecture, "nbrOfRows");
config.memSpec.NumberOfColumns = queryUIntParameter(architecture, "nbrOfColumns");
config.memSpec.NumberOfColumns = queryUIntParameter(architecture,
"nbrOfColumns");
config.memSpec.bitWidth = queryUIntParameter(architecture, "width");
config.memSpec.DLL = false;
config.memSpec.termination = false;
//MemTimings
XMLElement* timings = memspec->FirstChildElement("memtimingspec");
XMLElement *timings = memspec->FirstChildElement("memtimingspec");
double clkMhz = queryDoubleParameter(timings, "clkMhz");
config.memSpec.clk = FrequencyToClk(clkMhz);
sc_time clk = config.memSpec.clk;
@@ -434,13 +434,13 @@ void ConfigurationLoader::loadWideIO(Configuration& config, XMLElement* memspec)
config.memSpec.tREFI = clk * queryUIntParameter(timings, "REFI");
config.memSpec.refreshTimings.clear();
for (unsigned int i = 0; i < config.memSpec.NumberOfBanks; ++i)
{
config.memSpec.refreshTimings[Bank(i)] = RefreshTiming(config.memSpec.tRFC, config.memSpec.tREFI);
for (unsigned int i = 0; i < config.memSpec.NumberOfBanks; ++i) {
config.memSpec.refreshTimings[Bank(i)] = RefreshTiming(config.memSpec.tRFC,
config.memSpec.tREFI);
}
// Currents and Volatages:
XMLElement* powers = memspec->FirstChildElement("mempowerspec");
XMLElement *powers = memspec->FirstChildElement("mempowerspec");
config.memSpec.iDD0 = queryDoubleParameter(powers, "idd0");
config.memSpec.iDD02 = queryDoubleParameter(powers, "idd02");
config.memSpec.iDD2P0 = queryDoubleParameter(powers, "idd2p0");

View File

@@ -46,27 +46,31 @@ class ConfigurationLoader
{
public:
static void loadMCConfig(Configuration& config, std::string amconfigUri);
static void loadMCConfig(Configuration& config, tinyxml2::XMLElement* mcconfig);
static void loadMCConfig(Configuration &config, std::string amconfigUri);
static void loadMCConfig(Configuration &config, tinyxml2::XMLElement *mcconfig);
static void loadSimConfig(Configuration& config, std::string simconfigUri);
static void loadSimConfig(Configuration& config,tinyxml2::XMLElement* simconfig);
static void loadSimConfig(Configuration &config, std::string simconfigUri);
static void loadSimConfig(Configuration &config,
tinyxml2::XMLElement *simconfig);
static void loadMemSpec(Configuration& config, std::string memspecUri);
static void loadMemSpec(Configuration& config, tinyxml2::XMLElement* memspec);
static void loadMemSpec(Configuration &config, std::string memspecUri);
static void loadMemSpec(Configuration &config, tinyxml2::XMLElement *memspec);
static void loadTemperatureSimConfig(Configuration &config, std::string simconfigUri);
static void loadTemperatureSimConfig(Configuration& config, tinyxml2::XMLElement *simconfig);
static void loadTemperatureSimConfig(Configuration &config,
std::string simconfigUri);
static void loadTemperatureSimConfig(Configuration &config,
tinyxml2::XMLElement *simconfig);
private:
ConfigurationLoader(){}
static void loadConfig(Configuration& config, tinyxml2::XMLElement* configNode);
static void loadConfigFromUri(Configuration &config, std::string uri, std::string first_element);
ConfigurationLoader() {}
static void loadConfig(Configuration &config, tinyxml2::XMLElement *configNode);
static void loadConfigFromUri(Configuration &config, std::string uri,
std::string first_element);
//specific loader
static void loadDDR3(Configuration& config, tinyxml2::XMLElement* memspec);
static void loadDDR4(Configuration& config, tinyxml2::XMLElement* memspec);
static void loadLPDDR4(Configuration& config, tinyxml2::XMLElement* memspec);
static void loadWideIO(Configuration& config, tinyxml2::XMLElement* memspec);
static void loadDDR3(Configuration &config, tinyxml2::XMLElement *memspec);
static void loadDDR4(Configuration &config, tinyxml2::XMLElement *memspec);
static void loadLPDDR4(Configuration &config, tinyxml2::XMLElement *memspec);
static void loadWideIO(Configuration &config, tinyxml2::XMLElement *memspec);
};

View File

@@ -42,28 +42,24 @@
#include "../../../common/dramExtension.h"
struct RefreshTiming
{
struct RefreshTiming {
RefreshTiming() {}
RefreshTiming(sc_time tRFC, sc_time tREFI) : tRFC(tRFC), tREFI(tREFI) {}
sc_time tRFC;
sc_time tREFI;
sc_time tRFC;
sc_time tREFI;
};
struct MemSpec
{
struct MemSpec {
MemSpec()
{
{
//default DDR4
}
}
const std::vector<Bank>& getBanks() const
const std::vector<Bank> &getBanks() const
{
static std::vector<Bank> banks;
if (banks.size() == 0)
{
for (unsigned int i = 0; i < NumberOfBanks; i++)
{
if (banks.size() == 0) {
for (unsigned int i = 0; i < NumberOfBanks; i++) {
banks.push_back(Bank(i));
}
}
@@ -87,34 +83,34 @@ struct MemSpec
bool termination;
// Memspec Variables:
sc_time clk;
sc_time tRP; //precharge-time (pre -> act same bank)
sc_time tRPAB; //precharge-all time only for LPDDR4
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; //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)
sc_time tRRD_L; //.. (same bank group)
sc_time tRCD; //act -> read/write
sc_time tNAW; //n activate window
sc_time tRL; //read latency (read command start to data strobe)
sc_time tWL; //write latency
sc_time tWR; //write recovery (write to precharge)
sc_time tWTR_S; //write to read (different bank group)
sc_time tWTR_L; //.. (same bank group)
sc_time tCKESR; //min time in sref
sc_time tCKE; //min time in pdna or pdnp
sc_time tXP; //min delay to row access command after pdnpx pdnax
sc_time tXPDLL; //min delay to row access command after pdnpx pdnax for dll commands
sc_time tXSR; //min delay to row access command after srefx
sc_time tXSRDLL; //min delay to row access command after srefx for dll commands
sc_time tAL; //additive delay (delayed execution in dram)
sc_time clk;
sc_time tRP; //precharge-time (pre -> act same bank)
sc_time tRPAB; //precharge-all time only for LPDDR4
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; //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)
sc_time tRRD_L; //.. (same bank group)
sc_time tRCD; //act -> read/write
sc_time tNAW; //n activate window
sc_time tRL; //read latency (read command start to data strobe)
sc_time tWL; //write latency
sc_time tWR; //write recovery (write to precharge)
sc_time tWTR_S; //write to read (different bank group)
sc_time tWTR_L; //.. (same bank group)
sc_time tCKESR; //min time in sref
sc_time tCKE; //min time in pdna or pdnp
sc_time tXP; //min delay to row access command after pdnpx pdnax
sc_time tXPDLL; //min delay to row access command after pdnpx pdnax for dll commands
sc_time tXSR; //min delay to row access command after srefx
sc_time tXSRDLL; //min delay to row access command after srefx for dll commands
sc_time tAL; //additive delay (delayed execution in dram)
sc_time tDQSCK;
sc_time tRFC; //min ref->act delay
sc_time tREFI; //auto refresh must be issued at an average periodic interval tREFI
sc_time tRFC; //min ref->act delay
sc_time tREFI; //auto refresh must be issued at an average periodic interval tREFI
// Currents and Voltages:
double iDD0;
@@ -143,11 +139,18 @@ struct MemSpec
double vDD2;
std::map<Bank, RefreshTiming> refreshTimings;//ensure that map is populated completely in memspecloader
std::map<Bank, RefreshTiming>
refreshTimings;//ensure that map is populated completely in memspecloader
//act and read/write commands remain for this timespan in history
sc_time tActHistory(){return tNAW;}
sc_time tDataStrobeHistory(){return tWTR_L;}
//act and read/write commands remain for this timespan in history
sc_time tActHistory()
{
return tNAW;
}
sc_time tDataStrobeHistory()
{
return tWTR_L;
}
};
#endif /* MemSpec_H_ */

View File

@@ -79,8 +79,8 @@ struct TemperatureSimConfig {
printDebugMessage("Power Info File: " + powerInfoFile);
powerInfoFile = pathToResources
+ "/configs/thermalsim/"
+ powerInfoFile;
+ "/configs/thermalsim/"
+ powerInfoFile;
// Load the XML file into memory and parse it
tinyxml2::XMLDocument xml;
@@ -94,7 +94,8 @@ struct TemperatureSimConfig {
SC_REPORT_FATAL("Temperature Sim Config", errormsg.c_str());
}
for (tinyxml2::XMLElement *e = powInfoElem->FirstChildElement(); e != NULL; e = e->NextSiblingElement()) {
for (tinyxml2::XMLElement *e = powInfoElem->FirstChildElement(); e != NULL;
e = e->NextSiblingElement()) {
// Load initial power values for all devices
std::string init_pow_str = e->Attribute("init_pow");
@@ -114,17 +115,20 @@ struct TemperatureSimConfig {
{
int i = 0;
for (auto e : powerInitialValues) {
printDebugMessage("powerInitialValues[" + std::to_string(i++) + "]: " + std::to_string(e));
printDebugMessage("powerInitialValues[" + std::to_string(
i++) + "]: " + std::to_string(e));
}
i = 0;
for (auto e : powerThresholds) {
printDebugMessage("powerThreshold[" + std::to_string(i++) + "]: " + std::to_string(e));
printDebugMessage("powerThreshold[" + std::to_string(i++) + "]: " +
std::to_string(e));
}
}
void printDebugMessage(std::string message)
{
DebugManager::getInstance().printDebugMessage("Temperature Sim Config", message);
DebugManager::getInstance().printDebugMessage("Temperature Sim Config",
message);
}
};

View File

@@ -42,89 +42,87 @@
#include "../../Command.h"
enum class PowerDownState
{
Awake, AwakeForRefresh, PDNActive, PDNPrecharge, PDNSelfRefresh
enum class PowerDownState {
Awake, AwakeForRefresh, PDNActive, PDNPrecharge, PDNSelfRefresh
};
class IPowerDownManager
{
public:
virtual ~IPowerDownManager() {}
virtual ~IPowerDownManager() {}
virtual void sleep(Bank bank, sc_time time) = 0;
virtual void triggerSleep(Bank bank, sc_time time) = 0;
virtual void sleep(Bank bank, sc_time time) = 0;
virtual void triggerSleep(Bank bank, sc_time time) = 0;
virtual void wakeUp(Bank bank, sc_time time) = 0;
virtual void wakeUpForRefresh(Bank bank, sc_time time) = 0;
virtual void wakeUp(Bank bank, sc_time time) = 0;
virtual void wakeUpForRefresh(Bank bank, sc_time time) = 0;
virtual bool isInSelfRefresh(Bank bank) = 0;
virtual bool isInSelfRefresh(Bank bank) = 0;
protected:
Command getSleepCommand(PowerDownState state);
Command getWakeUpCommand(PowerDownState state);
Command getSleepCommand(PowerDownState state);
Command getWakeUpCommand(PowerDownState state);
};
inline Command IPowerDownManager::getSleepCommand(PowerDownState state)
{
Command cmd(Command::NOP);
switch (state)
{
case PowerDownState::PDNActive:
cmd = Command::PDNA;
break;
case PowerDownState::PDNPrecharge:
cmd = Command::PDNP;
break;
case PowerDownState::PDNSelfRefresh:
cmd = Command::SREF;
break;
default:
SC_REPORT_FATAL("In PowerDownManager sendPowerdownBegin", "invalid powerDownState");
break;
}
return cmd;
Command cmd(Command::NOP);
switch (state) {
case PowerDownState::PDNActive:
cmd = Command::PDNA;
break;
case PowerDownState::PDNPrecharge:
cmd = Command::PDNP;
break;
case PowerDownState::PDNSelfRefresh:
cmd = Command::SREF;
break;
default:
SC_REPORT_FATAL("In PowerDownManager sendPowerdownBegin",
"invalid powerDownState");
break;
}
return cmd;
}
inline Command IPowerDownManager::getWakeUpCommand(PowerDownState state)
{
Command cmd(Command::NOP);
switch (state)
{
case PowerDownState::PDNActive:
cmd = Command::PDNAX;
break;
case PowerDownState::PDNPrecharge:
cmd = Command::PDNPX;
break;
case PowerDownState::PDNSelfRefresh:
cmd = Command::SREFX;
break;
default:
SC_REPORT_FATAL("In PowerDownManager sendPowerdownEnd", "invalid powerDownState");
}
return cmd;
Command cmd(Command::NOP);
switch (state) {
case PowerDownState::PDNActive:
cmd = Command::PDNAX;
break;
case PowerDownState::PDNPrecharge:
cmd = Command::PDNPX;
break;
case PowerDownState::PDNSelfRefresh:
cmd = Command::SREFX;
break;
default:
SC_REPORT_FATAL("In PowerDownManager sendPowerdownEnd",
"invalid powerDownState");
}
return cmd;
}
inline std::string powerDownStateToString(PowerDownState powerDownState)
{
switch (powerDownState)
{
case PowerDownState::Awake:
return "Awake";
case PowerDownState::AwakeForRefresh:
return "Awake for refresh";
case PowerDownState::PDNActive:
return "PDN Active";
case PowerDownState::PDNPrecharge:
return "PDN Precharged";
case PowerDownState::PDNSelfRefresh:
return "PDN Self refresh";
default:
return "unknown state";
}
switch (powerDownState) {
case PowerDownState::Awake:
return "Awake";
case PowerDownState::AwakeForRefresh:
return "Awake for refresh";
case PowerDownState::PDNActive:
return "PDN Active";
case PowerDownState::PDNPrecharge:
return "PDN Precharged";
case PowerDownState::PDNSelfRefresh:
return "PDN Self refresh";
default:
return "unknown state";
}
}

View File

@@ -48,8 +48,8 @@
class NoPowerDown: public IPowerDownManager
{
public:
NoPowerDown(){}
virtual ~NoPowerDown(){}
NoPowerDown() {}
virtual ~NoPowerDown() {}
virtual void triggerSleep(Bank bank, sc_time time) override;
virtual void sleep(Bank bank, sc_time time) override;

View File

@@ -48,12 +48,12 @@ using namespace tlm;
using namespace std;
PowerDownManager::PowerDownManager(sc_module_name /*name*/, ControllerCore& controller) :
controllerCore(controller)
PowerDownManager::PowerDownManager(sc_module_name /*name*/,
ControllerCore &controller) :
controllerCore(controller)
{
powerDownState = PowerDownState::Awake;
for (Bank bank : controller.getBanks())
{
for (Bank bank : controller.getBanks()) {
setUpDummy(powerDownPayloads[bank], bank);
}
//controllerCore.controller.send(PDNTrigger, sc_time_stamp(), powerDownPayloads[Bank(0)]);
@@ -71,35 +71,31 @@ void PowerDownManager::sleep(Bank /*bank*/, sc_time time)
PowerDownState state = powerDownState;
if (state == PowerDownState::Awake) //coming from active
{
state = controllerCore.state->rowBufferStates->allRowBuffersAreClosed() ? PowerDownState::PDNPrecharge : PowerDownState::PDNActive;
}
else if (state == PowerDownState::AwakeForRefresh) //coming from refresh interrupting power down
{
if (state == PowerDownState::Awake) { //coming from active
state = controllerCore.state->rowBufferStates->allRowBuffersAreClosed() ?
PowerDownState::PDNPrecharge : PowerDownState::PDNActive;
} else if (state ==
PowerDownState::AwakeForRefresh) { //coming from refresh interrupting power down
sc_assert(controllerCore.state->rowBufferStates->allRowBuffersAreClosed());
if (controllerCore.state->getLastCommand(Command::PDNA).getStart()
>= controllerCore.state->getLastCommand(Command::PDNP).getStart())
state = PowerDownState::PDNPrecharge;
else
{
else {
state = PowerDownState::PDNSelfRefresh;
}
}
Command cmd = IPowerDownManager::getSleepCommand(state);
ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd),
DramExtension::getExtension(powerDownPayloads[Bank(0)]));
DramExtension::getExtension(powerDownPayloads[Bank(0)]));
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
if (state != PowerDownState::PDNSelfRefresh && controllerCore.refreshManager->hasCollision(pdn))
{
if (state != PowerDownState::PDNSelfRefresh
&& controllerCore.refreshManager->hasCollision(pdn)) {
return;
}
else
{
} else {
setPowerDownState(state);
sendPowerDownPayload(pdn);
}
@@ -107,86 +103,95 @@ void PowerDownManager::sleep(Bank /*bank*/, sc_time time)
void PowerDownManager::wakeUp(Bank bank, sc_time time)
{
printDebugMessage("Waking up at " + time.to_string() + " current power down state is " + powerDownStateToString(powerDownState));
printDebugMessage("Waking up at " + time.to_string() +
" current power down state is " + powerDownStateToString(powerDownState));
if (isAwakeForRefresh()) //Request enters system during Refresh
{
if (isAwakeForRefresh()) { //Request enters system during Refresh
setPowerDownState(PowerDownState::Awake);
}
else if (isInPowerDown()) //Request wakes up power down
{
} else if (isInPowerDown()) { //Request wakes up power down
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState);
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, powerDownPayloads[Bank(0)]),
DramExtension::getExtension(powerDownPayloads[Bank(0)]));
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd,
powerDownPayloads[Bank(0)]),
DramExtension::getExtension(powerDownPayloads[Bank(0)]));
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
if (cmd == Command::SREFX) {
// Leaving Self Refresh. Plan the next refresh.
controllerCore.refreshManager->reInitialize(bank, pdn.getEnd());
printDebugMessage("Waking up. Leaving Self Refresh at " + time.to_string() + " next refresh planned to " + pdn.getEnd().to_string());
printDebugMessage("Waking up. Leaving Self Refresh at " + time.to_string() +
" next refresh planned to " + pdn.getEnd().to_string());
}
setPowerDownState(PowerDownState::Awake);
printDebugMessage("Sending power down exit command " + commandToString(cmd) + " on all banks");
printDebugMessage("Sending power down exit command " + commandToString(
cmd) + " on all banks");
sendPowerDownPayload(pdn);
}
printDebugMessage("Awaken at " + time.to_string() + " current power down state is " + powerDownStateToString(powerDownState));
printDebugMessage("Awaken at " + time.to_string() +
" current power down state is " + powerDownStateToString(powerDownState));
}
void PowerDownManager::wakeUpForRefresh(Bank /*bank*/, sc_time time)
{
printDebugMessage("Waking up for refresh at " + time.to_string() + " current power down state is " + powerDownStateToString(powerDownState));
printDebugMessage("Waking up for refresh at " + time.to_string() +
" current power down state is " + powerDownStateToString(powerDownState));
if (isInPowerDown())
{
if (isInPowerDown()) {
Command cmd = IPowerDownManager::getWakeUpCommand(powerDownState);
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd, powerDownPayloads[Bank(0)]),
DramExtension::getExtension(powerDownPayloads[Bank(0)]));
ScheduledCommand pdn(cmd, time, getExecutionTime(cmd,
powerDownPayloads[Bank(0)]),
DramExtension::getExtension(powerDownPayloads[Bank(0)]));
setPowerDownState(PowerDownState::AwakeForRefresh);
printDebugMessage("Sending power down exit command " + commandToString(cmd) + " on all banks");
printDebugMessage("Sending power down exit command " + commandToString(
cmd) + " on all banks");
sendPowerDownPayload(pdn);
}
printDebugMessage("Awaken for refresh at " + time.to_string() + " current power down state is " + powerDownStateToString(powerDownState));
printDebugMessage("Awaken for refresh at " + time.to_string() +
" current power down state is " + powerDownStateToString(powerDownState));
}
void PowerDownManager::sendPowerDownPayload(ScheduledCommand& pdnToSend)
void PowerDownManager::sendPowerDownPayload(ScheduledCommand &pdnToSend)
{
controllerCore.state->bus.moveCommandToNextFreeSlot(pdnToSend);
for (size_t bank = 1; bank < controllerCore.getBanks().size(); bank++)
{
tlm_generic_payload& payloadToSend = powerDownPayloads[bank];
for (size_t bank = 1; bank < controllerCore.getBanks().size(); bank++) {
tlm_generic_payload &payloadToSend = powerDownPayloads[bank];
ScheduledCommand pdn(pdnToSend.getCommand(), pdnToSend.getStart(), pdnToSend.getExecutionTime(), DramExtension::getExtension(payloadToSend));
ScheduledCommand pdn(pdnToSend.getCommand(), pdnToSend.getStart(),
pdnToSend.getExecutionTime(), DramExtension::getExtension(payloadToSend));
controllerCore.state->change(pdn);
}
controllerCore.state->change(pdnToSend);
controllerCore.controller.send(pdnToSend, powerDownPayloads[Bank(0)]);
printDebugMessage("Sending power down command " + commandToString(pdnToSend.getCommand()) + " on bank " + to_string(pdnToSend.getBank().ID()) + " start time " + pdnToSend.getStart().to_string() + " end time " + pdnToSend.getEnd().to_string());
printDebugMessage("Sending power down command " + commandToString(
pdnToSend.getCommand()) + " on bank " + to_string(pdnToSend.getBank().ID()) +
" start time " + pdnToSend.getStart().to_string() + " end time " +
pdnToSend.getEnd().to_string());
}
void PowerDownManager::setPowerDownState(PowerDownState state)
{
powerDownState = state;
printDebugMessage("Is now in state " + powerDownStateToString(powerDownState) + " on all banks");
printDebugMessage("Is now in state " + powerDownStateToString(
powerDownState) + " on all banks");
}
bool PowerDownManager::isInPowerDown()
{
return (powerDownState == PowerDownState::PDNActive || powerDownState == PowerDownState::PDNPrecharge
return (powerDownState == PowerDownState::PDNActive
|| powerDownState == PowerDownState::PDNPrecharge
|| powerDownState == PowerDownState::PDNSelfRefresh);
}
bool PowerDownManager::canSleep()
{
for (Bank bank : controllerCore.getBanks())
{
for (Bank bank : controllerCore.getBanks()) {
if (!controllerCore.numberOfPayloads[bank] == 0)
return false;
}

View File

@@ -45,7 +45,7 @@ class ControllerCore;
class PowerDownManager: public IPowerDownManager, public sc_module
{
public:
PowerDownManager(sc_module_name /*name*/, ControllerCore& controllerCore);
PowerDownManager(sc_module_name /*name*/, ControllerCore &controllerCore);
virtual ~PowerDownManager();
virtual void triggerSleep(Bank bank, sc_time time) override;
@@ -55,7 +55,7 @@ public:
virtual bool isInSelfRefresh(Bank bank) override;
protected:
void sendPowerDownPayload(ScheduledCommand& pdnToSend);
void sendPowerDownPayload(ScheduledCommand &pdnToSend);
bool isInPowerDown();
void setPowerDownState(PowerDownState state);
bool canSleep();
@@ -63,7 +63,7 @@ protected:
PowerDownState powerDownState;
std::map<Bank, tlm::tlm_generic_payload> powerDownPayloads;
ControllerCore& controllerCore;
ControllerCore &controllerCore;
void printDebugMessage(std::string message);
};

View File

@@ -42,10 +42,10 @@
using namespace tlm;
PowerDownManagerBankwise::PowerDownManagerBankwise(sc_module_name /*name*/, ControllerCore& controllerCore) : controllerCore(controllerCore)
PowerDownManagerBankwise::PowerDownManagerBankwise(sc_module_name /*name*/,
ControllerCore &controllerCore) : controllerCore(controllerCore)
{
for (Bank bank : controllerCore.getBanks())
{
for (Bank bank : controllerCore.getBanks()) {
setUpDummy(powerDownPayloads[bank], bank);
powerDownStates[bank] = PowerDownState::Awake;
//controllerCore.controller.send(PDNTrigger, sc_time_stamp(), powerDownPayloads[bank]);
@@ -57,36 +57,33 @@ void PowerDownManagerBankwise::sleep(Bank bank, sc_time time)
if (!canSleep(bank) || isInPowerDown(bank))
return;
tlm_generic_payload& payload = powerDownPayloads[bank];
tlm_generic_payload &payload = powerDownPayloads[bank];
PowerDownState state = powerDownStates[bank];
if (state == PowerDownState::Awake) //coming from active
{
state = controllerCore.state->rowBufferStates->rowBufferIsOpen(bank) ? PowerDownState::PDNActive : PowerDownState::PDNPrecharge;
}
else if (state == PowerDownState::AwakeForRefresh) //coming from refresh interrupting power down
{
if (state == PowerDownState::Awake) { //coming from active
state = controllerCore.state->rowBufferStates->rowBufferIsOpen(
bank) ? PowerDownState::PDNActive : PowerDownState::PDNPrecharge;
} else if (state ==
PowerDownState::AwakeForRefresh) { //coming from refresh interrupting power down
sc_assert(!controllerCore.state->rowBufferStates->rowBufferIsOpen(bank));
if (controllerCore.state->getLastCommand(Command::PDNA, bank).getStart()
>= controllerCore.state->getLastCommand(Command::PDNP, bank).getStart())
state = PowerDownState::PDNPrecharge;
else
{
else {
state = PowerDownState::PDNSelfRefresh;
}
}
Command cmd = IPowerDownManager::getSleepCommand(state);
ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd), DramExtension::getExtension(payload));
ScheduledCommand pdn(cmd, time, getMinExecutionTimeForPowerDownCmd(cmd),
DramExtension::getExtension(payload));
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
if (state != PowerDownState::PDNSelfRefresh && controllerCore.refreshManager->hasCollision(pdn))
{
if (state != PowerDownState::PDNSelfRefresh
&& controllerCore.refreshManager->hasCollision(pdn)) {
return;
}
else
{
} else {
setPowerDownState(state, bank);
sendPowerDownPayload(pdn);
}
@@ -94,37 +91,50 @@ void PowerDownManagerBankwise::sleep(Bank bank, sc_time time)
void PowerDownManagerBankwise::wakeUp(Bank bank, sc_time time)
{
printDebugMessage("Waking up on bank " + to_string(bank.ID()) + " at " + time.to_string() + " current power down state is " + powerDownStateToString(powerDownStates[bank]));
printDebugMessage("Waking up on bank " + to_string(bank.ID()) + " at " +
time.to_string() + " current power down state is " + powerDownStateToString(
powerDownStates[bank]));
if (isAwakeForRefresh(bank)) {
printDebugMessage("It was already awake for refresh on bank " + to_string(bank.ID()) + " at " + time.to_string());
printDebugMessage("It was already awake for refresh on bank " + to_string(
bank.ID()) + " at " + time.to_string());
setPowerDownState(PowerDownState::Awake, bank);
} else if (isInPowerDown(bank)) {
// Request wake up from power down. A Power Down Exit request will be generated (PDNAX, PDNPX, SREFX).
Command pdnExitCmd = IPowerDownManager::getWakeUpCommand(powerDownStates[bank]);
// Mount the command to be scheduled
ScheduledCommand pdnExit(pdnExitCmd, time, getExecutionTime(pdnExitCmd, powerDownPayloads[bank]), DramExtension::getExtension(powerDownPayloads[bank]));
ScheduledCommand pdnExit(pdnExitCmd, time, getExecutionTime(pdnExitCmd,
powerDownPayloads[bank]), DramExtension::getExtension(powerDownPayloads[bank]));
// Ensure that time constraints are respected
controllerCore.getCommandChecker(pdnExitCmd).delayToSatisfyConstraints(pdnExit);
if (pdnExitCmd == Command::SREFX) {
// Leaving Self Refresh. Plan the next refresh.
controllerCore.refreshManager->reInitialize(bank, pdnExit.getEnd());
printDebugMessage("Waking up. Leaving Self Refresh on Bank " + to_string(bank.ID()) + " at " + time.to_string() + " next refresh planned to " + pdnExit.getEnd().to_string());
printDebugMessage("Waking up. Leaving Self Refresh on Bank " + to_string(
bank.ID()) + " at " + time.to_string() + " next refresh planned to " +
pdnExit.getEnd().to_string());
}
setPowerDownState(PowerDownState::Awake, bank);
printDebugMessage("Sending power down exit command " + commandToString(pdnExitCmd) + " on bank " + to_string(bank.ID()) + " at " + time.to_string() + " start time " + pdnExit.getStart().to_string() + " end time " + pdnExit.getEnd().to_string());
printDebugMessage("Sending power down exit command " + commandToString(
pdnExitCmd) + " on bank " + to_string(bank.ID()) + " at " + time.to_string() +
" start time " + pdnExit.getStart().to_string() + " end time " +
pdnExit.getEnd().to_string());
sendPowerDownPayload(pdnExit);
}
printDebugMessage("Awaken on bank " + to_string(bank.ID()) + " at " + time.to_string() + " current power down state is " + powerDownStateToString(powerDownStates[bank]));
printDebugMessage("Awaken on bank " + to_string(bank.ID()) + " at " +
time.to_string() + " current power down state is " + powerDownStateToString(
powerDownStates[bank]));
}
void PowerDownManagerBankwise::wakeUpForRefresh(Bank bank, sc_time time)
{
printDebugMessage("Waking up for refresh on bank " + to_string(bank.ID()) + " at " + time.to_string() + " current power down state is " + powerDownStateToString(powerDownStates[bank]));
printDebugMessage("Waking up for refresh on bank " + to_string(
bank.ID()) + " at " + time.to_string() + " current power down state is " +
powerDownStateToString(powerDownStates[bank]));
if (isInPowerDown(bank)) {
// A Power Down Exit request will be generated (PDNAX, PDNPX, SREFX).
@@ -132,15 +142,21 @@ void PowerDownManagerBankwise::wakeUpForRefresh(Bank bank, sc_time time)
// Get the execution time for this request
sc_time executionTime = getExecutionTime(pdnExitCmd, powerDownPayloads[bank]);
// Mount the command to be scheduled
ScheduledCommand pdnExit(pdnExitCmd, time, executionTime, DramExtension::getExtension(powerDownPayloads[bank]));
ScheduledCommand pdnExit(pdnExitCmd, time, executionTime,
DramExtension::getExtension(powerDownPayloads[bank]));
setPowerDownState(PowerDownState::AwakeForRefresh, bank);
printDebugMessage("Sending power down exit command " + commandToString(pdnExitCmd) + " on bank " + to_string(bank.ID()) + " at " + time.to_string() + " start time " + pdnExit.getStart().to_string() + " end time " + pdnExit.getEnd().to_string());
printDebugMessage("Sending power down exit command " + commandToString(
pdnExitCmd) + " on bank " + to_string(bank.ID()) + " at " + time.to_string() +
" start time " + pdnExit.getStart().to_string() + " end time " +
pdnExit.getEnd().to_string());
sendPowerDownPayload(pdnExit);
}
printDebugMessage("Awaken for refresh on bank " + to_string(bank.ID()) + " at " + time.to_string() + " current power down state is " + powerDownStateToString(powerDownStates[bank]));
printDebugMessage("Awaken for refresh on bank " + to_string(
bank.ID()) + " at " + time.to_string() + " current power down state is " +
powerDownStateToString(powerDownStates[bank]));
}
bool PowerDownManagerBankwise::isInPowerDown(Bank bank)
@@ -163,18 +179,22 @@ bool PowerDownManagerBankwise::isAwake(Bank bank)
return powerDownStates[bank] == PowerDownState::Awake;
}
void PowerDownManagerBankwise::setPowerDownState(PowerDownState state, Bank bank)
void PowerDownManagerBankwise::setPowerDownState(PowerDownState state,
Bank bank)
{
PowerDownState& bankstate = powerDownStates[bank];
PowerDownState &bankstate = powerDownStates[bank];
bankstate = state;
printDebugMessage("Is now in state " + powerDownStateToString(state) + " on Bank " + to_string(bank.ID()));
printDebugMessage("Is now in state " + powerDownStateToString(
state) + " on Bank " + to_string(bank.ID()));
}
void PowerDownManagerBankwise::sendPowerDownPayload(ScheduledCommand &pdn)
{
controllerCore.state->bus.moveCommandToNextFreeSlot(pdn);
controllerCore.state->change(pdn);
printDebugMessage("Sending power down command " + commandToString(pdn.getCommand()) + " on bank " + to_string(pdn.getBank().ID()) + " start time " + pdn.getStart().to_string() + " end time " + pdn.getEnd().to_string());
printDebugMessage("Sending power down command " + commandToString(
pdn.getCommand()) + " on bank " + to_string(pdn.getBank().ID()) + " start time "
+ pdn.getStart().to_string() + " end time " + pdn.getEnd().to_string());
controllerCore.controller.send(pdn, powerDownPayloads[pdn.getBank()]);
}

View File

@@ -52,8 +52,9 @@ class ControllerCore;
class PowerDownManagerBankwise : public sc_module, public IPowerDownManager
{
public:
PowerDownManagerBankwise(sc_module_name /*name*/, ControllerCore& controllerCore);
virtual ~PowerDownManagerBankwise(){}
PowerDownManagerBankwise(sc_module_name /*name*/,
ControllerCore &controllerCore);
virtual ~PowerDownManagerBankwise() {}
virtual void triggerSleep(Bank bank, sc_time time) override;
virtual void sleep(Bank bank, sc_time time) override;
virtual void wakeUp(Bank bank, sc_time time) override;

View File

@@ -44,7 +44,8 @@
using namespace tlm;
PowerDownManagerTimeout::PowerDownManagerTimeout(sc_module_name name, ControllerCore& controllerCore):
PowerDownManagerTimeout::PowerDownManagerTimeout(sc_module_name name,
ControllerCore &controllerCore):
PowerDownManager(name, controllerCore)
{
//controllerCore.controller.send(PDNTrigger, Configuration::getInstance().getPowerDownTimeout(), powerDownPayloads[Bank(0)]);
@@ -58,56 +59,51 @@ PowerDownManagerTimeout::~PowerDownManagerTimeout()
void PowerDownManagerTimeout::sleep(Bank /*bank*/, sc_time time)
{
bool timeoutTest;
if(!isAwakeForRefresh())
{
if (!isAwakeForRefresh()) {
sc_time lastReadScheduled;
sc_time lastWriteScheduled;
if(Configuration::getInstance().OpenPagePolicy)
{
lastReadScheduled= controllerCore.state->getLastCommand(Command::Read).getEnd();
lastWriteScheduled = controllerCore.state->getLastCommand(Command::Write).getEnd();
if (Configuration::getInstance().OpenPagePolicy) {
lastReadScheduled = controllerCore.state->getLastCommand(
Command::Read).getEnd();
lastWriteScheduled = controllerCore.state->getLastCommand(
Command::Write).getEnd();
} else {
lastReadScheduled = controllerCore.state->getLastCommand(
Command::ReadA).getEnd();
lastWriteScheduled = controllerCore.state->getLastCommand(
Command::WriteA).getEnd();
}
else
{
lastReadScheduled = controllerCore.state->getLastCommand(Command::ReadA).getEnd();
lastWriteScheduled = controllerCore.state->getLastCommand(Command::WriteA).getEnd();
}
sc_time lastScheduledCommand = max(lastReadScheduled,lastWriteScheduled);
timeoutTest = (time - lastScheduledCommand) >= Configuration::getInstance().getPowerDownTimeout();
}
else
{
sc_time lastScheduledCommand = max(lastReadScheduled, lastWriteScheduled);
timeoutTest = (time - lastScheduledCommand) >=
Configuration::getInstance().getPowerDownTimeout();
} else {
timeoutTest = true;
}
//test_awakeForRefresh = false;
if( canSleep() && !isInPowerDown() && timeoutTest)
{
if ( canSleep() && !isInPowerDown() && timeoutTest) {
PowerDownState newState;
if(Configuration::getInstance().PowerDownMode == EPowerDownMode::TimeoutPDN)
{
newState = controllerCore.state->rowBufferStates->allRowBuffersAreClosed() ? PowerDownState::PDNPrecharge : PowerDownState::PDNActive;
}
else // PowerDownMode == TimeoutSREF
{
if(!controllerCore.state->rowBufferStates->allRowBuffersAreClosed())
{
ScheduledCommand prechargeAllMaster(Command::PrechargeAll, time, getExecutionTime(Command::PrechargeAll, powerDownPayloads[Bank(0)]), DramExtension::getExtension(powerDownPayloads[Bank(0)]));
if (Configuration::getInstance().PowerDownMode == EPowerDownMode::TimeoutPDN) {
newState = controllerCore.state->rowBufferStates->allRowBuffersAreClosed() ?
PowerDownState::PDNPrecharge : PowerDownState::PDNActive;
} else { // PowerDownMode == TimeoutSREF
if (!controllerCore.state->rowBufferStates->allRowBuffersAreClosed()) {
ScheduledCommand prechargeAllMaster(Command::PrechargeAll, time,
getExecutionTime(Command::PrechargeAll, powerDownPayloads[Bank(0)]),
DramExtension::getExtension(powerDownPayloads[Bank(0)]));
controllerCore.getCommandChecker(Command::PrechargeAll).delayToSatisfyConstraints(prechargeAllMaster);
controllerCore.getCommandChecker(
Command::PrechargeAll).delayToSatisfyConstraints(prechargeAllMaster);
if (controllerCore.refreshManager->hasCollision(prechargeAllMaster))
{
if (controllerCore.refreshManager->hasCollision(prechargeAllMaster)) {
return;
}
else
{
for (size_t i = 1; i < controllerCore.getBanks().size(); i++)
{
ScheduledCommand prechargeAll(Command::PrechargeAll, prechargeAllMaster.getStart(), prechargeAllMaster.getExecutionTime(),
powerDownPayloads[Bank(i)]);
} else {
for (size_t i = 1; i < controllerCore.getBanks().size(); i++) {
ScheduledCommand prechargeAll(Command::PrechargeAll,
prechargeAllMaster.getStart(), prechargeAllMaster.getExecutionTime(),
powerDownPayloads[Bank(i)]);
controllerCore.state->change(prechargeAll);
}
controllerCore.state->change(prechargeAllMaster);
@@ -125,12 +121,9 @@ void PowerDownManagerTimeout::sleep(Bank /*bank*/, sc_time time)
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
if (controllerCore.refreshManager->hasCollision(pdn))
{
if (controllerCore.refreshManager->hasCollision(pdn)) {
return;
}
else
{
} else {
setPowerDownState(newState);
sendPowerDownPayload(pdn);
}
@@ -139,9 +132,9 @@ void PowerDownManagerTimeout::sleep(Bank /*bank*/, sc_time time)
void PowerDownManagerTimeout::triggerSleep(Bank /*bank*/, sc_time time)
{
if(canSleep() && !isInPowerDown())
{
controllerCore.controller.send(PDNTrigger, time + controllerCore.config.getPowerDownTimeout(), powerDownPayloads[Bank(0)]);
if (canSleep() && !isInPowerDown()) {
controllerCore.controller.send(PDNTrigger,
time + controllerCore.config.getPowerDownTimeout(), powerDownPayloads[Bank(0)]);
}
}

View File

@@ -50,7 +50,8 @@ class ControllerCore;
class PowerDownManagerTimeout: public PowerDownManager
{
public:
PowerDownManagerTimeout(sc_module_name /*name*/, ControllerCore& controllerCore);
PowerDownManagerTimeout(sc_module_name /*name*/,
ControllerCore &controllerCore);
virtual ~PowerDownManagerTimeout();
virtual void triggerSleep(Bank /*bank*/, sc_time time);

View File

@@ -44,7 +44,8 @@
using namespace tlm;
PowerDownManagerTimeoutBankwise::PowerDownManagerTimeoutBankwise(sc_module_name name, ControllerCore& controllerCore):
PowerDownManagerTimeoutBankwise::PowerDownManagerTimeoutBankwise(
sc_module_name name, ControllerCore &controllerCore):
PowerDownManagerBankwise(name, controllerCore)
{
/*for (Bank bank : controllerCore.getBanks())
@@ -61,49 +62,44 @@ PowerDownManagerTimeoutBankwise::~PowerDownManagerTimeoutBankwise()
void PowerDownManagerTimeoutBankwise::sleep(Bank bank, sc_time time)
{
bool timeoutTest;
if(!isAwakeForRefresh(bank))
{
if (!isAwakeForRefresh(bank)) {
sc_time lastReadScheduled;
sc_time lastWriteScheduled;
if(Configuration::getInstance().OpenPagePolicy)
{
lastReadScheduled= controllerCore.state->getLastCommand(Command::Read, bank).getEnd();
lastWriteScheduled = controllerCore.state->getLastCommand(Command::Write, bank).getEnd();
if (Configuration::getInstance().OpenPagePolicy) {
lastReadScheduled = controllerCore.state->getLastCommand(Command::Read,
bank).getEnd();
lastWriteScheduled = controllerCore.state->getLastCommand(Command::Write,
bank).getEnd();
} else {
lastReadScheduled = controllerCore.state->getLastCommand(Command::ReadA,
bank).getEnd();
lastWriteScheduled = controllerCore.state->getLastCommand(Command::WriteA,
bank).getEnd();
}
else
{
lastReadScheduled = controllerCore.state->getLastCommand(Command::ReadA, bank).getEnd();
lastWriteScheduled = controllerCore.state->getLastCommand(Command::WriteA, bank).getEnd();
}
sc_time lastScheduledCommand = max(lastReadScheduled,lastWriteScheduled);
timeoutTest = (time - lastScheduledCommand) >= Configuration::getInstance().getPowerDownTimeout();
}
else
{
sc_time lastScheduledCommand = max(lastReadScheduled, lastWriteScheduled);
timeoutTest = (time - lastScheduledCommand) >=
Configuration::getInstance().getPowerDownTimeout();
} else {
timeoutTest = true;
}
if( canSleep(bank) && !isInPowerDown(bank) && timeoutTest)
{
if ( canSleep(bank) && !isInPowerDown(bank) && timeoutTest) {
PowerDownState newState;
if(Configuration::getInstance().PowerDownMode == EPowerDownMode::TimeoutPDN)
{
newState = controllerCore.state->rowBufferStates->rowBufferIsOpen(bank) ? PowerDownState::PDNActive : PowerDownState::PDNPrecharge;
}
else // PowerDownMode == TimeoutSREF
{
if(controllerCore.state->rowBufferStates->rowBufferIsOpen(bank))
{
ScheduledCommand precharge(Command::Precharge, time, getExecutionTime(Command::Precharge, powerDownPayloads[bank]), DramExtension::getExtension(powerDownPayloads[bank]));
if (Configuration::getInstance().PowerDownMode == EPowerDownMode::TimeoutPDN) {
newState = controllerCore.state->rowBufferStates->rowBufferIsOpen(
bank) ? PowerDownState::PDNActive : PowerDownState::PDNPrecharge;
} else { // PowerDownMode == TimeoutSREF
if (controllerCore.state->rowBufferStates->rowBufferIsOpen(bank)) {
ScheduledCommand precharge(Command::Precharge, time,
getExecutionTime(Command::Precharge, powerDownPayloads[bank]),
DramExtension::getExtension(powerDownPayloads[bank]));
controllerCore.getCommandChecker(Command::Precharge).delayToSatisfyConstraints(precharge);
controllerCore.getCommandChecker(Command::Precharge).delayToSatisfyConstraints(
precharge);
if (controllerCore.refreshManager->hasCollision(precharge))
{
if (controllerCore.refreshManager->hasCollision(precharge)) {
return;
}
else
{
} else {
controllerCore.state->change(precharge);
controllerCore.controller.send(precharge, powerDownPayloads[bank]);
}
@@ -120,12 +116,9 @@ void PowerDownManagerTimeoutBankwise::sleep(Bank bank, sc_time time)
controllerCore.getCommandChecker(cmd).delayToSatisfyConstraints(pdn);
if (controllerCore.refreshManager->hasCollision(pdn))
{
if (controllerCore.refreshManager->hasCollision(pdn)) {
return;
}
else
{
} else {
setPowerDownState(newState, bank);
sendPowerDownPayload(pdn);
}
@@ -134,8 +127,8 @@ void PowerDownManagerTimeoutBankwise::sleep(Bank bank, sc_time time)
void PowerDownManagerTimeoutBankwise::triggerSleep(Bank bank, sc_time time)
{
if(canSleep(bank) && !isInPowerDown(bank))
{
controllerCore.controller.send(PDNTrigger, time + controllerCore.config.getPowerDownTimeout(), powerDownPayloads[bank]);
if (canSleep(bank) && !isInPowerDown(bank)) {
controllerCore.controller.send(PDNTrigger,
time + controllerCore.config.getPowerDownTimeout(), powerDownPayloads[bank]);
}
}

View File

@@ -50,7 +50,8 @@ class ControllerCore;
class PowerDownManagerTimeoutBankwise: public PowerDownManagerBankwise
{
public:
PowerDownManagerTimeoutBankwise(sc_module_name /*name*/, ControllerCore& controllerCore);
PowerDownManagerTimeoutBankwise(sc_module_name /*name*/,
ControllerCore &controllerCore);
virtual ~PowerDownManagerTimeoutBankwise();
virtual void triggerSleep(Bank bank, sc_time time);

View File

@@ -45,13 +45,14 @@
class IRefreshManager
{
public:
virtual ~IRefreshManager(){};
virtual bool hasCollision(const ScheduledCommand& command) = 0;
virtual void scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) = 0;
virtual void reInitialize(Bank bank, sc_time time) = 0;
virtual ~IRefreshManager() {};
virtual bool hasCollision(const ScheduledCommand &command) = 0;
virtual void scheduleRefresh(tlm::tlm_generic_payload &payload,
sc_time time) = 0;
virtual void reInitialize(Bank bank, sc_time time) = 0;
virtual bool isInvalidated(tlm::tlm_generic_payload& payload, sc_time time) = 0;
virtual bool isInvalidated(tlm::tlm_generic_payload &payload, sc_time time) = 0;
};

View File

@@ -44,19 +44,19 @@
using namespace tlm;
RefreshManager::RefreshManager(sc_module_name /*name*/, ControllerCore& controller) :
controllerCore(controller), timing(controller.config.memSpec.refreshTimings[Bank(0)]), nextPlannedRefresh(SC_ZERO_TIME)
RefreshManager::RefreshManager(sc_module_name /*name*/,
ControllerCore &controller) :
controllerCore(controller),
timing(controller.config.memSpec.refreshTimings[Bank(0)]),
nextPlannedRefresh(SC_ZERO_TIME)
{
if (controllerCore.config.ControllerCoreEnableRefPostpone)
{
if (controllerCore.config.ControllerCoreEnableRefPostpone) {
maxpostpone = controllerCore.config.ControllerCoreMaxPostponedARCmd;
}
if (controllerCore.config.ControllerCoreEnableRefPullIn)
{
if (controllerCore.config.ControllerCoreEnableRefPullIn) {
maxpullin = controllerCore.config.ControllerCoreMaxPulledInARCmd;
}
for (Bank bank : controller.getBanks())
{
for (Bank bank : controller.getBanks()) {
setUpDummy(refreshPayloads[bank], bank);
}
planNextRefresh(timing.tREFI);
@@ -67,33 +67,38 @@ RefreshManager::~RefreshManager()
}
//Check if a command will be scheduled during the next refresh period
bool RefreshManager::hasCollision(const ScheduledCommand& command)
bool RefreshManager::hasCollision(const ScheduledCommand &command)
{
bool collisionWithPreviousRefEnd = command.getStart() < controllerCore.state->getLastCommand(Command::AutoRefresh).getEnd();
bool collisionWithPreviousRefEnd = command.getStart() <
controllerCore.state->getLastCommand(Command::AutoRefresh).getEnd();
bool collisionWithNextRefStart = command.getEnd() >= nextPlannedRefresh;
if (controllerCore.config.ControllerCoreEnableRefPostpone && (arCmdCounter < maxpostpone)) // Flexible refresh is on and have "credits" to postpone
{
collisionWithNextRefStart = false; // Then there will not be a collision with next refresh because nextPlannedRefresh will be updated
if (controllerCore.config.ControllerCoreEnableRefPostpone
&& (arCmdCounter <
maxpostpone)) { // Flexible refresh is on and have "credits" to postpone
collisionWithNextRefStart =
false; // Then there will not be a collision with next refresh because nextPlannedRefresh will be updated
}
return collisionWithPreviousRefEnd || collisionWithNextRefStart;
}
void RefreshManager::doRefresh(tlm::tlm_generic_payload& payload __attribute__((unused)), sc_time time)
void RefreshManager::doRefresh(tlm::tlm_generic_payload &payload __attribute__((
unused)), sc_time time)
{
sc_assert(!isInvalidated(payload, time));
//Check if any row on all banks is activated and if so, a PrechargeAll command must be scheduled before the refresh command.
if (!controllerCore.state->rowBufferStates->allRowBuffersAreClosed())
{
ScheduledCommand prechargeAllMaster(Command::PrechargeAll, time, getExecutionTime(Command::PrechargeAll, refreshPayloads[Bank(0)]),
refreshPayloads[Bank(0)]);
controllerCore.getCommandChecker(Command::PrechargeAll).delayToSatisfyConstraints(prechargeAllMaster);
if (!controllerCore.state->rowBufferStates->allRowBuffersAreClosed()) {
ScheduledCommand prechargeAllMaster(Command::PrechargeAll, time,
getExecutionTime(Command::PrechargeAll, refreshPayloads[Bank(0)]),
refreshPayloads[Bank(0)]);
controllerCore.getCommandChecker(
Command::PrechargeAll).delayToSatisfyConstraints(prechargeAllMaster);
for (size_t i = 1;i < controllerCore.getBanks().size(); i++)
{
ScheduledCommand prechargeAll(Command::PrechargeAll, prechargeAllMaster.getStart(), prechargeAllMaster.getExecutionTime(),
refreshPayloads[Bank(i)]);
for (size_t i = 1; i < controllerCore.getBanks().size(); i++) {
ScheduledCommand prechargeAll(Command::PrechargeAll,
prechargeAllMaster.getStart(), prechargeAllMaster.getExecutionTime(),
refreshPayloads[Bank(i)]);
controllerCore.state->change(prechargeAll);
}
controllerCore.state->change(prechargeAllMaster);
@@ -101,13 +106,15 @@ void RefreshManager::doRefresh(tlm::tlm_generic_payload& payload __attribute__((
}
//Otherwise just the AutoRefresh command is scheduled.
ScheduledCommand refreshAllMaster(Command::AutoRefresh, time, getExecutionTime(Command::AutoRefresh, refreshPayloads[Bank(0)]),
DramExtension::getExtension(refreshPayloads[Bank(0)]));
controllerCore.getCommandChecker(Command::AutoRefresh).delayToSatisfyConstraints(refreshAllMaster);
ScheduledCommand refreshAllMaster(Command::AutoRefresh, time,
getExecutionTime(Command::AutoRefresh, refreshPayloads[Bank(0)]),
DramExtension::getExtension(refreshPayloads[Bank(0)]));
controllerCore.getCommandChecker(
Command::AutoRefresh).delayToSatisfyConstraints(refreshAllMaster);
for (size_t i = 1;i < controllerCore.getBanks().size(); i++)
{
ScheduledCommand refresh(Command::AutoRefresh, refreshAllMaster.getStart(), refreshAllMaster.getExecutionTime(),refreshPayloads[Bank(i)]);
for (size_t i = 1; i < controllerCore.getBanks().size(); i++) {
ScheduledCommand refresh(Command::AutoRefresh, refreshAllMaster.getStart(),
refreshAllMaster.getExecutionTime(), refreshPayloads[Bank(i)]);
controllerCore.state->change(refresh);
DramExtension::getExtension(refreshPayloads[Bank(i)]).incrementRow();
}
@@ -117,7 +124,8 @@ void RefreshManager::doRefresh(tlm::tlm_generic_payload& payload __attribute__((
}
void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload __attribute__((unused)), sc_time time)
void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload &payload
__attribute__((unused)), sc_time time)
{
sc_time nextRefTiming;
bool pendingReq = controllerCore.hasPendingRequests();
@@ -127,121 +135,103 @@ void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload __attribu
previousState = currentState;
currentState = nextState;
switch(currentState)
{
case ST_REFRESH:
switch (currentState) {
case ST_REFRESH:
// Regular Refresh. It's possible to migrate from this to the flexible refresh states
assert(arCmdCounter == 0); // The arCmdCounter should always be equal to zero here
assert(arCmdCounter ==
0); // The arCmdCounter should always be equal to zero here
if(canPostpone)
{
nextState = ST_POSTPONE;
nextRefTiming = SC_ZERO_TIME;
}
else if(canPullIn)
{
nextState = ST_PULLIN;
nextRefTiming = SC_ZERO_TIME; // Attempt to burst pull-in
}
else
{
doRefresh(payload, time);
nextRefTiming = timing.tREFI;
nextState = ST_REFRESH;
}
break;
if (canPostpone) {
nextState = ST_POSTPONE;
nextRefTiming = SC_ZERO_TIME;
} else if (canPullIn) {
nextState = ST_PULLIN;
nextRefTiming = SC_ZERO_TIME; // Attempt to burst pull-in
} else {
doRefresh(payload, time);
nextRefTiming = timing.tREFI;
nextState = ST_REFRESH;
}
break;
case ST_PULLIN:
case ST_PULLIN:
// Pull-In Refresh. Try to pull-in refreshes as long as the limit hasn't been reached yet and has credits
if(canPullIn)
{
doRefresh(payload, time);
arCmdCounter++;
nextState = ST_PULLIN;
nextRefTiming = timing.tRFC;
}
else
{
alignValue = arCmdCounter; // Saving value to be used by ST_ALIGN
nextState = ST_ALIGN;
nextRefTiming = SC_ZERO_TIME;
}
break;
if (canPullIn) {
doRefresh(payload, time);
arCmdCounter++;
nextState = ST_PULLIN;
nextRefTiming = timing.tRFC;
} else {
alignValue = arCmdCounter; // Saving value to be used by ST_ALIGN
nextState = ST_ALIGN;
nextRefTiming = SC_ZERO_TIME;
}
break;
case ST_SKIP:
case ST_SKIP:
// Skip Refresh. The arCmdCounter is used to skip the correct amount of refreshes
arCmdCounter--;
if(arCmdCounter == 0)
{
nextState = ST_REFRESH;
nextRefTiming = SC_ZERO_TIME;
}
else
{
nextState = ST_SKIP;
nextRefTiming = timing.tREFI;
}
break;
arCmdCounter--;
if (arCmdCounter == 0) {
nextState = ST_REFRESH;
nextRefTiming = SC_ZERO_TIME;
} else {
nextState = ST_SKIP;
nextRefTiming = timing.tREFI;
}
break;
case ST_POSTPONE:
case ST_POSTPONE:
// Postpone Refresh. Delaying refreshes as long as there are pending requests and credits to postpone. Should be followed by a burst refresh
if((arCmdCounter == maxpostpone) || ((!pendingReq) && !controllerCore.config.ControllerCoreForceMaxRefBurst)) // Burst conditions met
{
if(arCmdCounter < maxpostpone) // In case the burst was started by inactivity, need to also count the current REF
{
arCmdCounter++;
}
alignValue = arCmdCounter; // Will start a burst next, so the value is saved to be used by ST_ALIGN
nextState = ST_BURST;
nextRefTiming = SC_ZERO_TIME;
}
else
{
if ((arCmdCounter == maxpostpone) || ((!pendingReq)
&& !controllerCore.config.ControllerCoreForceMaxRefBurst)) { // Burst conditions met
if (arCmdCounter <
maxpostpone) { // In case the burst was started by inactivity, need to also count the current REF
arCmdCounter++;
nextState = ST_POSTPONE;
nextRefTiming = timing.tREFI;
}
break;
alignValue =
arCmdCounter; // Will start a burst next, so the value is saved to be used by ST_ALIGN
nextState = ST_BURST;
nextRefTiming = SC_ZERO_TIME;
} else {
arCmdCounter++;
nextState = ST_POSTPONE;
nextRefTiming = timing.tREFI;
}
break;
case ST_BURST:
case ST_BURST:
// Burst Refresh. The arCmdCounter is used to issue the correct amount of refreshes
arCmdCounter--;
doRefresh(payload, time);
if(arCmdCounter == 0) // All bursts issued, next state will align to tREFI
{
nextState = ST_ALIGN;
nextRefTiming = SC_ZERO_TIME;
}
else
{
nextState = ST_BURST;
nextRefTiming = timing.tRFC;
}
break;
arCmdCounter--;
doRefresh(payload, time);
if (arCmdCounter == 0) { // All bursts issued, next state will align to tREFI
nextState = ST_ALIGN;
nextRefTiming = SC_ZERO_TIME;
} else {
nextState = ST_BURST;
nextRefTiming = timing.tRFC;
}
break;
case ST_ALIGN:
case ST_ALIGN:
// Align Refresh. Adjusting the timing so the next REF timing will be a in a time multiple of tREFI
if(previousState == ST_PULLIN)
{
nextRefTiming = timing.tREFI-(timing.tRFC*(alignValue));
nextState = ST_SKIP;
}
else
{
nextRefTiming = timing.tREFI-(timing.tRFC*(alignValue-1));
nextState = ST_REFRESH;
}
break;
if (previousState == ST_PULLIN) {
nextRefTiming = timing.tREFI - (timing.tRFC * (alignValue));
nextState = ST_SKIP;
} else {
nextRefTiming = timing.tREFI - (timing.tRFC * (alignValue - 1));
nextState = ST_REFRESH;
}
break;
default:
SC_REPORT_FATAL(this->name(),"Invalid State in Flexible Refresh FSM. Stop.");
break;
default:
SC_REPORT_FATAL(this->name(), "Invalid State in Flexible Refresh FSM. Stop.");
break;
}
planNextRefresh(nextRefTiming);
@@ -250,7 +240,8 @@ void RefreshManager::scheduleRefresh(tlm::tlm_generic_payload& payload __attribu
void RefreshManager::planNextRefresh(sc_time nextRefTiming)
{
nextPlannedRefresh += nextRefTiming;
controllerCore.controller.send(REFTrigger, nextPlannedRefresh, refreshPayloads[Bank(0)]);
controllerCore.controller.send(REFTrigger, nextPlannedRefresh,
refreshPayloads[Bank(0)]);
}
void RefreshManager::reInitialize(Bank /*bank*/, sc_time time)
@@ -259,7 +250,8 @@ void RefreshManager::reInitialize(Bank /*bank*/, sc_time time)
planNextRefresh(timing.tREFI);
}
bool RefreshManager::isInvalidated(tlm::tlm_generic_payload& payload __attribute__((unused)), sc_time time)
bool RefreshManager::isInvalidated(tlm::tlm_generic_payload &payload
__attribute__((unused)), sc_time time)
{
return nextPlannedRefresh > time;
}

View File

@@ -40,8 +40,7 @@
#include "IRefreshManager.h"
#include "../configuration/MemSpec.h"
typedef enum
{
typedef enum {
ST_REFRESH = 0,
ST_PULLIN,
ST_POSTPONE,
@@ -55,17 +54,19 @@ class ControllerCore;
class RefreshManager : public IRefreshManager, public sc_module
{
public:
RefreshManager(sc_module_name /*name*/, ControllerCore& controllerCore);
RefreshManager(sc_module_name /*name*/, ControllerCore &controllerCore);
virtual ~RefreshManager();
virtual bool hasCollision(const ScheduledCommand& command) override;
virtual void scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) override;
virtual bool hasCollision(const ScheduledCommand &command) override;
virtual void scheduleRefresh(tlm::tlm_generic_payload &payload,
sc_time time) override;
void reInitialize(Bank bank, sc_time time) override;
virtual bool isInvalidated(tlm::tlm_generic_payload& payload, sc_time time) override;
virtual bool isInvalidated(tlm::tlm_generic_payload &payload,
sc_time time) override;
private:
ControllerCore& controllerCore;
RefreshTiming& timing;
ControllerCore &controllerCore;
RefreshTiming &timing;
sc_time nextPlannedRefresh;
std::map<Bank, tlm::tlm_generic_payload> refreshPayloads;
unsigned int maxpostpone = 0;
@@ -77,7 +78,7 @@ private:
ref_fsm_state_t previousState = ST_REFRESH;
ref_fsm_state_t nextState = ST_REFRESH;
void doRefresh(tlm::tlm_generic_payload& payload, sc_time time);
void doRefresh(tlm::tlm_generic_payload &payload, sc_time time);
void planNextRefresh(sc_time time);
void printDebugMessage(std::string message);
};

View File

@@ -42,10 +42,10 @@
using namespace std;
RefreshManagerBankwise::RefreshManagerBankwise(sc_module_name /*name*/, ControllerCore& controller) : controllerCore(controller)
RefreshManagerBankwise::RefreshManagerBankwise(sc_module_name /*name*/,
ControllerCore &controller) : controllerCore(controller)
{
for (Bank bank : controller.getBanks())
{
for (Bank bank : controller.getBanks()) {
setUpDummy(refreshPayloads[bank], bank);
planNextRefresh(bank);
}
@@ -55,50 +55,60 @@ RefreshManagerBankwise::~RefreshManagerBankwise()
{
}
bool RefreshManagerBankwise::hasCollision(const ScheduledCommand& command)
bool RefreshManagerBankwise::hasCollision(const ScheduledCommand &command)
{
Bank bank = command.getBank();
// Get the last AutoRefresh command for this bank and the time of its end
ScheduledCommand lastAutoRefreshCmd = controllerCore.state->getLastCommand(Command::AutoRefresh, bank);
sc_time endTimeLastAutoRefreshCmd = lastAutoRefreshCmd.getEnd();
// Get the time of the next planned refresh for this bank
sc_time timeNextPlannedRefresh = nextPlannedRefreshs[command.getBank()];
// Collision:
// - the start time of the command is before the end time of the last auto refresh command for this bank
// - the end time of the command is after the next planned refresh for this bank
return command.getStart() < endTimeLastAutoRefreshCmd || command.getEnd() > timeNextPlannedRefresh;
Bank bank = command.getBank();
// Get the last AutoRefresh command for this bank and the time of its end
ScheduledCommand lastAutoRefreshCmd = controllerCore.state->getLastCommand(
Command::AutoRefresh, bank);
sc_time endTimeLastAutoRefreshCmd = lastAutoRefreshCmd.getEnd();
// Get the time of the next planned refresh for this bank
sc_time timeNextPlannedRefresh = nextPlannedRefreshs[command.getBank()];
// Collision:
// - the start time of the command is before the end time of the last auto refresh command for this bank
// - the end time of the command is after the next planned refresh for this bank
return command.getStart() < endTimeLastAutoRefreshCmd
|| command.getEnd() > timeNextPlannedRefresh;
}
void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time)
void RefreshManagerBankwise::scheduleRefresh(tlm::tlm_generic_payload &payload,
sc_time time)
{
sc_assert(!isInvalidated(payload, time));
tlm::tlm_generic_payload& refreshPayload = refreshPayloads[DramExtension::getExtension(payload).getBank()];
tlm::tlm_generic_payload &refreshPayload =
refreshPayloads[DramExtension::getExtension(payload).getBank()];
DramExtension& extension = DramExtension::getExtension(refreshPayload);
DramExtension &extension = DramExtension::getExtension(refreshPayload);
if (controllerCore.state->rowBufferStates->rowBufferIsOpen(extension.getBank()))
{
ScheduledCommand precharge(Command::Precharge, time, getExecutionTime(Command::Precharge, refreshPayload), extension);
if (controllerCore.state->rowBufferStates->rowBufferIsOpen(
extension.getBank())) {
ScheduledCommand precharge(Command::Precharge, time,
getExecutionTime(Command::Precharge, refreshPayload), extension);
controllerCore.getCommandChecker(Command::Precharge).delayToSatisfyConstraints(precharge);
controllerCore.getCommandChecker(Command::Precharge).delayToSatisfyConstraints(
precharge);
controllerCore.state->change(precharge);
controllerCore.controller.send(precharge, refreshPayload);
}
ScheduledCommand refresh(Command::AutoRefresh, time, getExecutionTime(Command::AutoRefresh, refreshPayload), extension);
controllerCore.getCommandChecker(Command::AutoRefresh).delayToSatisfyConstraints(refresh);
ScheduledCommand refresh(Command::AutoRefresh, time,
getExecutionTime(Command::AutoRefresh, refreshPayload), extension);
controllerCore.getCommandChecker(
Command::AutoRefresh).delayToSatisfyConstraints(refresh);
controllerCore.state->change(refresh);
extension.incrementRow();
controllerCore.controller.send(refresh, refreshPayload);
planNextRefresh(extension.getBank());
planNextRefresh(extension.getBank());
}
void RefreshManagerBankwise::planNextRefresh(Bank bank)
{
nextPlannedRefreshs[bank] += Configuration::getInstance().memSpec.refreshTimings[bank].tREFI;
controllerCore.controller.send(REFTrigger, nextPlannedRefreshs[bank], refreshPayloads[bank]);
nextPlannedRefreshs[bank] +=
Configuration::getInstance().memSpec.refreshTimings[bank].tREFI;
controllerCore.controller.send(REFTrigger, nextPlannedRefreshs[bank],
refreshPayloads[bank]);
}
void RefreshManagerBankwise::reInitialize(Bank bank, sc_time time)
@@ -107,13 +117,15 @@ void RefreshManagerBankwise::reInitialize(Bank bank, sc_time time)
planNextRefresh(bank);
}
bool RefreshManagerBankwise::isInvalidated(tlm::tlm_generic_payload& payload, sc_time time)
bool RefreshManagerBankwise::isInvalidated(tlm::tlm_generic_payload &payload,
sc_time time)
{
return nextPlannedRefreshs[DramExtension::getExtension(payload).getBank()] > time;
return nextPlannedRefreshs[DramExtension::getExtension(payload).getBank()] >
time;
}
void RefreshManagerBankwise::printDebugMessage(std::string message)
{
DebugManager::getInstance().printDebugMessage(this->name(), message);
DebugManager::getInstance().printDebugMessage(this->name(), message);
}

View File

@@ -47,25 +47,26 @@ class ControllerCore;
class RefreshManagerBankwise : public IRefreshManager, public sc_module
{
public:
RefreshManagerBankwise(sc_module_name /*name*/, ControllerCore& controllerCore);
virtual ~RefreshManagerBankwise();
RefreshManagerBankwise(sc_module_name /*name*/, ControllerCore &controllerCore);
virtual ~RefreshManagerBankwise();
virtual bool hasCollision(const ScheduledCommand& command) override;
virtual void scheduleRefresh(tlm::tlm_generic_payload& payload, sc_time time) override;
virtual bool hasCollision(const ScheduledCommand &command) override;
virtual void scheduleRefresh(tlm::tlm_generic_payload &payload,
sc_time time) override;
void reInitialize(Bank bank, sc_time time) override;
void reInitialize(Bank bank, sc_time time) override;
bool isInvalidated(tlm::tlm_generic_payload& payload,sc_time time) override;
bool isInvalidated(tlm::tlm_generic_payload &payload, sc_time time) override;
private:
ControllerCore &controllerCore;
ControllerCore &controllerCore;
std::map<Bank, tlm::tlm_generic_payload> refreshPayloads;
std::map<Bank, sc_time> nextPlannedRefreshs;
std::map<Bank, tlm::tlm_generic_payload> refreshPayloads;
std::map<Bank, sc_time> nextPlannedRefreshs;
void planNextRefresh(Bank bank);
void planNextRefresh(Bank bank);
void printDebugMessage(std::string message);
void printDebugMessage(std::string message);
};
#endif /* BANKWISEREFRESHMANAGER_H_ */

View File

@@ -41,7 +41,8 @@
bool ScheduledCommand::isNoCommand() const
{
return (command == Command::NOP && start == SC_ZERO_TIME && executionTime == SC_ZERO_TIME && end == SC_ZERO_TIME);
return (command == Command::NOP && start == SC_ZERO_TIME
&& executionTime == SC_ZERO_TIME && end == SC_ZERO_TIME);
}
@@ -63,12 +64,13 @@ void ScheduledCommand::setStart(sc_time newStart)
void ScheduledCommand::delayStart(sc_time delay)
{
setStart(start+delay);
setStart(start + delay);
}
// Delays the command so that its start is at least value(constraint) from timepoint previous apart.
// If passed a constraint of 0ns, method will make sure that command starts no earlier than at timepoint previous
void ScheduledCommand::establishMinDistanceFromStart(sc_time previous, sc_time constraint)
void ScheduledCommand::establishMinDistanceFromStart(sc_time previous,
sc_time constraint)
{
delayStart(getDelayToMeetConstraint(previous, start, constraint));
}
@@ -108,12 +110,13 @@ unsigned int ScheduledCommand::getBurstLength() const
return extension.getBurstlength();
}
bool ScheduledCommand::operator ==(const ScheduledCommand& b) const
bool ScheduledCommand::operator ==(const ScheduledCommand &b) const
{
return b.command == command && b.start == start && b.executionTime == executionTime && b.end == end;
return b.command == command && b.start == start
&& b.executionTime == executionTime && b.end == end;
}
bool ScheduledCommand::commandIsIn(const std::vector<Command>& commandSet) const
bool ScheduledCommand::commandIsIn(const std::vector<Command> &commandSet) const
{
return isIn(command, commandSet);
}
@@ -122,17 +125,16 @@ TimeInterval ScheduledCommand::getIntervalOnDataStrobe() const
{
//only read and write commands have an assoicated time on the data strobe
sc_assert(getCommand() == Command::Read || getCommand() == Command::ReadA
|| getCommand() == Command::Write
|| getCommand() == Command::WriteA);
|| getCommand() == Command::Write
|| getCommand() == Command::WriteA);
MemSpec& timings = Configuration::getInstance().memSpec;
MemSpec &timings = Configuration::getInstance().memSpec;
if (getCommand() == Command::Read || getCommand() == Command::ReadA)
{
return TimeInterval(getStart() + timings.tRL, getStart() + timings.tRL + getReadAccessTime());
}
else
{
return TimeInterval(getStart() + timings.tWL - timings.clk / 2, getStart() + timings.tWL + getWriteAccessTime() - timings.clk / 2);
if (getCommand() == Command::Read || getCommand() == Command::ReadA) {
return TimeInterval(getStart() + timings.tRL,
getStart() + timings.tRL + getReadAccessTime());
} else {
return TimeInterval(getStart() + timings.tWL - timings.clk / 2,
getStart() + timings.tWL + getWriteAccessTime() - timings.clk / 2);
}
}

View File

@@ -47,20 +47,25 @@ class ScheduledCommand
{
public:
ScheduledCommand(Command command, sc_time start, sc_time executionTime, const DramExtension& extension) :
command(command), start(start), executionTime(executionTime),end(start+executionTime),
extension(extension)
ScheduledCommand(Command command, sc_time start, sc_time executionTime,
const DramExtension &extension) :
command(command), start(start), executionTime(executionTime),
end(start + executionTime),
extension(extension)
{
}
ScheduledCommand(Command command, sc_time start, sc_time executionTime, const tlm::tlm_generic_payload& payload) :
ScheduledCommand(command, start, executionTime, DramExtension::getExtension(payload))
ScheduledCommand(Command command, sc_time start, sc_time executionTime,
const tlm::tlm_generic_payload &payload) :
ScheduledCommand(command, start, executionTime,
DramExtension::getExtension(payload))
{
}
ScheduledCommand() :
command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME), end(SC_ZERO_TIME), extension()
command(Command::NOP), start(SC_ZERO_TIME), executionTime(SC_ZERO_TIME),
end(SC_ZERO_TIME), extension()
{
}
@@ -81,8 +86,8 @@ public:
Row getRow() const;
unsigned int getBurstLength() const;
bool operator ==(const ScheduledCommand& b) const;
bool commandIsIn(const std::vector<Command>& commandSet) const;
bool operator ==(const ScheduledCommand &b) const;
bool commandIsIn(const std::vector<Command> &commandSet) const;
TimeInterval getIntervalOnDataStrobe() const;

View File

@@ -45,67 +45,67 @@
using namespace std;
void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
void ActivateChecker::delayToSatisfyConstraints(ScheduledCommand &command) const
{
sc_assert(command.getCommand() == Command::Activate);
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
if (lastCommandOnBank.isValidCommand())
{
if (lastCommandOnBank.getCommand() == Command::Precharge || lastCommandOnBank.getCommand() == Command::PrechargeAll)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::ReadA)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRTP + config.memSpec.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::WriteA)
{
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(
command.getBank());
if (lastCommandOnBank.isValidCommand()) {
if (lastCommandOnBank.getCommand() == Command::Precharge
|| lastCommandOnBank.getCommand() == Command::PrechargeAll) {
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRFC);
}
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXP);
}
else if (lastCommandOnBank.getCommand() == Command::SREFX)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXSR);
}
else
reportFatal("Activate Checker", "Activate can not follow " + commandToString(lastCommandOnBank.getCommand()));
config.memSpec.tRP);
} else if (lastCommandOnBank.getCommand() == Command::ReadA) {
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tRTP + config.memSpec.tRP);
} else if (lastCommandOnBank.getCommand() == Command::WriteA) {
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR +
config.memSpec.tRP);
} else if (lastCommandOnBank.getCommand() == Command::AutoRefresh) {
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tRFC);
} else if (lastCommandOnBank.getCommand() == Command::PDNPX
|| lastCommandOnBank.getCommand() == Command::PDNAX) {
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tXP);
} else if (lastCommandOnBank.getCommand() == Command::SREFX) {
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tXSR);
} else
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)
&& satisfies_nActivateWindow(command)))
{
while (!(state.bus.isFree(command.getStart())
&& satsfies_activateToActivate_differentBank(command)
&& satisfies_nActivateWindow(command))) {
command.delayStart(config.memSpec.clk);
}
}
void ActivateChecker::delay_to_satisfy_activateToActivate_sameBank(ScheduledCommand& command) const
void ActivateChecker::delay_to_satisfy_activateToActivate_sameBank(
ScheduledCommand &command) const
{
ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate, command.getBank());
if (lastActivateOnBank.isValidCommand())
{
command.establishMinDistanceFromStart(lastActivateOnBank.getStart(), config.memSpec.tRC);
ScheduledCommand lastActivateOnBank = state.getLastCommand(Command::Activate,
command.getBank());
if (lastActivateOnBank.isValidCommand()) {
command.establishMinDistanceFromStart(lastActivateOnBank.getStart(),
config.memSpec.tRC);
}
}
bool ActivateChecker::satsfies_activateToActivate_differentBank(ScheduledCommand& command) const
bool ActivateChecker::satsfies_activateToActivate_differentBank(
ScheduledCommand &command) const
{
for (auto act : state.lastActivates)
{
for (auto act : state.lastActivates) {
sc_time time = act.first;
sc_time tRRD = (command.getBankGroup() == act.second.getBankGroup()) ? config.memSpec.tRRD_L : config.memSpec.tRRD_S;
sc_time tRRD = (command.getBankGroup() == act.second.getBankGroup()) ?
config.memSpec.tRRD_L : config.memSpec.tRRD_S;
if ((time < command.getStart() && command.getStart() - time < tRRD)
|| (command.getStart() <= time && time - command.getStart() < tRRD))
@@ -114,23 +114,21 @@ bool ActivateChecker::satsfies_activateToActivate_differentBank(ScheduledCommand
return true;
}
bool ActivateChecker::satisfies_nActivateWindow(ScheduledCommand& command) const
bool ActivateChecker::satisfies_nActivateWindow(ScheduledCommand &command) const
{
/*
* there may be activates scheduled in the future, so emplace
* command in a copied set (not necessarily the last in time),
* and check if the n-act constraint holds for the whole set.
*/
if (state.lastActivates.size() >= config.memSpec.nActivate)
{
if (state.lastActivates.size() >= config.memSpec.nActivate) {
map<sc_time, ScheduledCommand> lastActivates = state.lastActivates;
lastActivates.emplace(command.getStart(), command);
auto upper = lastActivates.begin();
advance(upper, config.memSpec.nActivate);
auto lower = lastActivates.begin();
while (upper != lastActivates.end())
{
while (upper != lastActivates.end()) {
if (upper->first - lower->first < config.memSpec.tNAW)
return false;
++upper;

View File

@@ -45,17 +45,20 @@
class ActivateChecker: public ICommandChecker
{
public:
ActivateChecker(const Configuration& config, ControllerState& state) : config(config), state(state){}
virtual ~ActivateChecker(){}
ActivateChecker(const Configuration &config,
ControllerState &state) : config(config), state(state) {}
virtual ~ActivateChecker() {}
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
virtual void delayToSatisfyConstraints(ScheduledCommand &command) const
override;
private:
const Configuration& config;
ControllerState& state;//TODO make const
const Configuration &config;
ControllerState &state;//TODO make const
void delay_to_satisfy_activateToActivate_sameBank(ScheduledCommand& command) const;
bool satsfies_activateToActivate_differentBank(ScheduledCommand& command) const;
bool satisfies_nActivateWindow(ScheduledCommand& command) const;
void delay_to_satisfy_activateToActivate_sameBank(ScheduledCommand &command)
const;
bool satsfies_activateToActivate_differentBank(ScheduledCommand &command) const;
bool satisfies_nActivateWindow(ScheduledCommand &command) const;
};
#endif /* ACTIVATESCHEDULER_H_ */

View File

@@ -44,8 +44,8 @@
class ICommandChecker
{
public:
virtual ~ICommandChecker() {}
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const = 0;
virtual ~ICommandChecker() {}
virtual void delayToSatisfyConstraints(ScheduledCommand &command) const = 0;
};

View File

@@ -38,77 +38,86 @@
#include "PowerDownChecker.h"
#include "../../TimingCalculation.h"
sc_time PowerDownChecker::getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const
sc_time PowerDownChecker::getTimeConstraintToEnterPowerDown(Command lastCmd,
Command pdnCmd) const
{
sc_assert(pdnCmd == Command::SREF || pdnCmd == Command::PDNA || pdnCmd == Command::PDNP);
sc_assert(pdnCmd == Command::SREF || pdnCmd == Command::PDNA
|| pdnCmd == Command::PDNP);
sc_time constraint;
sc_time constraint;
if (lastCmd == Command::Read || lastCmd == Command::ReadA) {
constraint = config.memSpec.tRL + getReadAccessTime() + config.memSpec.clk;
} else if (lastCmd == Command::Write) {
constraint = config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR;
} else if (lastCmd == Command::WriteA) {
constraint = config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.clk;
} else if (lastCmd == Command::AutoRefresh) {
constraint = config.memSpec.tRFC;
} else if (lastCmd == Command::PDNPX || lastCmd == Command::PDNAX) {
constraint = config.memSpec.tXP;
} else if (lastCmd == Command::SREFX) {
constraint = config.memSpec.tXSR;
} else if(lastCmd == Command::Precharge || lastCmd == Command::PrechargeAll) {
constraint = config.memSpec.tRP;
} else {
reportFatal("Powerdown checker", commandToString(pdnCmd) + " can not follow " + commandToString(lastCmd));
}
if (lastCmd == Command::Read || lastCmd == Command::ReadA) {
constraint = config.memSpec.tRL + getReadAccessTime() + config.memSpec.clk;
} else if (lastCmd == Command::Write) {
constraint = config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR;
} else if (lastCmd == Command::WriteA) {
constraint = config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR +
config.memSpec.clk;
} else if (lastCmd == Command::AutoRefresh) {
constraint = config.memSpec.tRFC;
} else if (lastCmd == Command::PDNPX || lastCmd == Command::PDNAX) {
constraint = config.memSpec.tXP;
} else if (lastCmd == Command::SREFX) {
constraint = config.memSpec.tXSR;
} else if (lastCmd == Command::Precharge || lastCmd == Command::PrechargeAll) {
constraint = config.memSpec.tRP;
} else {
reportFatal("Powerdown checker",
commandToString(pdnCmd) + " can not follow " + commandToString(lastCmd));
}
return constraint;
return constraint;
}
void PowerDownChecker::delayToSatisfyConstraints(ScheduledCommand &command) const
void PowerDownChecker::delayToSatisfyConstraints(ScheduledCommand &command)
const
{
sc_assert(command.commandIsIn({Command::PDNA, Command::PDNP, Command::SREF, Command::PDNAX, Command::PDNPX, Command::SREFX}));
sc_assert(command.commandIsIn({Command::PDNA, Command::PDNP, Command::SREF, Command::PDNAX, Command::PDNPX, Command::SREFX}));
// Power Down commmand (one of the listed above)
Command pdnCmd = command.getCommand();
Bank bank = command.getBank();
// Power Down commmand (one of the listed above)
Command pdnCmd = command.getCommand();
Bank bank = command.getBank();
sc_time timeConstraint;
sc_time timeConstraint;
if (pdnCmd == Command::PDNA || pdnCmd == Command::PDNP || pdnCmd == Command::SREF) {
// Entering in one of the Power Down modes:
// PDNA - Active Power Down
// PDNP - Precharge Power Down
// SREF - Self Refresh
if (pdnCmd == Command::PDNA || pdnCmd == Command::PDNP
|| pdnCmd == Command::SREF) {
// Entering in one of the Power Down modes:
// PDNA - Active Power Down
// PDNP - Precharge Power Down
// SREF - Self Refresh
// Get the last scheduled command on this bank
ScheduledCommand lastSchedCmdOnBank = state.getLastScheduledCommand(bank);
// Get the last scheduled command on this bank
ScheduledCommand lastSchedCmdOnBank = state.getLastScheduledCommand(bank);
if (lastSchedCmdOnBank.isValidCommand()) {
// Get the start time for the last scheduled command on this bank
sc_time lastSchedCmdOnBankStart = lastSchedCmdOnBank.getStart();
// Get the last command on this bank itself
Command lastCmdBank = lastSchedCmdOnBank.getCommand();
// Get the start time for the last scheduled command on this bank
sc_time lastSchedCmdOnBankStart = lastSchedCmdOnBank.getStart();
// Get the last command on this bank itself
Command lastCmdBank = lastSchedCmdOnBank.getCommand();
timeConstraint = getTimeConstraintToEnterPowerDown(lastCmdBank, pdnCmd);
timeConstraint = getTimeConstraintToEnterPowerDown(lastCmdBank, pdnCmd);
command.establishMinDistanceFromStart(lastSchedCmdOnBankStart, timeConstraint);
command.establishMinDistanceFromStart(lastSchedCmdOnBankStart, timeConstraint);
}
} else if (pdnCmd == Command::PDNAX) {
// Leaving Active Power Down
timeConstraint = config.memSpec.tCKE;
command.establishMinDistanceFromStart(state.getLastCommand(Command::PDNA, bank).getStart(), timeConstraint);
command.establishMinDistanceFromStart(state.getLastCommand(Command::PDNA,
bank).getStart(), timeConstraint);
} else if (pdnCmd == Command::PDNPX) {
// Leaving Precharge Power Down
timeConstraint = config.memSpec.tCKE;
command.establishMinDistanceFromStart(state.getLastCommand(Command::PDNP, bank).getStart(), timeConstraint);
command.establishMinDistanceFromStart(state.getLastCommand(Command::PDNP,
bank).getStart(), timeConstraint);
} else if (pdnCmd == Command::SREFX) {
// Leaving Self Refresh
timeConstraint = config.memSpec.tCKESR;
command.establishMinDistanceFromStart(state.getLastCommand(Command::SREF, bank).getStart(), timeConstraint);
command.establishMinDistanceFromStart(state.getLastCommand(Command::SREF,
bank).getStart(), timeConstraint);
}
state.bus.moveCommandToNextFreeSlot(command);
state.bus.moveCommandToNextFreeSlot(command);
}

View File

@@ -46,15 +46,18 @@
class PowerDownChecker : public ICommandChecker
{
public:
PowerDownChecker(const Configuration &config, ControllerState &state) : config(config), state(state) {}
virtual ~PowerDownChecker() {}
PowerDownChecker(const Configuration &config,
ControllerState &state) : config(config), state(state) {}
virtual ~PowerDownChecker() {}
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
virtual void delayToSatisfyConstraints(ScheduledCommand &command) const
override;
private:
const Configuration &config;
ControllerState &state;
sc_time getTimeConstraintToEnterPowerDown(Command lastCmd, Command pdnCmd) const;
const Configuration &config;
ControllerState &state;
sc_time getTimeConstraintToEnterPowerDown(Command lastCmd,
Command pdnCmd) const;
};
#endif /* POWERDOWNCHECKER_H_ */

View File

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

View File

@@ -45,19 +45,20 @@
class PrechargeAllChecker: public ICommandChecker
{
public:
PrechargeAllChecker(const Configuration& config, ControllerState& state) :
config(config), state(state)
{
}
virtual ~PrechargeAllChecker()
{
}
PrechargeAllChecker(const Configuration &config, ControllerState &state) :
config(config), state(state)
{
}
virtual ~PrechargeAllChecker()
{
}
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
virtual void delayToSatisfyConstraints(ScheduledCommand &command) const
override;
private:
const Configuration& config;
ControllerState& state;
const Configuration &config;
ControllerState &state;
};

View File

@@ -38,47 +38,45 @@
#include "../../TimingCalculation.h"
void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
void PrechargeChecker::delayToSatisfyConstraints(ScheduledCommand &command)
const
{
//return;
sc_assert(command.getCommand() == Command::Precharge);
ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank());
if (lastCommand.isValidCommand())
{
if (lastCommand.isValidCommand()) {
// the first two cases happen when a resfresh interrups the command sequence of a transaction
// (e.g. commands to process transaction are PRE-ACT-RD and refresh happens after the PRE or after the ACT)
if(lastCommand.getCommand() == Command::Precharge)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRP);
}
else if(lastCommand.getCommand() == Command::Activate)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRCD);
if (lastCommand.getCommand() == Command::Precharge) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tRP);
} else if (lastCommand.getCommand() == Command::Activate) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tRCD);
}
else if (lastCommand.getCommand() == Command::Read)
{
command.establishMinDistanceFromStart(lastCommand.getStart(),config.memSpec.tRTP);
}
else if (lastCommand.getCommand() == Command::Write)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR);
else if (lastCommand.getCommand() == Command::Read) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tRTP);
} else if (lastCommand.getCommand() == Command::Write) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR);
}
else if (lastCommand.getCommand() == Command::PDNAX)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tXP);
}
else
reportFatal("Precharge Checker", "Precharge can not follow " + commandToString(lastCommand.getCommand()));
} else if (lastCommand.getCommand() == Command::PDNAX) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tXP);
} else
reportFatal("Precharge Checker",
"Precharge can not follow " + commandToString(lastCommand.getCommand()));
}
ScheduledCommand lastActivate = state.getLastCommand(Command::Activate, command.getBank());
if (lastActivate.isValidCommand())
{
command.establishMinDistanceFromStart(lastActivate.getStart(), config.memSpec.tRAS);
ScheduledCommand lastActivate = state.getLastCommand(Command::Activate,
command.getBank());
if (lastActivate.isValidCommand()) {
command.establishMinDistanceFromStart(lastActivate.getStart(),
config.memSpec.tRAS);
}
state.bus.moveCommandToNextFreeSlot(command);

View File

@@ -45,13 +45,15 @@
class PrechargeChecker: public ICommandChecker
{
public:
PrechargeChecker(const Configuration& config, ControllerState& state) : config(config), state(state) {}
virtual ~PrechargeChecker() {}
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
PrechargeChecker(const Configuration &config,
ControllerState &state) : config(config), state(state) {}
virtual ~PrechargeChecker() {}
virtual void delayToSatisfyConstraints(ScheduledCommand &command) const
override;
private:
const Configuration& config;
ControllerState& state;
const Configuration &config;
ControllerState &state;
};

View File

@@ -41,44 +41,40 @@
using namespace std;
void ReadChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
void ReadChecker::delayToSatisfyConstraints(ScheduledCommand &command) const
{
sc_assert(command.getCommand() == Command::Read || command.getCommand() == Command::ReadA);
sc_assert(command.getCommand() == Command::Read
|| command.getCommand() == Command::ReadA);
delayToSatisfyDLL(command);
ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank());
if (lastCommand.isValidCommand())
{
if (lastCommand.getCommand() == Command::Activate)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRCD);
}
else if (lastCommand.getCommand() == Command::Read)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), ReadChecker::readToRead(lastCommand,command));
}
else if (lastCommand.getCommand() == Command::Write)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), ReadChecker::writeToRead(lastCommand, command));
}
else if (lastCommand.getCommand() == Command::PDNPX || lastCommand.getCommand() == Command::PDNAX)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tXP);
}
else
reportFatal("Read Checker", "Read can not follow " + commandToString(lastCommand.getCommand()));
if (lastCommand.isValidCommand()) {
if (lastCommand.getCommand() == Command::Activate) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tRCD);
} else if (lastCommand.getCommand() == Command::Read) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
ReadChecker::readToRead(lastCommand, command));
} else if (lastCommand.getCommand() == Command::Write) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
ReadChecker::writeToRead(lastCommand, command));
} else if (lastCommand.getCommand() == Command::PDNPX
|| lastCommand.getCommand() == Command::PDNAX) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tXP);
} else
reportFatal("Read Checker",
"Read can not follow " + commandToString(lastCommand.getCommand()));
}
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command))
{
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command)) {
command.delayStart(config.memSpec.clk);
}
}
bool ReadChecker::collidesOnDataStrobe(ScheduledCommand& read) const
bool ReadChecker::collidesOnDataStrobe(ScheduledCommand &read) const
{
for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands)
{
for (ScheduledCommand &strobeCommand : state.lastDataStrobeCommands) {
if (collidesWithStrobeCommand(read, strobeCommand))
return true;
}
@@ -86,51 +82,63 @@ bool ReadChecker::collidesOnDataStrobe(ScheduledCommand& read) const
return false;
}
bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand& read, ScheduledCommand& strobeCommand) const
bool ReadChecker::collidesWithStrobeCommand(ScheduledCommand &read,
ScheduledCommand &strobeCommand) const
{
if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA)
{
return getDistance(read.getStart(),strobeCommand.getStart()) < ReadChecker::readToRead(strobeCommand,read);
}
else if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA)
{
if (strobeCommand.getCommand() == Command::Read
|| strobeCommand.getCommand() == Command::ReadA) {
return getDistance(read.getStart(),
strobeCommand.getStart()) < ReadChecker::readToRead(strobeCommand, read);
} else if (strobeCommand.getCommand() == Command::Write
|| strobeCommand.getCommand() == Command::WriteA) {
if (strobeCommand.getStart() >= read.getStart())
return getDistance(read.getStart(), strobeCommand.getStart()) < WriteChecker::readToWrite(read,strobeCommand);
return getDistance(read.getStart(),
strobeCommand.getStart()) < WriteChecker::readToWrite(read, strobeCommand);
else
return getDistance(strobeCommand.getStart(), read.getStart()) < ReadChecker::writeToRead(strobeCommand, read);
}
else
{
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;
}
}
void ReadChecker::delayToSatisfyDLL(ScheduledCommand& read) const
void ReadChecker::delayToSatisfyDLL(ScheduledCommand &read) const
{
ScheduledCommand lastSREFX = state.getLastCommand(Command::SREFX, read.getBank());
ScheduledCommand lastSREFX = state.getLastCommand(Command::SREFX,
read.getBank());
if (lastSREFX.isValidCommand())
read.establishMinDistanceFromStart(lastSREFX.getStart(), config.memSpec.tXSRDLL);
read.establishMinDistanceFromStart(lastSREFX.getStart(),
config.memSpec.tXSRDLL);
}
sc_time ReadChecker::readToRead(ScheduledCommand& firstRead, ScheduledCommand& secondRead)
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);
sc_assert(firstRead.getCommand() == Command::Read
|| firstRead.getCommand() == Command::ReadA);
sc_assert(secondRead.getCommand() == Command::Read
|| secondRead.getCommand() == Command::ReadA);
MemSpec& config = Configuration::getInstance().memSpec;
sc_time tCCD = (firstRead.getBankGroup() == secondRead.getBankGroup()) ? config.tCCD_L : config.tCCD_S;
MemSpec &config = Configuration::getInstance().memSpec;
sc_time tCCD = (firstRead.getBankGroup() == secondRead.getBankGroup()) ?
config.tCCD_L : config.tCCD_S;
return max(tCCD, getReadAccessTime());
}
sc_time ReadChecker::writeToRead(ScheduledCommand& write, ScheduledCommand& read)
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);
sc_assert(read.getCommand() == Command::Read
|| read.getCommand() == Command::ReadA);
sc_assert(write.getCommand() == Command::Write
|| write.getCommand() == Command::WriteA);
MemSpec& config = Configuration::getInstance().memSpec;
sc_time tWTR = (write.getBankGroup() == read.getBankGroup()) ? config.tWTR_L : config.tWTR_S;
MemSpec &config = Configuration::getInstance().memSpec;
sc_time tWTR = (write.getBankGroup() == read.getBankGroup()) ? config.tWTR_L :
config.tWTR_S;
return config.tWL + getWriteAccessTime() + tWTR;
}

View File

@@ -44,21 +44,25 @@
class ReadChecker: public ICommandChecker
{
public:
ReadChecker(Configuration& config, ControllerState& state) : config(config), state(state) {}
virtual ~ReadChecker() {}
ReadChecker(Configuration &config, ControllerState &state) : config(config),
state(state) {}
virtual ~ReadChecker() {}
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
virtual void delayToSatisfyConstraints(ScheduledCommand &command) const
override;
static sc_time readToRead(ScheduledCommand& firstRead, ScheduledCommand& secondRead);
static sc_time writeToRead(ScheduledCommand& write, ScheduledCommand& read);
static sc_time readToRead(ScheduledCommand &firstRead,
ScheduledCommand &secondRead);
static sc_time writeToRead(ScheduledCommand &write, ScheduledCommand &read);
private:
const Configuration& config;
ControllerState& state;
const Configuration &config;
ControllerState &state;
void delayToSatisfyDLL(ScheduledCommand& read) const;
bool collidesOnDataStrobe(ScheduledCommand& read) const;
bool collidesWithStrobeCommand(ScheduledCommand& read, ScheduledCommand& strobeCommand) const;
void delayToSatisfyDLL(ScheduledCommand &read) const;
bool collidesOnDataStrobe(ScheduledCommand &read) const;
bool collidesWithStrobeCommand(ScheduledCommand &read,
ScheduledCommand &strobeCommand) const;
};
#endif /* READCHECKER_H_ */

View File

@@ -38,81 +38,71 @@
#include "RefreshChecker.h"
#include "../../TimingCalculation.h"
void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
void RefreshChecker::delayToSatisfyConstraints(ScheduledCommand &command) const
{
sc_assert(command.getCommand() == Command::AutoRefresh);
if(config.BankwiseLogic)
{
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(command.getBank());
if (config.BankwiseLogic) {
ScheduledCommand lastCommandOnBank = state.getLastScheduledCommand(
command.getBank());
if (lastCommandOnBank.isValidCommand())
{
if (lastCommandOnBank.getCommand() == Command::Precharge || lastCommandOnBank.getCommand() == Command::PrechargeAll)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::ReadA)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRTP + config.memSpec.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::WriteA)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.tRP);
}
else if (lastCommandOnBank.getCommand() == Command::PDNPX || lastCommandOnBank.getCommand() == Command::PDNAX)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXP);
}
else if (lastCommandOnBank.getCommand() == Command::SREFX)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tXSR);
}
else if (lastCommandOnBank.getCommand() == Command::AutoRefresh)
{
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(), config.memSpec.tRFC);
}
else
reportFatal("Refresh Checker", "Refresh can not follow " + commandToString(lastCommandOnBank.getCommand()));
if (lastCommandOnBank.isValidCommand()) {
if (lastCommandOnBank.getCommand() == Command::Precharge
|| lastCommandOnBank.getCommand() == Command::PrechargeAll) {
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tRP);
} else if (lastCommandOnBank.getCommand() == Command::ReadA) {
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tRTP + config.memSpec.tRP);
} else if (lastCommandOnBank.getCommand() == Command::WriteA) {
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR +
config.memSpec.tRP);
} else if (lastCommandOnBank.getCommand() == Command::PDNPX
|| lastCommandOnBank.getCommand() == Command::PDNAX) {
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tXP);
} else if (lastCommandOnBank.getCommand() == Command::SREFX) {
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tXSR);
} else if (lastCommandOnBank.getCommand() == Command::AutoRefresh) {
command.establishMinDistanceFromStart(lastCommandOnBank.getStart(),
config.memSpec.tRFC);
} else
reportFatal("Refresh Checker",
"Refresh can not follow " + commandToString(lastCommandOnBank.getCommand()));
}
}
else
{
for (unsigned int bank = 0; bank < config.memSpec.NumberOfBanks; ++bank)
{
} else {
for (unsigned int bank = 0; bank < config.memSpec.NumberOfBanks; ++bank) {
ScheduledCommand lastCommand = state.getLastScheduledCommand(Bank(bank));
if (lastCommand.isValidCommand())
{
if(lastCommand.getCommand() == Command::Precharge || lastCommand.getCommand() == Command::PrechargeAll)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRP);
}
else if(lastCommand.getCommand() == Command::Activate)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRCD);
}
else if (lastCommand.getCommand() == Command::ReadA)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRTP + config.memSpec.tRP);
}
else if(lastCommand.getCommand() == Command::WriteA)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR + config.memSpec.tRP);
}
else if (lastCommand.getCommand() == Command::PDNAX || lastCommand.getCommand() == Command::PDNPX)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tXP);
}
else if (lastCommand.getCommand() == Command::SREFX)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tXSR);
}
else if (lastCommand.getCommand() == Command::AutoRefresh)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRFC);
}
else
reportFatal("Refresh Checker", "Refresh can not follow " + commandToString(lastCommand.getCommand()));
if (lastCommand.isValidCommand()) {
if (lastCommand.getCommand() == Command::Precharge
|| lastCommand.getCommand() == Command::PrechargeAll) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tRP);
} else if (lastCommand.getCommand() == Command::Activate) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tRCD);
} else if (lastCommand.getCommand() == Command::ReadA) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tRTP + config.memSpec.tRP);
} else if (lastCommand.getCommand() == Command::WriteA) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tWL + getWriteAccessTime() + config.memSpec.tWR +
config.memSpec.tRP);
} else if (lastCommand.getCommand() == Command::PDNAX
|| lastCommand.getCommand() == Command::PDNPX) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tXP);
} else if (lastCommand.getCommand() == Command::SREFX) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tXSR);
} else if (lastCommand.getCommand() == Command::AutoRefresh) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tRFC);
} else
reportFatal("Refresh Checker",
"Refresh can not follow " + commandToString(lastCommand.getCommand()));
}
}
}

View File

@@ -46,19 +46,20 @@
class RefreshChecker: public ICommandChecker
{
public:
RefreshChecker(const Configuration& config, ControllerState& state) :
config(config), state(state)
{
}
virtual ~RefreshChecker()
{
}
RefreshChecker(const Configuration &config, ControllerState &state) :
config(config), state(state)
{
}
virtual ~RefreshChecker()
{
}
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
virtual void delayToSatisfyConstraints(ScheduledCommand &command) const
override;
private:
const Configuration& config;
ControllerState& state;
const Configuration &config;
ControllerState &state;
};

View File

@@ -41,88 +41,93 @@
using namespace std;
void WriteChecker::delayToSatisfyConstraints(ScheduledCommand& command) const
void WriteChecker::delayToSatisfyConstraints(ScheduledCommand &command) const
{
sc_assert(command.getCommand() == Command::Write || command.getCommand() == Command::WriteA);
sc_assert(command.getCommand() == Command::Write
|| command.getCommand() == Command::WriteA);
ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank());
ScheduledCommand lastCommand = state.getLastScheduledCommand(command.getBank());
if (lastCommand.isValidCommand())
{
if (lastCommand.getCommand() == Command::Activate)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tRCD);
}
else if (lastCommand.getCommand() == Command::Read)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), WriteChecker::readToWrite(lastCommand, command));
}
else if (lastCommand.getCommand() == Command::Write)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), WriteChecker::writeToWrite(lastCommand, command));
}
else if (lastCommand.getCommand() == Command::PDNPX || lastCommand.getCommand() == Command::PDNAX)
{
command.establishMinDistanceFromStart(lastCommand.getStart(), config.memSpec.tXP);
}
else
reportFatal("Write Checker", "Write can not follow " + commandToString(lastCommand.getCommand()));
}
if (lastCommand.isValidCommand()) {
if (lastCommand.getCommand() == Command::Activate) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tRCD);
} else if (lastCommand.getCommand() == Command::Read) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
WriteChecker::readToWrite(lastCommand, command));
} else if (lastCommand.getCommand() == Command::Write) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
WriteChecker::writeToWrite(lastCommand, command));
} else if (lastCommand.getCommand() == Command::PDNPX
|| lastCommand.getCommand() == Command::PDNAX) {
command.establishMinDistanceFromStart(lastCommand.getStart(),
config.memSpec.tXP);
} else
reportFatal("Write Checker",
"Write can not follow " + commandToString(lastCommand.getCommand()));
}
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command))
{
command.delayStart(config.memSpec.clk);
}
while (!state.bus.isFree(command.getStart()) || collidesOnDataStrobe(command)) {
command.delayStart(config.memSpec.clk);
}
}
bool WriteChecker::collidesOnDataStrobe(ScheduledCommand& write) const
bool WriteChecker::collidesOnDataStrobe(ScheduledCommand &write) const
{
for (ScheduledCommand& strobeCommand : state.lastDataStrobeCommands)
{
if (collidesWithStrobeCommand(write, strobeCommand))
return true;
}
for (ScheduledCommand &strobeCommand : state.lastDataStrobeCommands) {
if (collidesWithStrobeCommand(write, strobeCommand))
return true;
}
return false;
return false;
}
bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand& write, ScheduledCommand& strobeCommand) const
bool WriteChecker::collidesWithStrobeCommand(ScheduledCommand &write,
ScheduledCommand &strobeCommand) const
{
if (strobeCommand.getCommand() == Command::Write || strobeCommand.getCommand() == Command::WriteA)
{
return getDistance(write.getStart(),strobeCommand.getStart()) < WriteChecker::writeToWrite(strobeCommand,write);
}
else if (strobeCommand.getCommand() == Command::Read || strobeCommand.getCommand() == Command::ReadA)
{
if (strobeCommand.getStart() >= write.getStart())
return getDistance(write.getStart(),strobeCommand.getStart()) < ReadChecker::writeToRead(write, strobeCommand);
else
return getDistance(strobeCommand.getStart(), write.getStart()) < WriteChecker::readToWrite(strobeCommand, write);
}
else
{
reportFatal("Write Checker",
"Invalid strobeCommand in data strobe commands " + commandToString(strobeCommand.getCommand()));
return true;
}
if (strobeCommand.getCommand() == Command::Write
|| strobeCommand.getCommand() == Command::WriteA) {
return getDistance(write.getStart(),
strobeCommand.getStart()) < WriteChecker::writeToWrite(strobeCommand, write);
} else if (strobeCommand.getCommand() == Command::Read
|| strobeCommand.getCommand() == Command::ReadA) {
if (strobeCommand.getStart() >= write.getStart())
return getDistance(write.getStart(),
strobeCommand.getStart()) < ReadChecker::writeToRead(write, strobeCommand);
else
return getDistance(strobeCommand.getStart(),
write.getStart()) < WriteChecker::readToWrite(strobeCommand, write);
} else {
reportFatal("Write Checker",
"Invalid strobeCommand in data strobe commands " + commandToString(
strobeCommand.getCommand()));
return true;
}
}
sc_time WriteChecker::writeToWrite(ScheduledCommand& firstWrite, ScheduledCommand& secondWrite)
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);
sc_assert(firstWrite.getCommand() == Command::Write
|| firstWrite.getCommand() == Command::WriteA);
sc_assert(secondWrite.getCommand() == Command::Write
|| secondWrite.getCommand() == Command::WriteA);
MemSpec& config = Configuration::getInstance().memSpec;
sc_time tCCD = (firstWrite.getBankGroup() == secondWrite.getBankGroup()) ? config.tCCD_L : config.tCCD_S;
return max(tCCD, getWriteAccessTime());
MemSpec &config = Configuration::getInstance().memSpec;
sc_time tCCD = (firstWrite.getBankGroup() == secondWrite.getBankGroup()) ?
config.tCCD_L : config.tCCD_S;
return max(tCCD, getWriteAccessTime());
}
sc_time WriteChecker::readToWrite(ScheduledCommand& read __attribute__((unused)), ScheduledCommand& write __attribute__((unused)))
sc_time WriteChecker::readToWrite(ScheduledCommand &read __attribute__((
unused)), ScheduledCommand &write __attribute__((unused)))
{
sc_assert(read.getCommand() == Command::Read || read.getCommand() == Command::ReadA);
sc_assert(write.getCommand() == Command::Write || write.getCommand() == Command::WriteA);
sc_assert(read.getCommand() == Command::Read
|| read.getCommand() == Command::ReadA);
sc_assert(write.getCommand() == Command::Write
|| write.getCommand() == Command::WriteA);
MemSpec& config = Configuration::getInstance().memSpec;
return config.tRL + getReadAccessTime() - config.tWL + config.clk * 2;
MemSpec &config = Configuration::getInstance().memSpec;
return config.tRL + getReadAccessTime() - config.tWL + config.clk * 2;
}

View File

@@ -45,18 +45,22 @@
class WriteChecker: public ICommandChecker
{
public:
WriteChecker(const Configuration& config, ControllerState& state) : config(config), state(state) {}
virtual ~WriteChecker() {}
WriteChecker(const Configuration &config,
ControllerState &state) : config(config), state(state) {}
virtual ~WriteChecker() {}
virtual void delayToSatisfyConstraints(ScheduledCommand& command) const override;
virtual void delayToSatisfyConstraints(ScheduledCommand &command) const
override;
static sc_time writeToWrite(ScheduledCommand& firstWrite, ScheduledCommand& secondWrite);
static sc_time readToWrite(ScheduledCommand& read, ScheduledCommand& write);
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;
bool collidesOnDataStrobe(ScheduledCommand &write) const;
bool collidesWithStrobeCommand(ScheduledCommand &write,
ScheduledCommand &strobeCommand) const;
const Configuration &config;
ControllerState &state;
};

View File

@@ -38,31 +38,30 @@
using namespace std;
void Fifo::schedule(gp* payload)
void Fifo::schedule(gp *payload)
{
buffer[DramExtension::getExtension(payload).getBank()].emplace_back(payload);
}
pair<Command, tlm::tlm_generic_payload*> Fifo::getNextRequest(Bank bank)
pair<Command, tlm::tlm_generic_payload *> Fifo::getNextRequest(Bank bank)
{
if(!buffer[bank].empty())
{
gp* payload = buffer[bank].front();
if (!buffer[bank].empty()) {
gp *payload = buffer[bank].front();
Command command = IScheduler::getNextCommand(*payload);
if(command == Command::Read || command == Command::ReadA || command == Command::Write || command == Command::WriteA)
{
if (command == Command::Read || command == Command::ReadA
|| command == Command::Write || command == Command::WriteA) {
buffer[bank].pop_front();
}
return pair<Command, tlm::tlm_generic_payload*>(command, payload);
return pair<Command, tlm::tlm_generic_payload *>(command, payload);
}
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
return pair<Command, tlm::tlm_generic_payload *>(Command::NOP, NULL);
}
gp* Fifo::getPendingRequest(Bank /*bank*/)
gp *Fifo::getPendingRequest(Bank /*bank*/)
{
return NULL;
return NULL;
}

View File

@@ -50,12 +50,13 @@ public:
Fifo(ControllerCore &controllerCore) : IScheduler(controllerCore) {}
virtual ~Fifo() {}
void schedule(gp* payload) override;
std::pair<Command, tlm::tlm_generic_payload*> getNextRequest(Bank bank) override;
virtual gp* getPendingRequest(Bank bank) override;
void schedule(gp *payload) override;
std::pair<Command, tlm::tlm_generic_payload *> getNextRequest(
Bank bank) override;
virtual gp *getPendingRequest(Bank bank) override;
private:
std::map<Bank, std::deque<gp*>> buffer;
std::map<Bank, std::deque<gp *>> buffer;
};
#endif /* FIFO_H_ */

View File

@@ -44,7 +44,8 @@ void FifoStrict::schedule(tlm::tlm_generic_payload *payload)
buffer.push_back(std::pair<Bank, tlm::tlm_generic_payload *>(bank, payload));
}
std::pair<Command, tlm::tlm_generic_payload *> FifoStrict::getNextRequest(Bank bank)
std::pair<Command, tlm::tlm_generic_payload *> FifoStrict::getNextRequest(
Bank bank)
{
if (!buffer.empty()) {
@@ -76,7 +77,7 @@ std::pair<Command, tlm::tlm_generic_payload *> FifoStrict::getNextRequest(Bank b
//
Command command = IScheduler::getNextCommand(*payload);
if(commandIsIn(command, {Command::Read, Command::Write, Command::ReadA, Command::WriteA})) {
if (commandIsIn(command, {Command::Read, Command::Write, Command::ReadA, Command::WriteA})) {
buffer.pop_front();
// Check if the next transaction is a blocked read or write
@@ -91,7 +92,7 @@ std::pair<Command, tlm::tlm_generic_payload *> FifoStrict::getNextRequest(Bank b
}
}
return pair<Command, tlm::tlm_generic_payload*>(command, payload);
return pair<Command, tlm::tlm_generic_payload *>(command, payload);
} else {
// The next request in the FIFO is NOT for the bank passed as parameter.
@@ -115,20 +116,21 @@ std::pair<Command, tlm::tlm_generic_payload *> FifoStrict::getNextRequest(Bank b
// the next command for this request is read or write
// NOP will be returned and no operation will be
// performed.
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
} else {
return pair<Command, tlm::tlm_generic_payload *>(Command::NOP, NULL);
}
else {
// Commands other than read and write are issued normally.
return pair<Command, tlm::tlm_generic_payload*>(command, payload);
return pair<Command, tlm::tlm_generic_payload *>(command, payload);
}
}
}
}
}
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
return pair<Command, tlm::tlm_generic_payload *>(Command::NOP, NULL);
}
gp* FifoStrict::getPendingRequest(Bank /*bank*/)
gp *FifoStrict::getPendingRequest(Bank /*bank*/)
{
return NULL;
return NULL;
}

View File

@@ -51,12 +51,15 @@ class FifoStrict : public IScheduler
{
public:
IController &controller;
FifoStrict(IController &controller, ControllerCore &controllerCore) : IScheduler(controllerCore), controller(controller) {}
FifoStrict(IController &controller,
ControllerCore &controllerCore) : IScheduler(controllerCore),
controller(controller) {}
virtual ~FifoStrict() {}
void schedule(gp* payload) override;
std::pair<Command, tlm::tlm_generic_payload*> getNextRequest(Bank bank) override;
virtual gp* getPendingRequest(Bank bank) override;
void schedule(gp *payload) override;
std::pair<Command, tlm::tlm_generic_payload *> getNextRequest(
Bank bank) override;
virtual gp *getPendingRequest(Bank bank) override;
private:
std::deque<std::pair<Bank, tlm::tlm_generic_payload *>> buffer;

View File

@@ -65,32 +65,30 @@ void FR_FCFS::schedule(gp *payload)
// should provide a true or false when the placement into the buffer worked
// out or not (?).
buffer[DramExtension::getExtension(payload).getBank()]
.emplace_back(payload);
.emplace_back(payload);
}
std::pair<Command, gp*> FR_FCFS::getNextRequest(Bank bank)
std::pair<Command, gp *> FR_FCFS::getNextRequest(Bank bank)
{
// If the bank is empty like Bank0 in the example we do nothing
if(buffer[bank].empty())
{
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
if (buffer[bank].empty()) {
return pair<Command, tlm::tlm_generic_payload *>(Command::NOP, NULL);
}
// In FR_FCFS row hits have always the highest priority, therefore we search
// for row hits. If we find a row hit, we remove the transaction from the
// queue and send it to the DRAM.
deque<gp*>::iterator it = FindRowHit(bank);
if(it != buffer[bank].end())
{
gp* payload = *it;
deque<gp *>::iterator it = FindRowHit(bank);
if (it != buffer[bank].end()) {
gp *payload = *it;
buffer[bank].erase(it);
return pair<Command, gp*>(getReadWriteCommand(*payload), payload);
return pair<Command, gp *>(getReadWriteCommand(*payload), payload);
}
// If there is no row hit, the FR_FCFS takes always the oldest transaction
// in the buffer, i.e. the transaction in the front.
return pair<Command, gp*>(getNextCommand(buffer[bank].front()),
buffer[bank].front());
return pair<Command, gp *>(getNextCommand(buffer[bank].front()),
buffer[bank].front());
}
// This function searches for a row hit in the scheduling queue of the specific
@@ -100,21 +98,19 @@ std::pair<Command, gp*> FR_FCFS::getNextRequest(Bank bank)
// deque container. The past-the-end element is the theoretical element that
// would follow the last element in the deque container. It does not point to
// any element, and thus shall not be dereferenced.
deque<gp*>::iterator FR_FCFS::FindRowHit(Bank bank)
deque<gp *>::iterator FR_FCFS::FindRowHit(Bank bank)
{
deque<gp*> &queue = buffer[bank];
deque<gp *> &queue = buffer[bank];
if(!controllerCore.getRowBufferStates().rowBufferIsOpen(bank))
if (!controllerCore.getRowBufferStates().rowBufferIsOpen(bank))
return queue.end();
// Traverse the scheduling queue of the specific bank:
for(auto it = queue.begin(); it!=queue.end(); it++)
{
gp* payload = *it;
for (auto it = queue.begin(); it != queue.end(); it++) {
gp *payload = *it;
//Found row-hit and return the according iterator
if(DramExtension::getRow(payload)
== controllerCore.getRowBufferStates().getRowInRowBuffer(bank))
{
if (DramExtension::getRow(payload)
== controllerCore.getRowBufferStates().getRowInRowBuffer(bank)) {
return it;
}
}
@@ -122,7 +118,7 @@ deque<gp*>::iterator FR_FCFS::FindRowHit(Bank bank)
return queue.end();
}
gp* FR_FCFS::getPendingRequest(Bank /*bank*/)
gp *FR_FCFS::getPendingRequest(Bank /*bank*/)
{
return NULL;
return NULL;
}

View File

@@ -48,16 +48,17 @@
class FR_FCFS : public IScheduler
{
public:
FR_FCFS(ControllerCore &controllerCore) : IScheduler(controllerCore){}
virtual ~FR_FCFS(){}
FR_FCFS(ControllerCore &controllerCore) : IScheduler(controllerCore) {}
virtual ~FR_FCFS() {}
void schedule(gp* payload) override;
std::pair<Command, tlm::tlm_generic_payload*> getNextRequest(Bank bank) override;
virtual gp* getPendingRequest(Bank bank) override;
void schedule(gp *payload) override;
std::pair<Command, tlm::tlm_generic_payload *> getNextRequest(
Bank bank) override;
virtual gp *getPendingRequest(Bank bank) override;
protected:
std::map<Bank, std::deque<gp*>> buffer;
std::deque<gp*>::iterator FindRowHit(Bank bank);
std::map<Bank, std::deque<gp *>> buffer;
std::deque<gp *>::iterator FindRowHit(Bank bank);
private:

View File

@@ -40,56 +40,43 @@
// TODO: what is missed is a check if the buffers are full. This will only work
// if we have buffers with a fixed size (Prado's future patch).
std::pair<Command, gp*> FR_FCFS_GRP::getNextRequest(Bank bank)
std::pair<Command, gp *> FR_FCFS_GRP::getNextRequest(Bank bank)
{
// If the bank is empty we do nothing:
if(buffer[bank].empty())
{
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
if (buffer[bank].empty()) {
return pair<Command, tlm::tlm_generic_payload *>(Command::NOP, NULL);
}
// If we are in write mode we should check if we should switch to read mode
// because there are no writes anymore in the buffer.
if(readMode == false)
{
if(getNumberOfRequest(tlm::TLM_WRITE_COMMAND) == 0)
{
if (readMode == false) {
if (getNumberOfRequest(tlm::TLM_WRITE_COMMAND) == 0) {
readMode = true;
}
}
else // If we are in read mode but all reads are served we switch to write
{
if(getNumberOfRequest(tlm::TLM_READ_COMMAND) == 0)
{
} else { // If we are in read mode but all reads are served we switch to write
if (getNumberOfRequest(tlm::TLM_READ_COMMAND) == 0) {
readMode = false;
}
}
// Now lets search for read and write commands. However keep in mind that
// readMode is a shared variable for all the banks!
if(readMode == true)
{
if (readMode == true) {
// 1. Seach for read hit:
for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++)
{
gp* read = *it;
for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) {
gp *read = *it;
if(read->get_command() == tlm::TLM_READ_COMMAND)
{
if (read->get_command() == tlm::TLM_READ_COMMAND) {
// If there is a row hit:
if(DramExtension::getRow(read)
== controllerCore.getRowBufferStates()
.getRowInRowBuffer(bank))
{
if(hazardDetection(bank, it) == false)
{
if (DramExtension::getRow(read)
== controllerCore.getRowBufferStates()
.getRowInRowBuffer(bank)) {
if (hazardDetection(bank, it) == false) {
buffer[bank].erase(it);
printDebugMessage("Read Hit found");
return pair<Command, gp*>(getReadWriteCommand(*read),
read);
}
else
{
return pair<Command, gp *>(getReadWriteCommand(*read),
read);
} else {
// If there was a hazard, switch the mode and try again:
readMode = false;
return getNextRequest(bank);
@@ -99,68 +86,55 @@ std::pair<Command, gp*> FR_FCFS_GRP::getNextRequest(Bank bank)
}
// 2. Search for read miss:
for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++)
{
gp* read = *it;
for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) {
gp *read = *it;
if(read->get_command() == tlm::TLM_READ_COMMAND)
{
if(hazardDetection(bank, it) == false)
{
if (read->get_command() == tlm::TLM_READ_COMMAND) {
if (hazardDetection(bank, it) == false) {
printDebugMessage("Read miss found");
return pair<Command, gp*>(getNextCommand(read),read);
}
else
{
return pair<Command, gp *>(getNextCommand(read), read);
} else {
// If there was a hazard, switch the mode and try again:
readMode = false;
return getNextRequest(bank);
}
}
}
}
else // write mode:
{
} else { // write mode:
// 3. Search for write hit:
for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++)
{
gp* write = *it;
for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) {
gp *write = *it;
if(write->get_command() == tlm::TLM_WRITE_COMMAND)
{
if (write->get_command() == tlm::TLM_WRITE_COMMAND) {
// If there is a row hit:
if(DramExtension::getRow(write)
if (DramExtension::getRow(write)
== controllerCore.getRowBufferStates()
.getRowInRowBuffer(bank))
{
.getRowInRowBuffer(bank)) {
buffer[bank].erase(it);
printDebugMessage("Write Hit found");
return pair<Command, gp*>(getReadWriteCommand(*write),
write);
return pair<Command, gp *>(getReadWriteCommand(*write),
write);
}
}
}
// 4. Search for write miss:
for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++)
{
gp* write = *it;
for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) {
gp *write = *it;
if(write->get_command() == tlm::TLM_WRITE_COMMAND)
{
if (write->get_command() == tlm::TLM_WRITE_COMMAND) {
printDebugMessage("Write miss found");
return pair<Command, gp*>(getNextCommand(write),write);
return pair<Command, gp *>(getNextCommand(write), write);
}
}
}
// If nothing was found we check the other banks before we switch the mode:
pair<Command, gp*> other(Command::NOP, NULL);
pair<Command, gp *> other(Command::NOP, NULL);
unsigned int B = Configuration::getInstance().memSpec.NumberOfBanks;
for(unsigned int i=1; i<B; i++)
{
Bank nextBank((bank.ID()+i) % B);
for (unsigned int i = 1; i < B; i++) {
Bank nextBank((bank.ID() + i) % B);
ctrl->scheduleNextFromScheduler(nextBank);
}
@@ -175,21 +149,18 @@ std::pair<Command, gp*> FR_FCFS_GRP::getNextRequest(Bank bank)
// There is a hazard if a read is found which will be scheduled before a write
// to the same column and the same row of the same bank:
bool FR_FCFS_GRP::hazardDetection(Bank bank, std::deque<gp*>::iterator ext)
bool FR_FCFS_GRP::hazardDetection(Bank bank, std::deque<gp *>::iterator ext)
{
gp* read = *ext;
gp *read = *ext;
//for(unsigned long i=0; i < id; i++)
for(auto it = buffer[bank].begin(); it!=ext; it++)
{
gp* write = *it;
if(write->get_command() == tlm::TLM_WRITE_COMMAND)
{
if((DramExtension::getExtension(read).getColumn()
== DramExtension::getExtension(write).getColumn())
&& (DramExtension::getExtension(read).getRow()
== DramExtension::getExtension(write).getRow()))
{
for (auto it = buffer[bank].begin(); it != ext; it++) {
gp *write = *it;
if (write->get_command() == tlm::TLM_WRITE_COMMAND) {
if ((DramExtension::getExtension(read).getColumn()
== DramExtension::getExtension(write).getColumn())
&& (DramExtension::getExtension(read).getRow()
== DramExtension::getExtension(write).getRow())) {
printDebugMessage("Hazard Detected");
return true;
}
@@ -202,15 +173,12 @@ bool FR_FCFS_GRP::hazardDetection(Bank bank, std::deque<gp*>::iterator ext)
unsigned int FR_FCFS_GRP::getNumberOfRequest(tlm::tlm_command cmd)
{
unsigned int numberOfRequests = 0;
for(unsigned int i = 0;
i < Configuration::getInstance().memSpec.NumberOfBanks;
i++)
{
for(auto it = buffer[i].begin(); it!=buffer[i].end(); it++)
{
gp* trans = *it;
if(trans->get_command()==cmd)
{
for (unsigned int i = 0;
i < Configuration::getInstance().memSpec.NumberOfBanks;
i++) {
for (auto it = buffer[i].begin(); it != buffer[i].end(); it++) {
gp *trans = *it;
if (trans->get_command() == cmd) {
numberOfRequests++;
}
}

View File

@@ -44,20 +44,20 @@ class Controller;
class FR_FCFS_GRP : public FR_FCFS
{
public:
FR_FCFS_GRP(ControllerCore &controllerCore, Controller * c) :
FR_FCFS_GRP(ControllerCore &controllerCore, Controller *c) :
FR_FCFS(controllerCore),
ctrl(c),
readMode(true)
{
}
std::pair<Command, tlm::tlm_generic_payload*>
getNextRequest(Bank bank) override;
std::pair<Command, tlm::tlm_generic_payload *>
getNextRequest(Bank bank) override;
private:
Controller * ctrl;
bool hazardDetection(Bank bank, std::deque<gp*>::iterator ext);
Controller *ctrl;
bool hazardDetection(Bank bank, std::deque<gp *>::iterator ext);
unsigned int getNumberOfRequest(tlm::tlm_command cmd);
void printDebugMessage(std::string message);
bool readMode;

View File

@@ -38,12 +38,11 @@
// The FR_FCFS_Read_Priority works exactly like the FR_FCFS but reads are
// prioratized over writes. For detailed documentation look into the FR_FCFS.
std::pair<Command, gp*> FR_FCFS_RP::getNextRequest(Bank bank)
std::pair<Command, gp *> FR_FCFS_RP::getNextRequest(Bank bank)
{
// If the bank is empty like Bank0 in the example we do nothing:
if(buffer[bank].empty())
{
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
if (buffer[bank].empty()) {
return pair<Command, tlm::tlm_generic_payload *>(Command::NOP, NULL);
}
// Order of Priority:
@@ -53,40 +52,33 @@ std::pair<Command, gp*> FR_FCFS_RP::getNextRequest(Bank bank)
// 4. Write Miss
// 1. Seach for read hit:
for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++)
{
gp* read = *it;
for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) {
gp *read = *it;
if(read->get_command() == tlm::TLM_READ_COMMAND)
{
if (read->get_command() == tlm::TLM_READ_COMMAND) {
// If there is a row hit:
if(DramExtension::getRow(read)
== controllerCore.getRowBufferStates().getRowInRowBuffer(bank))
{
if(hazardDetection(bank, it) == false)
{
if (DramExtension::getRow(read)
== controllerCore.getRowBufferStates().getRowInRowBuffer(bank)) {
if (hazardDetection(bank, it) == false) {
buffer[bank].erase(it);
printDebugMessage("Read Hit found");
return pair<Command, gp*>(getReadWriteCommand(*read),read);
return pair<Command, gp *>(getReadWriteCommand(*read), read);
}
}
}
}
// 2. Search for write hit:
for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++)
{
gp* write = *it;
for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) {
gp *write = *it;
if(write->get_command() == tlm::TLM_WRITE_COMMAND)
{
if (write->get_command() == tlm::TLM_WRITE_COMMAND) {
// If there is a row hit:
if(DramExtension::getRow(write)
== controllerCore.getRowBufferStates().getRowInRowBuffer(bank))
{
if (DramExtension::getRow(write)
== controllerCore.getRowBufferStates().getRowInRowBuffer(bank)) {
buffer[bank].erase(it);
printDebugMessage("Write Hit found");
return pair<Command, gp*>(getReadWriteCommand(*write),write);
return pair<Command, gp *>(getReadWriteCommand(*write), write);
}
}
}
@@ -94,52 +86,45 @@ std::pair<Command, gp*> FR_FCFS_RP::getNextRequest(Bank bank)
// For now return the oldest request but prefere also reads before writes:
// 3. Search for read miss:
for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++)
{
gp* read = *it;
for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) {
gp *read = *it;
if(read->get_command() == tlm::TLM_READ_COMMAND)
{
if(hazardDetection(bank, it) == false)
{
if (read->get_command() == tlm::TLM_READ_COMMAND) {
if (hazardDetection(bank, it) == false) {
printDebugMessage("Read miss found");
return pair<Command, gp*>(getNextCommand(read),read);
return pair<Command, gp *>(getNextCommand(read), read);
}
}
}
// 3. Search for write miss:
for(auto it = buffer[bank].begin(); it!=buffer[bank].end(); it++)
{
gp* write = *it;
for (auto it = buffer[bank].begin(); it != buffer[bank].end(); it++) {
gp *write = *it;
if(write->get_command() == tlm::TLM_WRITE_COMMAND)
{
if (write->get_command() == tlm::TLM_WRITE_COMMAND) {
printDebugMessage("Write miss found");
return pair<Command, gp*>(getNextCommand(write),write);
return pair<Command, gp *>(getNextCommand(write), write);
}
}
reportFatal("FR_FCFS_RP", "Never should go here ...");
return pair<Command, tlm::tlm_generic_payload *>(Command::NOP, NULL);
}
// There is a hazard if a read is found which will be scheduled before a write
// to the same column and the same row of the same bank:
bool FR_FCFS_RP::hazardDetection(Bank bank, std::deque<gp*>::iterator ext)
bool FR_FCFS_RP::hazardDetection(Bank bank, std::deque<gp *>::iterator ext)
{
gp* read = *ext;
gp *read = *ext;
//for(unsigned long i=0; i < id; i++)
for(auto it = buffer[bank].begin(); it!=ext; it++)
{
gp* write = *it;
if(write->get_command() == tlm::TLM_WRITE_COMMAND)
{
if((DramExtension::getExtension(read).getColumn()
== DramExtension::getExtension(write).getColumn())
&& (DramExtension::getExtension(read).getRow()
== DramExtension::getExtension(write).getRow()))
{
for (auto it = buffer[bank].begin(); it != ext; it++) {
gp *write = *it;
if (write->get_command() == tlm::TLM_WRITE_COMMAND) {
if ((DramExtension::getExtension(read).getColumn()
== DramExtension::getExtension(write).getColumn())
&& (DramExtension::getExtension(read).getRow()
== DramExtension::getExtension(write).getRow())) {
printDebugMessage("Hazard Detected");
return true;
}

View File

@@ -43,12 +43,12 @@ class FR_FCFS_RP : public FR_FCFS
public:
FR_FCFS_RP(ControllerCore &controllerCore) : FR_FCFS(controllerCore) {}
std::pair<Command, tlm::tlm_generic_payload*>
getNextRequest(Bank bank) override;
std::pair<Command, tlm::tlm_generic_payload *>
getNextRequest(Bank bank) override;
private:
bool hazardDetection(Bank bank, std::deque<gp*>::iterator ext);
bool hazardDetection(Bank bank, std::deque<gp *>::iterator ext);
void printDebugMessage(std::string message);
};

View File

@@ -47,20 +47,16 @@ void IScheduler::printDebugMessage(std::string message)
}
// Get the next command that is necessary to process the request representend by the payload
Command IScheduler::getNextCommand(gp& payload)
Command IScheduler::getNextCommand(gp &payload)
{
Bank bank = DramExtension::getBank(payload);
if(!controllerCore.getRowBufferStates().rowBufferIsOpen(bank))
{
if (!controllerCore.getRowBufferStates().rowBufferIsOpen(bank)) {
return Command::Activate;
}
else if(controllerCore.getRowBufferStates().rowBufferIsOpen(bank) &&
controllerCore.getRowBufferStates().getRowInRowBuffer(bank) != DramExtension::getRow(payload))
{
} else if (controllerCore.getRowBufferStates().rowBufferIsOpen(bank) &&
controllerCore.getRowBufferStates().getRowInRowBuffer(bank) !=
DramExtension::getRow(payload)) {
return Command::Precharge;
}
else
{
} else {
return getReadWriteCommand(payload);
}
}
@@ -70,19 +66,16 @@ Command IScheduler::getNextCommand(gp *payload)
return getNextCommand(*payload);
}
Command IScheduler::getReadWriteCommand(gp& payload)
Command IScheduler::getReadWriteCommand(gp &payload)
{
if (payload.get_command() == tlm::TLM_READ_COMMAND)
{
if(Configuration::getInstance().OpenPagePolicy)
if (payload.get_command() == tlm::TLM_READ_COMMAND) {
if (Configuration::getInstance().OpenPagePolicy)
return Command::Read;
else
return Command::ReadA;
}
else
{
if(Configuration::getInstance().OpenPagePolicy)
} else {
if (Configuration::getInstance().OpenPagePolicy)
return Command::Write;
else
return Command::WriteA;

View File

@@ -49,12 +49,12 @@ typedef tlm::tlm_generic_payload gp;
class IScheduler
{
public:
virtual ~IScheduler(){}
IScheduler(ControllerCore &controllerCore) : controllerCore(controllerCore){}
virtual ~IScheduler() {}
IScheduler(ControllerCore &controllerCore) : controllerCore(controllerCore) {}
virtual void schedule(gp* payload) = 0;
virtual std::pair<Command, gp*> getNextRequest(Bank bank) = 0;
virtual gp* getPendingRequest(Bank bank) = 0;
virtual void schedule(gp *payload) = 0;
virtual std::pair<Command, gp *> getNextRequest(Bank bank) = 0;
virtual gp *getPendingRequest(Bank bank) = 0;
static std::string sendername;
protected:

View File

@@ -22,27 +22,25 @@ void SMS::schedule(gp *payload)
}
}
std::pair<Command, gp*> SMS::getNextRequest(Bank bank)
std::pair<Command, gp *> SMS::getNextRequest(Bank bank)
{
if (bankBuffers[bank].empty())
{
if (bankBuffers[bank].empty()) {
debugManager.printDebugMessage(name(),
"Get next request on bank " + to_string(bank.ID()) + " : EMPTY buffer");
return pair<Command, tlm::tlm_generic_payload*>(Command::NOP, NULL);
}
else
{
gp* payload = bankBuffers[bank].front();
return pair<Command, tlm::tlm_generic_payload *>(Command::NOP, NULL);
} else {
gp *payload = bankBuffers[bank].front();
Command command = IScheduler::getNextCommand(*payload);
if (command == Command::Read || command == Command::ReadA || command == Command::Write
|| command == Command::WriteA)
{
if (command == Command::Read || command == Command::ReadA
|| command == Command::Write
|| command == Command::WriteA) {
inFlightMemRequestCounter[DramExtension::getExtension(payload).getThread()]--;
bankBuffers[bank].pop_front();
}
debugManager.printDebugMessage(name(), "Get next request on bank " + to_string(bank.ID()));
return pair<Command, tlm::tlm_generic_payload*>(command, payload);
debugManager.printDebugMessage(name(),
"Get next request on bank " + to_string(bank.ID()));
return pair<Command, tlm::tlm_generic_payload *>(command, payload);
}
}
@@ -52,15 +50,15 @@ void SMS::batchScheduler()
std::default_random_engine generator;
std::bernoulli_distribution distribution((double) SJFprobability / 100.0);
while (true)
{
while (true) {
updateMPKCs(memClk);
if (isRequestBuffersEmpty()) {
wait(newRequest);
} else {
multiBatchFormation(memClk);
if (existReadyBatches()) {
if (!isSystemLightlyLoaded() && (existLowIntensityThread() || distribution(generator))) {
if (!isSystemLightlyLoaded() && (existLowIntensityThread()
|| distribution(generator))) {
pickSJF();
} else {
pickRR();
@@ -82,23 +80,18 @@ bool SMS::pickSJF()
{
// find threads with ready batches
std::vector<Thread> threadsWithReadyBatches;
for (const auto &each : readyBatchInclusiveEndLocs)
{
if (!each.second.empty())
{
for (const auto &each : readyBatchInclusiveEndLocs) {
if (!each.second.empty()) {
// marked as thread with non-empty request buffer
threadsWithReadyBatches.push_back(each.first);
}
}
if (!threadsWithReadyBatches.empty())
{
if (!threadsWithReadyBatches.empty()) {
// pick shortest-job thread among threads with non-empty request buffer
Thread &minThread = threadsWithReadyBatches.front();
for (const auto &thread : threadsWithReadyBatches)
{
if (inFlightMemRequestCounter[thread] < inFlightMemRequestCounter[minThread])
{
for (const auto &thread : threadsWithReadyBatches) {
if (inFlightMemRequestCounter[thread] < inFlightMemRequestCounter[minThread]) {
minThread = thread;
}
}
@@ -108,9 +101,7 @@ bool SMS::pickSJF()
debugManager.printDebugMessage(name(),
"[SJF] Select ready batch of thread " + to_string(minThread.ID()));
return true;
}
else
{
} else {
return false;
}
}
@@ -131,17 +122,16 @@ void SMS::drainOnePayloadFromReadybatch(const sc_time &memClk)
const size_t &inclusiveEndLoc = lastSelectedThread->second.front();
assert(inclusiveEndLoc < requestBuffers.size());
for (size_t i = 0; i <= inclusiveEndLoc; ++i)
{
for (size_t i = 0; i <= inclusiveEndLoc; ++i) {
wait(memClk);
Bank bank = DramExtension::getExtension(requestBuffers[selectedThread].front()).getBank();
Bank bank = DramExtension::getExtension(
requestBuffers[selectedThread].front()).getBank();
bankBuffers[bank].emplace_back(requestBuffers[selectedThread].front());
requestBuffers[selectedThread].pop_front();
// decrement inclusive end locations of ready batches
// except this ready batch
for (size_t i = 1; i < readyBatchInclusiveEndLocs[selectedThread].size(); ++i)
{
for (size_t i = 1; i < readyBatchInclusiveEndLocs[selectedThread].size(); ++i) {
--readyBatchInclusiveEndLocs[selectedThread][i];
}
@@ -160,18 +150,17 @@ void SMS::drainOnePayloadFromReadybatch(const sc_time &memClk)
*/
bool SMS::pickRR()
{
if (lastSelectedThread == readyBatchInclusiveEndLocs.end())
{
if (lastSelectedThread == readyBatchInclusiveEndLocs.end()) {
lastSelectedThread = readyBatchInclusiveEndLocs.begin();
if (!(*lastSelectedThread).second.empty()) {
return true;
}
}
std::map<Thread, std::deque<size_t>>::iterator savedOriginalNextSelectedThread = lastSelectedThread;
std::map<Thread, std::deque<size_t>>::iterator savedOriginalNextSelectedThread =
lastSelectedThread;
do
{
do {
lastSelectedThread++;
if (lastSelectedThread == readyBatchInclusiveEndLocs.end()) {
lastSelectedThread = readyBatchInclusiveEndLocs.begin();
@@ -182,11 +171,13 @@ bool SMS::pickRR()
} while ((*lastSelectedThread).second.empty());
debugManager.printDebugMessage(name(),
"[RR] Select ready batch of thread " + to_string((*lastSelectedThread).first.ID()));
"[RR] Select ready batch of thread " + to_string((
*lastSelectedThread).first.ID()));
return true;
}
bool SMS::isSystemLightlyLoaded() const {
bool SMS::isSystemLightlyLoaded() const
{
unsigned int totalRequest = 0;
for (const auto &bankBuffer : bankBuffers) {
totalRequest += bankBuffer.second.size();
@@ -194,7 +185,8 @@ bool SMS::isSystemLightlyLoaded() const {
return (totalRequest <= LOW_SYSTEM_LOAD);
}
bool SMS::existLowIntensityThread() const {
bool SMS::existLowIntensityThread() const
{
for (const auto &mpkcPerThread : MPKCs) {
if (mpkcPerThread.second < LOW_MPKC) {
return true;
@@ -203,12 +195,15 @@ bool SMS::existLowIntensityThread() const {
return false;
}
bool SMS::isThresholdAgeExceeded(const Thread &thread, sc_time const &memClk, size_t const &inclusiveBeginLoc, size_t const &exclusiveEndLoc) {
bool SMS::isThresholdAgeExceeded(const Thread &thread, sc_time const &memClk,
size_t const &inclusiveBeginLoc, size_t const &exclusiveEndLoc)
{
assert((exclusiveEndLoc - inclusiveBeginLoc) >= 1);
// find the oldest request in the thread's batch
sc_time oldestGenerationTime = sc_time_stamp();
for (size_t i = inclusiveBeginLoc; i != exclusiveEndLoc; ++i) {
sc_time reqGenerationTime = GenerationExtension::getExtension(requestBuffers[thread][i]).TimeOfGeneration();
sc_time reqGenerationTime = GenerationExtension::getExtension(
requestBuffers[thread][i]).TimeOfGeneration();
if (reqGenerationTime < oldestGenerationTime) {
oldestGenerationTime = reqGenerationTime;
}
@@ -216,16 +211,19 @@ bool SMS::isThresholdAgeExceeded(const Thread &thread, sc_time const &memClk, si
// check threshold age according to the thread's MPKC
sc_time oldestRequestAge = sc_time_stamp() - oldestGenerationTime;
if ((MPKCs[thread] <= MEDIUM_MPKC) && (oldestRequestAge > (MEDIUM_THRESHOLD_AGE * memClk))) {
if ((MPKCs[thread] <= MEDIUM_MPKC)
&& (oldestRequestAge > (MEDIUM_THRESHOLD_AGE * memClk))) {
return true;
} else if ((MPKCs[thread] > MEDIUM_MPKC) && (oldestRequestAge > (HIGH_THRESHOLD_AGE * memClk))) {
} else if ((MPKCs[thread] > MEDIUM_MPKC)
&& (oldestRequestAge > (HIGH_THRESHOLD_AGE * memClk))) {
return true;
} else {
return false;
}
}
void SMS::updateMPKCs(sc_time const &memClk) {
void SMS::updateMPKCs(sc_time const &memClk)
{
if (sc_time_stamp() % (MPKC_RESET_CYCLE * memClk) <= memClk) {
// reset for every 10k clk cycles
for (const auto &cacheMiss : cacheMisses) {
@@ -235,17 +233,20 @@ void SMS::updateMPKCs(sc_time const &memClk) {
} else {
// update MPKC for every thread
for (const auto &cacheMiss : cacheMisses) {
MPKCs[cacheMiss.first] = (cacheMiss.second * 1000.0 * memClk) / (sc_time_stamp());
MPKCs[cacheMiss.first] = (cacheMiss.second * 1000.0 * memClk) /
(sc_time_stamp());
}
debugManager.printDebugMessage(name(), "Update MPKCs");
}
}
bool SMS::isExceededReqBufferSize(size_t const &exclusiveEndLoc) {
bool SMS::isExceededReqBufferSize(size_t const &exclusiveEndLoc)
{
return exclusiveEndLoc <= Configuration::getInstance().RequestBufferSize;
}
bool SMS::isRequestBuffersEmpty() const {
bool SMS::isRequestBuffersEmpty() const
{
for (const auto &requestBuffer : requestBuffers) {
if (!requestBuffer.second.empty()) {
return false;
@@ -254,7 +255,8 @@ bool SMS::isRequestBuffersEmpty() const {
return true;
}
bool SMS::existReadyBatches() const {
bool SMS::existReadyBatches() const
{
for (const auto &each : readyBatchInclusiveEndLocs) {
if (!each.second.empty()) {
return true;
@@ -270,51 +272,45 @@ bool SMS::existReadyBatches() const {
* @param begin
* @return true if this batch is ready, otherwise false
*/
bool SMS::batchFormation(sc_time const &memClk, Thread const &thread, std::deque<gp*> const &requestBuffer, size_t const &inclusiveBeginLoc)
bool SMS::batchFormation(sc_time const &memClk, Thread const &thread,
std::deque<gp *> const &requestBuffer, size_t const &inclusiveBeginLoc)
{
if (requestBuffer.empty())
{
if (requestBuffer.empty()) {
return false;
}
assert(inclusiveBeginLoc <= requestBuffer.size());
if (requestBuffer.size() == inclusiveBeginLoc)
{
if (requestBuffer.size() == inclusiveBeginLoc) {
return false;
}
if (MPKCs[thread] < LOW_MPKC || isSystemLightlyLoaded())
{
if (MPKCs[thread] < LOW_MPKC || isSystemLightlyLoaded()) {
// bypass requests by forming batch with only one request (threshold age is ZERO)
readyBatchInclusiveEndLocs[thread].push_back(inclusiveBeginLoc);
return true;
}
else
{
} else {
// forming batch with FIFO size & threshold age constraints
size_t firstDifferentRowAccessReqLoc = inclusiveBeginLoc;
Row firstRow = DramExtension::getRow(requestBuffer[inclusiveBeginLoc]);
bool isBatchReady = false;
size_t bufferSize = requestBuffer.size();
while (firstDifferentRowAccessReqLoc != bufferSize
&& DramExtension::getRow(requestBuffer[firstDifferentRowAccessReqLoc]) == firstRow)
{
&& DramExtension::getRow(requestBuffer[firstDifferentRowAccessReqLoc]) ==
firstRow) {
++firstDifferentRowAccessReqLoc;
if (firstDifferentRowAccessReqLoc < bufferSize)
{
if (DramExtension::getRow(requestBuffer[firstDifferentRowAccessReqLoc]) != firstRow
if (firstDifferentRowAccessReqLoc < bufferSize) {
if (DramExtension::getRow(requestBuffer[firstDifferentRowAccessReqLoc]) !=
firstRow
|| isExceededReqBufferSize(firstDifferentRowAccessReqLoc)
|| isThresholdAgeExceeded(thread, memClk, inclusiveBeginLoc, firstDifferentRowAccessReqLoc))
{
|| isThresholdAgeExceeded(thread, memClk, inclusiveBeginLoc,
firstDifferentRowAccessReqLoc)) {
isBatchReady = true;
break;
}
}
else
{
} else {
if (isExceededReqBufferSize(firstDifferentRowAccessReqLoc)
|| isThresholdAgeExceeded(thread, memClk, inclusiveBeginLoc, firstDifferentRowAccessReqLoc))
{
|| isThresholdAgeExceeded(thread, memClk, inclusiveBeginLoc,
firstDifferentRowAccessReqLoc)) {
isBatchReady = true;
break;
}
@@ -322,16 +318,13 @@ bool SMS::batchFormation(sc_time const &memClk, Thread const &thread, std::deque
}
// store this ready batch location
if (isBatchReady)
{
if (isBatchReady) {
--firstDifferentRowAccessReqLoc;
readyBatchInclusiveEndLocs[thread].push_back(firstDifferentRowAccessReqLoc);
debugManager.printDebugMessage(name(),
"Deem batch ready - thread " + to_string(thread.ID()));
return true;
}
else
{
} else {
return false;
}
}
@@ -339,24 +332,20 @@ bool SMS::batchFormation(sc_time const &memClk, Thread const &thread, std::deque
void SMS::multiBatchFormation(sc_time const &memClk)
{
for (auto &requestBuffer : requestBuffers)
{
for (auto &requestBuffer : requestBuffers) {
bool formed = false;
do
{
if (readyBatchInclusiveEndLocs[requestBuffer.first].empty())
{
do {
if (readyBatchInclusiveEndLocs[requestBuffer.first].empty()) {
formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, 0);
}
else
{
formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second, readyBatchInclusiveEndLocs[requestBuffer.first].back() + 1);
} else {
formed = batchFormation(memClk, requestBuffer.first, requestBuffer.second,
readyBatchInclusiveEndLocs[requestBuffer.first].back() + 1);
}
} while (!requestBuffer.second.empty() && formed);
}
}
gp* SMS::getPendingRequest(Bank bank)
gp *SMS::getPendingRequest(Bank bank)
{
for (const auto &requestBuffer : requestBuffers) {
for (const auto &request : requestBuffer.second) {

View File

@@ -18,7 +18,7 @@
#define MPKC_RESET_CYCLE 10000
using namespace std;
typedef std::deque<gp*>::iterator gp_deque_iterator;
typedef std::deque<gp *>::iterator gp_deque_iterator;
/**
* SMS - Staged Memory Scheduler involves 3 steps:
@@ -32,7 +32,9 @@ typedef std::deque<gp*>::iterator gp_deque_iterator;
class SMS: public sc_module, public IScheduler
{
public:
SMS(sc_module_name /*_name*/, ControllerCore &controllerCore, unsigned int SJFprobability) : IScheduler(controllerCore), SJFprobability(SJFprobability), debugManager(DebugManager::getInstance())
SMS(sc_module_name /*_name*/, ControllerCore &controllerCore,
unsigned int SJFprobability) : IScheduler(controllerCore),
SJFprobability(SJFprobability), debugManager(DebugManager::getInstance())
{
// initialize selected thread iterator
lastSelectedThread = readyBatchInclusiveEndLocs.end();
@@ -45,14 +47,14 @@ public:
}
virtual void schedule(gp *payload) override;
virtual std::pair<Command, gp*> getNextRequest(Bank bank) override;
virtual gp* getPendingRequest(Bank bank) override;
virtual std::pair<Command, gp *> getNextRequest(Bank bank) override;
virtual gp *getPendingRequest(Bank bank) override;
void batchScheduler();
private:
std::map<Thread, std::deque<gp*>> requestBuffers;
std::map<Bank, std::deque<gp*>> bankBuffers;
std::map<Thread, std::deque<gp *>> requestBuffers;
std::map<Bank, std::deque<gp *>> bankBuffers;
std::map<Thread, std::deque<size_t>> readyBatchInclusiveEndLocs;
std::map<Thread, unsigned int> inFlightMemRequestCounter;
@@ -63,9 +65,10 @@ private:
std::map<Thread, std::deque<size_t>>::iterator lastSelectedThread;
sc_event newRequest;
DebugManager& debugManager;
DebugManager &debugManager;
bool batchFormation(sc_time const &memClk, Thread const &thread, const std::deque<gp*> &requestBuffer, const size_t &inclusiveBeginLoc);
bool batchFormation(sc_time const &memClk, Thread const &thread,
const std::deque<gp *> &requestBuffer, const size_t &inclusiveBeginLoc);
void multiBatchFormation(const sc_time &memClk);
bool pickSJF();
bool pickRR();
@@ -73,7 +76,8 @@ private:
bool existLowIntensityThread() const;
bool isSystemLightlyLoaded() const;
bool isThresholdAgeExceeded(const Thread &thread, const sc_time &memClk, const size_t &inclusiveBeginLoc, const size_t &exclusiveEndLoc);
bool isThresholdAgeExceeded(const Thread &thread, const sc_time &memClk,
const size_t &inclusiveBeginLoc, const size_t &exclusiveEndLoc);
bool isExceededReqBufferSize(size_t const &exclusiveEndLoc);
void updateMPKCs(const sc_time &memClk);

View File

@@ -50,59 +50,59 @@
//ThreadLoad::ThreadLoad()
//{
// // TODO Auto-generated constructor stub
// // TODO Auto-generated constructor stub
//}
//ThreadLoad::~ThreadLoad()
//{
// // TODO Auto-generated destructor stub
// // TODO Auto-generated destructor stub
//}
//unsigned int ThreadLoad::getMaxBankLoad() const
//{
// unsigned int maxLoad = 0;
// for (auto& bankVectorPair : load)
// {
// if (bankVectorPair.second.size() > maxLoad)
// maxLoad = bankVectorPair.second.size();
// }
// return maxLoad;
// unsigned int maxLoad = 0;
// for (auto& bankVectorPair : load)
// {
// if (bankVectorPair.second.size() > maxLoad)
// maxLoad = bankVectorPair.second.size();
// }
// return maxLoad;
//}
//unsigned int ThreadLoad::getTotalLoad() const
//{
// unsigned int totalLoad = 0;
// for (auto& bankVectorPair : load)
// {
// totalLoad += bankVectorPair.second.size();
// }
// return totalLoad;
// unsigned int totalLoad = 0;
// for (auto& bankVectorPair : load)
// {
// totalLoad += bankVectorPair.second.size();
// }
// return totalLoad;
//}
//void ThreadLoad::addTransaction(gp* payload)
//{
// load[DramExtension::getExtension(payload).getBank()].push_back(payload);
// load[DramExtension::getExtension(payload).getBank()].push_back(payload);
//}
//bool operator<(const ThreadLoad& lhs, const ThreadLoad& rhs)
//{
// if (lhs.getMaxBankLoad() < rhs.getMaxBankLoad())
// return true;
// else if (lhs.getMaxBankLoad() == rhs.getMaxBankLoad())
// return lhs.getTotalLoad() < rhs.getTotalLoad();
// else
// return false;
// if (lhs.getMaxBankLoad() < rhs.getMaxBankLoad())
// return true;
// else if (lhs.getMaxBankLoad() == rhs.getMaxBankLoad())
// return lhs.getTotalLoad() < rhs.getTotalLoad();
// else
// return false;
//}
//vector<gp*> ThreadLoad::getTransactions()
//{
// vector<gp*> result;
// for (auto& bankVectorPair : load)
// {
// result.insert(result.end(), bankVectorPair.second.begin(), bankVectorPair.second.end());
// }
// return result;
// vector<gp*> result;
// for (auto& bankVectorPair : load)
// {
// result.insert(result.end(), bankVectorPair.second.begin(), bankVectorPair.second.end());
// }
// return result;
//}
//} /* namespace scheduler

View File

@@ -56,16 +56,16 @@
//{
//public:
// ThreadLoad();d
// virtual ~ThreadLoad();
// virtual ~ThreadLoad();
// unsigned int getMaxBankLoad() const;
// unsigned int getTotalLoad() const;
// unsigned int getMaxBankLoad() const;
// unsigned int getTotalLoad() const;
// void addTransaction(gp* payload);
// std::vector<gp*> getTransactions();
// void addTransaction(gp* payload);
// std::vector<gp*> getTransactions();
//private:
// std::map<Bank,std::vector<gp*>> load;
// std::map<Bank,std::vector<gp*>> load;
//};
//bool operator< (const ThreadLoad &lhs, const ThreadLoad &rhs);

View File

@@ -6,7 +6,7 @@ using std::cout;
CBit::CBit(VALUE nVal)
{
m_nValue = nVal;
m_nValue = nVal;
}
@@ -16,12 +16,9 @@ CBit::~CBit()
void CBit::Print()
{
if (m_nValue == ZERO)
{
cout <<"0";
}
else
{
cout << "1";
}
if (m_nValue == ZERO) {
cout << "0";
} else {
cout << "1";
}
}

View File

@@ -2,72 +2,68 @@
class CBit
{
public:
enum VALUE
{
ZERO = 0,
ONE = 1
};
enum VALUE {
ZERO = 0,
ONE = 1
};
protected:
VALUE m_nValue;
VALUE m_nValue;
public:
CBit(VALUE nVal = ZERO);
virtual ~CBit();
CBit(VALUE nVal = ZERO);
virtual ~CBit();
inline void Set() { m_nValue = ONE; };
inline void Clear() { m_nValue = ZERO; };
inline unsigned Get()
{
if(m_nValue == ONE)
return 1;
else
return 0;
};
inline void Set()
{
m_nValue = ONE;
};
inline void Clear()
{
m_nValue = ZERO;
};
inline unsigned Get()
{
if (m_nValue == ONE)
return 1;
else
return 0;
};
void Print();
void Print();
CBit& operator=(unsigned d)
{
if (d == 0 )
{
m_nValue = ZERO;
}
else
{
m_nValue = ONE;
}
return *this;
}
CBit &operator=(unsigned d)
{
if (d == 0 ) {
m_nValue = ZERO;
} else {
m_nValue = ONE;
}
return *this;
}
friend CBit operator^(CBit l, const CBit& r)
{
if (l.m_nValue == r.m_nValue)
{
return CBit(ZERO);
}
else
{
return CBit(ONE);
}
}
friend CBit operator^(CBit l, const CBit &r)
{
if (l.m_nValue == r.m_nValue) {
return CBit(ZERO);
} else {
return CBit(ONE);
}
}
CBit& operator^=(const CBit& r)
{
if (m_nValue == r.m_nValue)
{
m_nValue = ZERO;
}
else
{
m_nValue = ONE;
}
return *this;
}
CBit &operator^=(const CBit &r)
{
if (m_nValue == r.m_nValue) {
m_nValue = ZERO;
} else {
m_nValue = ONE;
}
return *this;
}
inline bool operator==(const CBit::VALUE& r)
{
return m_nValue == r;
}
inline bool operator==(const CBit::VALUE &r)
{
return m_nValue == r;
}
};

View File

@@ -5,37 +5,35 @@
// to store the hamming code and parity bit for a SECDED implementation
unsigned ECC::GetNumParityBits(unsigned nDataBits)
{
unsigned nParityBits = 0;
unsigned nParityBits = 0;
// Function to calculate the nube of bits: n = 2^k - k - 1
// ( Source: Hacker's Delight; p. 310; math. function 1 )
while (nDataBits > ((1 << nParityBits) - nParityBits - 1))
{
++nParityBits;
}
while (nDataBits > ((1 << nParityBits) - nParityBits - 1)) {
++nParityBits;
}
return nParityBits+1; // +1 for the parity bit
return nParityBits + 1; // +1 for the parity bit
}
// ************************************************************************************************
// Function which extends a given data word to the needed length for a SECDED code
void ECC::ExtendWord(CWord & v)
void ECC::ExtendWord(CWord &v)
{
unsigned end = v.GetLength() + ECC::GetNumParityBits(v.GetLength());
unsigned end = v.GetLength() + ECC::GetNumParityBits(v.GetLength());
// Insert x bits for the hamming code at positions where pos = 2^a; a = [0..N]
// In "Hacker's Delight" the smallest index is 1 - But in this beautiful C-Code it's 0 as it
// should be. That's why there is a '-1' in the call of v.Insert.
unsigned i = 1;
while (i < end)
{
v.Insert(i-1, CBit());
i <<= 1;
}
unsigned i = 1;
while (i < end) {
v.Insert(i - 1, CBit());
i <<= 1;
}
// Append one bit for the parity
v.Append(CBit());
v.Append(CBit());
}
// ************************************************************************************************
@@ -43,12 +41,12 @@ void ECC::ExtendWord(CWord & v)
// Function ExtendWord must be called before calling this function
// The calculated bits are stored in p, so the length of p should be at least
// 'GetNumParityBits(#data bits)-1'
void ECC::CalculateCheckbits(CWord & v, CWord & p)
void ECC::CalculateCheckbits(CWord &v, CWord &p)
{
unsigned i = 1, l = 0;
// Last bit is the parity bit - don't use this in the algorithm for hamming code
unsigned len = v.GetLength()-1;
// Last bit is the parity bit - don't use this in the algorithm for hamming code
unsigned len = v.GetLength() - 1;
// Following Graph should show you the behaviour of this algorithm
// #Data bits: 11 #Hamming bits: 4 -> SECDED bits: 16 (incl. parity bit)
@@ -61,73 +59,67 @@ void ECC::CalculateCheckbits(CWord & v, CWord & p)
// ATTENTION: The order of indices is different from the one in the book,
// but it doesn't matter in which order your data or check bits are.
// But it should be the same for encoding and decoding
while (i < len)
{
for (unsigned j = (i - 1); j < len; j += (i << 1))
{
for (unsigned k = 0; k < (i); k++)
{
if(j + k >= len)
break;
p[l] ^= v[j + k];
}
}
l++;
i <<= 1;
}
while (i < len) {
for (unsigned j = (i - 1); j < len; j += (i << 1)) {
for (unsigned k = 0; k < (i); k++) {
if (j + k >= len)
break;
p[l] ^= v[j + k];
}
}
l++;
i <<= 1;
}
}
// ************************************************************************************************
// Function which inserts the checkbits which were calculated with 'CalculateCheckbits' in the
// extended data word. This is needed to calculate a proper parity of ALL bits to achive a SECDED
// behaviour.
void ECC::InsertCheckbits(CWord& v, CWord p)
void ECC::InsertCheckbits(CWord &v, CWord p)
{
unsigned i = 1, j = 0;
while (i <= v.GetLength()-1)
{
v[i - 1] = p[j++];
i <<= 1;
}
unsigned i = 1, j = 0;
while (i <= v.GetLength() - 1) {
v[i - 1] = p[j++];
i <<= 1;
}
}
// ************************************************************************************************
// Function which extracts the checkbits out of an extended data word. This is needed to check for
// bit error in the data word.
void ECC::ExtractCheckbits(CWord v, CWord & p)
void ECC::ExtractCheckbits(CWord v, CWord &p)
{
unsigned i = 1, j = 0;
while(i <= v.GetLength()-1)
{
p[j++] = v[i - 1];
i <<= 1;
}
unsigned i = 1, j = 0;
while (i <= v.GetLength() - 1) {
p[j++] = v[i - 1];
i <<= 1;
}
}
// ************************************************************************************************
// Function which calculates the overal parity
// Simply XOR all bits
void ECC::CalculateParityBit(CWord v, CBit & p)
void ECC::CalculateParityBit(CWord v, CBit &p)
{
// Paritybit
p = CBit::ZERO;
for (unsigned i = 0; i < v.GetLength(); i++)
{
p ^= v[i];
}
// Paritybit
p = CBit::ZERO;
for (unsigned i = 0; i < v.GetLength(); i++) {
p ^= v[i];
}
}
// ************************************************************************************************
// Function to insert the parity bit into the extended data word
void ECC::InsertParityBit(CWord& v, CBit p)
void ECC::InsertParityBit(CWord &v, CBit p)
{
v[v.GetLength() - 1] = p;
v[v.GetLength() - 1] = p;
}
// ************************************************************************************************
// Function to extract the parity bit out of an extended data word.
void ECC::ExtractParityBit(CWord v, CBit & p)
void ECC::ExtractParityBit(CWord v, CBit &p)
{
p = v[v.GetLength() - 1];
p = v[v.GetLength() - 1];
}

View File

@@ -21,19 +21,18 @@
// For further details read chapter 15 of "Hacker's Delight - second Edition"
// ************************************************************************************************
namespace ECC
{
unsigned GetNumParityBits(unsigned nDataBits);
namespace ECC {
unsigned GetNumParityBits(unsigned nDataBits);
// Extends the data word that it can be used with hamming code
// Several bits will be included at specific places
void ExtendWord(CWord &v);
// Extends the data word that it can be used with hamming code
// Several bits will be included at specific places
void ExtendWord(CWord &v);
void CalculateCheckbits(CWord &v, CWord & p);
void InsertCheckbits(CWord& v, CWord p);
void ExtractCheckbits(CWord v, CWord& p);
void CalculateCheckbits(CWord &v, CWord &p);
void InsertCheckbits(CWord &v, CWord p);
void ExtractCheckbits(CWord v, CWord &p);
void CalculateParityBit(CWord v, CBit& p);
void InsertParityBit(CWord& v, CBit p);
void ExtractParityBit(CWord v, CBit& p);
void CalculateParityBit(CWord v, CBit &p);
void InsertParityBit(CWord &v, CBit p);
void ExtractParityBit(CWord v, CBit &p);
}

View File

@@ -7,121 +7,109 @@
int main()
{
// Random number init
srand(time(NULL));
// Random number init
srand(time(NULL));
// Erstellen
unsigned size = 4;
CWord p(ECC::GetNumParityBits(size)), v(size);
// Erstellen
unsigned size = 4;
CWord p(ECC::GetNumParityBits(size)), v(size);
// Daten eingeben
for (unsigned a = 0; a < 16; a++)
{
v = a;
v.Rotate();
// Daten eingeben
for (unsigned a = 0; a < 16; a++) {
v = a;
v.Rotate();
ECC::ExtendWord(v);
printf("%d:\t", a);
ECC::ExtendWord(v);
printf("%d:\t", a);
p = 0;
ECC::CalculateCheckbits(v, p);
ECC::InsertCheckbits(v, p);
ECC::CalculateParityBit(v, p[3]);
ECC::InsertParityBit(v, p[3]);
p = 0;
ECC::CalculateCheckbits(v, p);
ECC::InsertCheckbits(v, p);
ECC::CalculateParityBit(v, p[3]);
ECC::InsertParityBit(v, p[3]);
v.Print();
v.Print();
v.Resize(size);
}
v.Resize(size);
}
printf("\r\n");
printf("\r\n");
for (unsigned x = 0; x < 100; x++)
{
//Get random number
unsigned a = rand() % 16;
for (unsigned x = 0; x < 100; x++) {
//Get random number
unsigned a = rand() % 16;
v.Resize(size);
v = a;
v.Rotate();
v.Resize(size);
v = a;
v.Rotate();
ECC::ExtendWord(v);
ECC::ExtendWord(v);
p = 0;
ECC::CalculateCheckbits(v, p);
ECC::InsertCheckbits(v, p);
ECC::CalculateParityBit(v, p[3]);
ECC::InsertParityBit(v, p[3]);
v.Print();
p = 0;
ECC::CalculateCheckbits(v, p);
ECC::InsertCheckbits(v, p);
ECC::CalculateParityBit(v, p[3]);
ECC::InsertParityBit(v, p[3]);
v.Print();
// Insert error
unsigned pos = rand() % 8;
v[pos] ^= CBit(CBit::ONE);
// Insert error
unsigned pos = rand() % 8;
v[pos] ^= CBit(CBit::ONE);
printf("Data: %d, Error at pos %d: ", a, pos + 1);
v[pos].Print();
printf("\r\n");
v.Print();
printf("Data: %d, Error at pos %d: ", a, pos + 1);
v[pos].Print();
printf("\r\n");
v.Print();
p = 0;
ECC::CalculateCheckbits(v, p);
ECC::CalculateParityBit(v, p[3]);
p = 0;
ECC::CalculateCheckbits(v, p);
ECC::CalculateParityBit(v, p[3]);
printf("%d:\t", a);
printf("%d:\t", a);
p.Print();
p.Print();
// Interpreting Data
// Interpreting Data
unsigned syndrome = 0;
for (unsigned i = 0; i < p.GetLength() - 1; i++)
{
if (p[i] == CBit::ONE)
syndrome += (1 << i);
}
unsigned syndrome = 0;
for (unsigned i = 0; i < p.GetLength() - 1; i++) {
if (p[i] == CBit::ONE)
syndrome += (1 << i);
}
if (p[3] == CBit::ZERO)
{
// Parity even
if (p[3] == CBit::ZERO) {
// Parity even
if (syndrome)
{
// Double error
printf("Double error detected.\r\n");
break;
}
else
{
// No Error
printf("No error detected.\r\n");
break;
}
}
else
{
// Parity odd
if (syndrome) {
// Double error
printf("Double error detected.\r\n");
break;
} else {
// No Error
printf("No error detected.\r\n");
break;
}
} else {
// Parity odd
if (syndrome)
{
// Bit error
printf("Error detected in Bit %d.\r\n", syndrome);
if (syndrome == pos + 1)
continue;
else
break;
}
else
{
// Overall parity Error
printf("Overall parity error detected.\r\n");
if (pos == 7 || pos == 3 || pos == 1 || pos == 0)
continue;
else
break;
}
}
}
system("pause");
if (syndrome) {
// Bit error
printf("Error detected in Bit %d.\r\n", syndrome);
if (syndrome == pos + 1)
continue;
else
break;
} else {
// Overall parity Error
printf("Overall parity error detected.\r\n");
if (pos == 7 || pos == 3 || pos == 1 || pos == 0)
continue;
else
break;
}
}
}
system("pause");
return 0;
}

View File

@@ -7,9 +7,9 @@
using std::cout;
CWord::CWord(unsigned nBitLength)
: m_nBitLength(nBitLength)
: m_nBitLength(nBitLength)
{
m_word.resize(nBitLength);
m_word.resize(nBitLength);
}
@@ -17,141 +17,127 @@ CWord::~CWord()
{
}
CBit * CWord::GetAt(unsigned nBitPos)
CBit *CWord::GetAt(unsigned nBitPos)
{
if (nBitPos < m_nBitLength)
{
return &m_word.at(nBitPos);
}
if (nBitPos < m_nBitLength) {
return &m_word.at(nBitPos);
}
return nullptr;
return nullptr;
}
void CWord::Set(unsigned data)
{
deque<CBit>::iterator it;
if (m_nBitLength < sizeof(data))
{
it = m_word.begin();
for (unsigned i = 0; i < m_nBitLength; i++)
{
(*it++) = data & 1;
data >>= 1;
}
}
else
{
for (it = m_word.begin(); it != m_word.end(); it++)
{
(*it) = data & 1;
data >>= 1;
}
}
deque<CBit>::iterator it;
if (m_nBitLength < sizeof(data)) {
it = m_word.begin();
for (unsigned i = 0; i < m_nBitLength; i++) {
(*it++) = data & 1;
data >>= 1;
}
} else {
for (it = m_word.begin(); it != m_word.end(); it++) {
(*it) = data & 1;
data >>= 1;
}
}
}
void CWord::Set(const unsigned char* data, unsigned lengthInBits)
void CWord::Set(const unsigned char *data, unsigned lengthInBits)
{
deque<CBit>::iterator it;
if (m_nBitLength < lengthInBits)
{
it = m_word.begin();
for (unsigned pos = 0; pos < m_nBitLength; pos++)
{
(*it) = data[pos>>3] & (1 << (7-(pos&7)));
it++;
}
}
else
{
unsigned pos = 0;
for (it = m_word.begin(); it != m_word.end(); it++)
{
(*it) = data[pos>>3] & (1 << (7-(pos&7)));
++pos;
}
}
deque<CBit>::iterator it;
if (m_nBitLength < lengthInBits) {
it = m_word.begin();
for (unsigned pos = 0; pos < m_nBitLength; pos++) {
(*it) = data[pos >> 3] & (1 << (7 - (pos & 7)));
it++;
}
} else {
unsigned pos = 0;
for (it = m_word.begin(); it != m_word.end(); it++) {
(*it) = data[pos >> 3] & (1 << (7 - (pos & 7)));
++pos;
}
}
}
void CWord::Rotate()
{
deque<CBit> buffer = m_word;
for (unsigned i = 0; i < m_nBitLength; i++)
{
m_word.at(m_nBitLength -i -1) = buffer.at(i);
}
deque<CBit> buffer = m_word;
for (unsigned i = 0; i < m_nBitLength; i++) {
m_word.at(m_nBitLength - i - 1) = buffer.at(i);
}
}
bool CWord::Insert(unsigned npos, CBit b)
{
if (npos >= m_nBitLength)
return false;
if (npos >= m_nBitLength)
return false;
deque<CBit>::iterator it = m_word.begin() + npos;
m_word.insert(it, b);
deque<CBit>::iterator it = m_word.begin() + npos;
m_word.insert(it, b);
m_nBitLength++;
m_nBitLength++;
return true;
return true;
}
bool CWord::Delete(unsigned npos)
{
if (npos >= m_nBitLength)
return false;
if (npos >= m_nBitLength)
return false;
deque<CBit>::iterator it = m_word.begin() + npos;
m_word.erase(it);
deque<CBit>::iterator it = m_word.begin() + npos;
m_word.erase(it);
m_nBitLength++;
m_nBitLength++;
return true;
return true;
}
void CWord::Append(CBit b)
{
m_word.push_back(b);
m_word.push_back(b);
m_nBitLength++;
m_nBitLength++;
}
void CWord::Resize(unsigned nsize)
{
m_word.resize(nsize);
m_nBitLength = nsize;
m_word.resize(nsize);
m_nBitLength = nsize;
}
bool CWord::PartShiftRight(unsigned nPos, unsigned /*nShift*/)
{
if(nPos >= m_nBitLength)
return false;
if (nPos >= m_nBitLength)
return false;
/*for (unsigned i = 0; i < nShift; i++)
{
m_word.insert()
}*/
/*for (unsigned i = 0; i < nShift; i++)
{
m_word.insert()
}*/
return true;
return true;
}
void CWord::Print()
{
deque<CBit>::iterator it;
for (it = m_word.begin(); it != m_word.end(); it++)
{
(*it).Print();
}
cout << "\r\n";
deque<CBit>::iterator it;
for (it = m_word.begin(); it != m_word.end(); it++) {
(*it).Print();
}
cout << "\r\n";
}
void CWord::Copy(unsigned char* ptr)
void CWord::Copy(unsigned char *ptr)
{
unsigned len = ceil(m_word.size()/8);
unsigned len = ceil(m_word.size() / 8);
memset(ptr, 0, len);
unsigned pos = 0;
for(auto it = m_word.begin(); it != m_word.end(); it++)
{
ptr[pos>>3] |= (*it).Get() << (7-(pos&7));
++pos;
}
unsigned pos = 0;
for (auto it = m_word.begin(); it != m_word.end(); it++) {
ptr[pos >> 3] |= (*it).Get() << (7 - (pos & 7));
++pos;
}
}

View File

@@ -10,54 +10,56 @@ class CWord
{
protected:
unsigned m_nBitLength;
deque<CBit> m_word;
unsigned m_nBitLength;
deque<CBit> m_word;
public:
CWord(unsigned nBitLength);
virtual ~CWord();
CWord(unsigned nBitLength);
virtual ~CWord();
CBit* GetAt(unsigned nBitPos);
CBit *GetAt(unsigned nBitPos);
void Set(unsigned data);
void Set(const unsigned char* data, unsigned lengthInBits);
void Rotate();
void Set(unsigned data);
void Set(const unsigned char *data, unsigned lengthInBits);
void Rotate();
bool Insert(unsigned npos, CBit b);
bool Delete(unsigned npos);
bool Insert(unsigned npos, CBit b);
bool Delete(unsigned npos);
void Copy(unsigned char* ptr);
void Copy(unsigned char *ptr);
void Append(CBit b);
void Append(CBit b);
void Resize(unsigned nsize);
void Resize(unsigned nsize);
bool PartShiftRight(unsigned nPos, unsigned nShift);
bool PartShiftRight(unsigned nPos, unsigned nShift);
inline unsigned GetLength() const { return m_nBitLength; };
inline unsigned GetLength() const
{
return m_nBitLength;
};
void Print();
void Print();
CWord& operator=(unsigned d)
{
Set(d);
return *this;
}
CWord &operator=(unsigned d)
{
Set(d);
return *this;
}
CBit& operator[](unsigned nPos)
{
return m_word.at(nPos);
}
CBit &operator[](unsigned nPos)
{
return m_word.at(nPos);
}
friend CWord operator >> (CWord l, const unsigned& r)
{
for (unsigned i = 0; i < r; i++)
{
l.m_word.pop_front();
l.m_word.push_back(CBit(CBit::VALUE::ZERO));
}
return l;
}
friend CWord operator >> (CWord l, const unsigned &r)
{
for (unsigned i = 0; i < r; i++) {
l.m_word.pop_front();
l.m_word.push_back(CBit(CBit::VALUE::ZERO));
}
return l;
}
};

View File

@@ -1,31 +1,30 @@
#include "eccbaseclass.h"
tlm::tlm_sync_enum ECCBaseClass::nb_transport_fw( int id, tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_time& delay )
tlm::tlm_sync_enum ECCBaseClass::nb_transport_fw( int id,
tlm::tlm_generic_payload &trans, tlm::tlm_phase &phase, sc_time &delay )
{
if(trans.get_command() == TLM_WRITE_COMMAND && phase == BEGIN_REQ)
{
if (trans.get_command() == TLM_WRITE_COMMAND && phase == BEGIN_REQ) {
// Allocate memory for encoded data using the size provided by AllocationEncode
unsigned nEncodedDataSize = AllocationSize(trans.get_data_length());
assert(nEncodedDataSize != 0);
unsigned char* pEncodedData = new unsigned char[nEncodedDataSize];
unsigned char *pEncodedData = new unsigned char[nEncodedDataSize];
// Save memory pointer and size
m_mDataPointer[pEncodedData].pData = trans.get_data_ptr();
m_mDataPointer[pEncodedData].nDataSize = trans.get_data_length();
// Data Encoding
Encode(trans.get_data_ptr(), trans.get_data_length(), pEncodedData, nEncodedDataSize);
Encode(trans.get_data_ptr(), trans.get_data_length(), pEncodedData,
nEncodedDataSize);
// Change transport data length and pointer
trans.set_data_length(nEncodedDataSize);
trans.set_data_ptr(pEncodedData);
}
else if(trans.get_command() == TLM_READ_COMMAND && phase == BEGIN_REQ)
{
} else if (trans.get_command() == TLM_READ_COMMAND && phase == BEGIN_REQ) {
// Allocate memory for reading data using the size provided by AllocationEncode
unsigned nReadDataSize = AllocationSize(trans.get_data_length());
assert(nReadDataSize != 0);
unsigned char* pReadData = new unsigned char[nReadDataSize];
unsigned char *pReadData = new unsigned char[nReadDataSize];
// Save memory pointer and size
m_mDataPointer[pReadData].pData = trans.get_data_ptr();
@@ -41,16 +40,17 @@ tlm::tlm_sync_enum ECCBaseClass::nb_transport_fw( int id, tlm::tlm_generic_paylo
// Backward interface
tlm::tlm_sync_enum ECCBaseClass::nb_transport_bw( int id, tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_time& delay )
tlm::tlm_sync_enum ECCBaseClass::nb_transport_bw( int id,
tlm::tlm_generic_payload &trans, tlm::tlm_phase &phase, sc_time &delay )
{
if(trans.get_command() == TLM_READ_COMMAND && phase == BEGIN_RESP)
{
if (trans.get_command() == TLM_READ_COMMAND && phase == BEGIN_RESP) {
//Look for the corresponding data pointer for decoding
auto it = m_mDataPointer.find(trans.get_data_ptr());
assert(it != m_mDataPointer.end());
// Data Decoding
Decode(trans.get_data_ptr(), trans.get_data_length(), it->second.pData, it->second.nDataSize);
Decode(trans.get_data_ptr(), trans.get_data_length(), it->second.pData,
it->second.nDataSize);
// delete data pointer from map
m_mDataPointer.erase(it);
@@ -61,9 +61,7 @@ tlm::tlm_sync_enum ECCBaseClass::nb_transport_bw( int id, tlm::tlm_generic_paylo
// Set data pointer and size for decoded data
trans.set_data_ptr(it->second.pData);
trans.set_data_length(it->second.nDataSize);
}
else if(trans.get_command() == TLM_WRITE_COMMAND && phase == BEGIN_RESP)
{
} else if (trans.get_command() == TLM_WRITE_COMMAND && phase == BEGIN_RESP) {
//Look for the corresponding data pointer for decoding
auto it = m_mDataPointer.find(trans.get_data_ptr());
assert(it != m_mDataPointer.end());

View File

@@ -17,14 +17,13 @@ using namespace tlm;
class ECCBaseClass : sc_module
{
public:
struct DataStruct
{
unsigned char* pData;
struct DataStruct {
unsigned char *pData;
unsigned int nDataSize;
};
private:
map<unsigned char*, DataStruct> m_mDataPointer;
map<unsigned char *, DataStruct> m_mDataPointer;
public:
// Function prototype for calculated the size of memory needed for saving the encoded data
@@ -37,14 +36,16 @@ protected:
// Data pointer is provided in pDataIn, length in Bytes provided in nDataIn
// Result should be written in pDataOut, which has a size of nDataOut.
// pDataOut is already allocated with a size given by function AllocationEncode
virtual void Encode(const unsigned char* pDataIn, const unsigned nDataIn, unsigned char* pDataOut, const unsigned nDataOut) = 0;
virtual void Encode(const unsigned char *pDataIn, const unsigned nDataIn,
unsigned char *pDataOut, const unsigned nDataOut) = 0;
// Function prototype for decoding data.
// Data pointer is provided in pDataIn, length in Bytes provided in nDataIn
// Result should be written in pDataOut, which has a size of nDataOut.
// pDataOut is already allocated with a size given by function AllocationDecode
virtual void Decode(const unsigned char* pDataIn, const unsigned nDataIn, unsigned char* pDataOut, const unsigned nDataOut) = 0;
virtual void Decode(const unsigned char *pDataIn, const unsigned nDataIn,
unsigned char *pDataOut, const unsigned nDataOut) = 0;
public:
tlm_utils::multi_passthrough_target_socket<ECCBaseClass> t_socket;
@@ -58,10 +59,12 @@ public:
i_socket.register_nb_transport_bw(this, &ECCBaseClass::nb_transport_bw);
}
// Forward interface
tlm::tlm_sync_enum nb_transport_fw( int id, tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_time& delay );
tlm::tlm_sync_enum nb_transport_fw( int id, tlm::tlm_generic_payload &trans,
tlm::tlm_phase &phase, sc_time &delay );
// Backward interface
tlm::tlm_sync_enum nb_transport_bw( int id, tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_time& delay );
tlm::tlm_sync_enum nb_transport_bw( int id, tlm::tlm_generic_payload &trans,
tlm::tlm_phase &phase, sc_time &delay );
};
#endif // ECCBASECLASS_H

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