+minor logging changes and comments git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1652 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
229 lines
6.6 KiB
C++
229 lines
6.6 KiB
C++
#include <iostream>
|
|
#include <sstream>
|
|
|
|
// getpid
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#include "util/Logger.hpp"
|
|
|
|
#include "experiment.hpp"
|
|
#include "campaign.hpp"
|
|
|
|
#include "sal/SALConfig.hpp"
|
|
#include "sal/SALInst.hpp"
|
|
#include "sal/Memory.hpp"
|
|
#include "sal/Listener.hpp"
|
|
|
|
#define LOCAL 0
|
|
|
|
#define STR_STATS "calculating stats"
|
|
#define STR_START "starting test pass"
|
|
#define STR_TESTED "tested "
|
|
#define STR_BADFRAME "bad frame at pfn "
|
|
|
|
using namespace std;
|
|
using namespace fail;
|
|
|
|
/*
|
|
// Check if configuration dependencies are satisfied:
|
|
#if !defined(CONFIG_EVENT_BREAKPOINTS) || !defined(CONFIG_SR_RESTORE) || \
|
|
!defined(CONFIG_SR_SAVE) || !defined(CONFIG_EVENT_TRAP)
|
|
#error This experiment needs: breakpoints, traps, save, and restore. Enable these in the configuration.
|
|
#endif
|
|
*/
|
|
|
|
bool RAMpageExperiment::run()
|
|
{
|
|
m_log << "startup" << std::endl;
|
|
|
|
// not implemented yet for QEMU:
|
|
//simulator.restore("rampage-cext-started");
|
|
|
|
// We cannot include the auto-generated rampage.pb.h in experiment.hpp,
|
|
// because it is included in an aspect header; therefore we need to work
|
|
// around not having the type available there.
|
|
m_param = new RAMpageExperimentData;
|
|
#if LOCAL
|
|
//m_param->msg.set_mem_addr(1024*604+123);
|
|
//m_param->msg.set_mem_addr(1024*1024*63+123);
|
|
m_param->msg.set_mem_addr(73728);
|
|
m_param->msg.set_mem_bit(7);
|
|
//m_param->msg.set_errortype(m_param->msg.ERROR_STUCK_AT_0);
|
|
m_param->msg.set_errortype(m_param->msg.ERROR_COUPLING);
|
|
m_param->msg.set_local_timeout(1000*60*10); // 10m
|
|
m_param->msg.set_global_timeout(1000*60*50); // 50m
|
|
#else
|
|
if (!m_jc.getParam(*m_param)) {
|
|
m_log << "Dying." << endl;
|
|
// communicate that we were told to die
|
|
simulator.terminate(1);
|
|
}
|
|
#endif
|
|
|
|
m_starttime = std::time(0);
|
|
m_param->msg.set_mem_written(false);
|
|
|
|
MemWriteListener l_mem1(m_param->msg.mem_addr());
|
|
IOPortListener l_io(0x2f8, true); // ttyS1 aka COM2
|
|
TimerListener l_timeout_local(m_param->msg.local_timeout());
|
|
TimerListener l_timeout_global(m_param->msg.global_timeout());
|
|
|
|
simulator.addListener(&l_mem1);
|
|
simulator.addListener(&l_io);
|
|
simulator.addListener(&l_timeout_local);
|
|
simulator.addListener(&l_timeout_global);
|
|
while (true) {
|
|
BaseListener *l = simulator.resume();
|
|
|
|
if (l == &l_mem1) {
|
|
simulator.addListener(&l_mem1);
|
|
handleMemWrite(l_mem1.getTriggerAddress());
|
|
m_param->msg.set_mem_written(true);
|
|
} else if (l == &l_io) {
|
|
simulator.addListener(&l_io);
|
|
if (handleIO(l_io.getData())) {
|
|
// we saw some progress, restart local timer
|
|
simulator.removeListener(&l_timeout_local);
|
|
simulator.addListener(&l_timeout_local);
|
|
}
|
|
} else if (l == &l_timeout_local) {
|
|
m_log << "local timeout" << std::endl;
|
|
terminateExperiment(m_param->msg.LOCAL_TIMEOUT);
|
|
} else if (l == &l_timeout_global) {
|
|
m_log << "global timeout" << std::endl;
|
|
terminateExperiment(m_param->msg.GLOBAL_TIMEOUT);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void RAMpageExperiment::handleMemWrite(address_t addr)
|
|
{
|
|
address_t addr1 = addr;
|
|
unsigned bit1 = m_param->msg.mem_bit();
|
|
unsigned bit2 = m_param->msg.mem_coupled_bit();
|
|
unsigned char data = m_mm.getByte(addr1);
|
|
|
|
m_log << "access to addr 0x" << std::hex << addr1 << ", FI" << endl;
|
|
|
|
switch (m_param->msg.errortype()) {
|
|
case RAMpageProtoMsg::ERROR_NONE:
|
|
m_log << "no fault injected" << endl;
|
|
break;
|
|
case RAMpageProtoMsg::ERROR_STUCK_AT_0:
|
|
m_log << "stuck-at-0, bit " << bit1 << endl;
|
|
data &= ~(1 << bit1); // stuck-at-0
|
|
break;
|
|
case RAMpageProtoMsg::ERROR_STUCK_AT_1:
|
|
m_log << "stuck-at-1, bit " << bit1 << endl;
|
|
data |= 1 << bit1; // stuck-at-1
|
|
break;
|
|
case RAMpageProtoMsg::ERROR_COUPLING:
|
|
m_log << "coupling, bit " << bit2 << " := bit " << bit1 << endl;
|
|
data &= ~(1 << bit2); // coupling bit2 := bit1
|
|
data |= ((data & (1 << bit1)) != 0) << bit2;
|
|
break;
|
|
case RAMpageProtoMsg::ERROR_INVERSE_COUPLING:
|
|
m_log << "coupling, bit " << bit2 << " := !bit " << bit1 << endl;
|
|
data &= ~(1 << bit2); // coupling bit2 := !bit1
|
|
data |= ((data & (1 << bit1)) == 0) << bit2;
|
|
break;
|
|
default:
|
|
m_log << "unknown error type" << std::endl;
|
|
}
|
|
m_mm.setByte(addr1, data);
|
|
/*
|
|
unsigned char data2 = m_mm.getByte(addr2);
|
|
data2 &= ~(1 << bit2); // coupling addr2:bit2 := !addr1:bit1
|
|
data2 |= ((data & (1 << bit1)) == 0) << bit2;
|
|
m_mm.setByte(addr2, data2);
|
|
*/
|
|
}
|
|
|
|
bool RAMpageExperiment::handleIO(char c)
|
|
{
|
|
if (c != '\n') {
|
|
m_output += c;
|
|
return false;
|
|
}
|
|
|
|
// calculating stats
|
|
if (!m_output.compare(0, sizeof(STR_STATS)-1, STR_STATS)) {
|
|
if (m_last_line_was_startingtestpass) {
|
|
// result: NO_PFNS_TESTED
|
|
m_log << "no PFNs were tested this time" << std::endl;
|
|
terminateExperiment(m_param->msg.NO_PFNS_TESTED);
|
|
}
|
|
m_log << STR_STATS << std::endl;
|
|
|
|
// starting test pass
|
|
} else if (!m_output.compare(0, sizeof(STR_START)-1, STR_START)) {
|
|
m_last_line_was_startingtestpass = true;
|
|
m_log << STR_START << std::endl;
|
|
|
|
// tested %08x-%08x %08x-%08x ...
|
|
} else if (!m_output.compare(0, sizeof(STR_TESTED)-1, STR_TESTED)) {
|
|
m_last_line_was_startingtestpass = false;
|
|
//m_log << STR_TESTED << std::endl;
|
|
|
|
// test whether the failing PFN was listed
|
|
stringstream ss;
|
|
ss << m_output.substr(sizeof(STR_TESTED) - 1);
|
|
while (!ss.eof()) {
|
|
char c;
|
|
uint32_t a, b;
|
|
ss >> hex >> a >> c >> b;
|
|
if (ss.fail()) {
|
|
m_param->msg.set_details("unknown serial output: " + m_output);
|
|
terminateExperiment(m_param->msg.UNKNOWN);
|
|
}
|
|
if (a <= (m_param->msg.mem_addr() >> 12) &&
|
|
(m_param->msg.mem_addr() >> 12) <= b) {
|
|
// we abort even if errortype == ERROR_NONE
|
|
m_log << "PF was tested but no error was found, aborting" << endl;
|
|
terminateExperiment(m_param->msg.PFN_WAS_LISTED);
|
|
}
|
|
}
|
|
|
|
// bad frame at pfn %08x
|
|
} else if (!m_output.compare(0, sizeof(STR_BADFRAME)-1, STR_BADFRAME)) {
|
|
m_log << m_output << std::endl;
|
|
|
|
// test whether it was the right PFN
|
|
uint64_t pfn;
|
|
stringstream ss;
|
|
ss << m_output.substr(sizeof(STR_BADFRAME) - 1);
|
|
ss >> hex >> pfn;
|
|
if (ss.fail()) {
|
|
m_param->msg.set_details("unknown serial output: " + m_output);
|
|
terminateExperiment(m_param->msg.UNKNOWN);
|
|
}
|
|
m_param->msg.set_error_detected_pfn(pfn);
|
|
if ((m_param->msg.mem_addr() >> 12) == pfn) {
|
|
terminateExperiment(m_param->msg.RIGHT_PFN_DETECTED);
|
|
} else {
|
|
terminateExperiment(m_param->msg.WRONG_PFN_DETECTED);
|
|
}
|
|
|
|
// unknown
|
|
} else {
|
|
m_log << "wtf unknown: " << m_output << std::endl;
|
|
m_param->msg.set_details("unknown serial output: " + m_output);
|
|
terminateExperiment(m_param->msg.UNKNOWN);
|
|
}
|
|
|
|
m_output.clear();
|
|
return true;
|
|
}
|
|
|
|
void RAMpageExperiment::terminateExperiment(int resulttype)
|
|
{
|
|
m_param->msg.set_resulttype((RAMpageProtoMsg::ResultType) resulttype);
|
|
m_param->msg.set_experiment_time(std::time(0) - m_starttime);
|
|
#if !LOCAL
|
|
m_jc.sendResult(*m_param);
|
|
#endif
|
|
simulator.terminate();
|
|
}
|