209 lines
5.9 KiB
C++
209 lines
5.9 KiB
C++
#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();
|
|
}
|
|
|