Merge pull request #27 from EIT-Wehn/new-error
New Retention Error Model
This commit is contained in:
@@ -68,8 +68,7 @@ SOURCES += \
|
||||
src/controller/RowBufferStates.cpp \
|
||||
src/controller/scheduler/IScheduler.cpp \
|
||||
src/controller/scheduler/FifoStrict.cpp \
|
||||
src/error/nest_map.cpp \
|
||||
src/error/flip_memory.cpp
|
||||
src/error/errormodel.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/common/third_party/tinyxml2/tinyxml2.h \
|
||||
@@ -116,6 +115,7 @@ HEADERS += \
|
||||
src/simulation/ReorderBuffer.h \
|
||||
src/controller/core/configuration/MemSpec.h \
|
||||
src/simulation/StlPlayer.h \
|
||||
src/simulation/StlDataPlayer.h \
|
||||
src/simulation/TracePlayerListener.h \
|
||||
src/simulation/TraceGenerator.h \
|
||||
src/controller/core/powerdown/NoPowerDown.h \
|
||||
@@ -127,6 +127,5 @@ HEADERS += \
|
||||
src/controller/scheduler/FifoStrict.h \
|
||||
src/controller/IController.h \
|
||||
src/controller/core/configuration/ConfigurationLoader.h \
|
||||
src/error/nest_map.h \
|
||||
src/error/flip_memory.h
|
||||
src/error/errormodel.h
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
<PowerDownTimeout value="100" />
|
||||
<!-- Error Model: -->
|
||||
<ErrorChipSeed value="42" />
|
||||
<ErrorCSVFile value="../src/error/error_new.csv" />
|
||||
<ErrorStoreMode value="NoStorage" /> <!--3 Modes: NoStorage, Store (store data without errormodel), ErrorModel (store data with errormodel)-->
|
||||
<ErrorCSVFile value="../../DRAMSys/dramSys/src/error/error.csv" />
|
||||
<ErrorStoreMode value="ErrorModel" /> <!--3 Modes: NoStorage, Store (store data without errormodel), ErrorModel (store data with errormodel)-->
|
||||
<!--
|
||||
<Buswidth value="128" />
|
||||
<ReadWriteGrouping value="false" />
|
||||
|
||||
@@ -50,6 +50,11 @@ void DebugManager::printDebugMessage(string sender, string message)
|
||||
}
|
||||
}
|
||||
|
||||
void DebugManager::printMessage(string sender, string message)
|
||||
{
|
||||
cout << " at " << sc_time_stamp() << "\t in " << sender << "\t: " << message << endl;
|
||||
}
|
||||
|
||||
void DebugManager::openDebugFile(string filename)
|
||||
{
|
||||
if(debugFile)
|
||||
|
||||
@@ -55,6 +55,7 @@ public:
|
||||
bool writeToFile;
|
||||
|
||||
void printDebugMessage(std::string sender, std::string message);
|
||||
void printMessage(std::string sender, std::string message);
|
||||
void openDebugFile(std::string filename);
|
||||
|
||||
private:
|
||||
|
||||
@@ -79,6 +79,8 @@ xmlAddressDecoder::xmlAddressDecoder(XMLElement* addressmap)
|
||||
|
||||
shifts[child->Name()] = from;
|
||||
masks[child->Name()] = pow(2.0, to + 1.0) - pow(2.0, from + 0.0);
|
||||
amount[child->Name()] = pow(2.0, to - from + 1.0);
|
||||
//std::cout << child->Name() << " XXXX " << pow(2.0, to - from + 1.0) <<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,9 +62,9 @@ struct DecodedAddress
|
||||
class xmlAddressDecoder
|
||||
{
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
static tinyxml2::XMLElement* addressmapping;
|
||||
static tinyxml2::XMLElement* addressmapping;
|
||||
static inline xmlAddressDecoder& getInstance()
|
||||
{
|
||||
static xmlAddressDecoder decoder(xmlAddressDecoder::addressmapping);
|
||||
@@ -83,12 +83,15 @@ static tinyxml2::XMLElement* addressmapping;
|
||||
|
||||
|
||||
void print();
|
||||
private:
|
||||
private:
|
||||
xmlAddressDecoder(std::string URI);
|
||||
xmlAddressDecoder(tinyxml2::XMLElement* addressMap);
|
||||
|
||||
std::map<std::string, sc_dt::uint64> masks;
|
||||
std::map<std::string, unsigned int> shifts;
|
||||
|
||||
public:
|
||||
std::map<std::string, unsigned int> amount;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
24
DRAMSys/dramSys/src/error/error.csv
Normal file
24
DRAMSys/dramSys/src/error/error.csv
Normal file
@@ -0,0 +1,24 @@
|
||||
75 64 0 0 0 0
|
||||
80 64 0 0 0 0
|
||||
85 64 0 0 0 0
|
||||
89 64 0 0 0 0
|
||||
75 127 0 0 0 0
|
||||
80 127 0 0 0 0
|
||||
85 127 0 0 0 0
|
||||
89 127 2 0.03 2 0.06
|
||||
75 145 0 0 0 0
|
||||
80 145 0 0 0 0
|
||||
85 145 0 0 1 0.03
|
||||
89 145 13 0.195 3 0.09
|
||||
75 164 0 0 0 0
|
||||
80 164 0 0 0 0
|
||||
85 164 8 0.12 2 0.06
|
||||
89 164 24 0.36 4 0.12
|
||||
75 182 0 0 0 0
|
||||
80 182 0 0 1 0.03
|
||||
85 182 16 0.24 2 0.06
|
||||
89 182 41 0.615 8 0.24
|
||||
75 200 0 0 0 0
|
||||
80 200 5 0.075 3 0.09
|
||||
85 200 24 0.36 4 0.12
|
||||
89 200 67 1.005 15 0.45
|
||||
|
@@ -1,20 +0,0 @@
|
||||
75,127,0,0,0,0
|
||||
80,127,0,0,0,0
|
||||
85,127,0,0,0,0
|
||||
89,127,2,0.03,2,0.06
|
||||
75,145,0,0,0,0
|
||||
80,145,0,0,0,0
|
||||
85,145,0,0,1,0.03
|
||||
89,145,13,0.195,3,0.09
|
||||
75,164,0,0,0,0
|
||||
80,164,0,0,0,0
|
||||
85,164,8,0.12,2,0.06
|
||||
89,164,24,0.36,4,0.12
|
||||
75,182,0,0,0,0
|
||||
80,182,0,0,1,0.03
|
||||
85,182,16,0.24,2,0.06
|
||||
89,182,41,0.615,8,0.24
|
||||
75,200,0,0,0,0
|
||||
80,200,5,0.075,3,0.09
|
||||
85,200,24,0.36,4,0.12
|
||||
89,200,67,1.005,15,0.45
|
||||
|
741
DRAMSys/dramSys/src/error/errormodel.cpp
Normal file
741
DRAMSys/dramSys/src/error/errormodel.cpp
Normal file
@@ -0,0 +1,741 @@
|
||||
/*
|
||||
* 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:
|
||||
* Matthias Jung
|
||||
*/
|
||||
|
||||
#include "errormodel.h"
|
||||
#include "../common/DebugManager.h"
|
||||
#include <random>
|
||||
#include <chrono>
|
||||
#include <bitset>
|
||||
|
||||
errorModel::errorModel()
|
||||
{
|
||||
// Get Configuration parameters:
|
||||
busWidth = Configuration::getInstance().Buswidth;
|
||||
burstLenght = Configuration::getInstance().memSpec.BurstLength;
|
||||
numberOfColumns = Configuration::getInstance().memSpec.NumberOfColumns;
|
||||
bytesPerColumn = xmlAddressDecoder::getInstance().amount["bytes"];
|
||||
numberOfRows = Configuration::getInstance().memSpec.NumberOfRows;
|
||||
numberOfBitErrorEvents = 0;
|
||||
|
||||
// Initialize the lastRow Access array:
|
||||
lastRowAccess = new sc_time[numberOfRows];
|
||||
for(unsigned int i = 0; i < numberOfRows; i++)
|
||||
{
|
||||
lastRowAccess[i] = SC_ZERO_TIME;
|
||||
}
|
||||
|
||||
// The name is set when the context is clear.
|
||||
name = "";
|
||||
|
||||
// Parse data input:
|
||||
parseInputData();
|
||||
prepareWeakCells();
|
||||
|
||||
// Initialize context variables:
|
||||
myChannel = -1;
|
||||
myRank = -1;
|
||||
myBankgroup = -1;
|
||||
myBank = -1;
|
||||
|
||||
// Test 1:
|
||||
// If you want to test the function that get the number
|
||||
// of bit errors for a given temperature and time
|
||||
// uncomment the following lines:
|
||||
//
|
||||
//std::cout << "MAXTemp:" << maxTemperature << std::endl;
|
||||
//std::cout << "MAXTime:" << maxTime << std::endl;
|
||||
//getNumberOfFlips(45.0,sc_time(200.0,SC_MS));
|
||||
//getNumberOfFlips(45.0,sc_time(190.0,SC_MS));
|
||||
//getNumberOfFlips(45.0,sc_time(180.0,SC_MS));
|
||||
//getNumberOfFlips(75.0,sc_time(200.0,SC_MS));
|
||||
//getNumberOfFlips(75.0,sc_time(190.0,SC_MS));
|
||||
//getNumberOfFlips(75.0,sc_time(180.0,SC_MS));
|
||||
//getNumberOfFlips(85.0,sc_time(200.0,SC_MS));
|
||||
//getNumberOfFlips(85.0,sc_time(190.0,SC_MS));
|
||||
//getNumberOfFlips(85.0,sc_time(180.0,SC_MS));
|
||||
//getNumberOfFlips(88.0,sc_time(200.0,SC_MS));
|
||||
//getNumberOfFlips(88.0,sc_time(190.0,SC_MS));
|
||||
//getNumberOfFlips(88.0,sc_time(180.0,SC_MS));
|
||||
//getNumberOfFlips(89.0,sc_time(64.0,SC_MS));
|
||||
//getNumberOfFlips(89.0,sc_time(64.0,SC_MS));
|
||||
//getNumberOfFlips(89.0,sc_time(64.0,SC_MS));
|
||||
|
||||
// Test 2:
|
||||
// X X X
|
||||
// X 1 1
|
||||
// X 1 1
|
||||
//weakCells[0].bit = 0;
|
||||
//weakCells[0].col = 0;
|
||||
//weakCells[0].row = 0;
|
||||
//weakCells[0].dependent = true;
|
||||
|
||||
setTemperature(89);
|
||||
markBitFlips();
|
||||
}
|
||||
|
||||
errorModel::~errorModel()
|
||||
{
|
||||
// Remove all data from the dataMap:
|
||||
for (std::map<DecodedAddress, unsigned char*>::iterator it = dataMap.begin(); it != dataMap.end(); ++it )
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
// Delete all elements from the dataMap:
|
||||
dataMap.clear();
|
||||
|
||||
// Remove all data from the lastRowAccess
|
||||
delete [] lastRowAccess;
|
||||
|
||||
// Clean errorMap
|
||||
errorMap.clear();
|
||||
|
||||
// Clean list of weak cells:
|
||||
delete [] weakCells;
|
||||
|
||||
// If an access happened to a bank the numner of error events should be shown:
|
||||
if(myChannel != -1 && myBank != -1 && myBankgroup != -1 && myRank != -1 )
|
||||
{
|
||||
std::cout << name
|
||||
<< ": Number of Retention Error Events = " << numberOfBitErrorEvents
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
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 = xmlAddressDecoder::getInstance().decodeAddress(trans.get_address());
|
||||
|
||||
// Set context:
|
||||
setContext(key);
|
||||
|
||||
// Check if the provided data length is correct:
|
||||
assert((bytesPerColumn * burstLenght) == trans.get_data_length());
|
||||
|
||||
// Handle the DRAM burst,
|
||||
for (unsigned int i = 0; i < trans.get_data_length(); i+=bytesPerColumn)
|
||||
{
|
||||
unsigned char * data;
|
||||
|
||||
// Check if address is not already stored:
|
||||
if(dataMap.count(key) == 0)
|
||||
{
|
||||
// Generate a new data entry
|
||||
data = new unsigned char[bytesPerColumn];
|
||||
}
|
||||
else // In case the address was stored before:
|
||||
{
|
||||
data = dataMap[key];
|
||||
}
|
||||
|
||||
// Copy the data from the transaction to the data pointer
|
||||
memcpy(data, trans.get_data_ptr()+i, bytesPerColumn);
|
||||
|
||||
// Save part of the burst in the dataMap
|
||||
// TODO: Check if we can have double entries, is key unique?
|
||||
dataMap.insert(std::pair<DecodedAddress, unsigned char*>(key,data));
|
||||
|
||||
// Reset flipped weak cells in this area, since they are rewritten now
|
||||
for(unsigned int i = 0; i < maxNumberOfWeakCells; i++)
|
||||
{
|
||||
// If the current written column in a row has a week cell:
|
||||
if(weakCells[i].row == key.row && weakCells[i].col == key.column)
|
||||
{
|
||||
// If the bit was marked as flipped due to a retention error
|
||||
// mark it as unflipped:
|
||||
if(weakCells[i].flipped == true)
|
||||
{
|
||||
weakCells[i].flipped = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The next burst element is handled, therfore the column address must be increased
|
||||
key.column++;
|
||||
|
||||
// Check that there is no column overfow:
|
||||
assert(key.column <= numberOfColumns);
|
||||
}
|
||||
}
|
||||
|
||||
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 = xmlAddressDecoder::getInstance().decodeAddress(trans.get_address());
|
||||
|
||||
// Set context:
|
||||
setContext(key);
|
||||
|
||||
// Check if the provided data length is correct:
|
||||
assert((bytesPerColumn * burstLenght) == trans.get_data_length());
|
||||
|
||||
// Handle the DRAM burst:
|
||||
for (unsigned int i = 0; i < trans.get_data_length(); i+=bytesPerColumn)
|
||||
{
|
||||
// Check if address is not stored:
|
||||
if(dataMap.count(key) == 0)
|
||||
{
|
||||
SC_REPORT_FATAL("errormodel","Reading from an empty memory location");
|
||||
}
|
||||
|
||||
// Copy the dataMap to the transaction data pointer
|
||||
memcpy(trans.get_data_ptr()+i, dataMap[key], bytesPerColumn);
|
||||
|
||||
// The next burst element is handled, therfore the column address must be increased
|
||||
key.column++;
|
||||
|
||||
// Check that there is no column overfow:
|
||||
assert(key.column <= numberOfColumns);
|
||||
}
|
||||
}
|
||||
|
||||
void errorModel::markBitFlips()
|
||||
{
|
||||
for(unsigned int row = 0; row < Configuration::getInstance().memSpec.NumberOfRows; row++)
|
||||
{
|
||||
// Get the time interval between now and the last acivate/refresh
|
||||
sc_time interval = sc_time_stamp() - lastRowAccess[row];
|
||||
|
||||
// Obtain the number of bit flips for the current temperature and the time interval:
|
||||
unsigned int n = getNumberOfFlips(temperature, interval);
|
||||
|
||||
// Check if the current row is in the range of bit flips for this interval
|
||||
// and temperature, if yes mark it as flipped:
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
{
|
||||
// Check if Bit has marked as flipped yet, if yes mark it as flipped
|
||||
if(weakCells[i].flipped == false && weakCells[i].row == row)
|
||||
{
|
||||
std::stringstream msg;
|
||||
msg << "Maked weakCell[" << i << "] as flipped" << std::endl;
|
||||
DebugManager::getInstance().printDebugMessage(name, msg.str());
|
||||
|
||||
weakCells[i].flipped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void errorModel::refresh(unsigned int row)
|
||||
{
|
||||
// A refresh is internally composed of ACT and PRE that are executed
|
||||
// on all banks, therefore we call the activate method:
|
||||
activate(row);
|
||||
}
|
||||
|
||||
void errorModel::activate(unsigned int row)
|
||||
{
|
||||
// Check wich bits have flipped during the last access and mark them as flipped:
|
||||
markBitFlips();
|
||||
|
||||
// The Activate command is responsible that an retention error is manifested.
|
||||
// Therefore, Flip the bit in the data structure if it is marked as flipped
|
||||
// and if it is a one. Transisitons from 0 to 1 are only happening
|
||||
// in DRAM with anticells. This behavior is not implemented yet.
|
||||
for (unsigned int i=0; i < maxNumberOfWeakCells; i++)
|
||||
{
|
||||
if(weakCells[i].flipped == true && weakCells[i].row == row)
|
||||
{
|
||||
// Estimate key to access column data
|
||||
DecodedAddress key;
|
||||
key.bank = myBank;
|
||||
key.bankgroup = myBankgroup;
|
||||
key.channel = myChannel;
|
||||
key.column = weakCells[i].col;
|
||||
key.rank = myRank;
|
||||
key.row = row;
|
||||
|
||||
// Byte position in column:
|
||||
unsigned int byte = weakCells[i].bit / 8;
|
||||
|
||||
// Bit position in byte:
|
||||
unsigned int bitInByte = weakCells[i].bit % 8;
|
||||
|
||||
// Check if the bit is 1 (only 1->0 transitions are supported)
|
||||
// DRAMs based on anti cells are not supported yet by this model
|
||||
if(getBit(key,byte,bitInByte) == 1)
|
||||
{
|
||||
// Prepare bit mask: invert mask and AND it later
|
||||
unsigned char mask = pow(2, bitInByte);
|
||||
mask = ~mask;
|
||||
|
||||
// Temporal storage for modification:
|
||||
unsigned char tempByte;
|
||||
|
||||
if(weakCells[i].dependent == false)
|
||||
{
|
||||
// Load the affected byte to tempByte
|
||||
memcpy(&tempByte, dataMap[key]+byte, 1);
|
||||
|
||||
// Flip the bit:
|
||||
tempByte = (tempByte & mask);
|
||||
|
||||
// Output on the Console:
|
||||
std::stringstream msg;
|
||||
msg << "Bit Flipped!"
|
||||
<< " row: " << key.row
|
||||
<< " col: " << key.column
|
||||
<< " bit: " << weakCells[i].bit;
|
||||
DebugManager::getInstance().printDebugMessage(name, msg.str());
|
||||
|
||||
numberOfBitErrorEvents++;
|
||||
|
||||
// Copy the modified byte back to the dataMap:
|
||||
memcpy(dataMap[key]+byte, &tempByte, 1);
|
||||
}
|
||||
else // if(weakCells[i].dependent == true)
|
||||
{
|
||||
// Get the neighbourhood of the bit and store it in the
|
||||
// grid variable:
|
||||
// | 0 1 2 |
|
||||
// grid = | 3 4 5 |
|
||||
// | 6 7 8 |
|
||||
|
||||
unsigned int grid[9];
|
||||
|
||||
grid[0] = getBit(key.row-1,key.column,byte,bitInByte-1);
|
||||
grid[1] = getBit(key.row-1,key.column,byte,bitInByte );
|
||||
grid[2] = getBit(key.row-1,key.column,byte,bitInByte+1);
|
||||
|
||||
grid[3] = getBit(key.row ,key.column,byte,bitInByte-1);
|
||||
grid[4] = getBit(key.row ,key.column,byte,bitInByte );
|
||||
grid[5] = getBit(key.row ,key.column,byte,bitInByte+1);
|
||||
|
||||
grid[6] = getBit(key.row+1,key.column,byte,bitInByte-1);
|
||||
grid[7] = getBit(key.row+1,key.column,byte,bitInByte );
|
||||
grid[8] = getBit(key.row+1,key.column,byte,bitInByte+1);
|
||||
|
||||
unsigned int sum = 0;
|
||||
for(int s = 0; s < 9; s++)
|
||||
{
|
||||
sum += grid[s];
|
||||
}
|
||||
|
||||
if(sum <= 4)
|
||||
{
|
||||
// Load the affected byte to tempByte
|
||||
memcpy(&tempByte, dataMap[key]+byte, 1);
|
||||
|
||||
// Flip the bit:
|
||||
tempByte = (tempByte & mask);
|
||||
numberOfBitErrorEvents++;
|
||||
|
||||
// Copy the modified byte back to the dataMap:
|
||||
memcpy(dataMap[key]+byte, &tempByte, 1);
|
||||
|
||||
// Output on the Console:
|
||||
std::stringstream msg;
|
||||
msg << "Dependent Bit Flipped!"
|
||||
<< " row: " << key.row
|
||||
<< " col: " << key.column
|
||||
<< " bit: " << weakCells[i].bit
|
||||
<< " sum: " << sum << std::endl
|
||||
<< grid[0] << grid[1] << grid[2] << std::endl
|
||||
<< grid[3] << grid[4] << grid[5] << std::endl
|
||||
<< grid[6] << grid[7] << grid[8];
|
||||
DebugManager::getInstance().printDebugMessage(name, msg.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Output on the Console:
|
||||
std::stringstream msg;
|
||||
msg << "Dependent Bit NOT Flipped!"
|
||||
<< " row: " << key.row
|
||||
<< " col: " << key.column
|
||||
<< " bit: " << weakCells[i].bit
|
||||
<< " sum: " << sum << std::endl
|
||||
<< grid[0] << grid[1] << grid[2] << std::endl
|
||||
<< grid[3] << grid[4] << grid[5] << std::endl
|
||||
<< grid[6] << grid[7] << grid[8];
|
||||
DebugManager::getInstance().printDebugMessage(name, msg.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastRowAccess[row] = sc_time_stamp();
|
||||
}
|
||||
|
||||
// This method is used to get a bit with a key, usually for independent case:
|
||||
unsigned int errorModel::getBit(DecodedAddress key, unsigned int byteInColumn, unsigned int bitInByte)
|
||||
{
|
||||
// If the data was not writte by the produce yet it is zero:
|
||||
if(dataMap.count(key) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else // Return the value of the bit
|
||||
{
|
||||
unsigned char tempByte;
|
||||
|
||||
// Copy affected byte to a temporal variable:
|
||||
memcpy(&tempByte, dataMap[key]+byteInColumn, 1);
|
||||
unsigned char mask = pow(2, bitInByte);
|
||||
unsigned int result = (tempByte & mask) >> bitInByte;
|
||||
std::bitset<8> x(mask);
|
||||
|
||||
std::stringstream msg;
|
||||
msg << "mask = " << x
|
||||
<< " bitInByte = " << bitInByte
|
||||
<< " tempByte = " << (unsigned int)tempByte
|
||||
<< " result = " << result;
|
||||
|
||||
DebugManager::getInstance().printDebugMessage(name, msg.str());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// This method is used to get neighbourhoods, for the dependent case:
|
||||
unsigned int errorModel::getBit(int row, int column, int byteInColumn, int bitInByte)
|
||||
{
|
||||
// Border-Exception handling:
|
||||
|
||||
// Switch the byte if bit under/overflow:
|
||||
if(bitInByte < 0)
|
||||
{
|
||||
byteInColumn--;
|
||||
bitInByte = 7;
|
||||
}
|
||||
else if(bitInByte >= 8)
|
||||
{
|
||||
byteInColumn++;
|
||||
bitInByte = 0;
|
||||
}
|
||||
|
||||
// Switch the column if byte under/overflow
|
||||
if(byteInColumn < 0)
|
||||
{
|
||||
column--;
|
||||
byteInColumn = bytesPerColumn;
|
||||
}
|
||||
else if(byteInColumn >= int(byteInColumn))
|
||||
{
|
||||
column++;
|
||||
byteInColumn = 0;
|
||||
}
|
||||
|
||||
// If we switch the row we return 0 (culumn under/overflow)
|
||||
if(column < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if(column >= int(numberOfColumns))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Row over/underflow return 0
|
||||
if(row < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if(row >= int(numberOfRows))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
DecodedAddress key;
|
||||
key.bank = myBank;
|
||||
key.bankgroup = myBankgroup;
|
||||
key.channel = myChannel;
|
||||
key.rank = myRank;
|
||||
key.column = column;
|
||||
key.row = row;
|
||||
|
||||
return getBit(key, byteInColumn, bitInByte);
|
||||
}
|
||||
|
||||
void errorModel::setTemperature(double t)
|
||||
{
|
||||
temperature = t;
|
||||
}
|
||||
|
||||
void errorModel::parseInputData()
|
||||
{
|
||||
std::string fileName = Configuration::getInstance().ErrorCSVFile;
|
||||
std::ifstream inputFile(fileName);
|
||||
|
||||
if(inputFile.is_open())
|
||||
{
|
||||
std::string line;
|
||||
while(std::getline(inputFile,line))
|
||||
{
|
||||
std::istringstream iss(line);
|
||||
std::string str_temperature;
|
||||
std::string str_retentionTime;
|
||||
std::string str_mu_independent;
|
||||
std::string str_sigma_independent;
|
||||
std::string str_mu_dependent;
|
||||
std::string str_sigma_dependent;
|
||||
|
||||
// Parse file:
|
||||
iss >> str_temperature
|
||||
>> str_retentionTime
|
||||
>> str_mu_independent
|
||||
>> str_sigma_independent
|
||||
>> str_mu_dependent
|
||||
>> str_sigma_dependent;
|
||||
|
||||
double temp = std::stod(str_temperature.c_str(), 0);
|
||||
sc_time retentionTime = sc_time(std::stod(str_retentionTime.c_str(),0),SC_MS);
|
||||
|
||||
unsigned int mu_independent = std::stod(str_mu_independent.c_str(),0);
|
||||
unsigned int sigma_independent = std::stod(str_sigma_independent.c_str(),0);
|
||||
unsigned int mu_dependent = std::stod(str_mu_dependent.c_str(),0);
|
||||
unsigned int sigma_dependent = std::stod(str_sigma_dependent.c_str(),0);
|
||||
|
||||
errors e;
|
||||
|
||||
//calculate normal distribution of # of independent errors
|
||||
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
std::default_random_engine generator(seed);
|
||||
std::normal_distribution<double> distribution(mu_independent,sigma_independent);
|
||||
e.independent = ceil(distribution(generator));
|
||||
|
||||
// calculate normal distribution of # of dependent errors
|
||||
unsigned seed2 = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
std::default_random_engine generator2(seed2);
|
||||
std::normal_distribution<double> distribution2(mu_dependent,sigma_dependent);
|
||||
e.dependent = ceil(distribution2(generator2));
|
||||
|
||||
// Store parsed data to the errorMap:
|
||||
errorMap[temp][retentionTime] = e;
|
||||
|
||||
std::stringstream msg;
|
||||
msg << "Temperature = " << temp
|
||||
<< " Time = " << retentionTime
|
||||
<< " independent = " << errorMap[temp][retentionTime].independent
|
||||
<< " dependent = " << errorMap[temp][retentionTime].dependent;
|
||||
|
||||
DebugManager::getInstance().printDebugMessage(name, msg.str());
|
||||
}
|
||||
inputFile.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL("errormodel","Cannot open ErrorCSVFile");
|
||||
}
|
||||
}
|
||||
|
||||
void errorModel::prepareWeakCells()
|
||||
{
|
||||
// Get the Maxium number of weak cells by iterating over the errorMap:
|
||||
maxNumberOfWeakCells = 0;
|
||||
maxNumberOfDepWeakCells = 0;
|
||||
for( const auto &i : errorMap )
|
||||
{
|
||||
for( const auto &j : i.second )
|
||||
{
|
||||
// Get number of dependent weak cells:
|
||||
if( j.second.dependent > maxNumberOfDepWeakCells)
|
||||
{
|
||||
maxNumberOfDepWeakCells = j.second.dependent;
|
||||
}
|
||||
|
||||
// Get the total number of weak cells (independet + dependent):
|
||||
if( j.second.independent + j.second.dependent > maxNumberOfWeakCells)
|
||||
{
|
||||
maxNumberOfWeakCells = j.second.independent + j.second.dependent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the highest temperature in the error map:
|
||||
maxTemperature = 0;
|
||||
for( const auto &i : errorMap )
|
||||
{
|
||||
if(i.first > maxTemperature)
|
||||
{
|
||||
maxTemperature = i.first;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the highest time in the error map:
|
||||
maxTime = SC_ZERO_TIME;
|
||||
for( const auto &i : errorMap )
|
||||
{
|
||||
for( const auto &j : i.second )
|
||||
{
|
||||
if(j.first > maxTime)
|
||||
{
|
||||
maxTime = j.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate weak cells:
|
||||
|
||||
weakCells = new weakCell[maxNumberOfWeakCells];
|
||||
|
||||
for (unsigned int i=0; i<maxNumberOfWeakCells; i++)
|
||||
{
|
||||
unsigned int row, col, bit;
|
||||
|
||||
// Select positions of weak cells randomly, uniformly distributed:
|
||||
row = (unsigned int) (rand() % numberOfRows);
|
||||
col = (unsigned int) (rand() % numberOfColumns);
|
||||
bit = (unsigned int) (rand() % (bytesPerColumn*8));
|
||||
|
||||
// Test if weak cell has been chosen already before:
|
||||
bool found = false;
|
||||
for (unsigned int k=0; k<i; k++)
|
||||
{
|
||||
if ((weakCells[k].row==row) && (weakCells[k].col==col) && (weakCells[k].bit==bit))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If a cell was already choosen as weak we have to roll the dice again:
|
||||
if(found == true)
|
||||
{
|
||||
i--;
|
||||
}
|
||||
else
|
||||
{
|
||||
weakCells[i].row = row; // Row in the bank
|
||||
weakCells[i].col = col; // Column in the row
|
||||
weakCells[i].bit = bit; // Bit position in column
|
||||
weakCells[i].flipped = false; // Flag whether this position has already flipped
|
||||
weakCells[i].dependent = false; // init dependency flag with false, dependent cells will be estimated in the next step
|
||||
}
|
||||
}
|
||||
|
||||
// Generate dependent weak cells:
|
||||
for (unsigned int i = 1; i <= maxNumberOfDepWeakCells; i++)
|
||||
{
|
||||
unsigned int r = (rand()%maxNumberOfWeakCells);
|
||||
|
||||
// If the dependent weak cell was choosen before roll the dice again:
|
||||
if(weakCells[r].dependent == true)
|
||||
{
|
||||
i--;
|
||||
}
|
||||
else
|
||||
{
|
||||
weakCells[r].dependent = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Debug output where the weak cells are located:
|
||||
for (unsigned int i=0; i<maxNumberOfWeakCells; i++)
|
||||
{
|
||||
std::stringstream msg;
|
||||
msg << "row=" << weakCells[i].row
|
||||
<< " col=" << weakCells[i].col
|
||||
<< " bit=" << weakCells[i].bit
|
||||
<< " flip=" << weakCells[i].flipped
|
||||
<< " dep=" << weakCells[i].dependent;
|
||||
DebugManager::getInstance().printDebugMessage(name, msg.str());
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve number of flipping bits which fits best to temperature input and time since last refresh
|
||||
unsigned int errorModel::getNumberOfFlips(double temp, sc_time time)
|
||||
{
|
||||
// Check if the provided temperature and time are in a valid range that
|
||||
// is covered by the input data stored in the errorMap:
|
||||
if(temp > maxTemperature)
|
||||
{
|
||||
SC_REPORT_FATAL("errormodel","temperature out of range");
|
||||
}
|
||||
else if(time > maxTime)
|
||||
{
|
||||
SC_REPORT_FATAL("errormodel","time out of range");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find nearest temperature:
|
||||
double nearestTemperature = 0;
|
||||
for( const auto &i : errorMap )
|
||||
{
|
||||
if(i.first >= temp) // for worst case reasons we go to the next bin
|
||||
{
|
||||
nearestTemperature = i.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find nearest time:
|
||||
sc_time nearestTime;
|
||||
for( const auto &i : errorMap[nearestTemperature])
|
||||
{
|
||||
if(i.first >= time) // for worst case reasons we go to the next bin
|
||||
{
|
||||
nearestTime = i.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
errors e = errorMap[nearestTemperature][nearestTime];
|
||||
|
||||
//std::stringstream msg;
|
||||
//msg << "ACT/REF temp:" << temp
|
||||
// << " time:" << time
|
||||
// << " nearestTemp:" << nearestTemperature
|
||||
// << " nearestTime:" << nearestTime
|
||||
// << " ind:" << e.independent
|
||||
// << " dep:" << e.dependent;
|
||||
|
||||
//DebugManager::getInstance().printDebugMessage(name, msg.str());
|
||||
|
||||
return e.independent + e.dependent;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void errorModel::setContext(DecodedAddress addr)
|
||||
{
|
||||
// This function is called the first store ore load to get the context in
|
||||
// which channel, rank or bank the error model is used.
|
||||
if(myChannel == -1 && myBank == -1 && myBankgroup == -1 && myRank == -1 )
|
||||
{
|
||||
myChannel = addr.channel;
|
||||
myBank = addr.bank;
|
||||
myBankgroup = addr.bankgroup;
|
||||
myRank = addr.rank;
|
||||
|
||||
name = "Channel_" + std::to_string(myChannel) + "_Bank_" + std::to_string(myBank);
|
||||
}
|
||||
}
|
||||
135
DRAMSys/dramSys/src/error/errormodel.h
Normal file
135
DRAMSys/dramSys/src/error/errormodel.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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:
|
||||
* Matthias Jung
|
||||
*/
|
||||
|
||||
#ifndef ERRORMODEL_H
|
||||
#define ERRORMODEL_H
|
||||
#include "../controller/core/configuration/Configuration.h"
|
||||
#include "../common/xmlAddressdecoder.h"
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
class errorModel
|
||||
{
|
||||
public:
|
||||
errorModel();
|
||||
~errorModel();
|
||||
|
||||
// Access Methods:
|
||||
void store(tlm::tlm_generic_payload &trans);
|
||||
void load(tlm::tlm_generic_payload &trans);
|
||||
void refresh(unsigned int row);
|
||||
void activate(unsigned int row);
|
||||
void setTemperature(double t);
|
||||
|
||||
private:
|
||||
// Configuration Parameters:
|
||||
unsigned int busWidth;
|
||||
unsigned int burstLenght;
|
||||
unsigned int numberOfColumns;
|
||||
unsigned int bytesPerColumn;
|
||||
unsigned int numberOfRows;
|
||||
|
||||
// Name:
|
||||
std::string name;
|
||||
|
||||
// Online Parameters:
|
||||
double temperature;
|
||||
unsigned int numberOfBitErrorEvents;
|
||||
|
||||
// Private Methods:
|
||||
void parseInputData();
|
||||
void prepareWeakCells();
|
||||
void markBitFlips();
|
||||
unsigned int getNumberOfFlips(double temp, sc_time time);
|
||||
void setContext(DecodedAddress addr);
|
||||
unsigned int getBit(DecodedAddress key, unsigned int byte, unsigned int bitInByte);
|
||||
unsigned int getBit(int row, int column, int byteInColumn, int bitInByte);
|
||||
|
||||
// Input related data structures:
|
||||
|
||||
struct errors
|
||||
{
|
||||
double independent;
|
||||
double dependent;
|
||||
};
|
||||
|
||||
// temperature time number of errors
|
||||
// | | |
|
||||
std::map<double, std::map<sc_time, errors> > errorMap;
|
||||
|
||||
unsigned int maxNumberOfWeakCells;
|
||||
unsigned int maxNumberOfDepWeakCells;
|
||||
double maxTemperature;
|
||||
sc_time maxTime;
|
||||
|
||||
// Storage of weak cells:
|
||||
struct weakCell
|
||||
{
|
||||
unsigned int row;
|
||||
unsigned int col;
|
||||
unsigned int bit;
|
||||
bool flipped;
|
||||
bool dependent;
|
||||
};
|
||||
|
||||
weakCell * weakCells;
|
||||
|
||||
// To use a map for storing the data a comparing function must be defined
|
||||
struct DecodedAddressComparer
|
||||
{
|
||||
bool operator()( const DecodedAddress& first , const DecodedAddress& second) const
|
||||
{
|
||||
sc_dt::uint64 addrFirst = xmlAddressDecoder::getInstance().encodeAddress(first);
|
||||
sc_dt::uint64 addrSecond = xmlAddressDecoder::getInstance().encodeAddress(second);
|
||||
return addrFirst < addrSecond;
|
||||
}
|
||||
};
|
||||
|
||||
// The data structure stores complete column accesses
|
||||
// A DRAM burst will be splitted up in several column accesses
|
||||
// e.g. BL=4 means that 4 elements will be added to the dataMap!
|
||||
std::map<DecodedAddress, unsigned char *, DecodedAddressComparer> dataMap;
|
||||
|
||||
// An array to save when the last ACT/REF to a row happened:
|
||||
sc_time * lastRowAccess;
|
||||
|
||||
// Context Variables (will be written by the first dram access)
|
||||
int myChannel;
|
||||
int myRank;
|
||||
int myBankgroup;
|
||||
int myBank;
|
||||
};
|
||||
|
||||
#endif // ERRORMODEL_H
|
||||
@@ -1,434 +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:
|
||||
* Matthias Jung
|
||||
* Patrick Andres
|
||||
* Peter Ehses
|
||||
*/
|
||||
|
||||
#include "flip_memory.h"
|
||||
#include <time.h>
|
||||
// Console out
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
// String conversion (debugging)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <chrono>
|
||||
|
||||
#include "../common/third_party/DRAMPower/src/MemorySpecification.h"
|
||||
#include "../common/third_party/DRAMPower/src/MemCommand.h"
|
||||
#include "../controller/core/configuration/Configuration.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
void flip_memory::setBank(unsigned int b)
|
||||
{
|
||||
accordingBank = b;
|
||||
}
|
||||
|
||||
flip_memory::flip_memory()
|
||||
{
|
||||
// Initialize Random generator with current system time
|
||||
// Only do this once in a simulation
|
||||
//srand(time(NULL));
|
||||
srand(Configuration::getInstance().ErrorChipSeed); // ErrorChipSeed constant, so that errors allways at the same address
|
||||
|
||||
// Fixed values for development process
|
||||
TEMPERATURE = 90;
|
||||
|
||||
// Initialize number of bit errors
|
||||
BIT_ERR = 0;
|
||||
|
||||
// path of csv file
|
||||
errormap = new nest_map(Configuration::getInstance().ErrorCSVFile);
|
||||
|
||||
// Constants for address calculations
|
||||
ROWS_PER_BANK = Configuration::getInstance().memSpec.NumberOfRows; //8192
|
||||
COLS_PER_ROW = Configuration::getInstance().memSpec.NumberOfColumns; //changed later to variable 128
|
||||
BYTES_PER_COL = 16; //TODO changed later to variable, wie genau, mit config file oder im programm selbst
|
||||
BITS_PER_ROW = COLS_PER_ROW * BYTES_PER_COL * 8;
|
||||
|
||||
// Fill array with random addresses
|
||||
initWeakCells();
|
||||
|
||||
for(unsigned int i = 0; i < ROWS_PER_BANK; i++)
|
||||
{
|
||||
refr[i] = SC_ZERO_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
flip_memory::~flip_memory()
|
||||
{
|
||||
cout << endl << endl << endl << "Bit-Fehler: " << BIT_ERR << endl << endl << endl;
|
||||
}
|
||||
|
||||
DecodedAddress flip_memory::getUnifiedNode(unsigned int addr)
|
||||
{
|
||||
DecodedAddress n = xmlAddressDecoder::getInstance().decodeAddress(addr);
|
||||
n.channel = 0;
|
||||
n.bank = 0;
|
||||
return n;
|
||||
}
|
||||
//TODO: here get map createt on which address errors will occur, so insert here errormap from board.
|
||||
// dont forget to delete this line
|
||||
// Decide which Cells will be weak cells
|
||||
void flip_memory::initWeakCells()
|
||||
{
|
||||
unsigned int maxWeakCells = errormap->getMaxWeakCells();
|
||||
|
||||
weakCells = new unsigned int*[maxWeakCells];
|
||||
|
||||
for (unsigned int i=0; i<maxWeakCells; i++)
|
||||
{
|
||||
unsigned int row, col, bit;
|
||||
|
||||
weakCells[i] = new unsigned int[4];
|
||||
|
||||
row = (unsigned int) (rand() % ROWS_PER_BANK);
|
||||
col = (unsigned int) (rand() % COLS_PER_ROW);
|
||||
bit = (unsigned int) (rand() % (BYTES_PER_COL*8));
|
||||
|
||||
cout << "row" << row << "\t col" << col << "\t bit" << bit << endl;
|
||||
|
||||
// Avoid duplicates in weakCells[]
|
||||
bool found = false;
|
||||
|
||||
for (unsigned int k=0; k<i; k++) {
|
||||
if ((weakCells[k][0]==row) && (weakCells[k][1]==col) && (weakCells[k][2]==bit)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found == true) {
|
||||
i--;
|
||||
}
|
||||
else
|
||||
{
|
||||
weakCells[i][0] = row;
|
||||
weakCells[i][1] = col;
|
||||
weakCells[i][2] = bit; // Bit position in column
|
||||
weakCells[i][3] = 0; // Flag whether this position has already flipped
|
||||
weakCells[i][4] = 0; // init dependency flag
|
||||
}
|
||||
//cout << i << ". weak cell, at row: " << weakCells[i][0] << " and column: " << weakCells[i][1] << " and bit: " << weakCells[i][2] << endl;
|
||||
}
|
||||
|
||||
for (unsigned int i = 1; i <= errormap->getMaxDependentCells(); i++)
|
||||
{
|
||||
unsigned int r = (rand()%maxWeakCells);
|
||||
|
||||
if(weakCells[r][4] == 1)
|
||||
{
|
||||
i--;
|
||||
}
|
||||
else
|
||||
{
|
||||
weakCells[r][4] = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Debug
|
||||
for (unsigned int i=0; i<maxWeakCells; i++)
|
||||
{
|
||||
cout << "row=" << weakCells[i][0];
|
||||
cout << "\tcol=" << weakCells[i][1];
|
||||
cout << "\tbit=" << weakCells[i][2];
|
||||
cout << "\tflip=" << weakCells[i][3];
|
||||
cout << "\tdep=" << weakCells[i][4] << endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Reset "HasFlipped"-Flag, set Refresh-Timestamp
|
||||
void flip_memory::resetCell(DecodedAddress n)
|
||||
{
|
||||
unsigned int arraySize = errormap->getMaxWeakCells();
|
||||
|
||||
for (unsigned int i=0; i<arraySize; i++)
|
||||
{
|
||||
if ((weakCells[i][0] == n.row) && (weakCells[i][1] == n.column)) weakCells[i][3] = 0;
|
||||
}
|
||||
|
||||
refr[n.row] = sc_time_stamp();
|
||||
}
|
||||
|
||||
|
||||
// Store data in memory
|
||||
void flip_memory::store(tlm::tlm_generic_payload &trans)
|
||||
{
|
||||
unsigned int t_addr, t_len;
|
||||
unsigned char* t_ptr;
|
||||
|
||||
t_addr = trans.get_address();
|
||||
t_len = trans.get_data_length();
|
||||
t_ptr = trans.get_data_ptr();
|
||||
t_ptr = trans.get_data_ptr();
|
||||
|
||||
// Generate XML Node
|
||||
DecodedAddress no;
|
||||
no = getUnifiedNode(t_addr);
|
||||
|
||||
for (unsigned int i = 0; i < t_len; i+=BYTES_PER_COL)
|
||||
{
|
||||
// Store data in vector of size BYTES_PER_COL temporarily, later write to mem
|
||||
vector<unsigned char> v;
|
||||
for (unsigned int n = 0; n < BYTES_PER_COL; n++) v.push_back(*(t_ptr + i + n));
|
||||
|
||||
// Switch to next column if necessary
|
||||
if (i > 0) no.column++;
|
||||
|
||||
// Swap around if more columns addressed than exist
|
||||
if (no.column>(COLS_PER_ROW - 1)) no.column -= BURSTLENGTH*BYTES_PER_COL;
|
||||
|
||||
unsigned int addr = xmlAddressDecoder::getInstance().encodeAddress(no);
|
||||
//cout << "ADDRESSE=" << addr << endl;
|
||||
|
||||
mem.insert(pair<unsigned int, vector<unsigned char> >(addr, v));
|
||||
|
||||
// Reset weak cells; they have reliable data now till next check
|
||||
resetCell(no);
|
||||
}
|
||||
|
||||
//cout << "STORE:" << endl;
|
||||
//debugMap();
|
||||
|
||||
trans.set_response_status(TLM_OK_RESPONSE);
|
||||
}
|
||||
|
||||
|
||||
void flip_memory::load(tlm::tlm_generic_payload &trans)
|
||||
{
|
||||
unsigned int t_addr, t_len;
|
||||
unsigned char* t_ptr;
|
||||
|
||||
t_addr = trans.get_address();
|
||||
t_len = trans.get_data_length();
|
||||
t_ptr = trans.get_data_ptr();
|
||||
|
||||
// Generate XML Node
|
||||
DecodedAddress no;
|
||||
no = getUnifiedNode(t_addr);
|
||||
|
||||
|
||||
if (mem.count(t_addr) > 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < t_len; i += BYTES_PER_COL)
|
||||
{
|
||||
// Switch to next column if necessary
|
||||
if (i > 0) no.column++;
|
||||
|
||||
// Swap around if more columns addressed than exist
|
||||
if (no.column>(COLS_PER_ROW - 1)) no.column -= BURSTLENGTH*BYTES_PER_COL;
|
||||
|
||||
unsigned int addr = xmlAddressDecoder::getInstance().encodeAddress(no);
|
||||
|
||||
// Write out data
|
||||
for (unsigned int n = 0; n < BYTES_PER_COL; n++)
|
||||
{
|
||||
*(t_ptr + i + n) = mem[addr][n];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
trans.set_response_status(TLM_OK_RESPONSE);
|
||||
}
|
||||
|
||||
|
||||
// Function to trigger row refresh externally; errors are manifested
|
||||
void flip_memory::refresh(unsigned int row)
|
||||
{
|
||||
// How many Bits have flipped?
|
||||
//cout << "TEST=" << refr[row] << endl;
|
||||
sc_time deltaT = sc_time_stamp() - refr[row];
|
||||
|
||||
unsigned int n = errormap->getFlipRate(TEMPERATURE, deltaT);
|
||||
|
||||
//cout << sc_time_stamp() << ": deltaT=" << deltaT << " n=" << n << endl;
|
||||
//cout << "Flip_Memory::refresh" << endl;
|
||||
// Flip the first n Bits in array
|
||||
for (unsigned int i=0; i<n; i++) {
|
||||
// Check if Bit has not flipped yet
|
||||
if (weakCells[i][3] == 0 && weakCells[i][0] == row)
|
||||
{
|
||||
//cout << "weak3=0, weak0=row" << endl;
|
||||
DecodedAddress no;
|
||||
no = getUnifiedNode(0);
|
||||
no.row = weakCells[i][0];
|
||||
no.column = weakCells[i][1];
|
||||
|
||||
int addr = xmlAddressDecoder::getInstance().encodeAddress(no);
|
||||
int byte = weakCells[i][2] / 8; // Byte position in column
|
||||
int bit = weakCells[i][2] % 8; // Bit position in byte
|
||||
|
||||
unsigned char mask = pow(2, bit); // 1 Byte long character
|
||||
mask = ~mask; // invert mask (only one 0) and AND it later
|
||||
|
||||
// Address has already been allocated?
|
||||
if (mem.count(addr) > 0)
|
||||
{
|
||||
char memBefore = mem[addr][byte];
|
||||
//cout << "Flip1?" << endl;
|
||||
|
||||
if(getBit(no.row,no.column,byte,bit) == 1) // flip only if it is really a one
|
||||
{
|
||||
//cout << "Flip2?" << endl;
|
||||
if(weakCells[i][4] == 1) // data dependent weak cell
|
||||
{
|
||||
// 0 1 2
|
||||
// 3 4 5
|
||||
// 6 7 8
|
||||
|
||||
unsigned int grid[9];
|
||||
|
||||
grid[0] = getBit(no.row-1,no.column,byte,bit-1);
|
||||
grid[1] = getBit(no.row-1,no.column,byte,bit );
|
||||
grid[2] = getBit(no.row-1,no.column,byte,bit+1);
|
||||
|
||||
grid[3] = getBit(no.row ,no.column,byte,bit-1);
|
||||
grid[4] = getBit(no.row ,no.column,byte,bit );
|
||||
grid[5] = getBit(no.row ,no.column,byte,bit+1);
|
||||
|
||||
grid[6] = getBit(no.row+1,no.column,byte,bit-1);
|
||||
grid[7] = getBit(no.row+1,no.column,byte,bit );
|
||||
grid[8] = getBit(no.row+1,no.column,byte,bit+1);
|
||||
|
||||
unsigned int sum = 0;
|
||||
for(int s = 0; s < 9; s++)
|
||||
{
|
||||
sum += grid[s];
|
||||
}
|
||||
|
||||
if(sum <= 4)
|
||||
{
|
||||
mem[addr][byte] &= mask;
|
||||
weakCells[i][3] = 1;
|
||||
cout << sc_time_stamp() << ": Bit flipped dependent at address=" << addr << " in byte=" << byte << "sum=" << sum << endl;
|
||||
cout << grid[0] << grid[1] << grid[2] <<endl;
|
||||
cout << grid[3] << grid[4] << grid[5] <<endl;
|
||||
cout << grid[6] << grid[7] << grid[8] <<endl;
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// cout << sc_time_stamp() << ": Bit not flipped dependent at address=" << addr << " in byte=" << byte << "sum=" << sum << endl;
|
||||
//}
|
||||
}
|
||||
else // data independent weak cell
|
||||
{
|
||||
mem[addr][byte] &= mask;
|
||||
weakCells[i][3] = 1;
|
||||
cout << sc_time_stamp() << ": Bit flipped independent at address=" << addr << " in byte=" << byte << endl;
|
||||
}
|
||||
}
|
||||
char memAfter = mem[addr][byte];
|
||||
|
||||
// Data has changed?
|
||||
if (memBefore!=memAfter)
|
||||
{
|
||||
BIT_ERR++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
refr[row] = sc_time_stamp();
|
||||
}
|
||||
|
||||
unsigned int flip_memory::getBit(int r, int c, int y, int b)
|
||||
{
|
||||
// Border-Exception handling:
|
||||
|
||||
// Switch the byte if bit under/overflow
|
||||
if(b < 0)
|
||||
{
|
||||
y--;
|
||||
b = 7;
|
||||
}
|
||||
else if(b >= 8)
|
||||
{
|
||||
y++;
|
||||
b = 0;
|
||||
}
|
||||
|
||||
// Switch the column if byte under/overflow
|
||||
if(y < 0)
|
||||
{
|
||||
c--;
|
||||
y = BYTES_PER_COL;
|
||||
}
|
||||
else if(y >= int(BYTES_PER_COL))
|
||||
{
|
||||
c++;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
// If we switch the row we return 0 (culumn under/overflow)
|
||||
if(c < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if(c >= int(COLS_PER_ROW))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// row over/underflow return 0
|
||||
if(r < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if(r >= int(ROWS_PER_BANK))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calculate the address for the map
|
||||
DecodedAddress no;
|
||||
no = getUnifiedNode(0);
|
||||
no.row = r;
|
||||
no.column = c;
|
||||
unsigned int addr = xmlAddressDecoder::getInstance().encodeAddress(no);
|
||||
|
||||
if(mem.count(addr) == 0) // If the address does not exist in the map tree the bit must be 0
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else // Return the value of the bit
|
||||
{
|
||||
unsigned char byte = mem[addr][y];
|
||||
unsigned char mask = pow(2, b);
|
||||
return (byte & mask) >> b;
|
||||
}
|
||||
}
|
||||
@@ -1,111 +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:
|
||||
* Matthias Jung
|
||||
* Patrick Andres
|
||||
* Peter Ehses
|
||||
*/
|
||||
|
||||
#ifndef _FLIP_MEMORY_H
|
||||
#define _FLIP_MEMORY_H
|
||||
#include "nest_map.h"
|
||||
#include <tlm.h>
|
||||
#include <map>
|
||||
#include "../common/xmlAddressdecoder.h"
|
||||
#include "../common/third_party/DRAMPower/src/MemorySpecification.h"
|
||||
#include "../common/third_party/DRAMPower/src/MemCommand.h"
|
||||
#include "../controller/core/configuration/Configuration.h"
|
||||
|
||||
|
||||
using namespace tlm;
|
||||
using namespace std;
|
||||
|
||||
class flip_memory
|
||||
{
|
||||
private:
|
||||
// Remember to adjust this value by hand when editing in simulation
|
||||
unsigned int BUSWIDTH = Configuration::getInstance().memSpec.BusWidth; //static const unsigned int BUSWIDTH=128;
|
||||
unsigned int BURSTLENGTH = Configuration::getInstance().memSpec.BurstLength; //static const unsigned int BURSTLENGTH = 2; but in wideIO.xml its 4
|
||||
|
||||
nest_map *errormap;
|
||||
map <unsigned int, vector<unsigned char> > mem;
|
||||
map <unsigned int, sc_time> refr;
|
||||
unsigned int **weakCells;
|
||||
|
||||
// This will be an input from ICE 3D
|
||||
unsigned int TEMPERATURE;
|
||||
|
||||
unsigned int ROWS_PER_BANK;
|
||||
unsigned int COLS_PER_ROW;
|
||||
unsigned int BYTES_PER_COL;
|
||||
unsigned int BITS_PER_ROW;
|
||||
unsigned int accordingBank;
|
||||
|
||||
// Generates an XML node which is tied to one memory class instance
|
||||
DecodedAddress getUnifiedNode(unsigned int addr);
|
||||
|
||||
// Decide randomly which cells are weak
|
||||
void initWeakCells();
|
||||
|
||||
// Reset "HasFlipped"-Flag, set Refresh-Timestamp
|
||||
void resetCell(DecodedAddress n);
|
||||
|
||||
public:
|
||||
// Compute number of generated bit errors
|
||||
unsigned int BIT_ERR;
|
||||
|
||||
flip_memory();
|
||||
~flip_memory();
|
||||
void setBank(unsigned int b);
|
||||
void store(tlm::tlm_generic_payload &trans);
|
||||
void load(tlm::tlm_generic_payload &trans);
|
||||
// Trigger row refresh externally; errors are manifested
|
||||
void refresh(unsigned int row);
|
||||
unsigned int getBit(int r, int c, int y, int b);
|
||||
|
||||
void debugMap()
|
||||
{
|
||||
typedef map<unsigned int, vector<unsigned char> >::const_iterator MapIterator;
|
||||
for (MapIterator iter = mem.begin(); iter != mem.end(); iter++)
|
||||
{
|
||||
cout << "Key: " << iter->first << endl << "Values: 0x";
|
||||
typedef vector<unsigned char>::const_iterator vectorIterator;
|
||||
for (vectorIterator list_iter = iter->second.begin(); list_iter != iter->second.end(); list_iter++)
|
||||
{
|
||||
cout << " " << hex << int(*list_iter);
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
@@ -1,205 +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:
|
||||
* Matthias Jung
|
||||
* Patrick Andres
|
||||
* Peter Ehses
|
||||
*/
|
||||
|
||||
#include "nest_map.h"
|
||||
#include <limits>
|
||||
#include <chrono>
|
||||
#include <random>
|
||||
|
||||
nest_map::nest_map(string fn)
|
||||
{
|
||||
initMap(fn);
|
||||
}
|
||||
|
||||
nest_map::~nest_map(void)
|
||||
{
|
||||
delete tr;
|
||||
}
|
||||
|
||||
// Read data from CSV file with filename "fn" and store it inside the errormap instance
|
||||
void nest_map::initMap(string fn)
|
||||
{
|
||||
unsigned int noOfLines = 0;
|
||||
maxWeakCells = 0;
|
||||
maxDependentCells=0;
|
||||
string line;
|
||||
|
||||
ifstream input;
|
||||
input.open(fn.c_str(), ios::in);
|
||||
|
||||
if (input.is_open())
|
||||
{
|
||||
// Count number of entries in CSV file
|
||||
while (getline(input, line))
|
||||
{
|
||||
++noOfLines;
|
||||
}
|
||||
input.clear();
|
||||
input.seekg(0, ios::beg);
|
||||
|
||||
// Knowing the size, allocate the errormap
|
||||
size = noOfLines;
|
||||
tr = new quadrupel[noOfLines];
|
||||
|
||||
// Copy entries from CSV to errormap
|
||||
for (unsigned int i = 0; i < noOfLines; i++)
|
||||
{
|
||||
getline(input, line);
|
||||
|
||||
// "split" returns a matrix with 6 columns with temperature, retention time, number of data indipendent errors, sigma, number of data dependent errors, sigma (this order)
|
||||
vector<string> tmp = split(line, *",");
|
||||
|
||||
tr[i].T = atoi(tmp[0].c_str());
|
||||
// Don't forget to set right unit for times from CSV here
|
||||
tr[i].t = sc_time(atoi(tmp[1].c_str()), SC_MS);
|
||||
|
||||
double mean = atoi(tmp[2].c_str());
|
||||
|
||||
double sigma = atoi(tmp[3].c_str()); //(mean/100)*1.5 saved in csv file
|
||||
|
||||
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
|
||||
std::default_random_engine generator(seed);
|
||||
std::normal_distribution<double> distribution(mean,sigma);
|
||||
|
||||
tr[i].n = ceil(distribution(generator)); //calculate normal distribution of # of independent errors
|
||||
|
||||
double mean2 = atoi(tmp[4].c_str()); //data dependent errors from file reading
|
||||
double sigma2 = atoi(tmp[5].c_str()); //(mean/100)*3 from csv file
|
||||
std::default_random_engine generator2(seed);
|
||||
std::normal_distribution<double> distribution2(mean2,sigma2);
|
||||
tr[i].d = ceil(distribution2(generator2)); // calculate normal distribution of # of dependent errors
|
||||
|
||||
//print normal distribution of csv file
|
||||
//cout << "T=\t" << tr[i].T << "\t t=" << tr[i].t << "\t n=" << tr[i].n << "\t s=" << sigma << "\t d=" << tr[i].d << "\t s=" << sigma2 << endl;
|
||||
|
||||
// Search the largest entry of n in list
|
||||
if ((tr[i].n + tr[i].d)> maxWeakCells)
|
||||
{
|
||||
maxWeakCells = (tr[i].n + tr[i].d);
|
||||
}
|
||||
|
||||
if (tr[i].d > maxDependentCells)
|
||||
{
|
||||
maxDependentCells = tr[i].d;
|
||||
}
|
||||
}
|
||||
|
||||
input.close();
|
||||
}
|
||||
else cout << "Fehler beim Oeffnen der Daten" << endl;
|
||||
}
|
||||
|
||||
|
||||
// Retrieve number of flipping bits which fits best to temperature input and time since last refresh
|
||||
unsigned int nest_map::getFlipRate(unsigned int T_in, sc_time t_in)
|
||||
{
|
||||
unsigned int temperatureClosest = 0;
|
||||
unsigned int noOfWeakCells = 0;
|
||||
sc_time timeLowerBound = sc_time(0,SC_SEC);
|
||||
|
||||
// Search all entries in LUT for temperature closest to T_in
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
{
|
||||
if (abs((double)tr[i].T-(double)T_in)<abs((double)temperatureClosest-(double)T_in))
|
||||
{
|
||||
temperatureClosest = tr[i].T;
|
||||
}
|
||||
}
|
||||
|
||||
// Which time mark has already been passed?
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
{
|
||||
// Only check entries with temperature temperatureClosest
|
||||
if (tr[i].T == temperatureClosest)
|
||||
{
|
||||
if ((tr[i].t.value() > timeLowerBound.value()) && (t_in.value() >= tr[i].t.value()))
|
||||
{
|
||||
timeLowerBound = tr[i].t;
|
||||
noOfWeakCells = tr[i].n + tr[i].d;
|
||||
}
|
||||
}
|
||||
}
|
||||
return noOfWeakCells;
|
||||
}
|
||||
|
||||
|
||||
unsigned int nest_map::getMaxWeakCells()
|
||||
{
|
||||
return maxWeakCells;
|
||||
}
|
||||
|
||||
unsigned int nest_map::getMaxDependentCells()
|
||||
{
|
||||
return maxDependentCells;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Remove all spaces out of a string and split it at every occurance of char c
|
||||
vector<string> nest_map::split(string str, char c)
|
||||
{
|
||||
vector<string> tmp_v;
|
||||
string tmp_str = str;
|
||||
|
||||
// Remove spaces
|
||||
while (true)
|
||||
{
|
||||
size_t posSpace = tmp_str.find_first_of(" ");
|
||||
if (posSpace == string::npos)
|
||||
{
|
||||
break;
|
||||
}
|
||||
tmp_str.erase(posSpace, 1);
|
||||
}
|
||||
|
||||
// Split string at every occurance of char c
|
||||
while (true)
|
||||
{
|
||||
size_t pos_del = tmp_str.find_first_of(c);
|
||||
if (pos_del == string::npos)
|
||||
{
|
||||
tmp_v.push_back(tmp_str);
|
||||
break;
|
||||
}
|
||||
|
||||
tmp_v.push_back(tmp_str.substr(0, pos_del));
|
||||
tmp_str.erase(0, pos_del + 1);
|
||||
}
|
||||
|
||||
return tmp_v;
|
||||
}
|
||||
@@ -1,88 +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:
|
||||
* Matthias Jung
|
||||
* Patrick Andres
|
||||
* Peter Ehses
|
||||
*/
|
||||
|
||||
#ifndef _NEST_MAP_H
|
||||
#define _NEST_MAP_H
|
||||
|
||||
#include <systemc.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class nest_map
|
||||
{
|
||||
private:
|
||||
// Helper class to store 6 values of temperature, (retention) time, # of independent errors, sigma, # of dependent errors, sigma
|
||||
struct quadrupel
|
||||
{
|
||||
unsigned int T; //Temperature
|
||||
sc_time t; //retention time
|
||||
unsigned int n; //data independent errors
|
||||
unsigned int d; //data dependent errors
|
||||
};
|
||||
|
||||
// Array of "6 values" with dynamic size
|
||||
quadrupel *tr;
|
||||
|
||||
// Number of entrys in tr[]
|
||||
unsigned int size;
|
||||
|
||||
// Largest value of n in tr[]
|
||||
unsigned int maxWeakCells;
|
||||
unsigned int maxDependentCells;
|
||||
|
||||
// Default CSV filename
|
||||
const string def_fn;
|
||||
|
||||
void initMap(string fn);
|
||||
vector<string> split(string str, char c);
|
||||
|
||||
public:
|
||||
nest_map(string fn);
|
||||
~nest_map();
|
||||
|
||||
// Retrieve number of flipping bits which fits best to temperature input and time since last refresh
|
||||
unsigned int getFlipRate(unsigned int T, sc_time t);
|
||||
|
||||
unsigned int getMaxWeakCells();
|
||||
unsigned int getMaxDependentCells();
|
||||
};
|
||||
#endif
|
||||
@@ -51,7 +51,7 @@
|
||||
#include "../common/Utils.h"
|
||||
#include "../common/TlmRecorder.h"
|
||||
#include "../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h"
|
||||
#include "../error/flip_memory.h"
|
||||
#include "../error/errormodel.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace tlm;
|
||||
@@ -69,7 +69,7 @@ struct Dram : sc_module
|
||||
|
||||
// Error Model related:
|
||||
ErrorStorageMode ErrorStoreMode = Configuration::getInstance().ErrorStoreMode;
|
||||
flip_memory * fmemory;
|
||||
errorModel * ememory;
|
||||
|
||||
// Data Storage:
|
||||
map< unsigned long int, unsigned char[BUSWIDTH/2] > memory;
|
||||
@@ -166,9 +166,10 @@ struct Dram : sc_module
|
||||
|
||||
printDebugMessage(string("ErrorStorageMode: ") + EnumToString(ErrorStoreMode));
|
||||
|
||||
// For each bank in a channel a error Model is created:
|
||||
if(ErrorStoreMode == ErrorStorageMode::ErrorModel)
|
||||
{
|
||||
fmemory = new flip_memory[Configuration::getInstance().memSpec.NumberOfBanks];
|
||||
ememory = new errorModel[Configuration::getInstance().memSpec.NumberOfBanks];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,15 +182,9 @@ struct Dram : sc_module
|
||||
cout << name() << string("\tTotal Energy: \t") + to_string(DRAMPower->getEnergy().total_energy) << endl;
|
||||
cout << name() << string("\tAverage Power: \t") + to_string(DRAMPower->getPower().average_power) << endl;
|
||||
}
|
||||
if(ErrorStoreMode == ErrorStorageMode::ErrorModel)
|
||||
{
|
||||
for(int b = 0; b < 8; b++)
|
||||
{
|
||||
cout << "BIT_ERRORS Bank: " <<b <<"="<< fmemory[b].BIT_ERR << endl;
|
||||
}
|
||||
}
|
||||
// TODO Aufrauemen!
|
||||
//delete fmemory; // TODO Testen!
|
||||
|
||||
// Clean up:
|
||||
delete [] ememory;
|
||||
//std::cout << "Simulated Memory Size: " << memory.size() << endl; // TODO Aufrauemen
|
||||
}
|
||||
|
||||
@@ -223,7 +218,7 @@ struct Dram : sc_module
|
||||
|
||||
if (ErrorStoreMode == ErrorStorageMode::ErrorModel)
|
||||
{
|
||||
fmemory[bank].refresh(row);
|
||||
ememory[bank].activate(row);
|
||||
}
|
||||
}
|
||||
else if (phase == BEGIN_WR)
|
||||
@@ -241,7 +236,7 @@ struct Dram : sc_module
|
||||
}
|
||||
else // == 2 Use Storage with Error Model
|
||||
{
|
||||
fmemory[bank].store(payload);
|
||||
ememory[bank].store(payload);
|
||||
}
|
||||
sendToController(payload, END_WR, delay + getExecutionTime(Command::Write, payload));
|
||||
}
|
||||
@@ -263,7 +258,7 @@ struct Dram : sc_module
|
||||
}
|
||||
else if(ErrorStoreMode == ErrorStorageMode::ErrorModel)// use ErrorStorageMode with errormodel
|
||||
{
|
||||
fmemory[bank].load(payload);
|
||||
ememory[bank].load(payload);
|
||||
}
|
||||
|
||||
sendToController(payload, END_RD, delay + getExecutionTime(Command::Read, payload));
|
||||
@@ -283,7 +278,7 @@ struct Dram : sc_module
|
||||
}
|
||||
else // == 2 Use Storage with Error Model
|
||||
{
|
||||
fmemory[bank].store(payload);
|
||||
ememory[bank].store(payload);
|
||||
}
|
||||
sendToController(payload, END_WRA, delay + getExecutionTime(Command::WriteA, payload));
|
||||
}
|
||||
@@ -305,7 +300,7 @@ struct Dram : sc_module
|
||||
}
|
||||
else if(ErrorStoreMode == ErrorStorageMode::ErrorModel)// use ErrorStorageMode with errormodel
|
||||
{
|
||||
fmemory[bank].load(payload);
|
||||
ememory[bank].load(payload);
|
||||
}
|
||||
|
||||
sendToController(payload, END_RDA, delay + getExecutionTime(Command::ReadA, payload));
|
||||
@@ -318,7 +313,7 @@ struct Dram : sc_module
|
||||
|
||||
if (ErrorStoreMode == ErrorStorageMode::ErrorModel)
|
||||
{
|
||||
fmemory[bank].refresh(row);
|
||||
ememory[bank].refresh(row);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,7 +402,7 @@ struct Dram : sc_module
|
||||
}
|
||||
else
|
||||
{
|
||||
fmemory[bank].load(trans);
|
||||
ememory[bank].load(trans);
|
||||
}
|
||||
}
|
||||
else if ( cmd == tlm::TLM_WRITE_COMMAND )
|
||||
@@ -418,7 +413,7 @@ struct Dram : sc_module
|
||||
}
|
||||
else
|
||||
{
|
||||
fmemory[bank].store(trans);
|
||||
ememory[bank].store(trans);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
#include "../controller/core/ControllerCore.h"
|
||||
#include "../controller/core/configuration/ConfigurationLoader.h"
|
||||
#include "../common/Utils.h"
|
||||
#include "../error/flip_memory.h"
|
||||
#include "../simulation/StlDataPlayer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -107,7 +107,18 @@ void Simulation::instantiateModules(const string &traceName, const string &pathT
|
||||
{
|
||||
for (size_t i = 0; i < Configuration::getInstance().NumberOfTracePlayers; i++) {
|
||||
std::string playerStr = "player" + std::to_string(i);
|
||||
TracePlayer<> *player = new StlPlayer<>(playerStr.c_str(), pathToResources + string("traces/") + devices[i].trace, devices[i].clkMhz, this);
|
||||
TracePlayer<> *player;
|
||||
// When data should be stored during the simulation the StlDataPlayer is needed.
|
||||
// Else: no data should be stored, for instance to get a faster simulation
|
||||
// or if you simply dont care about the data the normal StlPlayer is used.
|
||||
if(Configuration::getInstance().ErrorStoreMode == ErrorStorageMode::NoStorage)
|
||||
{
|
||||
player = new StlPlayer<>(playerStr.c_str(), pathToResources + string("traces/") + devices[i].trace, devices[i].clkMhz, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
player = new StlDataPlayer<>(playerStr.c_str(), pathToResources + string("traces/") + devices[i].trace, devices[i].clkMhz, this);
|
||||
}
|
||||
players.push_back(player);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
#include "StlPlayer.h"
|
||||
#include "../controller/Controller.h"
|
||||
#include "../common/third_party/tinyxml2/tinyxml2.h"
|
||||
#include "../error/flip_memory.h"
|
||||
|
||||
struct DramSetup
|
||||
{
|
||||
|
||||
166
DRAMSys/dramSys/src/simulation/StlDataPlayer.h
Normal file
166
DRAMSys/dramSys/src/simulation/StlDataPlayer.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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 STLDATAPLAYER_H
|
||||
#define STLDATAPLAYER_H
|
||||
|
||||
|
||||
#include "../common/xmlAddressdecoder.h"
|
||||
#include "TracePlayer.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace tlm;
|
||||
|
||||
template<unsigned int BUSWIDTH = 128>
|
||||
struct StlDataPlayer: public TracePlayer<BUSWIDTH>
|
||||
{
|
||||
public:
|
||||
StlDataPlayer(sc_module_name /*name*/, string pathToTrace, unsigned int clkMhz,
|
||||
TracePlayerListener* listener);
|
||||
virtual void nextPayload() override
|
||||
{
|
||||
string line;
|
||||
while(line.empty() && file)
|
||||
{
|
||||
std::getline(file, line);
|
||||
}
|
||||
|
||||
if(!file)
|
||||
{
|
||||
this->terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
std::istringstream iss(line);
|
||||
string time, command, address, data;
|
||||
iss >> time >> command >> address >> data;
|
||||
|
||||
// check if data length in the trace file is correct:
|
||||
if((data.length()/2) != (bytesPerColumn*burstlength))
|
||||
{
|
||||
SC_REPORT_FATAL("StlDataPlayer", "Data in the trace file has not the right length");
|
||||
}
|
||||
|
||||
unsigned long long parsedAdress = std::stoull(address.c_str(), 0, 16);
|
||||
|
||||
gp* payload = this->allocatePayload();
|
||||
unsigned char * dataElement = new unsigned char[bytesPerColumn*burstlength];
|
||||
|
||||
payload->set_address(parsedAdress);
|
||||
payload->set_response_status(TLM_INCOMPLETE_RESPONSE);
|
||||
payload->set_dmi_allowed(false);
|
||||
payload->set_byte_enable_length(0);
|
||||
payload->set_streaming_width(burstlength);
|
||||
payload->set_data_length(bytesPerColumn*burstlength);
|
||||
payload->set_data_ptr(dataElement);
|
||||
|
||||
// set data:
|
||||
for(int i = 0; i < bytesPerColumn*burstlength ; i++)
|
||||
{
|
||||
dataElement[i] = (unsigned char)std::stoi(data.substr(i*2,2).c_str(),0,16);
|
||||
}
|
||||
|
||||
if (command == "read")
|
||||
{
|
||||
payload->set_command(TLM_READ_COMMAND);
|
||||
}
|
||||
else if (command == "write")
|
||||
{
|
||||
payload->set_command(TLM_WRITE_COMMAND);
|
||||
|
||||
// Parse and set data
|
||||
string data;
|
||||
iss >> data;
|
||||
|
||||
if(!data.empty())
|
||||
{
|
||||
//cout << "parsing write data: " << data << std::endl;
|
||||
|
||||
for(int i = 0; i < 16*2; i++) // TODO column / burst breite
|
||||
{
|
||||
std::string byteString = "0x";
|
||||
byteString.append(data.substr(2*(i+1), 2));
|
||||
//cout << byteString << " " << std::stoi(byteString.c_str(), 0, 16) << endl;
|
||||
dataElement[i] = std::stoi(byteString.c_str(), 0, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SC_REPORT_FATAL(0,
|
||||
(string("Corrupted tracefile, command ") + command + string(" unknown")).c_str());
|
||||
}
|
||||
|
||||
sc_time sendingTime = std::stoull(time.c_str())*clk;
|
||||
|
||||
if (sendingTime <= sc_time_stamp())
|
||||
{
|
||||
this->payloadEventQueue.notify(*payload, BEGIN_REQ, SC_ZERO_TIME);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->payloadEventQueue.notify(*payload, BEGIN_REQ, sendingTime - sc_time_stamp());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
ifstream file;
|
||||
unsigned int burstlength;
|
||||
unsigned int bytesPerColumn;
|
||||
sc_time clk;
|
||||
};
|
||||
|
||||
|
||||
template<unsigned int BUSWIDTH>
|
||||
StlDataPlayer<BUSWIDTH>::StlDataPlayer(sc_module_name /*name*/, string pathToTrace, unsigned int clkMhz,
|
||||
TracePlayerListener* listener) :
|
||||
TracePlayer<BUSWIDTH>(listener),file(pathToTrace)
|
||||
{
|
||||
if (!file.is_open())
|
||||
SC_REPORT_FATAL(0, (string("Could not open trace ") + pathToTrace).c_str());
|
||||
|
||||
if(clkMhz == 0)
|
||||
clk = Configuration::getInstance().memSpec.clk;
|
||||
else
|
||||
clk = FrequencyToClk(clkMhz);
|
||||
|
||||
this->burstlength = Configuration::getInstance().memSpec.BurstLength;
|
||||
this->bytesPerColumn = xmlAddressDecoder::getInstance().amount["bytes"];
|
||||
}
|
||||
|
||||
#endif // STLDATAPLAYER_H
|
||||
@@ -72,14 +72,14 @@ public:
|
||||
unsigned long long parsedAdress = std::stoull(address.c_str(), 0, 16);
|
||||
|
||||
gp* payload = this->allocatePayload();
|
||||
unsigned char * dataElement = new unsigned char[16*2]; // TODO: column / burst breite
|
||||
unsigned char * dataElement = new unsigned char[bytesPerColumn*burstlength];
|
||||
|
||||
payload->set_address(parsedAdress);
|
||||
payload->set_response_status(TLM_INCOMPLETE_RESPONSE);
|
||||
payload->set_dmi_allowed(false);
|
||||
payload->set_byte_enable_length(0);
|
||||
payload->set_streaming_width(burstlenght);
|
||||
this->setDataPointer(payload, dataElement);
|
||||
payload->set_streaming_width(burstlength);
|
||||
this->setDataPointer(payload, dataElement, bytesPerColumn*burstlength);
|
||||
|
||||
if (command == "read")
|
||||
{
|
||||
@@ -127,7 +127,8 @@ public:
|
||||
|
||||
private:
|
||||
ifstream file;
|
||||
unsigned int burstlenght;
|
||||
unsigned int burstlength;
|
||||
unsigned int bytesPerColumn;
|
||||
sc_time clk;
|
||||
};
|
||||
|
||||
@@ -145,7 +146,8 @@ StlPlayer<BUSWIDTH>::StlPlayer(sc_module_name /*name*/, string pathToTrace, unsi
|
||||
else
|
||||
clk = FrequencyToClk(clkMhz);
|
||||
|
||||
this->burstlenght = Configuration::getInstance().memSpec.BurstLength;
|
||||
this->burstlength = Configuration::getInstance().memSpec.BurstLength;
|
||||
this->bytesPerColumn = xmlAddressDecoder::getInstance().amount["bytes"];
|
||||
}
|
||||
|
||||
#endif // STLPLAYER_H
|
||||
|
||||
@@ -67,7 +67,7 @@ protected:
|
||||
gp* allocatePayload();
|
||||
tlm_utils::peq_with_cb_and_phase<TracePlayer> payloadEventQueue;
|
||||
void terminate();
|
||||
void setDataPointer(gp* p, unsigned char * data);
|
||||
void setDataPointer(gp* p, unsigned char * data, unsigned int size);
|
||||
void printDebugMessage(std::string message);
|
||||
|
||||
private:
|
||||
@@ -108,12 +108,12 @@ void TracePlayer<BUSWIDTH>::printDebugMessage(std::string message)
|
||||
|
||||
template<unsigned int BUSWIDTH>
|
||||
//TODO: this doesn't depend on the tracePlayer, move it somewhere
|
||||
void TracePlayer<BUSWIDTH>::setDataPointer(gp* payload, unsigned char * dataElement)
|
||||
void TracePlayer<BUSWIDTH>::setDataPointer(gp* payload, unsigned char * dataElement, unsigned int size)
|
||||
{
|
||||
//check if payload takes ownership
|
||||
payload->set_data_length(16*2); // TODO: column / burst breite ..... buswidth * burst /8
|
||||
payload->set_data_length(size);
|
||||
payload->set_data_ptr(dataElement);
|
||||
for(int i = 0; i < 16*2; i++) // TODO: column / burst breite
|
||||
for(int i = 0; i < size; i++)
|
||||
dataElement[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
61
DRAMSys/tests/error/WideIO.xml
Normal file
61
DRAMSys/tests/error/WideIO.xml
Normal file
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE memspec SYSTEM "memspec.dtd">
|
||||
<memspec>
|
||||
<parameter id="memoryId" type="string" value="Matze_WideIO" />
|
||||
<parameter id="memoryType" type="string" value="WIDEIO_SDR" />
|
||||
<memarchitecturespec>
|
||||
<parameter id="width" type="uint" value="128" />
|
||||
<parameter id="nbrOfBanks" type="uint" value="8" />
|
||||
<parameter id="nbrOfColumns" type="uint" value="128" />
|
||||
<parameter id="nbrOfRows" type="uint" value="8192" />
|
||||
<parameter id="dataRate" type="uint" value="1" />
|
||||
<parameter id="burstLength" type="uint" value="4" />
|
||||
</memarchitecturespec>
|
||||
<memtimingspec>
|
||||
<parameter id="clkMhz" type="double" value="166" />
|
||||
<parameter id="RC" type="uint" value="9" /><!--tRP+tRAS-->
|
||||
<parameter id="RCD" type="uint" value="3" />
|
||||
<parameter id="RL" type="uint" value="3" />
|
||||
<parameter id="RP" type="uint" value="3" />
|
||||
<parameter id="RFC" type="uint" value="22" />
|
||||
<parameter id="RAS" type="uint" value="6" />
|
||||
<parameter id="WL" type="uint" value="1" />
|
||||
<parameter id="AL" type="uint" value="0" />
|
||||
<parameter id="RTP" type="uint" value="4" />
|
||||
<parameter id="WR" type="uint" value="2" />
|
||||
<parameter id="XP" type="uint" value="2" />
|
||||
<parameter id="XS" type="uint" value="20" /><!--tRFC+2clk-->
|
||||
<parameter id="REFI" type="uint" value="4000" />
|
||||
<parameter id="TAW" type="uint" value="10" />
|
||||
<parameter id="RRD" type="uint" value="2" />
|
||||
<parameter id="CCD" type="uint" value="1" />
|
||||
<parameter id="WTR" type="uint" value="3" />
|
||||
<parameter id="CKE" type="uint" value="3" />
|
||||
<parameter id="CKESR" type="uint" value="3" />
|
||||
</memtimingspec>
|
||||
<mempowerspec>
|
||||
<parameter id="idd0" type="double" value="5.88" />
|
||||
<parameter id="idd02" type="double" value="21.18" />
|
||||
<parameter id="idd2p0" type="double" value="0.05" />
|
||||
<parameter id="idd2p02" type="double" value="0.17" />
|
||||
<parameter id="idd2p1" type="double" value="0.05" />
|
||||
<parameter id="idd2p12" type="double" value="0.17" />
|
||||
<parameter id="idd2n" type="double" value="0.13" />
|
||||
<parameter id="idd2n2" type="double" value="4.04" />
|
||||
<parameter id="idd3p0" type="double" value="0.25" />
|
||||
<parameter id="idd3p02" type="double" value="1.49" />
|
||||
<parameter id="idd3p1" type="double" value="0.25" />
|
||||
<parameter id="idd3p12" type="double" value="1.49" />
|
||||
<parameter id="idd3n" type="double" value="0.52" />
|
||||
<parameter id="idd3n2" type="double" value="6.55" />
|
||||
<parameter id="idd4r" type="double" value="1.41" />
|
||||
<parameter id="idd4r2" type="double" value="85.73" />
|
||||
<parameter id="idd4w" type="double" value="1.42" />
|
||||
<parameter id="idd4w2" type="double" value="60.79" />
|
||||
<parameter id="idd5" type="double" value="14.43" />
|
||||
<parameter id="idd52" type="double" value="48.17" />
|
||||
<parameter id="idd6" type="double" value="0.07" />
|
||||
<parameter id="idd62" type="double" value="0.27" />
|
||||
<parameter id="vdd" type="double" value="1.8" />
|
||||
<parameter id="vdd2" type="double" value="1.2" />
|
||||
</mempowerspec>
|
||||
</memspec>
|
||||
18
DRAMSys/tests/error/am_wideio.xml
Executable file
18
DRAMSys/tests/error/am_wideio.xml
Executable file
@@ -0,0 +1,18 @@
|
||||
<addressmapping>
|
||||
<channel from="27" to="28" />
|
||||
<row from="14" to="26" />
|
||||
<column from="7" to="13" />
|
||||
<bank from="4" to="6" />
|
||||
<bytes from="0" to="3" />
|
||||
</addressmapping>
|
||||
<!-- Magali values: -->
|
||||
<!--
|
||||
<addressmapping>
|
||||
<channel from="27" to="28" />
|
||||
<bank from="24" to="26" />
|
||||
<row from="11" to="23" />
|
||||
<column from="4" to="10" />
|
||||
<bytes from="0" to="3" />
|
||||
</addressmapping>
|
||||
-->
|
||||
|
||||
21
DRAMSys/tests/error/fr_fcfs.xml
Normal file
21
DRAMSys/tests/error/fr_fcfs.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<memconfig>
|
||||
<BankwiseLogic value="0"/>
|
||||
<OpenPagePolicy value="1" />
|
||||
<MaxNrOfTransactions value="50" />
|
||||
<Scheduler value="FR_FCFS" />
|
||||
<Capsize value="5" />
|
||||
<PowerDownMode value="TimeoutPDN" />
|
||||
<PowerDownTimeout value="100" />
|
||||
<!-- Error Model: -->
|
||||
<ErrorChipSeed value="42" />
|
||||
<ErrorCSVFile value="../../DRAMSys/dramSys/src/error/error.csv" />
|
||||
<ErrorStoreMode value="ErrorModel" /> <!--3 Modes: NoStorage, Store (store data without errormodel), ErrorModel (store data with errormodel)-->
|
||||
<!--
|
||||
<Buswidth value="128" />
|
||||
<ReadWriteGrouping value="false" />
|
||||
<ModelStorage value="false" />
|
||||
<ModelErrorInjection value="false" />
|
||||
<ReorderBuffer value="false" />
|
||||
<DatabaseRecording value="true" />
|
||||
-->
|
||||
</memconfig>
|
||||
60
DRAMSys/tests/error/generateErrorTest.pl
Normal file
60
DRAMSys/tests/error/generateErrorTest.pl
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/perl -w
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
# Assuming this address mapping:
|
||||
# <addressmapping>
|
||||
# <channel from="27" to="28" />
|
||||
# <row from="14" to="26" />
|
||||
# <column from="7" to="13" />
|
||||
# <bank from="4" to="6" />
|
||||
# <bytes from="0" to="3" />
|
||||
# </addressmapping>
|
||||
|
||||
# This is how it should look like later:
|
||||
# 31: write 0x0 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
|
||||
my $numberOfRows = 8192;
|
||||
my $numberOfColumnsPerRow = 128;
|
||||
|
||||
my $rowOffset = 0x4000;
|
||||
my $colOffset = 0x80;
|
||||
|
||||
# Generate Data Pattern:
|
||||
my $dataPatternByte = "ff";
|
||||
|
||||
my $dataPattern = "";
|
||||
for(my $i = 0; $i < 64; $i++)
|
||||
{
|
||||
$dataPattern .= $dataPatternByte;
|
||||
}
|
||||
|
||||
my $clkCounter = 0;
|
||||
my $addr = 0;
|
||||
|
||||
# Generate Trace file (writes):
|
||||
for(my $row = 0; $row < ($numberOfRows * $rowOffset); $row = $row + $rowOffset)
|
||||
{
|
||||
for(my $col = 0; $col < ($numberOfColumnsPerRow * $colOffset); $col = $col + $colOffset)
|
||||
{
|
||||
my $addrHex = sprintf("0x%x", $addr);
|
||||
print "$clkCounter:\twrite\t$addrHex\t$dataPattern\n";
|
||||
$clkCounter++;
|
||||
$addr += $colOffset;
|
||||
}
|
||||
}
|
||||
|
||||
$clkCounter = 350000000;
|
||||
$addr = 0;
|
||||
|
||||
# Generate Trace file (reads):
|
||||
for(my $row = 0; $row < ($numberOfRows * $rowOffset); $row = $row + $rowOffset)
|
||||
{
|
||||
for(my $col = 0; $col < ($numberOfColumnsPerRow * $colOffset); $col = $col + $colOffset)
|
||||
{
|
||||
my $addrHex = sprintf("0x%x", $addr);
|
||||
print "$clkCounter:\tread\t$addrHex\t$dataPattern\n";
|
||||
$clkCounter++;
|
||||
$addr += $colOffset;
|
||||
}
|
||||
}
|
||||
28
DRAMSys/tests/error/sim-batch.xml
Normal file
28
DRAMSys/tests/error/sim-batch.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<simulation>
|
||||
<simconfig>
|
||||
<Debug value="0" />
|
||||
<DatabaseRecording value="1" />
|
||||
<PowerAnalysis value="1" />
|
||||
<NumberOfTracePlayers value="4"/>
|
||||
<NumberOfMemChannels value="4"/>
|
||||
</simconfig>
|
||||
|
||||
<memspecs>
|
||||
<memspec src="../../DRAMSys/dramSys/resources/configs/memspecs/WideIO.xml"></memspec>
|
||||
</memspecs>
|
||||
|
||||
<addressmappings>
|
||||
<addressmapping src="../../DRAMSys/dramSys/resources/configs/amconfigs/am_wideio.xml"></addressmapping>
|
||||
</addressmappings>
|
||||
|
||||
<memconfigs>
|
||||
<memconfig src="../../DRAMSys/dramSys/resources/configs/memconfigs/fr_fcfs.xml"/>
|
||||
</memconfigs>
|
||||
|
||||
<tracesetups>
|
||||
<tracesetup id="fifo">
|
||||
<device clkMhz="1000">test_error.stl</device>
|
||||
</tracesetup>
|
||||
</tracesetups>
|
||||
</simulation>
|
||||
|
||||
Reference in New Issue
Block a user