Merge branch 'ehses-master'

This commit is contained in:
Matthias Jung
2015-04-09 10:33:54 +02:00
21 changed files with 911 additions and 29 deletions

View File

@@ -72,7 +72,9 @@ SOURCES += \
../src/controller/ControllerState.cpp \
../src/controller/RowBufferStates.cpp \
../src/controller/scheduler/IScheduler.cpp \
../src/controller/scheduler/FifoStrict.cpp
../src/controller/scheduler/FifoStrict.cpp \
../src/error/nest_map.cpp \
../src/error/flip_memory.cpp
HEADERS += \
../src/common/third_party/tinyxml2.h \
@@ -128,6 +130,8 @@ HEADERS += \
../src/controller/core/powerdown/IPowerDownManager.h \
../src/controller/scheduler/IScheduler.h \
../src/controller/scheduler/FifoStrict.h \
../src/controller/IController.h
../src/controller/core/configuration/ConfigurationLoader.h
../src/controller/IController.h \
../src/controller/core/configuration/ConfigurationLoader.h \
../src/error/nest_map.h \
../src/error/flip_memory.h

View File

@@ -1,4 +1,3 @@
<addressmapping>
<channel from="27" to="28" />
<row from="14" to="26" />
@@ -6,4 +5,14 @@
<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>
-->

View File

@@ -1,9 +1,13 @@
<memconfig>
<BankwiseLogic value="0"/>
<OpenPagePolicy value="1" />
<MaxNrOfTransactions value="50" />
<Scheduler value="FIFO_STRICT" />
<MaxNrOfTransactions value="8" />
<Scheduler value="FR_FCFS" />
<Capsize value="5" />
<PowerDownMode value="TimeoutPDN" />
<PowerDownMode value="TimeoutSREF" />
<PowerDownTimeout value="100" />
<!-- Error Modelling -->
<Chipseed value="42" />
<csvfile value="/home/ehses/projects/dram.vp.system/dram/src/error/error_new.csv" />
<StorMo value="0" /><!--3 Modes: 0 no storage, 1 store data without errormodel, 2 store data with errormodel-->
</memconfig>

View File

@@ -1,9 +1,13 @@
<memconfig>
<BankwiseLogic value="0"/>
<OpenPagePolicy value="1" />
<MaxNrOfTransactions value="50" />
<MaxNrOfTransactions value="8" />
<Scheduler value="FIFO_STRICT" />
<Capsize value="5" />
<PowerDownMode value="TimeoutPDN" />
<PowerDownTimeout value="100" />
<!-- Error Modelling -->
<Chipseed value="42" />
<csvfile value="/home/ehses/projects/dram.vp.system/dram/src/error/error_new.csv" />
<StorMo value="0" /><!--3 Modes: 0 no storage, 1 store data without errormodel, 2 store data with errormodel-->
</memconfig>

View File

@@ -6,11 +6,16 @@
<Capsize value="5" />
<PowerDownMode value="TimeoutPDN" />
<PowerDownTimeout value="100" />
<!-- Error Model: -->
<Chipseed value="42" />
<csvfile value="/home/ehses/projects/dram.vp.system/dram/src/error/error_new.csv" />
<StorMo value="0" /><!--3 Modes: 0 no storage, 1 store data without errormodel, 2 store data with errormodel-->
<!--
<Buswidth value="128" />
<ReadWriteGrouping value="false" />
<ModelStorage value="false" />
<ModelErrorInjection value="false" />
<ReorderBuffer value="false" />
<DatabaseRecording value="true" />
-->
</memconfig>
</memconfig>

View File

@@ -60,6 +60,17 @@ DecodedAddress xmlAddressDecoder::decodeAddress(sc_dt::uint64 addr)
return result;
}
sc_dt::uint64 xmlAddressDecoder::encodeAddress(DecodedAddress n)
{
return n.channel << shifts["channel"] |
n.rank << shifts["rank"] |
n.bankgroup << shifts["bankgroup"] |
n.row << shifts["row"] |
n.bank << shifts["bank"] |
n.column << shifts["column"] |
n.bytes << shifts["bytes"];
}
void xmlAddressDecoder::print()
{
cout << "Used addressmapping:" << endl;

View File

@@ -54,6 +54,8 @@ static tinyxml2::XMLElement* addressmapping;
}
DecodedAddress decodeAddress(sc_dt::uint64 addr);
sc_dt::uint64 encodeAddress(DecodedAddress n);
void print();
private:

View File

