tools/import-trace: sanity checks
These can be enabled if something looks fishy. Change-Id: Iba4f73dc0a70ec4e548456edb36e21fecbaad410
This commit is contained in:
@ -173,9 +173,102 @@ bool Importer::copy_to_database(fail::ProtoIStream &ps) {
|
|||||||
LOG << "Inserted " << row_count << " trace events (+" << row_count_fake
|
LOG << "Inserted " << row_count << " trace events (+" << row_count_fake
|
||||||
<< " fake events) into the database" << std::endl;
|
<< " fake events) into the database" << std::endl;
|
||||||
|
|
||||||
// TODO: (configurable) sanity checks
|
// sanity checks
|
||||||
// PC-based fault space rectangular, covered, and non-overlapping?
|
if (m_sanitychecks) {
|
||||||
// (same for timing-based fault space?)
|
std::stringstream ss;
|
||||||
|
bool all_ok = true;
|
||||||
|
MYSQL_RES *res;
|
||||||
|
|
||||||
|
// PC-based fault space rectangular, covered, and non-overlapping?
|
||||||
|
// (same for timing-based fault space?)
|
||||||
|
|
||||||
|
LOG << "Sanity check: EC overlaps ..." << std::flush;
|
||||||
|
ss <<
|
||||||
|
"SELECT t1.variant_id\n" //, v.variant, v.benchmark, t1.instr1, t1.instr2, t1.data_address, t2.instr1, t2.instr2
|
||||||
|
"FROM trace t1\n"
|
||||||
|
"JOIN variant v\n"
|
||||||
|
" ON v.id = t1.variant_id\n"
|
||||||
|
"JOIN trace t2\n"
|
||||||
|
" ON t1.variant_id = t2.variant_id AND t1.data_address = t2.data_address\n"
|
||||||
|
" AND (t1.instr1 != t2.instr1 OR t2.instr2 != t2.instr2)\n"
|
||||||
|
" AND ((t1.instr1 >= t2.instr1 AND t1.instr1 <= t2.instr2)\n"
|
||||||
|
" OR (t1.instr2 >= t2.instr1 AND t1.instr2 <= t2.instr2)\n"
|
||||||
|
" OR (t1.instr1 < t2.instr1 AND t1.instr2 > t2.instr2))\n"
|
||||||
|
"WHERE t1.variant_id = " << m_variant_id;
|
||||||
|
|
||||||
|
res = db->query(ss.str().c_str(), true);
|
||||||
|
ss.str("");
|
||||||
|
ss.clear();
|
||||||
|
if (res && mysql_num_rows(res) == 0) {
|
||||||
|
std::cout << " OK" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << " FAILED: not all ECs are disjoint" << std::endl;
|
||||||
|
// TODO: show a list of overlapping ECs?
|
||||||
|
all_ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG << "Sanity check: FS row sum = total width ..." << std::flush;
|
||||||
|
ss <<
|
||||||
|
"SELECT t.variant_id, t.data_address,\n"
|
||||||
|
" (SELECT (MAX(t2.instr2) - MIN(t2.instr1) + 1)\n"
|
||||||
|
" FROM trace t2\n"
|
||||||
|
" WHERE t2.variant_id = t.variant_id)\n"
|
||||||
|
" -\n"
|
||||||
|
" (SELECT SUM(t3.instr2 - t3.instr1 + 1)\n"
|
||||||
|
" FROM trace t3\n"
|
||||||
|
" WHERE t3.variant_id = t.variant_id AND t3.data_address = t.data_address)\n"
|
||||||
|
" AS diff\n"
|
||||||
|
"FROM trace t\n"
|
||||||
|
"WHERE t.variant_id = " << m_variant_id << "\n"
|
||||||
|
"GROUP BY t.variant_id, t.data_address\n"
|
||||||
|
"HAVING diff != 0\n"
|
||||||
|
"ORDER BY t.data_address\n";
|
||||||
|
|
||||||
|
res = db->query(ss.str().c_str(), true);
|
||||||
|
ss.str("");
|
||||||
|
ss.clear();
|
||||||
|
if (res && mysql_num_rows(res) == 0) {
|
||||||
|
std::cout << " OK" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << " FAILED: MAX(instr2)-MIN(instr1)+1 == SUM(instr2-instr1+1) not true for all fault-space rows" << std::endl;
|
||||||
|
// TODO: show a list of failing data_addresses?
|
||||||
|
all_ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG << "Sanity check: Global min/max = FS row local min/max ..." << std::flush;
|
||||||
|
ss <<
|
||||||
|
"SELECT t.variant_id, local.data_address, global.min_instr, global.max_instr, local.min_instr, local.max_instr\n"
|
||||||
|
"FROM trace t\n"
|
||||||
|
"JOIN\n"
|
||||||
|
" (SELECT t2.variant_id, MIN(instr1) AS min_instr, MAX(instr2) AS max_instr\n"
|
||||||
|
" FROM trace t2\n"
|
||||||
|
" GROUP BY t2.variant_id) AS global\n"
|
||||||
|
" ON global.variant_id = t.variant_id\n"
|
||||||
|
"JOIN\n"
|
||||||
|
" (SELECT variant_id, data_address, MIN(instr1) AS min_instr, MAX(instr2) AS max_instr\n"
|
||||||
|
" FROM trace t3\n"
|
||||||
|
" GROUP BY t3.variant_id, t3.data_address) AS local\n"
|
||||||
|
" ON local.variant_id = t.variant_id\n"
|
||||||
|
"AND (local.min_instr != global.min_instr\n"
|
||||||
|
" OR local.max_instr != global.max_instr)\n"
|
||||||
|
"WHERE t.variant_id = " << m_variant_id << "\n"
|
||||||
|
"GROUP BY t.variant_id, local.data_address\n";
|
||||||
|
|
||||||
|
res = db->query(ss.str().c_str(), true);
|
||||||
|
ss.str("");
|
||||||
|
ss.clear();
|
||||||
|
if (res && mysql_num_rows(res) == 0) {
|
||||||
|
std::cout << " OK" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << " FAILED: global MIN(instr1)/MAX(instr2) != row-local MIN(instr1)/MAX(instr2)" << std::endl;
|
||||||
|
// TODO: show a list of failing data_addresses and global min/max?
|
||||||
|
all_ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!all_ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,11 +16,13 @@ protected:
|
|||||||
fail::ElfReader *m_elf;
|
fail::ElfReader *m_elf;
|
||||||
fail::MemoryMap *m_mm;
|
fail::MemoryMap *m_mm;
|
||||||
char m_faultspace_rightmargin;
|
char m_faultspace_rightmargin;
|
||||||
|
bool m_sanitychecks;
|
||||||
fail::Database *db;
|
fail::Database *db;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef unsigned instruction_count_t; //!< not big enough for some benchmarks
|
typedef unsigned instruction_count_t; //!< not big enough for some benchmarks
|
||||||
|
|
||||||
|
Importer() : m_sanitychecks(false) {}
|
||||||
bool init(const std::string &variant, const std::string &benchmark, fail::Database *db);
|
bool init(const std::string &variant, const std::string &benchmark, fail::Database *db);
|
||||||
|
|
||||||
virtual bool create_database() = 0;
|
virtual bool create_database() = 0;
|
||||||
@ -33,6 +35,7 @@ public:
|
|||||||
void set_elf_file(fail::ElfReader *elf) { m_elf = elf; }
|
void set_elf_file(fail::ElfReader *elf) { m_elf = elf; }
|
||||||
void set_memorymap(fail::MemoryMap *mm) { m_mm = mm; }
|
void set_memorymap(fail::MemoryMap *mm) { m_mm = mm; }
|
||||||
void set_faultspace_rightmargin(char accesstype) { m_faultspace_rightmargin = accesstype; }
|
void set_faultspace_rightmargin(char accesstype) { m_faultspace_rightmargin = accesstype; }
|
||||||
|
void set_sanitychecks(bool enabled) { m_sanitychecks = enabled; }
|
||||||
protected:
|
protected:
|
||||||
private:
|
private:
|
||||||
struct leftmargin_info_t { instruction_count_t dyninstr; fail::simtime_t time; };
|
struct leftmargin_info_t { instruction_count_t dyninstr; fail::simtime_t time; };
|
||||||
|
|||||||
@ -100,6 +100,11 @@ int main(int argc, char *argv[]) {
|
|||||||
// "--faultspace-cutoff-end \tCut off fault space end (no, lastr) "
|
// "--faultspace-cutoff-end \tCut off fault space end (no, lastr) "
|
||||||
// "(default: no)");
|
// "(default: no)");
|
||||||
|
|
||||||
|
CommandLine::option_handle ENABLE_SANITYCHECKS =
|
||||||
|
cmd.addOption("", "enable-sanitychecks", Arg::None,
|
||||||
|
"--enable-sanitychecks \tEnable sanity checks "
|
||||||
|
"(in case something looks fishy)"
|
||||||
|
"(default: disabled)");
|
||||||
|
|
||||||
if (!cmd.parse()) {
|
if (!cmd.parse()) {
|
||||||
std::cerr << "Error parsing arguments." << std::endl;
|
std::cerr << "Error parsing arguments." << std::endl;
|
||||||
@ -181,6 +186,10 @@ int main(int argc, char *argv[]) {
|
|||||||
importer->set_faultspace_rightmargin('W');
|
importer->set_faultspace_rightmargin('W');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd[ENABLE_SANITYCHECKS].count() > 0) {
|
||||||
|
importer->set_sanitychecks(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (!importer->init(variant, benchmark, db)) {
|
if (!importer->init(variant, benchmark, db)) {
|
||||||
LOG << "importer->init() failed" << endl;
|
LOG << "importer->init() failed" << endl;
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|||||||
Reference in New Issue
Block a user