From a366ed8f91bbd7f7f7a77b95b1550bd74c43fe3e Mon Sep 17 00:00:00 2001 From: Peter Ehses Date: Tue, 16 Sep 2014 10:27:14 +0200 Subject: [PATCH] easy error model from patrick implemented --- dram/src/error/flip_memory.cpp | 208 +++++++++++++++++++++++++++++++++ dram/src/error/flip_memory.h | 53 +++++++++ dram/src/error/nest_map.cpp | 117 +++++++++++++++++++ dram/src/error/nest_map.h | 46 ++++++++ 4 files changed, 424 insertions(+) create mode 100644 dram/src/error/flip_memory.cpp create mode 100644 dram/src/error/flip_memory.h create mode 100644 dram/src/error/nest_map.cpp create mode 100644 dram/src/error/nest_map.h diff --git a/dram/src/error/flip_memory.cpp b/dram/src/error/flip_memory.cpp new file mode 100644 index 00000000..9b2b5071 --- /dev/null +++ b/dram/src/error/flip_memory.cpp @@ -0,0 +1,208 @@ +#include "flip_memory.h" +#include +// Console out +#include + +// String conversion (debugging) +#include +#include + +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; igetMaxWeakCells(); + + for (unsigned int i=0; i 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 >(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; igetAddress(&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(); +} + diff --git a/dram/src/error/flip_memory.h b/dram/src/error/flip_memory.h new file mode 100644 index 00000000..cc4abb75 --- /dev/null +++ b/dram/src/error/flip_memory.h @@ -0,0 +1,53 @@ +#ifndef _FLIP_MEMORY_H +#define _FLIP_MEMORY_H +#include "nest_map.h" +#include +#include +#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 > mem; + map 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 diff --git a/dram/src/error/nest_map.cpp b/dram/src/error/nest_map.cpp new file mode 100644 index 00000000..25aaa009 --- /dev/null +++ b/dram/src/error/nest_map.cpp @@ -0,0 +1,117 @@ +#include "nest_map.h" +#include + +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 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) 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 nest_map::split(string str, char c) { + vector 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; +} \ No newline at end of file diff --git a/dram/src/error/nest_map.h b/dram/src/error/nest_map.h new file mode 100644 index 00000000..58ce02b7 --- /dev/null +++ b/dram/src/error/nest_map.h @@ -0,0 +1,46 @@ +#ifndef _NEST_MAP_H +#define _NEST_MAP_H + +#include +#include +#include +#include +#include +#include + +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 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