@@ -78,10 +78,11 @@ void Configuration::setParameter(std::string name, std::string value)
Buswidth = string2int(value);
else if(name == "ReadWriteGrouping")
ReadWriteGrouping = string2bool(value);
else if(name == "ModelStorage")
ModelStorage = string2bool(value);
else if(name == "ModelErrorInjection")
ModelErrorInjection = string2bool(value);
//removed because of Peters error model TODO clean up!
//else if(name == "ModelStorage")
// ModelStorage = string2bool(value);
//else if(name == "ModelErrorInjection")
// ModelErrorInjection = string2bool(value);
else if(name == "ReorderBuffer")
ReorderBuffer = string2bool(value);
@@ -92,6 +93,13 @@ void Configuration::setParameter(std::string name, std::string value)
PowerAnalysys = string2bool(value);
else if(name == "Debug")
Debug = string2bool(value);
//Specification for Chipseed, csvfile path and StorageMode
else if(name == "Chipseed")
Chipseed = string2int(value);
else if(name == "csvfile")
csvfile = value;
else if(name == "StorMo")
StorMode = string2int(value);
else
{
SC_REPORT_FATAL("Configuration", ("Parameter " + name + " not defined in Configuration").c_str());

View File

@@ -51,6 +51,11 @@ struct Configuration
void setParameter(std::string name, std::string value);
void setParameters(std::map<std::string, std::string> parameterMap);
//Configs for Seed, csv file and StorageMode
unsigned int Chipseed;
std::string csvfile ="not defined.";
unsigned int StorMode;
private:
Configuration();
unsigned int powerDownTimeoutInClk = 3;

View File

@@ -47,7 +47,6 @@ void ConfigurationLoader::loadConfig(Configuration& config, XMLElement* configNo
void ConfigurationLoader::loadMemSpec(Configuration& config, string memspecUri)
{
tinyxml2::XMLDocument doc;
loadXML(memspecUri, doc);
XMLElement* memspec = doc.FirstChildElement("memspec");
loadMemSpec(config, memspec);
@@ -114,6 +113,7 @@ void ConfigurationLoader::loadDDR4(Configuration& config, XMLElement* memspec)
config.memSpec.DataRate = queryUIntParameter(architecture, "dataRate");
config.memSpec.NumberOfRows = queryUIntParameter(architecture, "nbrOfRows");
config.memSpec.NumberOfColumns = queryUIntParameter(architecture, "nbrOfColumns");
config.memSpec.BusWidth = queryUIntParameter(architecture, "width");
//MemTimings
XMLElement* timings = memspec->FirstChildElement("memtimingspec");
@@ -165,6 +165,7 @@ void ConfigurationLoader::loadWideIO(Configuration& config, XMLElement* memspec)
config.memSpec.DataRate = queryUIntParameter(architecture, "dataRate");
config.memSpec.NumberOfRows = queryUIntParameter(architecture, "nbrOfRows");
config.memSpec.NumberOfColumns = queryUIntParameter(architecture, "nbrOfColumns");
config.memSpec.BusWidth = queryUIntParameter(architecture, "width");
//MemTimings
XMLElement* timings = memspec->FirstChildElement("memtimingspec");

View File

@@ -53,6 +53,7 @@ struct MemSpec
unsigned int DataRate;
unsigned int NumberOfRows;
unsigned int NumberOfColumns;
unsigned int BusWidth;
sc_time clk;
sc_time tRP; //precharge-time (pre -> act same bank)

View File

@@ -0,0 +1,20 @@
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 75 127 0 0 0 0
2 80 127 0 0 0 0
3 85 127 0 0 0 0
4 89 127 2 0.03 2 0.06
5 75 145 0 0 0 0
6 80 145 0 0 0 0
7 85 145 0 0 1 0.03
8 89 145 13 0.195 3 0.09
9 75 164 0 0 0 0
10 80 164 0 0 0 0
11 85 164 8 0.12 2 0.06
12 89 164 24 0.36 4 0.12
13 75 182 0 0 0 0
14 80 182 0 0 1 0.03
15 85 182 16 0.24 2 0.06
16 89 182 41 0.615 8 0.24
17 75 200 0 0 0 0
18 80 200 5 0.075 3 0.09
19 85 200 24 0.36 4 0.12
20 89 200 67 1.005 15 0.45

View File

@@ -0,0 +1,402 @@
/*
* Created on: Juli, 2014
* Author: patrick, peter
*/
#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().Chipseed); // Chipseed 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().csvfile);
// 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;
}
}

View File

@@ -0,0 +1,79 @@
/*
* Created on: Juli, 2014
* Author: patrick, peter
*/
#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

173
dram/src/error/nest_map.cpp Normal file
View File

@@ -0,0 +1,173 @@
/*
* Created on: Juli, 2014
* Author: patrick, peter
*/
#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;
}

