Merge branch 'addressdecoder_unification' into 'master'
Address decoder unification See merge request ems/astdm/dram.sys!245
This commit is contained in:
@@ -66,13 +66,11 @@ include_directories(
|
||||
|
||||
add_library(DRAMSysLibrary
|
||||
src/common/AddressDecoder.cpp
|
||||
src/common/CongenAddressDecoder.cpp
|
||||
src/common/DebugManager.cpp
|
||||
src/common/dramExtensions.cpp
|
||||
src/common/tlm2_base_protocol_checker.h
|
||||
src/common/TlmRecorder.cpp
|
||||
src/common/utils.cpp
|
||||
src/common/XmlAddressDecoder.cpp
|
||||
src/common/third_party/tinyxml2/tinyxml2.cpp
|
||||
|
||||
src/configuration/Configuration.cpp
|
||||
@@ -140,11 +138,9 @@ add_library(DRAMSysLibrary
|
||||
src/simulation/Arbiter.cpp
|
||||
src/simulation/DRAMSys.cpp
|
||||
src/simulation/ExampleInitiator.h
|
||||
src/simulation/IArbiter.h
|
||||
src/simulation/MemoryManager.cpp
|
||||
src/simulation/ReorderBuffer.h
|
||||
src/simulation/Setup.cpp
|
||||
src/simulation/SimpleArbiter.h
|
||||
src/simulation/StlPlayer.h
|
||||
src/simulation/TemperatureController.cpp
|
||||
src/simulation/TraceGenerator.h
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" ?>
|
||||
<CONGEN>
|
||||
<SOLUTION ID="0">
|
||||
<XOR FIRST="13" SECOND="16"/>
|
||||
<BYTE_BIT>0</BYTE_BIT>
|
||||
<BYTE_BIT>1</BYTE_BIT>
|
||||
<BYTE_BIT>2</BYTE_BIT>
|
||||
<COLUMN_BIT>3</COLUMN_BIT>
|
||||
<COLUMN_BIT>4</COLUMN_BIT>
|
||||
<COLUMN_BIT>5</COLUMN_BIT>
|
||||
<COLUMN_BIT>6</COLUMN_BIT>
|
||||
<COLUMN_BIT>7</COLUMN_BIT>
|
||||
<COLUMN_BIT>8</COLUMN_BIT>
|
||||
<COLUMN_BIT>9</COLUMN_BIT>
|
||||
<COLUMN_BIT>10</COLUMN_BIT>
|
||||
<COLUMN_BIT>11</COLUMN_BIT>
|
||||
<COLUMN_BIT>12</COLUMN_BIT>
|
||||
<BANK_BIT>13</BANK_BIT>
|
||||
<BANK_BIT>14</BANK_BIT>
|
||||
<BANK_BIT>15</BANK_BIT>
|
||||
<ROW_BIT>16</ROW_BIT>
|
||||
<ROW_BIT>17</ROW_BIT>
|
||||
<ROW_BIT>18</ROW_BIT>
|
||||
<ROW_BIT>19</ROW_BIT>
|
||||
<ROW_BIT>20</ROW_BIT>
|
||||
<ROW_BIT>21</ROW_BIT>
|
||||
<ROW_BIT>22</ROW_BIT>
|
||||
<ROW_BIT>23</ROW_BIT>
|
||||
<ROW_BIT>24</ROW_BIT>
|
||||
<ROW_BIT>25</ROW_BIT>
|
||||
<ROW_BIT>26</ROW_BIT>
|
||||
<ROW_BIT>27</ROW_BIT>
|
||||
<ROW_BIT>28</ROW_BIT>
|
||||
<ROW_BIT>29</ROW_BIT>
|
||||
</SOLUTION>
|
||||
</CONGEN>
|
||||
@@ -31,32 +31,270 @@
|
||||
*
|
||||
* Authors:
|
||||
* Johannes Feldmann
|
||||
* Lukas Steiner
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <bitset>
|
||||
|
||||
#include "AddressDecoder.h"
|
||||
#include "XmlAddressDecoder.h"
|
||||
#include "CongenAddressDecoder.h"
|
||||
#include "utils.h"
|
||||
#include "../configuration/Configuration.h"
|
||||
|
||||
AddressDecoder *AddressDecoder::m_pInstance = nullptr;
|
||||
|
||||
AddressDecoder &AddressDecoder::getInstance()
|
||||
tinyxml2::XMLElement *AddressDecoder::getXMLNode(tinyxml2::XMLElement
|
||||
*pRoot, std::string strName)
|
||||
{
|
||||
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::CONGEN:
|
||||
m_pInstance = new CongenAddressDecoder;
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Instance type not supported.");
|
||||
break;
|
||||
tinyxml2::XMLElement *pNode = pRoot->FirstChildElement(strName.c_str());
|
||||
if (pNode == nullptr) {
|
||||
reportFatal("AddressDecorder",
|
||||
"XML File corrupted. Missing node " + strName + ".");
|
||||
}
|
||||
return pNode;
|
||||
}
|
||||
|
||||
unsigned int AddressDecoder::getUnsignedTextFromXMLNode(
|
||||
tinyxml2::XMLElement *pRoot)
|
||||
{
|
||||
std::string str = pRoot->GetText();
|
||||
if (str.empty() || std::find_if(str.begin(), str.end(), [](char c) {
|
||||
return !std::isdigit(c);
|
||||
}) != str.end()) {
|
||||
reportFatal("AddressDecoder",
|
||||
"Node " + std::string(pRoot->Name()) + " is empty or not a number.");
|
||||
return (unsigned)(-1);
|
||||
}
|
||||
return atol(str.c_str());
|
||||
}
|
||||
|
||||
unsigned int AddressDecoder::getUnsignedAttrFromXMLNode(
|
||||
tinyxml2::XMLElement *pRoot, std::string strName)
|
||||
{
|
||||
std::string str = pRoot->Attribute(strName.c_str());
|
||||
if (str.empty() || std::find_if(str.begin(), str.end(), [](char c) {
|
||||
return !std::isdigit(c);
|
||||
}) != str.end()) {
|
||||
reportFatal("AddressDecoder",
|
||||
"Attribute " + strName + " is empty or not a number.");
|
||||
return (unsigned)(-1);
|
||||
}
|
||||
return atol(str.c_str());
|
||||
}
|
||||
|
||||
AddressDecoder::AddressDecoder(std::string pathToAddressMapping)
|
||||
{
|
||||
tinyxml2::XMLDocument doc;
|
||||
loadXML(pathToAddressMapping, doc);
|
||||
tinyxml2::XMLElement *pRoot = doc.RootElement();
|
||||
std::string xmlNodeName(pRoot->Name());
|
||||
|
||||
if (xmlNodeName != "CONGEN")
|
||||
reportFatal("AddressDecorder",
|
||||
"Root node name differs from \"CONGEN\". File format not supported.");
|
||||
|
||||
// Load address mapping
|
||||
tinyxml2::XMLElement *pNode;
|
||||
|
||||
for (pNode = pRoot->FirstChildElement("SOLUTION"); pNode != nullptr;
|
||||
pNode = pNode->NextSiblingElement("SOLUTION"))
|
||||
{
|
||||
if (getUnsignedAttrFromXMLNode(pNode, "ID") == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pNode == nullptr)
|
||||
SC_REPORT_FATAL("AddressDecoder", "No mapping with ID 0 was found.");
|
||||
|
||||
// get XOR connections
|
||||
// An XOR connection needs two parameters: A first bit and a second bit.
|
||||
for (tinyxml2::XMLElement *pXor = pNode->FirstChildElement("XOR");
|
||||
pXor != nullptr; pXor = pXor->NextSiblingElement("XOR"))
|
||||
{
|
||||
vXor.push_back(std::pair<unsigned, unsigned>(getUnsignedAttrFromXMLNode(pXor, "FIRST"),
|
||||
getUnsignedAttrFromXMLNode(pXor, "SECOND")));
|
||||
}
|
||||
|
||||
for (tinyxml2::XMLElement *pChannel = pNode->FirstChildElement("CHANNEL_BIT");
|
||||
pChannel != nullptr; pChannel = pChannel->NextSiblingElement("CHANNEL_BIT"))
|
||||
vChannelBits.push_back(getUnsignedTextFromXMLNode(pChannel));
|
||||
|
||||
for (tinyxml2::XMLElement *pRank = pNode->FirstChildElement("RANK_BIT");
|
||||
pRank != nullptr; pRank = pRank->NextSiblingElement("RANK_BIT"))
|
||||
vRankBits.push_back(getUnsignedTextFromXMLNode(pRank));
|
||||
|
||||
for (tinyxml2::XMLElement *pBankGroup = pNode->FirstChildElement("BANKGROUP_BIT");
|
||||
pBankGroup != nullptr; pBankGroup = pBankGroup->NextSiblingElement("BANKGROUP_BIT"))
|
||||
vBankGroupBits.push_back(getUnsignedTextFromXMLNode(pBankGroup));
|
||||
|
||||
for (tinyxml2::XMLElement *pBank = pNode->FirstChildElement("BANK_BIT");
|
||||
pBank != nullptr; pBank = pBank->NextSiblingElement("BANK_BIT"))
|
||||
vBankBits.push_back(getUnsignedTextFromXMLNode(pBank));
|
||||
|
||||
for (tinyxml2::XMLElement *pRow = pNode->FirstChildElement("ROW_BIT");
|
||||
pRow != nullptr; pRow = pRow->NextSiblingElement("ROW_BIT"))
|
||||
vRowBits.push_back(getUnsignedTextFromXMLNode(pRow));
|
||||
|
||||
for (tinyxml2::XMLElement *pColumn = pNode->FirstChildElement("COLUMN_BIT");
|
||||
pColumn != nullptr; pColumn = pColumn->NextSiblingElement("COLUMN_BIT"))
|
||||
vColumnBits.push_back(getUnsignedTextFromXMLNode(pColumn));
|
||||
|
||||
for (tinyxml2::XMLElement *pByte = pNode->FirstChildElement("BYTE_BIT");
|
||||
pByte != nullptr; pByte = pByte->NextSiblingElement("BYTE_BIT"))
|
||||
vByteBits.push_back(getUnsignedTextFromXMLNode(pByte));
|
||||
|
||||
unsigned channels = pow(2.0, vChannelBits.size());
|
||||
unsigned ranks = pow(2.0, vRankBits.size());
|
||||
unsigned bankgroups = pow(2.0, vBankGroupBits.size());
|
||||
unsigned banks = pow(2.0, vBankBits.size());
|
||||
unsigned rows = pow(2.0, vRowBits.size());
|
||||
unsigned columns = pow(2.0, vColumnBits.size());
|
||||
unsigned bytes = pow(2.0, vByteBits.size());
|
||||
|
||||
maximumAddress = bytes * columns * rows * banks * bankgroups * ranks * channels - 1;
|
||||
|
||||
banksPerGroup = banks;
|
||||
banks = banksPerGroup * bankgroups * ranks;
|
||||
|
||||
bankgroupsPerRank = bankgroups;
|
||||
bankgroups = bankgroupsPerRank * ranks;
|
||||
|
||||
Configuration &config = Configuration::getInstance();
|
||||
MemSpec *memSpec = config.memSpec;
|
||||
|
||||
if (config.numberOfMemChannels != channels || memSpec->numberOfRanks != ranks
|
||||
|| memSpec->numberOfBankGroups != bankgroups || memSpec->numberOfBanks != banks
|
||||
|| memSpec->numberOfRows != rows || memSpec->numberOfColumns != columns
|
||||
|| config.numberOfDevicesOnDIMM * memSpec->bitWidth != bytes * 8)
|
||||
SC_REPORT_FATAL("AddressDecoder", "Memspec and address mapping do not match");
|
||||
}
|
||||
|
||||
DecodedAddress AddressDecoder::decodeAddress(uint64_t encAddr)
|
||||
{
|
||||
if (encAddr > maximumAddress)
|
||||
SC_REPORT_WARNING("AddressDecoder", ("Address " + std::to_string(encAddr) + " out of range (maximum address is " + std::to_string(maximumAddress) + ")").c_str());
|
||||
|
||||
// Apply XOR
|
||||
// For each used xor:
|
||||
// Get the first bit and second bit. Apply a bitwise xor operator and save it back to the first bit.
|
||||
for (auto it = vXor.begin(); it != vXor.end(); it++)
|
||||
{
|
||||
unsigned xoredBit;
|
||||
xoredBit = (((encAddr >> it->first) & 1) ^ ((encAddr >> it->second) & 1));
|
||||
encAddr &= ~(1 << it->first);
|
||||
encAddr |= xoredBit << it->first;
|
||||
}
|
||||
|
||||
DecodedAddress decAddr;
|
||||
|
||||
for (unsigned it = 0; it < vChannelBits.size(); it++)
|
||||
decAddr.channel |= ((encAddr >> vChannelBits[it]) & 1) << it;
|
||||
|
||||
for (unsigned it = 0; it < vRankBits.size(); it++)
|
||||
decAddr.rank |= ((encAddr >> vRankBits[it]) & 1) << it;
|
||||
|
||||
for (unsigned it = 0; it < vBankGroupBits.size(); it++)
|
||||
decAddr.bankgroup |= ((encAddr >> vBankGroupBits[it]) & 1) << it;
|
||||
|
||||
for (unsigned it = 0; it < vBankBits.size(); it++)
|
||||
decAddr.bank |= ((encAddr >> vBankBits[it]) & 1) << it;
|
||||
|
||||
for (unsigned it = 0; it < vRowBits.size(); it++)
|
||||
decAddr.row |= ((encAddr >> vRowBits[it]) & 1) << it;
|
||||
|
||||
for (unsigned it = 0; it < vColumnBits.size(); it++)
|
||||
decAddr.column |= ((encAddr >> vColumnBits[it]) & 1) << it;
|
||||
|
||||
for (unsigned it = 0; it < vByteBits.size(); it++)
|
||||
decAddr.byte |= ((encAddr >> vByteBits[it]) & 1) << it;
|
||||
|
||||
decAddr.bankgroup = decAddr.bankgroup + decAddr.rank * bankgroupsPerRank;
|
||||
decAddr.bank = decAddr.bank + decAddr.bankgroup * banksPerGroup;
|
||||
|
||||
return decAddr;
|
||||
}
|
||||
|
||||
void AddressDecoder::print()
|
||||
{
|
||||
std::cout << headline << std::endl;
|
||||
std::cout << "Used Address Mapping:" << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
for (int it = vChannelBits.size() - 1; it >= 0; it--)
|
||||
{
|
||||
uint64_t addressBits = (1 << vChannelBits[it]);
|
||||
for (auto it2 : vXor)
|
||||
{
|
||||
if (it2.first == vChannelBits[it])
|
||||
addressBits |= (1 << it2.second);
|
||||
}
|
||||
std::cout << " Ch " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl;
|
||||
}
|
||||
|
||||
for (int it = vRankBits.size() - 1; it >= 0; it--)
|
||||
{
|
||||
uint64_t addressBits = (1 << vRankBits[it]);
|
||||
for (auto it2 : vXor)
|
||||
{
|
||||
if (it2.first == vRankBits[it])
|
||||
addressBits |= (1 << it2.second);
|
||||
}
|
||||
std::cout << " Ra " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl;
|
||||
}
|
||||
|
||||
for (int it = vBankGroupBits.size() - 1; it >= 0; it--)
|
||||
{
|
||||
uint64_t addressBits = (1 << vBankGroupBits[it]);
|
||||
for (auto it2 : vXor)
|
||||
{
|
||||
if (it2.first == vBankGroupBits[it])
|
||||
addressBits |= (1 << it2.second);
|
||||
}
|
||||
std::cout << " Bg " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl;
|
||||
}
|
||||
|
||||
for (int it = vBankBits.size() - 1; it >= 0; it--)
|
||||
{
|
||||
uint64_t addressBits = (1 << vBankBits[it]);
|
||||
for (auto it2 : vXor)
|
||||
{
|
||||
if (it2.first == vBankBits[it])
|
||||
addressBits |= (1 << it2.second);
|
||||
}
|
||||
std::cout << " Ba " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl;
|
||||
}
|
||||
|
||||
for (int it = vRowBits.size() - 1; it >= 0; it--)
|
||||
{
|
||||
uint64_t addressBits = (1 << vRowBits[it]);
|
||||
for (auto it2 : vXor)
|
||||
{
|
||||
if (it2.first == vRowBits[it])
|
||||
addressBits |= (1 << it2.second);
|
||||
}
|
||||
std::cout << " Ro " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl;
|
||||
}
|
||||
|
||||
for (int it = vColumnBits.size() - 1; it >= 0; it--)
|
||||
{
|
||||
uint64_t addressBits = (1 << vColumnBits[it]);
|
||||
for (auto it2 : vXor)
|
||||
{
|
||||
if (it2.first == vColumnBits[it])
|
||||
addressBits |= (1 << it2.second);
|
||||
}
|
||||
std::cout << " Co " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl;
|
||||
}
|
||||
|
||||
for (int it = vByteBits.size() - 1; it >= 0; it--)
|
||||
{
|
||||
uint64_t addressBits = (1 << vByteBits[it]);
|
||||
for (auto it2 : vXor)
|
||||
{
|
||||
if (it2.first == vByteBits[it])
|
||||
addressBits |= (1 << it2.second);
|
||||
}
|
||||
std::cout << " By " << std::setw(2) << it << ": " << std::bitset<64>(addressBits) << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,70 +31,69 @@
|
||||
*
|
||||
* Authors:
|
||||
* Johannes Feldmann
|
||||
* Lukas Steiner
|
||||
*/
|
||||
|
||||
#ifndef ADDRESSDECODER_H
|
||||
#define ADDRESSDECODER_H
|
||||
|
||||
#include <tlm.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
struct DecodedAddress {
|
||||
DecodedAddress() : channel(0),
|
||||
rank(0),
|
||||
bankgroup(0),
|
||||
row(0),
|
||||
bank(0),
|
||||
column(0),
|
||||
bytes(0)
|
||||
{
|
||||
}
|
||||
#include "third_party/tinyxml2/tinyxml2.h"
|
||||
|
||||
unsigned int channel;
|
||||
unsigned int rank;
|
||||
unsigned int bankgroup;
|
||||
unsigned int row;
|
||||
unsigned int bank;
|
||||
unsigned int column;
|
||||
unsigned int bytes;
|
||||
struct DecodedAddress
|
||||
{
|
||||
DecodedAddress(unsigned channel, unsigned rank,
|
||||
unsigned bankgroup, unsigned bank,
|
||||
unsigned row, unsigned column, unsigned bytes)
|
||||
: channel(channel), rank(rank), bankgroup(bankgroup),
|
||||
bank(bank), row(row), column(column), byte(bytes) {}
|
||||
|
||||
DecodedAddress()
|
||||
: channel(0), rank(0), bankgroup(0),
|
||||
bank(0), row(0), column(0), byte(0) {}
|
||||
|
||||
unsigned channel;
|
||||
unsigned rank;
|
||||
unsigned bankgroup;
|
||||
unsigned bank;
|
||||
unsigned row;
|
||||
unsigned column;
|
||||
unsigned byte;
|
||||
};
|
||||
|
||||
class AddressDecoder
|
||||
{
|
||||
public:
|
||||
enum class Type {
|
||||
XML,
|
||||
CONGEN
|
||||
};
|
||||
AddressDecoder(std::string);
|
||||
DecodedAddress decodeAddress(uint64_t addr);
|
||||
void print();
|
||||
|
||||
protected:
|
||||
AddressDecoder() {}
|
||||
private:
|
||||
tinyxml2::XMLElement *getXMLNode(tinyxml2::XMLElement *pRoot,
|
||||
std::string strName);
|
||||
unsigned int getUnsignedTextFromXMLNode(tinyxml2::XMLElement *pRoot);
|
||||
unsigned int getUnsignedAttrFromXMLNode(tinyxml2::XMLElement *pRoot,
|
||||
std::string strName);
|
||||
|
||||
static AddressDecoder *m_pInstance;
|
||||
public:
|
||||
static AddressDecoder &getInstance();
|
||||
static void createInstance(Type t);
|
||||
unsigned banksPerGroup;
|
||||
unsigned bankgroupsPerRank;
|
||||
|
||||
virtual void setConfiguration(std::string url) = 0;
|
||||
uint64_t maximumAddress;
|
||||
|
||||
virtual DecodedAddress decodeAddress(uint64_t addr) = 0;
|
||||
virtual uint64_t encodeAddress(DecodedAddress n) = 0;
|
||||
|
||||
virtual void print() = 0;
|
||||
|
||||
struct Amount
|
||||
{
|
||||
unsigned channel = 1;
|
||||
unsigned rank = 1;
|
||||
unsigned bankgroup = 1;
|
||||
unsigned bank = 1;
|
||||
unsigned row = 1;
|
||||
unsigned column = 1;
|
||||
unsigned bytes = 1;
|
||||
} amount;
|
||||
// This container stores for each used xor gate a pair of address bits, the first bit is overwritten with the result
|
||||
std::vector<std::pair<unsigned, unsigned>> vXor;
|
||||
std::vector<unsigned> vChannelBits;
|
||||
std::vector<unsigned> vRankBits;
|
||||
std::vector<unsigned> vBankGroupBits;
|
||||
std::vector<unsigned> vBankBits;
|
||||
std::vector<unsigned> vRowBits;
|
||||
std::vector<unsigned> vColumnBits;
|
||||
std::vector<unsigned> vByteBits;
|
||||
};
|
||||
|
||||
#endif // ADDRESSDECODER_H
|
||||
|
||||
@@ -1,341 +0,0 @@
|
||||
/*
|
||||
* 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 "CongenAddressDecoder.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
|
||||
using std::ifstream;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::set;
|
||||
using std::pair;
|
||||
using std::map;
|
||||
using std::deque;
|
||||
|
||||
tinyxml2::XMLElement *CongenAddressDecoder::GetXMLNode(tinyxml2::XMLElement
|
||||
*pRoot, std::string strName)
|
||||
{
|
||||
tinyxml2::XMLElement *pNode = pRoot->FirstChildElement(strName.c_str());
|
||||
if (pNode == nullptr) {
|
||||
reportFatal("ConGenAddressDecorder",
|
||||
"XML File corrupted. Missing node " + strName + ".");
|
||||
}
|
||||
return pNode;
|
||||
}
|
||||
|
||||
unsigned int CongenAddressDecoder::GetUnsignedTextFromXMLNode(
|
||||
tinyxml2::XMLElement *pRoot)
|
||||
{
|
||||
std::string str = pRoot->GetText();
|
||||
if (str.empty() || std::find_if(str.begin(), str.end(), [](char c) {
|
||||
return !std::isdigit(c);
|
||||
}) != str.end()) {
|
||||
reportFatal("ConGenAddressDecoder",
|
||||
"Node " + std::string(pRoot->Name()) + " is empty or not a number.");
|
||||
return (unsigned)(-1);
|
||||
}
|
||||
return atol(str.c_str());
|
||||
}
|
||||
|
||||
unsigned int CongenAddressDecoder::GetUnsignedAttrFromXMLNode(
|
||||
tinyxml2::XMLElement *pRoot, std::string strName)
|
||||
{
|
||||
std::string str = pRoot->Attribute(strName.c_str());
|
||||
if (str.empty() || std::find_if(str.begin(), str.end(), [](char c) {
|
||||
return !std::isdigit(c);
|
||||
}) != str.end()) {
|
||||
reportFatal("ConGenAddressDecoder",
|
||||
"Attribute " + strName + " is empty or not a number.");
|
||||
return (unsigned)(-1);
|
||||
}
|
||||
return atol(str.c_str());
|
||||
}
|
||||
|
||||
CongenAddressDecoder::CongenAddressDecoder()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CongenAddressDecoder::setConfiguration(std::string url)
|
||||
{
|
||||
tinyxml2::XMLDocument doc;
|
||||
loadXML(url, doc);
|
||||
tinyxml2::XMLElement *pRoot = doc.RootElement();
|
||||
std::string xmlNodeName(pRoot->Name());
|
||||
|
||||
if ( xmlNodeName != "CONGEN") {
|
||||
reportFatal("ConGenAddressDecorder",
|
||||
"Root node name differs from \"CONGEN\". File format not supported.");
|
||||
}
|
||||
|
||||
// Load basic configuration
|
||||
tinyxml2::XMLElement *pNode = GetXMLNode(pRoot, "NAME");
|
||||
m_strName = pNode->GetText();
|
||||
pNode = GetXMLNode(pRoot, "COSTS");
|
||||
m_nCost = GetUnsignedTextFromXMLNode(pNode);
|
||||
tinyxml2::XMLElement *pConfig = GetXMLNode(pRoot, "CONFIG");
|
||||
pNode = GetXMLNode(pConfig, "NUM_BANK_BITS");
|
||||
m_nBankBits = GetUnsignedTextFromXMLNode(pNode);
|
||||
pNode = GetXMLNode(pConfig, "NUM_ROW_BITS");
|
||||
m_nRowBits = GetUnsignedTextFromXMLNode(pNode);
|
||||
pNode = GetXMLNode(pConfig, "NUM_COLUMN_BITS");
|
||||
m_nColumnBits = GetUnsignedTextFromXMLNode(pNode);
|
||||
pNode = GetXMLNode(pConfig, "NUM_BL_BITS");
|
||||
m_nBurstLengthBits = GetUnsignedTextFromXMLNode(pNode);
|
||||
pNode = GetXMLNode(pConfig, "NUM_BYTE_BITS");
|
||||
m_nByteBits = GetUnsignedTextFromXMLNode(pNode);
|
||||
|
||||
// Load address mapping
|
||||
unsigned id = 0;
|
||||
|
||||
for (pNode = pRoot->FirstChildElement("SOLUTION"); pNode != nullptr;
|
||||
pNode = pNode->NextSiblingElement("SOLUTION")) {
|
||||
if (GetUnsignedAttrFromXMLNode(pNode, "ID") == id) {
|
||||
// Correct mapping was found.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no mapping was found report error and return
|
||||
if (pNode == nullptr) {
|
||||
reportFatal("ConGenAddressDecoder",
|
||||
"No mapping with ID " + std::to_string(id) + " was found.");
|
||||
return;
|
||||
}
|
||||
|
||||
// get XOR connections
|
||||
// An XOR connection needs two parameters: A bank bit and a Row bit.
|
||||
for (tinyxml2::XMLElement *pXor = pNode->FirstChildElement("XOR");
|
||||
pXor != nullptr; pXor = pXor->NextSiblingElement("XOR")) {
|
||||
m_vXor.push_back(XOR(GetUnsignedAttrFromXMLNode(pXor, "BANK"),
|
||||
GetUnsignedAttrFromXMLNode(pXor, "ROW")));
|
||||
}
|
||||
|
||||
set<unsigned> sUsed;
|
||||
|
||||
// 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 (tinyxml2::XMLElement *pBank = pNode->FirstChildElement("BANK_BIT");
|
||||
pBank != nullptr; pBank = pBank->NextSiblingElement("BANK_BIT")) {
|
||||
unsigned nBank = GetUnsignedTextFromXMLNode(pBank);
|
||||
m_vBankBits.push_back(pair<unsigned, unsigned>(counter++, nBank));
|
||||
sUsed.insert(nBank);
|
||||
}
|
||||
|
||||
// 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 (tinyxml2::XMLElement *pRow = pNode->FirstChildElement("ROW_BIT");
|
||||
pRow != nullptr; pRow = pRow->NextSiblingElement("ROW_BIT")) {
|
||||
unsigned nRow = GetUnsignedTextFromXMLNode(pRow);
|
||||
m_vRowBits.push_back(pair<unsigned, unsigned>(counter++, nRow));
|
||||
sUsed.insert(nRow);
|
||||
}
|
||||
|
||||
// Add byte bits
|
||||
for (unsigned i = 0; i < m_nByteBits; i++) {
|
||||
sUsed.insert(i);
|
||||
}
|
||||
|
||||
// Theset bits are ignored (fixed in Congen)
|
||||
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, m_nByteBits);
|
||||
}
|
||||
|
||||
DecodedAddress CongenAddressDecoder::decodeAddress(uint64_t 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->nBank) & 1) ^ ((addr >> it->nRow) & 1));
|
||||
addr &= ~(1 << it->nBank);
|
||||
addr |= new_bank_bit << it->nBank;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
uint64_t CongenAddressDecoder::encodeAddress(DecodedAddress n)
|
||||
{
|
||||
uint64_t 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->nBank) & 1) ^ ((address >> it->nRow) & 1));
|
||||
address &= ~(1 << it->nBank);
|
||||
address |= new_bank_bit << it->nBank;
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
bool CongenAddressDecoder::testConfigFile(std::string url)
|
||||
{
|
||||
// Simple test if the root node has the correct name.
|
||||
// This is suitable for now, but can be extended in future.
|
||||
|
||||
tinyxml2::XMLDocument doc;
|
||||
loadXML(url, doc);
|
||||
tinyxml2::XMLElement *pRoot = doc.RootElement();
|
||||
|
||||
return (strcmp(pRoot->Name(), "CONGEN") == 0);
|
||||
}
|
||||
|
||||
void CongenAddressDecoder::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;
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* 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 CONGENADDRESSDECODER_H
|
||||
#define CONGENADDRESSDECODER_H
|
||||
|
||||
#include "AddressDecoder.h"
|
||||
|
||||
#include "third_party/tinyxml2/tinyxml2.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
class CongenAddressDecoder : private AddressDecoder
|
||||
{
|
||||
// Friendship needed so that the AddressDecoder can access the
|
||||
// constructor of this class to create the object in CreateInstance.
|
||||
friend class AddressDecoder;
|
||||
|
||||
public:
|
||||
struct XOR {
|
||||
unsigned nBank;
|
||||
unsigned nRow;
|
||||
XOR() {};
|
||||
XOR(unsigned bank, unsigned row) : nBank(bank), nRow(row) {};
|
||||
};
|
||||
|
||||
// Member variables
|
||||
private:
|
||||
std::string m_strName; // The Name of this mapping
|
||||
|
||||
unsigned int
|
||||
m_nCost; // Number of row misses produced by this mapping
|
||||
|
||||
unsigned int
|
||||
m_nBankBits; // Number of Bank bits used by this mapping
|
||||
unsigned int
|
||||
m_nRowBits; // Number of Row bits used by this mapping
|
||||
unsigned int
|
||||
m_nColumnBits; // Number of Column bits used by this mapping
|
||||
unsigned int
|
||||
m_nBurstLengthBits; // Number of Burst length bits used by this mapping
|
||||
unsigned int
|
||||
m_nByteBits; // Number of Byte bits used by this mapping
|
||||
|
||||
|
||||
std::vector<XOR>
|
||||
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"
|
||||
std::vector<std::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"
|
||||
std::vector<std::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"
|
||||
std::vector<std::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"
|
||||
|
||||
//Methods
|
||||
private:
|
||||
tinyxml2::XMLElement *GetXMLNode(tinyxml2::XMLElement *pRoot,
|
||||
std::string strName);
|
||||
unsigned int GetUnsignedTextFromXMLNode(tinyxml2::XMLElement *pRoot);
|
||||
unsigned int GetUnsignedAttrFromXMLNode(tinyxml2::XMLElement *pRoot,
|
||||
std::string strName);
|
||||
public:
|
||||
CongenAddressDecoder();
|
||||
|
||||
virtual void setConfiguration(std::string url);
|
||||
|
||||
virtual DecodedAddress decodeAddress(uint64_t addr);
|
||||
virtual uint64_t encodeAddress(DecodedAddress n);
|
||||
|
||||
static bool testConfigFile(std::string url);
|
||||
|
||||
virtual void print();
|
||||
};
|
||||
|
||||
#endif // CONGENADDRESSDECODER_H
|
||||
@@ -41,7 +41,6 @@
|
||||
|
||||
#include "TlmRecorder.h"
|
||||
#include "dramExtensions.h"
|
||||
#include "XmlAddressDecoder.h"
|
||||
#include "../configuration/Configuration.h"
|
||||
#include "../controller/Command.h"
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
#include <cerrno>
|
||||
#include <tlm.h>
|
||||
#include <systemc.h>
|
||||
#include "XmlAddressDecoder.h"
|
||||
#include "DebugManager.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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:
|
||||
* Janik Schlemminger
|
||||
* Robert Gernhardt
|
||||
* Matthias Jung
|
||||
*/
|
||||
|
||||
#include "XmlAddressDecoder.h"
|
||||
#include <systemc.h>
|
||||
#include "utils.h"
|
||||
#include "bitset"
|
||||
#include "../configuration/Configuration.h"
|
||||
|
||||
using namespace tinyxml2;
|
||||
|
||||
XmlAddressDecoder::XmlAddressDecoder()
|
||||
{
|
||||
addressmapping = NULL;
|
||||
}
|
||||
|
||||
void XmlAddressDecoder::setConfiguration(std::string addressConfigURI)
|
||||
{
|
||||
tinyxml2::XMLDocument doc;
|
||||
loadXML(addressConfigURI, doc);
|
||||
tinyxml2::XMLElement *addressMap = doc.RootElement();
|
||||
std::string xmlNodeName(addressMap->Name());
|
||||
|
||||
if (xmlNodeName != "addressmapping")
|
||||
reportFatal("AddressDecorder", "addressmap node expected");
|
||||
|
||||
for (XMLElement *child = addressMap->FirstChildElement();
|
||||
child != NULL; child = child->NextSiblingElement())
|
||||
{
|
||||
unsigned from;
|
||||
unsigned to;
|
||||
|
||||
child->QueryAttribute("from", &from);
|
||||
child->QueryAttribute("to", &to);
|
||||
|
||||
if (std::strcmp(child->Name(), "channel") == 0)
|
||||
{
|
||||
shifts.channel = from;
|
||||
masks.channel = pow(2.0, to + 1.0) - pow(2.0, from + 0.0);
|
||||
amount.channel = pow(2.0, to - from + 1.0);
|
||||
}
|
||||
else if (std::strcmp(child->Name(), "rank") == 0)
|
||||
{
|
||||
shifts.rank = from;
|
||||
masks.rank = pow(2.0, to + 1.0) - pow(2.0, from + 0.0);
|
||||
amount.rank = pow(2.0, to - from + 1.0);
|
||||
}
|
||||
else if (std::strcmp(child->Name(), "bankgroup") == 0)
|
||||
{
|
||||
shifts.bankgroup = from;
|
||||
masks.bankgroup = pow(2.0, to + 1.0) - pow(2.0, from + 0.0);
|
||||
amount.bankgroup = pow(2.0, to - from + 1.0);
|
||||
}
|
||||
else if (std::strcmp(child->Name(), "bank") == 0)
|
||||
{
|
||||
shifts.bank = from;
|
||||
masks.bank = pow(2.0, to + 1.0) - pow(2.0, from + 0.0);
|
||||
amount.bank = pow(2.0, to - from + 1.0);
|
||||
}
|
||||
else if (std::strcmp(child->Name(), "row") == 0)
|
||||
{
|
||||
shifts.row = from;
|
||||
masks.row = pow(2.0, to + 1.0) - pow(2.0, from + 0.0);
|
||||
amount.row = pow(2.0, to - from + 1.0);
|
||||
}
|
||||
else if (std::strcmp(child->Name(), "column") == 0)
|
||||
{
|
||||
shifts.column = from;
|
||||
masks.column = pow(2.0, to + 1.0) - pow(2.0, from + 0.0);
|
||||
amount.column = pow(2.0, to - from + 1.0);
|
||||
}
|
||||
else if (std::strcmp(child->Name(), "bytes") == 0)
|
||||
{
|
||||
shifts.bytes = from;
|
||||
masks.bytes = pow(2.0, to + 1.0) - pow(2.0, from + 0.0);
|
||||
amount.bytes = pow(2.0, to - from + 1.0);
|
||||
}
|
||||
else
|
||||
SC_REPORT_FATAL("XmlAddressDecoder", ("Unknown field " + std::string(child->Name())).c_str());
|
||||
}
|
||||
|
||||
banksPerGroup = amount.bank;
|
||||
amount.bank = banksPerGroup * amount.bankgroup * amount.rank;
|
||||
|
||||
bankgroupsPerRank = amount.bankgroup;
|
||||
amount.bankgroup = bankgroupsPerRank * amount.rank;
|
||||
|
||||
maximumAddress = amount.bytes * amount.column * amount.row * banksPerGroup * bankgroupsPerRank * amount.rank * amount.channel - 1;
|
||||
|
||||
Configuration &config = Configuration::getInstance();
|
||||
MemSpec *memSpec = config.memSpec;
|
||||
|
||||
if (config.numberOfMemChannels != amount.channel || memSpec->numberOfRanks != amount.rank
|
||||
|| memSpec->numberOfBankGroups != amount.bankgroup || memSpec->numberOfBanks != amount.bank
|
||||
|| memSpec->numberOfRows != amount.row || memSpec->numberOfColumns != amount.column
|
||||
|| config.numberOfDevicesOnDIMM * memSpec->bitWidth != amount.bytes * 8)
|
||||
SC_REPORT_FATAL("XmlAddressDecoder", "Memspec and addressmapping do not match");
|
||||
}
|
||||
|
||||
|
||||
DecodedAddress XmlAddressDecoder::decodeAddress(uint64_t addr)
|
||||
{
|
||||
if (addr > maximumAddress)
|
||||
SC_REPORT_WARNING("XmlAddressDecoder", ("Address " + std::to_string(addr) + " out of range (maximum address is " + std::to_string(maximumAddress) + ")").c_str());
|
||||
|
||||
DecodedAddress result;
|
||||
result.channel = (addr & masks.channel) >> shifts.channel;
|
||||
result.rank = (addr & masks.rank) >> shifts.rank;
|
||||
result.bankgroup = ((addr & masks.bankgroup) >> shifts.bankgroup)
|
||||
+ result.rank * bankgroupsPerRank;
|
||||
result.bank = ((addr & masks.bank) >> shifts.bank)
|
||||
+ result.bankgroup * banksPerGroup;
|
||||
result.row = (addr & masks.row) >> shifts.row;
|
||||
result.column = (addr & masks.column) >> shifts.column;
|
||||
result.bytes = (addr & masks.bytes) >> shifts.bytes;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t XmlAddressDecoder::encodeAddress(DecodedAddress n)
|
||||
{
|
||||
return (n.channel << shifts.channel) |
|
||||
(n.rank << shifts.rank) |
|
||||
((n.bankgroup % bankgroupsPerRank) << shifts.bankgroup) |
|
||||
((n.bank % banksPerGroup) << shifts.bank) |
|
||||
(n.row << shifts.row) |
|
||||
(n.column << shifts.column) |
|
||||
(n.bytes << shifts.bytes);
|
||||
}
|
||||
|
||||
bool XmlAddressDecoder::testConfigFile(std::string url)
|
||||
{
|
||||
// Simple test if the root node has the correct name.
|
||||
// This is suitable for now, but can be extended in future.
|
||||
|
||||
tinyxml2::XMLDocument doc;
|
||||
loadXML(url, doc);
|
||||
tinyxml2::XMLElement *addressMap = doc.RootElement();
|
||||
|
||||
return (strcmp(addressMap->Name(), "addressmapping") == 0);
|
||||
}
|
||||
|
||||
void XmlAddressDecoder::print()
|
||||
{
|
||||
std::cout << headline << std::endl;
|
||||
std::cout << "Address Mapping:" << std::endl << std::endl;
|
||||
std::cout << " channel: " << std::bitset<64>(masks.channel) << std::endl;
|
||||
std::cout << " rank: " << std::bitset<64>(masks.rank) << std::endl;
|
||||
std::cout << " bankgroup: " << std::bitset<64>(masks.bankgroup) << std::endl;
|
||||
std::cout << " bank: " << std::bitset<64>(masks.bank) << std::endl;
|
||||
std::cout << " row: " << std::bitset<64>(masks.row) << std::endl;
|
||||
std::cout << " column: " << std::bitset<64>(masks.column) << std::endl;
|
||||
std::cout << " bytes: " << std::bitset<64>(masks.bytes) << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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:
|
||||
* Janik Schlemminger
|
||||
* Robert Gernhardt
|
||||
* Matthias Jung
|
||||
*/
|
||||
|
||||
#ifndef XMLADDRESSDECODER_H
|
||||
#define XMLADDRESSDECODER_H
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "third_party/tinyxml2/tinyxml2.h"
|
||||
#include "AddressDecoder.h"
|
||||
|
||||
class XmlAddressDecoder : private AddressDecoder
|
||||
{
|
||||
// Friendship needed so that the AddressDecoder can access the
|
||||
// constructor of this class to create the object in CreateInstance.
|
||||
friend class AddressDecoder;
|
||||
|
||||
private:
|
||||
struct Masks
|
||||
{
|
||||
uint64_t channel = 0;
|
||||
uint64_t rank = 0;
|
||||
uint64_t bankgroup = 0;
|
||||
uint64_t bank = 0;
|
||||
uint64_t row = 0;
|
||||
uint64_t column = 0;
|
||||
uint64_t bytes = 0;
|
||||
} masks;
|
||||
|
||||
struct Shifts
|
||||
{
|
||||
unsigned channel = 0;
|
||||
unsigned rank = 0;
|
||||
unsigned bankgroup = 0;
|
||||
unsigned bank = 0;
|
||||
unsigned row = 0;
|
||||
unsigned column = 0;
|
||||
unsigned bytes = 0;
|
||||
} shifts;
|
||||
|
||||
unsigned banksPerGroup;
|
||||
unsigned banksPerRank;
|
||||
unsigned bankgroupsPerRank;
|
||||
|
||||
tinyxml2::XMLElement *addressmapping;
|
||||
uint64_t maximumAddress;
|
||||
|
||||
public:
|
||||
XmlAddressDecoder();
|
||||
|
||||
virtual DecodedAddress decodeAddress(uint64_t addr);
|
||||
virtual uint64_t encodeAddress(DecodedAddress n);
|
||||
|
||||
void setConfiguration(std::string url);
|
||||
|
||||
static bool testConfigFile(std::string url);
|
||||
|
||||
public:
|
||||
virtual void print();
|
||||
};
|
||||
|
||||
#endif // XMLADDRESSDECODER_H
|
||||
@@ -40,7 +40,6 @@
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "ConfigurationLoader.h"
|
||||
#include "../common/XmlAddressDecoder.h"
|
||||
|
||||
std::string Configuration::memspecUri = "";
|
||||
std::string Configuration::mcconfigUri = "";
|
||||
@@ -230,28 +229,13 @@ std::uint64_t Configuration::getSimMemSizeInBytes()
|
||||
// The bus width is given in bits, e.g., 64-bit data bus, 128-bit data bus, etc.
|
||||
unsigned int Configuration::getDataBusWidth()
|
||||
{
|
||||
unsigned int dataBusWidth = memSpec->bitWidth * numberOfDevicesOnDIMM;
|
||||
assert(dataBusWidth > 0);
|
||||
return dataBusWidth;
|
||||
return memSpec->bitWidth * numberOfDevicesOnDIMM;
|
||||
}
|
||||
|
||||
// Returns the number of bytes transfered in a burst
|
||||
unsigned int Configuration::getBytesPerBurst()
|
||||
{
|
||||
// First multiply to get the number of bits in a burst, then divide by 8 to get the value in bytes. The order is important. Think on a single x4 device.
|
||||
unsigned int bytesPerBurst = (memSpec->burstLength * getDataBusWidth()) / 8;
|
||||
assert(bytesPerBurst > 0);
|
||||
|
||||
if (numberOfDevicesOnDIMM > 1) {
|
||||
// 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 =
|
||||
AddressDecoder::getInstance().amount.bytes;
|
||||
assert(bytesPerBurst == (burstElementSizeInBytes * memSpec->burstLength));
|
||||
}
|
||||
|
||||
return bytesPerBurst;
|
||||
return (memSpec->burstLength * getDataBusWidth()) / 8;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include "ECC/ECC.h"
|
||||
|
||||
#include "../common/XmlAddressDecoder.h"
|
||||
#include "../common/DebugManager.h"
|
||||
|
||||
class ECCBaseClass : sc_module
|
||||
|
||||
@@ -36,10 +36,13 @@
|
||||
#include "errormodel.h"
|
||||
#include "../common/DebugManager.h"
|
||||
#include "../simulation/TemperatureController.h"
|
||||
#include "../common/AddressDecoder.h"
|
||||
#include "../common/dramExtensions.h"
|
||||
|
||||
#include <random>
|
||||
#include <chrono>
|
||||
#include <bitset>
|
||||
#include <cmath>
|
||||
|
||||
void errorModel::init()
|
||||
{
|
||||
@@ -48,7 +51,7 @@ void errorModel::init()
|
||||
// Get Configuration parameters:
|
||||
burstLenght = Configuration::getInstance().memSpec->burstLength;
|
||||
numberOfColumns = Configuration::getInstance().memSpec->numberOfColumns;
|
||||
bytesPerColumn = AddressDecoder::getInstance().amount.bytes;
|
||||
bytesPerColumn = std::log2(Configuration::getInstance().getDataBusWidth());
|
||||
|
||||
// Adjust number of bytes per column dynamically to the selected ecc controller
|
||||
bytesPerColumn = Configuration::getInstance().adjustNumBytesAfterECC(
|
||||
@@ -60,9 +63,8 @@ void errorModel::init()
|
||||
|
||||
// Initialize the lastRow Access array:
|
||||
lastRowAccess = new sc_time[numberOfRows];
|
||||
for (unsigned int i = 0; i < numberOfRows; i++) {
|
||||
for (unsigned int i = 0; i < numberOfRows; i++)
|
||||
lastRowAccess[i] = SC_ZERO_TIME;
|
||||
}
|
||||
|
||||
// The name is set when the context is clear.
|
||||
contextStr = "";
|
||||
@@ -155,15 +157,17 @@ void errorModel::store(tlm::tlm_generic_payload &trans)
|
||||
// Check wich bits have flipped during the last access and mark them as flipped:
|
||||
markBitFlips();
|
||||
|
||||
// Get the key for the dataMap from the transaction's address:
|
||||
DecodedAddress key = AddressDecoder::getInstance().decodeAddress(
|
||||
trans.get_address());
|
||||
// Get the key for the dataMap from the transaction's dram extension:
|
||||
DramExtension &ext = DramExtension::getExtension(trans);
|
||||
DecodedAddress key = DecodedAddress(ext.getChannel().ID(), ext.getRank().ID(),
|
||||
ext.getBankGroup().ID(), ext.getBank().ID(),
|
||||
ext.getRow().ID(), ext.getColumn().ID(), 0);
|
||||
// Set context:
|
||||
setContext(key);
|
||||
|
||||
std::stringstream msg;
|
||||
msg << "bank: " << key.bank << " group: " << key.bankgroup << " bytes: " <<
|
||||
key.bytes << " channel: " << key.channel << " column: " << key.column <<
|
||||
key.byte << " channel: " << key.channel << " column: " << key.column <<
|
||||
" rank: " << key.rank << " row: " << key.row;
|
||||
PRINTDEBUGMESSAGE(name(), msg.str());
|
||||
|
||||
@@ -221,9 +225,11 @@ void errorModel::load(tlm::tlm_generic_payload &trans)
|
||||
// Check wich bits have flipped during the last access and mark them as flipped:
|
||||
markBitFlips();
|
||||
|
||||
// Get the key for the dataMap from the transaction's address:
|
||||
DecodedAddress key = AddressDecoder::getInstance().decodeAddress(
|
||||
trans.get_address());
|
||||
// Get the key for the dataMap from the transaction's dram extension:
|
||||
DramExtension &ext = DramExtension::getExtension(trans);
|
||||
DecodedAddress key = DecodedAddress(ext.getChannel().ID(), ext.getRank().ID(),
|
||||
ext.getBankGroup().ID(), ext.getBank().ID(),
|
||||
ext.getRow().ID(), ext.getColumn().ID(), 0);
|
||||
|
||||
// Set context:
|
||||
setContext(key);
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include <iostream>
|
||||
#include <systemc.h>
|
||||
#include "../configuration/Configuration.h"
|
||||
#include "../common/XmlAddressDecoder.h"
|
||||
#include "../common/AddressDecoder.h"
|
||||
#include "../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h"
|
||||
|
||||
class errorModel : public sc_module
|
||||
@@ -113,13 +113,15 @@ private:
|
||||
weakCell *weakCells;
|
||||
|
||||
// To use a map for storing the data a comparing function must be defined
|
||||
struct DecodedAddressComparer {
|
||||
bool operator()( const DecodedAddress &first ,
|
||||
struct DecodedAddressComparer
|
||||
{
|
||||
bool operator() (const DecodedAddress &first ,
|
||||
const DecodedAddress &second) const
|
||||
{
|
||||
uint64_t addrFirst = AddressDecoder::getInstance().encodeAddress(first);
|
||||
uint64_t addrSecond = AddressDecoder::getInstance().encodeAddress(second);
|
||||
return addrFirst < addrSecond;
|
||||
if (first.row == second.row)
|
||||
return first.column < second.column;
|
||||
else
|
||||
return first.row < second.row;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -36,10 +36,11 @@
|
||||
*/
|
||||
|
||||
#include "Arbiter.h"
|
||||
#include "../common/AddressDecoder.h"
|
||||
|
||||
using namespace tlm;
|
||||
|
||||
Arbiter::Arbiter(sc_module_name name) :
|
||||
Arbiter::Arbiter(sc_module_name name, std::string pathToAddressMapping) :
|
||||
sc_module(name), payloadEventQueue(this, &Arbiter::peqCallback)
|
||||
{
|
||||
// The arbiter communicates with one or more memory unity through one or more sockets (one or more memory channels).
|
||||
@@ -60,6 +61,9 @@ Arbiter::Arbiter(sc_module_name name) :
|
||||
tSocket.register_nb_transport_fw(this, &Arbiter::nb_transport_fw);
|
||||
|
||||
tSocket.register_transport_dbg(this, &Arbiter::transport_dbg);
|
||||
|
||||
addressDecoder = new AddressDecoder(pathToAddressMapping);
|
||||
addressDecoder->print();
|
||||
}
|
||||
|
||||
// Initiated by initiator side
|
||||
@@ -114,8 +118,7 @@ unsigned int Arbiter::transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans)
|
||||
trans.set_address(trans.get_address() -
|
||||
Configuration::getInstance().addressOffset);
|
||||
|
||||
DecodedAddress decodedAddress = AddressDecoder::getInstance().decodeAddress(
|
||||
trans.get_address());
|
||||
DecodedAddress decodedAddress = addressDecoder->decodeAddress(trans.get_address());
|
||||
return iSocket[decodedAddress.channel]->transport_dbg(trans);
|
||||
}
|
||||
|
||||
@@ -213,33 +216,11 @@ void Arbiter::appendDramExtension(int socketId, tlm_generic_payload &payload)
|
||||
payload.set_auto_extension(genExtension);
|
||||
|
||||
unsigned int burstlength = payload.get_streaming_width();
|
||||
DecodedAddress decodedAddress = AddressDecoder::getInstance().decodeAddress(payload.get_address());
|
||||
// Check the valid range of decodedAddress
|
||||
if (addressIsValid(decodedAddress)) {
|
||||
DramExtension *extension = new DramExtension(Thread(socketId),
|
||||
Channel(decodedAddress.channel), Rank(decodedAddress.rank),
|
||||
BankGroup(decodedAddress.bankgroup), Bank(decodedAddress.bank),
|
||||
Row(decodedAddress.row), Column(decodedAddress.column),
|
||||
burstlength, nextPayloadID[decodedAddress.channel]++);
|
||||
payload.set_auto_extension(extension);
|
||||
} else {
|
||||
SC_REPORT_FATAL("Arbiter", "Decoded Address is not inside the valid range");
|
||||
}
|
||||
}
|
||||
|
||||
bool Arbiter::addressIsValid(DecodedAddress &decodedAddress)
|
||||
{
|
||||
if (decodedAddress.channel >= AddressDecoder::getInstance().amount.channel)
|
||||
return false;
|
||||
if (decodedAddress.rank >= AddressDecoder::getInstance().amount.rank)
|
||||
return false;
|
||||
if (decodedAddress.bankgroup >= AddressDecoder::getInstance().amount.bankgroup)
|
||||
return false;
|
||||
if (decodedAddress.bank >= AddressDecoder::getInstance().amount.bank)
|
||||
return false;
|
||||
if (decodedAddress.row >= AddressDecoder::getInstance().amount.row)
|
||||
return false;
|
||||
if (decodedAddress.column >= AddressDecoder::getInstance().amount.column)
|
||||
return false;
|
||||
return true;
|
||||
DecodedAddress decodedAddress = addressDecoder->decodeAddress(payload.get_address());
|
||||
DramExtension *extension = new DramExtension(Thread(socketId),
|
||||
Channel(decodedAddress.channel), Rank(decodedAddress.rank),
|
||||
BankGroup(decodedAddress.bankgroup), Bank(decodedAddress.bank),
|
||||
Row(decodedAddress.row), Column(decodedAddress.column),
|
||||
burstlength, nextPayloadID[decodedAddress.channel]++);
|
||||
payload.set_auto_extension(extension);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
#include <tlm_utils/multi_passthrough_target_socket.h>
|
||||
#include <tlm_utils/multi_passthrough_initiator_socket.h>
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
#include "../common/XmlAddressDecoder.h"
|
||||
#include "../common/AddressDecoder.h"
|
||||
#include "../common/dramExtensions.h"
|
||||
#include "../configuration/ConfigurationLoader.h"
|
||||
|
||||
@@ -56,10 +56,12 @@ public:
|
||||
tlm_utils::multi_passthrough_initiator_socket<Arbiter> iSocket;
|
||||
tlm_utils::multi_passthrough_target_socket<Arbiter> tSocket;
|
||||
|
||||
Arbiter(sc_module_name);
|
||||
Arbiter(sc_module_name, std::string);
|
||||
SC_HAS_PROCESS(Arbiter);
|
||||
|
||||
private:
|
||||
AddressDecoder *addressDecoder;
|
||||
|
||||
tlm_utils::peq_with_cb_and_phase<Arbiter> payloadEventQueue;
|
||||
|
||||
std::vector<bool> channelIsFree;
|
||||
@@ -93,8 +95,6 @@ private:
|
||||
|
||||
void appendDramExtension(int socketId, tlm::tlm_generic_payload &payload);
|
||||
std::vector<uint64_t> nextPayloadID;
|
||||
|
||||
bool addressIsValid(DecodedAddress &decodedAddress);
|
||||
};
|
||||
|
||||
#endif // ARBITER_H
|
||||
|
||||
@@ -44,10 +44,9 @@
|
||||
|
||||
#include "DRAMSys.h"
|
||||
#include "Setup.h"
|
||||
#include "../common/third_party/tinyxml2/tinyxml2.h"
|
||||
#include "../common/TlmRecorder.h"
|
||||
#include "../common/DebugManager.h"
|
||||
#include "../common/XmlAddressDecoder.h"
|
||||
#include "../common/CongenAddressDecoder.h"
|
||||
#include "../configuration/ConfigurationLoader.h"
|
||||
#include "../common/utils.h"
|
||||
#include "../simulation/TemperatureController.h"
|
||||
@@ -81,7 +80,6 @@ DRAMSys::DRAMSys(sc_module_name name,
|
||||
std::string simconfig;
|
||||
std::string thermalconfig;
|
||||
|
||||
// TODO: Setup never used?
|
||||
Setup setup(simulationToRun,
|
||||
memspec,
|
||||
mcconfig,
|
||||
@@ -112,25 +110,6 @@ DRAMSys::DRAMSys(sc_module_name name,
|
||||
+ "configs/thermalsim/"
|
||||
+ thermalconfig);
|
||||
|
||||
// Load addressmapping
|
||||
if (XmlAddressDecoder::testConfigFile(pathToResources + "configs/amconfigs/" +
|
||||
amconfig)) {
|
||||
AddressDecoder::createInstance(AddressDecoder::Type::XML);
|
||||
AddressDecoder::getInstance().setConfiguration(pathToResources
|
||||
+ "configs/amconfigs/"
|
||||
+ amconfig);
|
||||
} else if (CongenAddressDecoder::testConfigFile(pathToResources +
|
||||
"configs/amconfigs/" + amconfig)) {
|
||||
AddressDecoder::createInstance(AddressDecoder::Type::CONGEN);
|
||||
AddressDecoder::getInstance().setConfiguration(pathToResources
|
||||
+ "configs/amconfigs/"
|
||||
+ amconfig);
|
||||
} else {
|
||||
throw std::runtime_error("No address mapping loaded. Unsupported file format");
|
||||
}
|
||||
|
||||
AddressDecoder::getInstance().print();
|
||||
|
||||
// Setup the debug manager:
|
||||
setupDebugManager(Configuration::getInstance().simulationName);
|
||||
|
||||
@@ -153,8 +132,9 @@ DRAMSys::DRAMSys(sc_module_name name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiate all internal DRAMSys modules:
|
||||
instantiateModules(simName, pathToResources);
|
||||
instantiateModules(simName, pathToResources, amconfig);
|
||||
// Connect all internal DRAMSys modules:
|
||||
bindSockets();
|
||||
|
||||
@@ -163,8 +143,8 @@ DRAMSys::DRAMSys(sc_module_name name,
|
||||
|
||||
void DRAMSys::logo()
|
||||
{
|
||||
#define REDTXT(s) std::string("\033[0;31m"+std::string(s)+"\033[0m")
|
||||
#define BOLDBLUETXT(s) std::string("\033[1;34m"+std::string(s)+"\033[0m")
|
||||
#define REDTXT(s) std::string("\033[0;31m" + std::string(s) + "\033[0m")
|
||||
#define BOLDBLUETXT(s) std::string("\033[1;34m" + std::string(s) + "\033[0m")
|
||||
std::cout << std::endl;
|
||||
std::cout << REDTXT(" |||") << std::endl;
|
||||
std::cout << REDTXT(" +---+ Microelectronic Systems") << std::endl;
|
||||
@@ -172,7 +152,7 @@ void DRAMSys::logo()
|
||||
std::cout << REDTXT("=| |= ") << BOLDBLUETXT("University of Kaiserslautern")
|
||||
<< std::endl;
|
||||
std::cout << REDTXT(" +---+ ") << std::endl;
|
||||
std::cout << REDTXT(" ||| ") << "DRAMSys v4.0" << std::endl;
|
||||
std::cout << REDTXT(" ||| ") << "DRAMSys4.0" << std::endl;
|
||||
std::cout << std::endl;
|
||||
#undef REDTXT
|
||||
#undef BOLDBLUETXT
|
||||
@@ -180,7 +160,7 @@ void DRAMSys::logo()
|
||||
|
||||
void DRAMSys::setupDebugManager(const std::string &traceName __attribute__((unused)))
|
||||
{
|
||||
#ifdef DEBUGGING
|
||||
#ifndef NDEBUG
|
||||
auto &dbg = DebugManager::getInstance();
|
||||
dbg.writeToConsole = false;
|
||||
dbg.writeToFile = true;
|
||||
@@ -219,7 +199,8 @@ void DRAMSys::setupTlmRecorders(const std::string &traceName,
|
||||
}
|
||||
|
||||
void DRAMSys::instantiateModules(const std::string &traceName,
|
||||
const std::string &pathToResources)
|
||||
const std::string &pathToResources,
|
||||
const std::string &amconfig)
|
||||
{
|
||||
// The first call to getInstance() creates the Temperature Controller.
|
||||
// The same instance will be accessed by all other modules.
|
||||
@@ -243,7 +224,7 @@ void DRAMSys::instantiateModules(const std::string &traceName,
|
||||
Configuration::getInstance().pECC = ecc;
|
||||
|
||||
// Create arbiter
|
||||
arbiter = new Arbiter("arbiter");
|
||||
arbiter = new Arbiter("arbiter", pathToResources + "configs/amconfigs/" + amconfig);
|
||||
|
||||
// Create DRAM
|
||||
std::string memoryType = Configuration::getInstance().memSpec->memoryType;
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
#include "ReorderBuffer.h"
|
||||
#include <tlm_utils/multi_passthrough_target_socket.h>
|
||||
#include <tlm_utils/multi_passthrough_initiator_socket.h>
|
||||
#include "../common/third_party/tinyxml2/tinyxml2.h"
|
||||
#include "../common/tlm2_base_protocol_checker.h"
|
||||
#include "../error/eccbaseclass.h"
|
||||
#include "../controller/ControllerIF.h"
|
||||
@@ -103,7 +102,8 @@ private:
|
||||
void setupTlmRecorders(const std::string &traceName,
|
||||
const std::string &pathToResources);
|
||||
void instantiateModules(const std::string &traceName,
|
||||
const std::string &pathToResources);
|
||||
const std::string &pathToResources,
|
||||
const std::string &amconfig);
|
||||
void bindSockets();
|
||||
void setupDebugManager(const std::string &traceName);
|
||||
};
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* 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:
|
||||
* Felipe S. Prado
|
||||
* Matthias Jung
|
||||
*/
|
||||
|
||||
#ifndef IARBITER_H
|
||||
#define IARBITER_H
|
||||
|
||||
#include <tlm.h>
|
||||
#include <systemc.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <tlm_utils/multi_passthrough_target_socket.h>
|
||||
#include <tlm_utils/multi_passthrough_initiator_socket.h>
|
||||
#include "../configuration/ConfigurationLoader.h"
|
||||
|
||||
struct IArbiter : public sc_module
|
||||
{
|
||||
public:
|
||||
tlm_utils::multi_passthrough_target_socket<IArbiter> tSocket;
|
||||
tlm_utils::multi_passthrough_initiator_socket<IArbiter> iSocket;
|
||||
|
||||
SC_CTOR(IArbiter)
|
||||
{
|
||||
// One or more devices can accesss all the memory units through the arbiter.
|
||||
// Devices' initiator sockets are bound to arbiter's target sockets.
|
||||
// As soon the arbiter receives a request in any of its target sockets it should treat and forward it to the proper memory channel.
|
||||
tSocket.register_nb_transport_fw(this, &IArbiter::nb_transport_fw);
|
||||
|
||||
// The arbiter communicates with one or more memory unity through one or more sockets (one or more memory channels).
|
||||
// Each of the arbiter's initiator sockets is bound to a memory controller's target socket.
|
||||
// Anytime an transaction comes from a memory unity to the arbiter the "bw" callback is called.
|
||||
iSocket.register_nb_transport_bw(this, &IArbiter::nb_transport_bw);
|
||||
|
||||
tSocket.register_transport_dbg(this, &IArbiter::transport_dbg);
|
||||
}
|
||||
|
||||
virtual void setTlmRecorder(TlmRecorder *recorder) = 0;
|
||||
virtual bool isOutputBufferFull(unsigned int initiatorSocket) = 0;
|
||||
virtual void incrementNumberOfOutputBufferTransactions(unsigned int
|
||||
initiatorSocket) = 0;
|
||||
|
||||
protected:
|
||||
// Initiated by initiator side
|
||||
// This function is called when an arbiter's target socket receives a transaction from a device
|
||||
virtual tlm::tlm_sync_enum nb_transport_fw(int id, tlm::tlm_generic_payload &payload,
|
||||
tlm::tlm_phase &phase, sc_time &fwDelay) = 0;
|
||||
|
||||
// Initiated by dram side
|
||||
// This function is called when an arbiter's initiator socket receives a transaction from a memory controller
|
||||
virtual tlm::tlm_sync_enum nb_transport_bw(int channelId,
|
||||
tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase, sc_time &bwDelay) = 0;
|
||||
|
||||
virtual unsigned int transport_dbg(int /*id*/,
|
||||
tlm::tlm_generic_payload &trans) = 0;
|
||||
|
||||
void appendDramExtension(int socketId, tlm::tlm_generic_payload &payload)
|
||||
{
|
||||
// Append Generation Extension
|
||||
GenerationExtension *genExtension = new GenerationExtension(clkAlign(
|
||||
sc_time_stamp(), Configuration::getInstance().ControllerClk));
|
||||
payload.set_auto_extension(genExtension);
|
||||
|
||||
unsigned int burstlength = payload.get_streaming_width();
|
||||
DecodedAddress decodedAddress = XmlAddressDecoder::getInstance().decodeAddress(
|
||||
payload.get_address());
|
||||
// Check the valid range of decodedAddress
|
||||
if (addressIsValid(decodedAddress)) {
|
||||
DramExtension *extension = new DramExtension(Thread(socketId + 1),
|
||||
Channel(decodedAddress.channel), Bank(decodedAddress.bank),
|
||||
BankGroup(decodedAddress.bankgroup), Row(decodedAddress.row),
|
||||
Column(decodedAddress.column), burstlength, 0);
|
||||
payload.set_auto_extension(extension);
|
||||
} else {
|
||||
SC_REPORT_FATAL("Arbiter", "Decoded Address are not inside the valid range");
|
||||
}
|
||||
}
|
||||
|
||||
bool addressIsValid(DecodedAddress &decodedAddress)
|
||||
{
|
||||
if (decodedAddress.channel >=
|
||||
XmlAddressDecoder::getInstance().amount.channel) {
|
||||
return false;
|
||||
}
|
||||
if (decodedAddress.bank >= XmlAddressDecoder::getInstance().amount.bank) {
|
||||
return false;
|
||||
}
|
||||
// if (decodedAddress.bankgroup >
|
||||
// XmlAddressDecoder::getInstance().amount["bankgroup"]) {
|
||||
// return false;
|
||||
// }
|
||||
if (decodedAddress.column >=
|
||||
XmlAddressDecoder::getInstance().amount.column) {
|
||||
return false;
|
||||
}
|
||||
if (decodedAddress.row >= XmlAddressDecoder::getInstance().amount.row) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // IARBITER_H
|
||||
@@ -39,11 +39,14 @@
|
||||
#include "../configuration/Configuration.h"
|
||||
#include <iostream>
|
||||
|
||||
MemoryManager::MemoryManager(): numberOfAllocations(0), numberOfFrees(0) {}
|
||||
using namespace tlm;
|
||||
|
||||
MemoryManager::MemoryManager()
|
||||
: numberOfAllocations(0), numberOfFrees(0) {}
|
||||
|
||||
MemoryManager::~MemoryManager()
|
||||
{
|
||||
for (gp *payload : freePayloads) {
|
||||
for (tlm_generic_payload *payload : freePayloads) {
|
||||
delete[] payload->get_data_ptr();
|
||||
delete payload;
|
||||
numberOfFrees++;
|
||||
@@ -54,11 +57,11 @@ MemoryManager::~MemoryManager()
|
||||
//PRINTDEBUGMESSAGE("MemoryManager","Number of freed payloads: " + to_string(numberOfFrees));
|
||||
}
|
||||
|
||||
gp *MemoryManager::allocate()
|
||||
tlm_generic_payload *MemoryManager::allocate()
|
||||
{
|
||||
if (freePayloads.empty()) {
|
||||
numberOfAllocations++;
|
||||
gp *payload = new gp(this);
|
||||
tlm_generic_payload *payload = new tlm_generic_payload(this);
|
||||
|
||||
// Allocate a data buffer and initialize it with zeroes:
|
||||
unsigned int dataLength = Configuration::getInstance().getBytesPerBurst();
|
||||
@@ -68,13 +71,13 @@ gp *MemoryManager::allocate()
|
||||
payload->set_data_ptr(data);
|
||||
return payload;
|
||||
} else {
|
||||
gp *result = freePayloads.back();
|
||||
tlm_generic_payload *result = freePayloads.back();
|
||||
freePayloads.pop_back();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryManager::free(gp *payload)
|
||||
void MemoryManager::free(tlm_generic_payload *payload)
|
||||
{
|
||||
payload->reset(); // clears all extensions
|
||||
freePayloads.push_back(payload);
|
||||
|
||||
@@ -39,20 +39,19 @@
|
||||
|
||||
#include <tlm.h>
|
||||
#include <vector>
|
||||
typedef tlm::tlm_generic_payload gp;
|
||||
|
||||
class MemoryManager : public tlm::tlm_mm_interface
|
||||
{
|
||||
public:
|
||||
MemoryManager();
|
||||
virtual ~MemoryManager();
|
||||
virtual gp *allocate();
|
||||
virtual void free(gp *payload);
|
||||
virtual tlm::tlm_generic_payload *allocate();
|
||||
virtual void free(tlm::tlm_generic_payload *payload);
|
||||
|
||||
private:
|
||||
unsigned int numberOfAllocations;
|
||||
unsigned int numberOfFrees;
|
||||
std::vector<gp *> freePayloads;
|
||||
std::vector<tlm::tlm_generic_payload *> freePayloads;
|
||||
};
|
||||
|
||||
#endif // MEMORYMANAGER_H
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* 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:
|
||||
* Felipe S. Prado
|
||||
* Matthias Jung
|
||||
*/
|
||||
|
||||
#ifndef SIMPLEARBITER_H
|
||||
#define SIMPLEARBITER_H
|
||||
|
||||
#include "IArbiter.h"
|
||||
#include "../common/XmlAddressDecoder.h"
|
||||
#include "../common/dramExtensions.h"
|
||||
|
||||
// Annotated References [X,Y] --> Please refer to TLM AT Cheat Sheet on README
|
||||
|
||||
struct SimpleArbiter: public IArbiter {
|
||||
public:
|
||||
SimpleArbiter(sc_module_name name) : IArbiter(name)
|
||||
{
|
||||
}
|
||||
|
||||
void setTlmRecorder(TlmRecorder *recorder)
|
||||
{
|
||||
tlmRecorder = recorder;
|
||||
}
|
||||
|
||||
virtual bool isOutputBufferFull(unsigned int /*initiatorSocket*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void incrementNumberOfOutputBufferTransactions(unsigned
|
||||
int /*initiatorSocket*/)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
TlmRecorder *tlmRecorder;
|
||||
// Initiated by initiator side
|
||||
// This function is called when an arbiter's target socket receives a transaction from a device
|
||||
virtual tlm::tlm_sync_enum nb_transport_fw(int id, tlm::tlm_generic_payload &payload,
|
||||
tlm::tlm_phase &phase, sc_time &fwDelay)
|
||||
{
|
||||
if (phase == BEGIN_REQ) {
|
||||
payload.acquire();
|
||||
// adjust address offset, e.g. for gem5 simulation
|
||||
payload.set_address(payload.get_address() -
|
||||
Configuration::getInstance().AddressOffset);
|
||||
|
||||
// In the begin request phase the socket ID is appended to the payload.
|
||||
// It will extracted from the payload and used later.
|
||||
appendDramExtension(id, payload);
|
||||
|
||||
tlmRecorder->recordArbiterPhase(payload, phase, sc_time_stamp() + fwDelay);
|
||||
tlmRecorder->recordArbiterPhase(payload, END_REQ, sc_time_stamp() + fwDelay);
|
||||
tlmRecorder->recordPhase(payload, phase, sc_time_stamp() + fwDelay);
|
||||
|
||||
// Forward Path [1.0]
|
||||
iSocket[getISocketIndex(payload)]->nb_transport_fw(payload, phase, fwDelay);
|
||||
} else if (phase == END_RESP) {
|
||||
payload.release();
|
||||
tlmRecorder->recordArbiterPhase(payload, phase, sc_time_stamp() + fwDelay);
|
||||
} else {
|
||||
SC_REPORT_FATAL("Arbiter", "Illegal phase received by initiator");
|
||||
}
|
||||
|
||||
// 4-Phase Handshake [1.1]
|
||||
// 4-Phase Handshake [1.7]
|
||||
return tlm::TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
// Initiated by dram side
|
||||
// This function is called when an arbiter's initiator socket receives a transaction from a memory controller
|
||||
virtual tlm::tlm_sync_enum nb_transport_bw(int /*channelId*/,
|
||||
tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase, sc_time &bwDelay)
|
||||
{
|
||||
tlmRecorder->recordPhase(payload, phase, bwDelay + sc_time_stamp());
|
||||
|
||||
tSocket[DramExtension::getThread(payload).ID()]->nb_transport_bw(payload,
|
||||
TPhase, bwDelay);
|
||||
|
||||
if (phase == BEGIN_RESP) {
|
||||
// Early Completion [3.1]
|
||||
tlmRecorder->recordPhase(payload, END_RESP, bwDelay + sc_time_stamp());
|
||||
tlmRecorder->recordArbiterPhase(payload, BEGIN_RESP, sc_time_stamp() + bwDelay);
|
||||
return tlm::TLM_COMPLETED;
|
||||
}
|
||||
// 4-Phase Handshake [1.3]
|
||||
return tlm::TLM_ACCEPTED;
|
||||
}
|
||||
|
||||
virtual unsigned int transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans)
|
||||
{
|
||||
// adjust address offset:
|
||||
trans.set_address(trans.get_address() -
|
||||
Configuration::getInstance().AddressOffset);
|
||||
|
||||
return iSocket[getISocketIndex(trans)]->transport_dbg(trans);
|
||||
}
|
||||
|
||||
virtual unsigned int getISocketIndex(tlm::tlm_generic_payload &payload)
|
||||
{
|
||||
return DramExtension::getBank(payload).ID();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SIMPLEARBITER_H
|
||||
@@ -40,7 +40,7 @@
|
||||
#ifndef STLPLAYER_H
|
||||
#define STLPLAYER_H
|
||||
|
||||
#include "../common/XmlAddressDecoder.h"
|
||||
#include <sstream>
|
||||
#include "TracePlayer.h"
|
||||
|
||||
template<bool relative>
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
numberOfTransactions++;
|
||||
}
|
||||
// Allocate a generic payload for this request.
|
||||
gp *payload = this->allocatePayload();
|
||||
tlm::tlm_generic_payload *payload = this->allocatePayload();
|
||||
payload->acquire();
|
||||
unsigned char *data = payload->get_data_ptr();
|
||||
|
||||
@@ -126,8 +126,8 @@ public:
|
||||
iss >> address;
|
||||
if (address.empty())
|
||||
SC_REPORT_FATAL("StlPlayer",
|
||||
("Malformed trace file. Address could not be found (line " + std::to_string(
|
||||
lineCnt) + ").").c_str());
|
||||
("Malformed trace file. Address could not be found (line "
|
||||
+ std::to_string(lineCnt) + ").").c_str());
|
||||
unsigned long long addr = std::stoull(address.c_str(), 0, 16);
|
||||
|
||||
// Get the data if necessary.
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
this->terminate();
|
||||
}
|
||||
|
||||
gp *payload = this->allocatePayload();
|
||||
tlm::tlm_generic_payload *payload = this->allocatePayload();
|
||||
payload->acquire();
|
||||
unsigned char *dataElement = new unsigned
|
||||
char[16]; // TODO: column / burst breite
|
||||
|
||||
@@ -47,11 +47,13 @@ TracePlayer::TracePlayer(sc_module_name name, TracePlayerListener *listener) :
|
||||
{
|
||||
iSocket.register_nb_transport_bw(this, &TracePlayer::nb_transport_bw);
|
||||
|
||||
if (Configuration::getInstance().storeMode != "NoStorage")
|
||||
if (Configuration::getInstance().storeMode == "NoStorage")
|
||||
storageEnabled = false;
|
||||
else
|
||||
storageEnabled = true;
|
||||
}
|
||||
|
||||
gp *TracePlayer::allocatePayload()
|
||||
tlm_generic_payload *TracePlayer::allocatePayload()
|
||||
{
|
||||
return memoryManager.allocate();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
#include "MemoryManager.h"
|
||||
#include "../configuration/Configuration.h"
|
||||
#include "../common/DebugManager.h"
|
||||
#include "../common/XmlAddressDecoder.h"
|
||||
#include "TracePlayerListener.h"
|
||||
|
||||
struct TracePlayer : public sc_module
|
||||
@@ -61,13 +60,13 @@ public:
|
||||
unsigned int getNumberOfLines(std::string pathToTrace);
|
||||
|
||||
protected:
|
||||
gp *allocatePayload();
|
||||
tlm::tlm_generic_payload *allocatePayload();
|
||||
tlm_utils::peq_with_cb_and_phase<TracePlayer> payloadEventQueue;
|
||||
void finish();
|
||||
void terminate();
|
||||
void setNumberOfTransactions(unsigned int n);
|
||||
unsigned int numberOfTransactions = 0;
|
||||
bool storageEnabled;
|
||||
bool storageEnabled = false;
|
||||
|
||||
private:
|
||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload &payload, tlm::tlm_phase &phase,
|
||||
|
||||
@@ -157,7 +157,15 @@ DramWideIO::DramWideIO(sc_module_name name) : Dram(name)
|
||||
else
|
||||
{
|
||||
if (storeMode == StorageMode::ErrorModel)
|
||||
SC_REPORT_FATAL("DramWideIO", "Error modeling without power analysis is not supported");
|
||||
{
|
||||
for (unsigned i = 0; i < memSpec->numberOfBanks; i++)
|
||||
{
|
||||
errorModel *em;
|
||||
std::string errorModelStr = "errorModel_bank" + std::to_string(i);
|
||||
em = new errorModel(errorModelStr.c_str());
|
||||
ememory.push_back(em);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user