easy error model from patrick implemented
This commit is contained in:
208
dram/src/error/flip_memory.cpp
Normal file
208
dram/src/error/flip_memory.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
#include "flip_memory.h"
|
||||
#include <time.h>
|
||||
// Console out
|
||||
#include <iostream>
|
||||
|
||||
// String conversion (debugging)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
flip_memory::flip_memory() {
|
||||
// Initialize Random generator with current system time
|
||||
// Only do this once in a simulation
|
||||
srand(time(NULL));
|
||||
|
||||
// Fixed values for development process
|
||||
TEMPERATURE = 90;
|
||||
|
||||
// Initialize number of bit errors
|
||||
BIT_ERR = 0;
|
||||
|
||||
errormap = new nest_map("errors.csv");
|
||||
xade = new xmlAddressDecoder("config.xml");
|
||||
|
||||
// Constants for address calculations
|
||||
ROWS_PER_BANK = xade->getRowSize();
|
||||
COLS_PER_ROW = xade->getColumSize();
|
||||
BYTES_PER_COL = xade->getBytesSize();
|
||||
BITS_PER_ROW = COLS_PER_ROW * BYTES_PER_COL * 8;
|
||||
|
||||
// Fill array with random addresses
|
||||
initWeakCells();
|
||||
}
|
||||
|
||||
flip_memory::~flip_memory() {
|
||||
cout << endl << endl << endl << "Bit-Fehler: " << BIT_ERR << endl << endl << endl;
|
||||
}
|
||||
|
||||
void flip_memory::getUnifiedNode(unsigned int addr, node *n) {
|
||||
xade->getNode(addr, n);
|
||||
n->channel = 0;
|
||||
n->bank = 0;
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Reset "HasFlipped"-Flag, set Refresh-Timestamp
|
||||
void flip_memory::resetCell(node n) {
|
||||
unsigned int arraySize = errormap->getMaxWeakCells();
|
||||
|
||||
for (unsigned int i=0; i<arraySize; i++) {
|
||||
if ((weakCells[i][0] == n.row) && (weakCells[i][1] == n.colum)) weakCells[i][3] = 0;
|
||||
}
|
||||
|
||||
refr[n.row] = sc_time_stamp();
|
||||
}
|
||||
|
||||
|
||||
// Store data in memory
|
||||
void flip_memory::store(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
|
||||
node no;
|
||||
getUnifiedNode(t_addr, &no);
|
||||
|
||||
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.colum++;
|
||||
|
||||
// Swap around if more columns addressed than exist
|
||||
if (no.colum>(COLS_PER_ROW - 1)) no.colum -= BURSTLENGTH*BYTES_PER_COL;
|
||||
|
||||
unsigned int addr = xade->getAddress(&no);
|
||||
|
||||
mem.insert(pair<unsigned int, vector<unsigned char> >(addr, v));
|
||||
|
||||
// Reset weak cells; they have reliable data now till next check
|
||||
resetCell(no);
|
||||
}
|
||||
|
||||
trans.set_response_status(TLM_OK_RESPONSE);
|
||||
}
|
||||
|
||||
|
||||
void flip_memory::load(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
|
||||
node no;
|
||||
getUnifiedNode(t_addr, &no);
|
||||
|
||||
|
||||
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.colum++;
|
||||
|
||||
// Swap around if more columns addressed than exist
|
||||
if (no.colum>(COLS_PER_ROW - 1)) no.colum -= BURSTLENGTH*BYTES_PER_COL;
|
||||
|
||||
unsigned int addr = xade->getAddress(&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?
|
||||
sc_time deltaT = sc_time_stamp() - refr[row];
|
||||
unsigned int n = errormap->getFlipRate(TEMPERATURE, deltaT);
|
||||
|
||||
// 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) {
|
||||
node no;
|
||||
getUnifiedNode(0, &no);
|
||||
no.row = weakCells[i][0];
|
||||
no.colum = weakCells[i][1];
|
||||
|
||||
unsigned int addr = xade->getAddress(&no);
|
||||
unsigned int byte = weakCells[i][2] / 8; // Byte position in column
|
||||
unsigned 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];
|
||||
|
||||
mem[addr][byte] &= mask;
|
||||
weakCells[i][3] = 1;
|
||||
|
||||
char memAfter = mem[addr][byte];
|
||||
|
||||
// Data has changed?
|
||||
if (memBefore!=memAfter) {
|
||||
BIT_ERR++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
refr[row] = sc_time_stamp();
|
||||
}
|
||||
|
||||
53
dram/src/error/flip_memory.h
Normal file
53
dram/src/error/flip_memory.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef _FLIP_MEMORY_H
|
||||
#define _FLIP_MEMORY_H
|
||||
#include "nest_map.h"
|
||||
#include <tlm.h>
|
||||
#include <map>
|
||||
#include "common/xmlAddressdecoder.h"
|
||||
|
||||
|
||||
using namespace tlm;
|
||||
using namespace std;
|
||||
|
||||
class flip_memory {
|
||||
private:
|
||||
xmlAddressDecoder *xade;
|
||||
|
||||
// Remember to adjust this value by hand when editing in simulation
|
||||
static const unsigned int BUSWIDTH = 128;
|
||||
static const unsigned int BURSTLENGTH = 1;
|
||||
|
||||
// Compute number of generated bit errors
|
||||
unsigned int BIT_ERR;
|
||||
|
||||
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;
|
||||
|
||||
// Generates an XML node which is tied to one memory class instance
|
||||
void getUnifiedNode(unsigned int addr, node *n);
|
||||
|
||||
// Decide randomly which cells are weak
|
||||
void initWeakCells();
|
||||
|
||||
// Reset "HasFlipped"-Flag, set Refresh-Timestamp
|
||||
void resetCell(node n);
|
||||
|
||||
public:
|
||||
flip_memory();
|
||||
~flip_memory();
|
||||
void store(tlm_generic_payload &trans);
|
||||
void load(tlm_generic_payload &trans);
|
||||
// Trigger row refresh externally; errors are manifested
|
||||
void refresh(unsigned int row);
|
||||
};
|
||||
#endif
|
||||
117
dram/src/error/nest_map.cpp
Normal file
117
dram/src/error/nest_map.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
#include "nest_map.h"
|
||||
#include <limits>
|
||||
|
||||
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;
|
||||
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 triple[noOfLines];
|
||||
|
||||
// Copy entries from CSV to errormap
|
||||
for (unsigned int i = 0; i < noOfLines; i++) {
|
||||
getline(input, line);
|
||||
|
||||
// "split" returns a 3d vector with temperature, time, number of errors (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);
|
||||
tr[i].n = atoi(tmp[2].c_str());
|
||||
|
||||
// Search the largest entry of n in list
|
||||
if (tr[i].n > maxWeakCells) {
|
||||
maxWeakCells = tr[i].n;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return noOfWeakCells;
|
||||
}
|
||||
|
||||
|
||||
unsigned int nest_map::getMaxWeakCells() {
|
||||
return maxWeakCells;
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
46
dram/src/error/nest_map.h
Normal file
46
dram/src/error/nest_map.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#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 triples of temperature, (retention) time and number of errors
|
||||
struct triple {
|
||||
unsigned int T;
|
||||
sc_time t;
|
||||
unsigned int n;
|
||||
};
|
||||
|
||||
// Array of "triple" with dynamic size
|
||||
triple *tr;
|
||||
|
||||
// Number of entrys in tr[]
|
||||
unsigned int size;
|
||||
|
||||
// Largest value of n in tr[]
|
||||
unsigned int maxWeakCells;
|
||||
|
||||
// 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();
|
||||
};
|
||||
#endif
|
||||
Reference in New Issue
Block a user