56
dram/src/error/nest_map.h Normal file
View File

@@ -0,0 +1,56 @@
/*
* Created on: Juli, 2014
* Author: patrick, peter
*/
#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

View File

@@ -21,8 +21,9 @@
#include "../common/TlmRecorder.h"
#include "../common/third_party/DRAMPower/src/libdrampower/LibDRAMPower.h"
#include "../common/third_party/DRAMPower/src/xmlparser/MemSpecParser.h"
#include "../common/third_party/DRAMPower/src/MemorySpecification.h"
#include "../common/third_party/DRAMPower/src/MemCommand.h"
#include "../error/flip_memory.h"
using namespace std;
using namespace tlm;
@@ -49,6 +50,10 @@ struct Dram: sc_module
tlm_utils::simple_target_socket<Dram, BUSWIDTH, tlm::tlm_base_protocol_types> tSocket;
IFPOW(libDRAMPower *DRAMPower);
const unsigned int StorageMode = Configuration::getInstance().StorMode; // 0 no storage, 1 store, 2 error model
flip_memory * fmemory;
//Configuration::getInstance().memSpec.NumberOfBanks];
map< unsigned long int, unsigned char[BUSWIDTH/2] > memory;
SC_CTOR(Dram) : tSocket("socket")
@@ -57,6 +62,12 @@ struct Dram: sc_module
IFPOW( MemorySpecification memSpec(MemSpecParser::getMemSpecFromXML(Configuration::getInstance().memspecUri)) );
IFPOW( DRAMPower = new libDRAMPower( memSpec, 0 ) );
cout << "StorageMode = " << StorageMode << endl;
if(StorageMode == 2)
{
fmemory = new flip_memory[Configuration::getInstance().memSpec.NumberOfBanks];
}
}
~Dram()
@@ -65,7 +76,16 @@ struct Dram: sc_module
IFPOW( DRAMPower->calcEnergy() );
IFPOW( cout << endl << endl << "Total Energy" << "\t" << DRAMPower->getEnergy().total_energy << endl);
IFPOW( cout << "Average Power" << "\t" << DRAMPower->getPower().average_power << endl );
std::cout << "Simulated Memory Size: " << memory.size() << endl;
if(StorageMode == 2)
{
for(int b = 0; b < 8; b++)
{
cout << "BIT_ERRORS Bank: " <<b <<"="<< fmemory[b].BIT_ERR << endl;
}
}
// TODO Aufrauemen!
//delete fmemory; // TODO Testen!
//std::cout << "Simulated Memory Size: " << memory.size() << endl; // TODO Aufrauemen
}
virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& payload, tlm::tlm_phase& phase, sc_time& delay)
@@ -90,43 +110,107 @@ struct Dram: sc_module
{
IFPOW(DRAMPower->doCommand(MemCommand::ACT, bank, cycle));
sendToController(payload, END_ACT, delay + getExecutionTime(Command::Activate, payload));
unsigned int row = DramExtension::getExtension(payload).getRow().ID();
if (StorageMode == 2)
{
fmemory[bank].refresh(row);
}
}
else if (phase == BEGIN_WR)
{
IFPOW(DRAMPower->doCommand(MemCommand::WR, bank, cycle));
//save data:
memcpy(&memory[payload.get_address()], payload.get_data_ptr(), BUSWIDTH/8);
if (StorageMode == 0)
{
// Don't store data
}
else if (StorageMode == 1) // Use Storage
{
memcpy(&memory[payload.get_address()], payload.get_data_ptr(), BUSWIDTH/8);
}
else // == 2 Use Storage with Error Model
{
fmemory[bank].store(payload);
}
sendToController(payload, END_WR, delay + getExecutionTime(Command::Write, payload));
}
else if (phase == BEGIN_RD)
{
IFPOW(DRAMPower->doCommand(MemCommand::RD, bank, cycle));
sendToController(payload, END_RD, delay + getExecutionTime(Command::Read, payload));
// Load data:
if(memory.count(payload.get_address()) == 1)
if (StorageMode == 1) //use StorageMode
{
memcpy(payload.get_data_ptr(), &memory[payload.get_address()], BUSWIDTH/8);
if(memory.count(payload.get_address()) == 1)
{
memcpy(payload.get_data_ptr(), &memory[payload.get_address()], BUSWIDTH/8);
}
else
{
//SC_REPORT_WARNING ("DRAM", "Reading from an empty memory location.");
}
}
else
else if(StorageMode == 2)// use StorageMode with errormodel
{
//SC_REPORT_WARNING ("DRAM", "Reading from an empty memory location.");
fmemory[bank].load(payload);
}
sendToController(payload, END_RD, delay + getExecutionTime(Command::Read, payload));
}
else if (phase == BEGIN_WRA)
{
IFPOW(DRAMPower->doCommand(MemCommand::WRA, bank, cycle));
//save data:
if (StorageMode == 0)
{
// Don't store data
}
else if (StorageMode == 1) // Use Storage
{
memcpy(&memory[payload.get_address()], payload.get_data_ptr(), BUSWIDTH/8);
}
else // == 2 Use Storage with Error Model
{
fmemory[bank].store(payload);
}
sendToController(payload, END_WRA, delay + getExecutionTime(Command::WriteA, payload));
}
else if (phase == BEGIN_RDA)
{
IFPOW(DRAMPower->doCommand(MemCommand::RDA, bank, cycle));
// Load data:
if (StorageMode == 1) //use StorageMode
{
if(memory.count(payload.get_address()) == 1)
{
memcpy(payload.get_data_ptr(), &memory[payload.get_address()], BUSWIDTH/8);
}
else
{
//SC_REPORT_WARNING ("DRAM", "Reading from an empty memory location.");
}
}
else if(StorageMode == 2)// use StorageMode with errormodel
{
fmemory[bank].load(payload);
}
sendToController(payload, END_RDA, delay + getExecutionTime(Command::ReadA, payload));
}
else if (phase == BEGIN_REFA)
{
IFPOW(DRAMPower->doCommand(MemCommand::REF, bank, cycle));
sendToController(payload, END_REFA, delay + getExecutionTime(Command::AutoRefresh, payload));
unsigned int row = DramExtension::getExtension(payload).getRow().ID();
if (StorageMode == 2)
{
fmemory[bank].refresh(row);
}
}
else if (phase == BEGIN_REFB)
@@ -205,6 +289,4 @@ struct Dram: sc_module
};
#endif /* DRAM_H_ */

View File

@@ -16,6 +16,7 @@
#include <fstream>
#include <vector>
#include "../common/Utils.h"
#include "../error/flip_memory.h"
#include "StlPlayer.h"
using namespace std;

View File

@@ -18,6 +18,7 @@
#include <systemc.h>
#include "TracePlayerListener.h"
#include "../common/third_party/tinyxml2.h"
#include "../error/flip_memory.h"
struct DramSetup
{

View File

@@ -35,7 +35,7 @@ public:
unsigned long long parsedAdress = std::stoull(address.c_str(), 0, 16);
gp* payload = this->allocatePayload();
unsigned char * dataElement = new unsigned char[16]; // TODO: column / burst breite
unsigned char * dataElement = new unsigned char[16*2]; // TODO: column / burst breite
payload->set_address(parsedAdress);
payload->set_response_status(TLM_INCOMPLETE_RESPONSE);
@@ -60,7 +60,7 @@ public:
{
//cout << "parsing write data: " << data << std::endl;
for(int i = 0; i < 16; i++) // TODO column / burst breite
for(int i = 0; i < 16*2; i++) // TODO column / burst breite
{
std::string byteString = "0x";
byteString.append(data.substr(2*(i+1), 2));

View File

@@ -86,9 +86,9 @@ template<unsigned int BUSWIDTH>
void TracePlayer<BUSWIDTH>::setDataPointer(gp* payload, unsigned char * dataElement)
{
//check if payload takes ownership
payload->set_data_length(16); // TODO: column / burst breite ..... buswidth * burst /8
payload->set_data_length(16*2); // TODO: column / burst breite ..... buswidth * burst /8
payload->set_data_ptr(dataElement);
for(int i = 0; i < 16; i++) // TODO: column / burst breite
for(int i = 0; i < 16*2; i++) // TODO: column / burst breite
dataElement[i] = 0;
}
@@ -120,6 +120,19 @@ void TracePlayer<BUSWIDTH>::peqCallback(tlm_generic_payload &payload, const tlm_
}
else if (phase == BEGIN_RESP)
{
//TODO: cleanup:
// unsigned char * dataElement = payload.get_data_ptr();
//
// if(payload.get_command() == TLM_READ_COMMAND)
// {
// cout << "0x";
// for(int i=0; i < 16*2; i++)
// {
// cout << hex << int(dataElement[i]);
// }
// cout << endl;
// }
sendToTarget(payload, END_RESP, SC_ZERO_TIME);
payload.release();
}
@@ -141,3 +154,4 @@ void TracePlayer<BUSWIDTH>::sendToTarget(tlm_generic_payload &payload, const tlm
}
#endif /* TRACEPLAYER_H_ */