From 52baab2d762011ce52164ccc3619bbf8fec60795 Mon Sep 17 00:00:00 2001 From: Michael Lenz Date: Mon, 8 Feb 2016 15:44:34 +0100 Subject: [PATCH 01/23] faultspaceplot as analysis tool This change adds the faultspace-plotting scripts into FAIL*'s tools/analysis/ folder and makes it CMake-configurable. Change-Id: I9364a448a33853520629291721a6ed6d4e82eb32 --- doc/how-to-build.txt | 1 + tools/CMakeLists.txt | 6 + tools/analysis/faultspaceplot/CMakeLists.txt | 1 + .../analysis/faultspaceplot/faultspaceplot.sh | 51 ++++++++ .../faultspaceplot/fsp.compact-horizontal.sh | 52 +++++++++ .../faultspaceplot/fsp.compact-vertical.sh | 63 ++++++++++ tools/analysis/faultspaceplot/fsp.compact.sh | 43 +++++++ tools/analysis/faultspaceplot/fsp.plot.py | 110 ++++++++++++++++++ 8 files changed, 327 insertions(+) create mode 100644 tools/analysis/faultspaceplot/CMakeLists.txt create mode 100755 tools/analysis/faultspaceplot/faultspaceplot.sh create mode 100755 tools/analysis/faultspaceplot/fsp.compact-horizontal.sh create mode 100755 tools/analysis/faultspaceplot/fsp.compact-vertical.sh create mode 100755 tools/analysis/faultspaceplot/fsp.compact.sh create mode 100755 tools/analysis/faultspaceplot/fsp.plot.py diff --git a/doc/how-to-build.txt b/doc/how-to-build.txt index 10553c35..b8e0acd5 100644 --- a/doc/how-to-build.txt +++ b/doc/how-to-build.txt @@ -33,6 +33,7 @@ Required for Fail*: * a MySQL 5.0+ or MariaDB 5.1+ (MariaDB 5.5 recommended) server * doxygen * cmake-curses-gui + * python-numpy and python-matplotlib for the faultspaceplot tool diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 269dc4b9..3f0b2f58 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -6,6 +6,8 @@ option(BUILD_CONVERT_TRACE "Build the trace converter tool?" OFF) option(BUILD_COMPUTE_HOPS "Build the compute hops tool?" OFF) option(BUILD_DUMP_HOPS "Build the hops dump tool?" OFF) +option(BUILD_FAULTSPACEPLOT "Build the faultspace plotting tool?" OFF) + ### Setup search paths for headers ## include_directories(${CMAKE_CURRENT_BINARY_DIR}/../src/core) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/core) @@ -33,3 +35,7 @@ endif(BUILD_COMPUTE_HOPS) if(BUILD_DUMP_HOPS) add_subdirectory(dump-hops) endif(BUILD_DUMP_HOPS) + +if(BUILD_FAULTSPACEPLOT) + add_subdirectory(analysis/faultspaceplot) +endif(BUILD_FAULTSPACEPLOT) diff --git a/tools/analysis/faultspaceplot/CMakeLists.txt b/tools/analysis/faultspaceplot/CMakeLists.txt new file mode 100644 index 00000000..d3c83219 --- /dev/null +++ b/tools/analysis/faultspaceplot/CMakeLists.txt @@ -0,0 +1 @@ +install(PROGRAMS faultspaceplot.sh fsp.compact-horizontal.sh fsp.compact.sh fsp.compact-vertical.sh fsp.plot.py DESTINATION bin) diff --git a/tools/analysis/faultspaceplot/faultspaceplot.sh b/tools/analysis/faultspaceplot/faultspaceplot.sh new file mode 100755 index 00000000..168ea168 --- /dev/null +++ b/tools/analysis/faultspaceplot/faultspaceplot.sh @@ -0,0 +1,51 @@ +#!/bin/bash +set -e + +if [ ! $# -eq 3 ]; then + echo "usage: $0 DATABASE VARIANT BENCHMARK" >&2 + exit 1 +fi + +DATABASE=$1 +VARIANT=$2 +BENCHMARK=$3 +# add "-t" for more readable output +MYSQL="mysql -B --quick $DATABASE" + +# get data +echo "getting faultspace data.." +$MYSQL < "$VARIANT"_"$BENCHMARK"-raw.csv + SELECT t.time1 - (SELECT MIN(t2.time1) FROM trace t2 WHERE t.variant_id = t2.variant_id) AS time1, + t.time2 - (SELECT MIN(t2.time1) FROM trace t2 WHERE t.variant_id = t2.variant_id) AS time2, + t.data_address, r.bitoffset, 1, + CASE + WHEN r.resulttype = 'OK_MARKER' THEN '#FFFFFF' + WHEN r.resulttype = 'FAIL_MARKER' THEN '#EE0000' + WHEN r.resulttype = 'DETECTED_MARKER' THEN '#00FF00' + WHEN r.resulttype = 'GROUP0_MARKER' THEN '#EAEAEA' + WHEN r.resulttype = 'GROUP1_MARKER' THEN '#EBEBEB' + WHEN r.resulttype = 'GROUP2_MARKER' THEN '#ECECEC' + WHEN r.resulttype = 'GROUP3_MARKER' THEN '#EDEDED' + WHEN r.resulttype = 'TIMEOUT' THEN '#00EE00' + WHEN r.resulttype = 'TRAP' THEN '#00DD00' + WHEN r.resulttype = 'WRITE_TEXTSEGMENT' THEN '#0000AA' + WHEN r.resulttype = 'WRITE_OUTERSPACE' THEN '#0000BB' + WHEN r.resulttype = 'SDC' THEN '#FF0000' + WHEN r.resulttype = 'UNKNOWN' THEN '#000000' + END AS color + FROM trace t + JOIN fspgroup g ON t.variant_id = g.variant_id AND t.data_address = g.data_address AND t.instr2 = g.instr2 + JOIN variant v ON v.id = t.variant_id + JOIN result_GenericExperimentMessage r ON r.pilot_id=g.pilot_id + WHERE + v.variant = '$VARIANT' AND v.benchmark = '$BENCHMARK' + AND t.accesstype = 'R'; +EOT + +# compact data +echo "compacting data.." +fsp.compact.sh "$VARIANT"_"$BENCHMARK"-raw.csv "$VARIANT"_"$BENCHMARK"-plot.csv + +# plot data +echo "plotting.." +fsp.plot.py "$VARIANT"_"$BENCHMARK"-plot.csv diff --git a/tools/analysis/faultspaceplot/fsp.compact-horizontal.sh b/tools/analysis/faultspaceplot/fsp.compact-horizontal.sh new file mode 100755 index 00000000..82710868 --- /dev/null +++ b/tools/analysis/faultspaceplot/fsp.compact-horizontal.sh @@ -0,0 +1,52 @@ +#!/bin/bash +set -e + +TMP=$(mktemp) + +read HEADER +echo "$HEADER" + +BASE='' +LAST='' +sort -snk 1 | sort -snk 4 | sort -snk 3 > $TMP + +while read CUR +do + a=($CUR) + C_I1=${a[0]} + C_I2=${a[1]} + C_ADDR=${a[2]} + C_BIT=${a[3]} + C_BW=${a[4]} + C_COL=${a[5]} + + if [ -z "$BASE" ] + then + BASE=$CUR + LAST=$CUR + elif (($C_I1 != $L_I2 + 1 || $L_ADDR != $C_ADDR || $L_BIT != $C_BIT || $L_BW != $C_BW)) || \ + [ "$C_COL" != "$L_COL" ] + then + a=($BASE) + B_I1=${a[0]} + + echo -e "$B_I1\t$L_I2\t$L_ADDR\t$L_BIT\t$L_BW\t$L_COL" + + BASE=$CUR + fi + + LAST="$CUR" + L_I1=$C_I1 + L_I2=$C_I2 + L_ADDR=$C_ADDR + L_BIT=$C_BIT + L_BW=$C_BW + L_COL=$C_COL +done < $TMP + +a=($BASE) +B_I1=${a[0]} + +echo -e "$B_I1\t$L_I2\t$L_ADDR\t$L_BIT\t$L_BW\t$L_COL" + +rm $TMP diff --git a/tools/analysis/faultspaceplot/fsp.compact-vertical.sh b/tools/analysis/faultspaceplot/fsp.compact-vertical.sh new file mode 100755 index 00000000..f819a643 --- /dev/null +++ b/tools/analysis/faultspaceplot/fsp.compact-vertical.sh @@ -0,0 +1,63 @@ +#!/bin/bash +set -e + +TMP=$(mktemp) + +read HEADER +echo "$HEADER" + +BASE='' +LAST='' +sort -snk 4 | sort -snk 3 | sort -snk 1 > $TMP + +while read CUR +do + a=($CUR) + C_I1=${a[0]} + C_I2=${a[1]} + C_ADDR=${a[2]} + C_BIT=${a[3]} + C_BW=${a[4]} + C_COL=${a[5]} + C_N=$(($C_ADDR*8 + $C_BIT)) + + if [ -z "$BASE" ] + then + BASE=$CUR + LAST=$CUR + elif (($C_I1 != $L_I1 || $C_I2 != $L_I2 || \ + $L_N + $L_BW != $C_N)) || \ + [ "$C_COL" != "$L_COL" ] + then + a=($BASE) + B_ADDR=${a[2]} + B_BIT=${a[3]} + B_N=$(($B_ADDR*8 + $B_BIT)) + + BW=$(($L_N + $L_BW - $B_N)) + + echo -e "$L_I1\t$L_I2\t$B_ADDR\t$B_BIT\t$BW\t$L_COL" + + BASE=$CUR + fi + + LAST="$CUR" + L_I1=$C_I1 + L_I2=$C_I2 + L_ADDR=$C_ADDR + L_BIT=$C_BIT + L_BW=$C_BW + L_COL=$C_COL + L_N=$C_N +done < $TMP + +a=($BASE) +B_ADDR=${a[2]} +B_BIT=${a[3]} +B_N=$(($B_ADDR*8 + $B_BIT)) + +BW=$(($L_N + $L_BW - $B_N)) + +echo -e "$L_I1\t$L_I2\t$B_ADDR\t$B_BIT\t$BW\t$L_COL" + +rm $TMP diff --git a/tools/analysis/faultspaceplot/fsp.compact.sh b/tools/analysis/faultspaceplot/fsp.compact.sh new file mode 100755 index 00000000..bd291339 --- /dev/null +++ b/tools/analysis/faultspaceplot/fsp.compact.sh @@ -0,0 +1,43 @@ +#!/bin/bash +set -e + +FIRST=vertical + +[ $# -lt 2 -o $# -gt 3 ] && echo "usage: $0 input.csv output.csv [vertical|horizontal]" >&2 && exit 1 + +if [ -z $3 ]; then + FIRST=vertical +else + FIRST=$3 +fi + +TMP1=$(mktemp) +TMP2=$(mktemp) + +cp $1 $TMP1 +COUNT=$(wc -l <$TMP1) + +NEXT=$FIRST + +while true +do + echo "at $COUNT, $NEXT ..." + fsp.compact-$NEXT.sh < $TMP1 > $TMP2 + + PREVCOUNT=$COUNT + COUNT=$(wc -l <$TMP2) + + if (($COUNT >= $PREVCOUNT)) + then + echo "no improvement (now $COUNT), stop." + cp $TMP1 $2 + break + fi + + mv $TMP2 $TMP1 + if [ $NEXT = vertical ]; then + NEXT=horizontal + else + NEXT=vertical + fi +done diff --git a/tools/analysis/faultspaceplot/fsp.plot.py b/tools/analysis/faultspaceplot/fsp.plot.py new file mode 100755 index 00000000..510b1eed --- /dev/null +++ b/tools/analysis/faultspaceplot/fsp.plot.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python + +# ------------------------------------------------------------------------- +# Import modules +import csv, sys +import matplotlib.pyplot as plt +import numpy as np +import matplotlib.patches as mpatches +import matplotlib.pylab as pylab + +ENTRY_COUNT_PER_LINE = 6 +RESULT_RECT_HEIGHT = 1.0/8 + +# ------------------------------------------------------------------------- +# Basic drawing class +class Rectangle: + def __init__(self, x, y, w, h, color): + # w + self.xpos = x # |-------------------| + self.ypos = y # | | h + self.width = w # | | + self.height = h # (x,y)---------------| + self.color = color # fill color + self.alpha = None # transparency level [0,1] + def draw(self): + """ Draw the rectangle. """ + if self.color == (1,1,1): + return + tmp = self.xpos, self.ypos, + p = mpatches.Rectangle(tmp, self.width, self.height, color=self.color, \ + alpha=self.alpha) + plt.gca().add_patch(p) + +# ------------------------------------------------------------------------- +# Check provided arguments: +if len(sys.argv) <= 1: + print "ERROR: Not enough arguments provided! See -h for more infos." + exit(1) +if sys.argv[1] == '-h': + print "Displays experiment results for the weather-monitor-experiment." + print " CALL-SYNTAX: fsp.plot.py DATA_FILE [USER_TAG_FILE]" + print "DATA_FILE is a CSV-file, storing the tab-separated values" + print "retrieved by the experiment run. USER_TAG_FILE is an optional" + print "CSV-file which can be used to add user-specific marks to the" + print "plot (not implemented yet)." # TODO: be more precise here + exit(0) + +print "WARNING: This script needs a newer version of Matplotlib for axis label rotation; run this on Ubuntu 12.10 or alike." + +print "Opening and processing \"" + sys.argv[1] + "\"..." +file = open(sys.argv[1], "r") +dialect = csv.Sniffer().sniff(file.read(1024)) +file.seek(0) +reader = csv.reader(file, dialect) +reader.next() # Move down a line to skip the header + +fig = plt.figure() + +xmin = 99999999 +xmax = 0 +ymin = 99999999 +ymax = 0 + +line_counter = 1 +for row in reader: + line_counter += 1 + # Check if there are at least ENTRY_COUNT_PER_LINE entries per line: + if len(row) != ENTRY_COUNT_PER_LINE: + print "ERROR: Line " + str(line_counter) + " is invalid (" +\ + str(ENTRY_COUNT_PER_LINE) + " entries expected)" + sys.exit(1) + + # Some constants to access the row-entries much easier: + IDX_INSTR1 = 0; IDX_INSTR2 = 1; IDX_DATA_ADDRESS = 2; + IDX_BITNR = 3; IDX_BITWIDTH = 4; IDX_COLOR = 5; + + # Update xmin/xmax/ymin/ymax + x1 = int(row[IDX_INSTR1]) + x2 = int(row[IDX_INSTR2]) + 1 # inclusive + width = x2 - x1 + if xmin > x1: + xmin = x1 + if xmax < x2: + xmax = x2 + + y1 = float(row[IDX_DATA_ADDRESS]) + float(row[IDX_BITNR]) / 8.0 + height = float(row[IDX_BITWIDTH]) / 8.0 + y2 = y1 + height + + if ymin > y1: + ymin = y1 + if ymax < y2: + ymax = y2 + + Rectangle(x1, y1, width, height, row[IDX_COLOR]).draw() + if line_counter == 50000: # debug stuff + pass + #break + +ymin = int(ymin / 1000) * 1000 + +file.close() +plt.xlim(xmin, xmax) +plt.ylim(ymin, ymax) + +plt.ylabel('Data Memory (RAM)') +plt.xlabel('Time (Cycles)') + +plt.show() +#pylab.savefig('baseline.pdf', bbox_inches='tight') From bcf75bceee3782c8a47a1c9d9defbc5250f0ad12 Mon Sep 17 00:00:00 2001 From: Michael Lenz Date: Wed, 10 Feb 2016 10:21:31 +0100 Subject: [PATCH 02/23] GenericExperiment: target ELF file now specifiable Up until now only generic-tracing had the feature to directly pass an ELF file to the experiment. generic-experiment lacked that functionality and resorted to using the $FAIL_ELF_PATH environment variable. This change introduces the "--elf-file" command line argument to generic-experiment. Change-Id: Ie74de9e1781275ab247786856e13e412bac39224 --- .../generic-experiment/experiment.cc | 30 ++++++++++++++++--- .../generic-experiment/experiment.hpp | 3 +- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/experiments/generic-experiment/experiment.cc b/src/experiments/generic-experiment/experiment.cc index c11cb690..496df53e 100644 --- a/src/experiments/generic-experiment/experiment.cc +++ b/src/experiments/generic-experiment/experiment.cc @@ -56,7 +56,7 @@ void GenericExperiment::parseSymbols(const std::string &args, std::setgetSymbol(item)); if (!symbol->isValid()) { m_log << "ELF Symbol not found: " << item << endl; simulator.terminate(1); @@ -76,6 +76,9 @@ bool GenericExperiment::cb_start_experiment() { cmd.addOption("", "", Arg::None, "USAGE: fail-client -Wf,[option] -Wf,[option] ... \n\n"); CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h,--help \tPrint usage and exit"); + CommandLine::option_handle ELF_FILE = cmd.addOption("", "elf-file", Arg::Required, + "--elf-file \tELF Binary File (default: $FAIL_ELF_PATH)"); + CommandLine::option_handle STATE_DIR = cmd.addOption("", "state-dir", Arg::Required, "--state-dir \t Path to the state directory"); @@ -104,7 +107,7 @@ bool GenericExperiment::cb_start_experiment() { if (!cmd.parse()) { cerr << "Error parsing arguments." << endl; - exit(-1); + exit(1); } if (cmd[HELP]) { @@ -112,13 +115,32 @@ bool GenericExperiment::cb_start_experiment() { exit(0); } + if (cmd[ELF_FILE]) { + elf_file = cmd[ELF_FILE].first()->arg; + m_elf = new ElfReader(elf_file.c_str()); + m_log << "ELF file specified: " << elf_file << std::endl; + } else { + char *elfpath = getenv("FAIL_ELF_PATH"); + if (elfpath == NULL) { + m_elf = NULL; + } else { + elf_file = elfpath; + m_elf = new ElfReader(elf_file.c_str()); + m_log << "ELF file via environment variable: " << elf_file << std::endl; + } + } + if (m_elf == NULL) { + m_log << "ERROR: no FAIL_ELF_PATH set or --elf-file given. exiting!" << std::endl; + exit(1); + } + address_t minimal_ip = INT_MAX; // Every address is lower address_t maximal_ip = 0; address_t minimal_data = 0x100000; // 1 Mbyte address_t maximal_data = 0; - for (ElfReader::section_iterator it = m_elf.sec_begin(); - it != m_elf.sec_end(); ++it) { + for (ElfReader::section_iterator it = m_elf->sec_begin(); + it != m_elf->sec_end(); ++it) { const ElfSymbol &symbol = *it; std::string prefix(".text"); if (symbol.getName().compare(0, prefix.size(), prefix) == 0) { diff --git a/src/experiments/generic-experiment/experiment.hpp b/src/experiments/generic-experiment/experiment.hpp index 9d63f338..ae63e9bb 100644 --- a/src/experiments/generic-experiment/experiment.hpp +++ b/src/experiments/generic-experiment/experiment.hpp @@ -14,7 +14,8 @@ class GenericExperiment : public fail::DatabaseExperiment { - fail::ElfReader m_elf; + fail::ElfReader *m_elf; + std::string elf_file; std::string m_state_dir; From ad558abeb6209353947f05a5fc5e38305e3f7145 Mon Sep 17 00:00:00 2001 From: Michael Lenz Date: Wed, 10 Feb 2016 12:12:24 +0100 Subject: [PATCH 03/23] DatabaseCampaign/-Experiment: add burst faults This change introduces the ability to inject burst faults to the DatabaseCampaign/-Experiment and thus to all derived campaigns/experiments. Change-Id: I491d021ed3953562bd7c908e9de50d448bc8ef33 --- .../comm/DatabaseCampaignMessage.proto.in | 7 ++++-- src/core/cpn/DatabaseCampaign.cc | 14 ++++++++++- src/core/cpn/DatabaseCampaign.hpp | 6 ++++- src/core/efw/DatabaseExperiment.cc | 25 ++++++++++++++++--- src/core/efw/DatabaseExperiment.hpp | 1 + 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/core/comm/DatabaseCampaignMessage.proto.in b/src/core/comm/DatabaseCampaignMessage.proto.in index 9e4c4dbc..3389b223 100644 --- a/src/core/comm/DatabaseCampaignMessage.proto.in +++ b/src/core/comm/DatabaseCampaignMessage.proto.in @@ -19,9 +19,12 @@ message DatabaseCampaignMessage { required string benchmark = 9 [(sql_ignore) = true]; required InjectionPointMessage injection_point = 10 [(sql_ignore) = true]; + + required bool inject_bursts = 11 [default = false]; } message DatabaseExperimentMessage { - required uint32 bitoffset = 1 [(sql_primary_key) = true]; - required uint32 original_value = 2; + required uint32 bitoffset = 1 [(sql_primary_key) = true]; + required uint32 original_value = 2; + required uint32 injection_width = 3; } diff --git a/src/core/cpn/DatabaseCampaign.cc b/src/core/cpn/DatabaseCampaign.cc index 1d445df1..c093e70d 100644 --- a/src/core/cpn/DatabaseCampaign.cc +++ b/src/core/cpn/DatabaseCampaign.cc @@ -46,6 +46,10 @@ bool DatabaseCampaign::run() { cmd.addOption("p", "prune-method", Arg::Required, "-p/--prune-method \tWhich import method(s) to use (default: \"%\"; use % and _ as wildcard characters)"); + CommandLine::option_handle BURST = + cmd.addOption("","inject-bursts", Arg::None, + "--inject-bursts \tinject burst faults (default: single bitflips)"); + if (!cmd.parse()) { log_send << "Error parsing arguments." << std::endl; exit(-1); @@ -91,6 +95,14 @@ bool DatabaseCampaign::run() { benchmarks.push_back("%"); } + if (cmd[BURST]) { + m_inject_bursts = true; + log_send << "fault model: burst" << std::endl; + } else { + m_inject_bursts = false; + log_send << "fault model: single-bit flip" << std::endl; + } + if (cmd[PRUNER]) { m_fspmethod = std::string(cmd[PRUNER].first()->arg); } else { @@ -225,7 +237,7 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) { } pilot.set_data_address(data_address); pilot.set_data_width(data_width); - + pilot.set_inject_bursts(m_inject_bursts); this->cb_send_pilot(pilot); diff --git a/src/core/cpn/DatabaseCampaign.hpp b/src/core/cpn/DatabaseCampaign.hpp index 97bafc30..6546d722 100644 --- a/src/core/cpn/DatabaseCampaign.hpp +++ b/src/core/cpn/DatabaseCampaign.hpp @@ -39,6 +39,8 @@ class DatabaseCampaign : public Campaign { id_map completed_pilots; // !< map: Pilot IDs -> result count #endif + bool m_inject_bursts; // !< inject burst faults? + public: DatabaseCampaign() {}; @@ -61,7 +63,9 @@ public: * there are less result rows, the pilot will be again sent to the clients * @return \c exptected number of results */ - virtual int expected_number_of_results(std::string variant, std::string benchmark) { return 8;} + virtual int expected_number_of_results(std::string variant, std::string benchmark) { + return (m_inject_bursts ? 1 : 8); + } /** * Callback function that can be used to add command line options diff --git a/src/core/efw/DatabaseExperiment.cc b/src/core/efw/DatabaseExperiment.cc index 7cc67d30..7a2bf6d4 100644 --- a/src/core/efw/DatabaseExperiment.cc +++ b/src/core/efw/DatabaseExperiment.cc @@ -27,6 +27,18 @@ DatabaseExperiment::~DatabaseExperiment() { delete this->m_jc; } +unsigned DatabaseExperiment::injectBurst(address_t data_address) { + unsigned value, burst_value; + value = m_mm.getByte(data_address); + burst_value = value ^ 0xff; + m_mm.setByte(data_address, burst_value); + + m_log << "INJECTED BURST at: 0x" << hex<< setw(2) << setfill('0') << data_address + << " value: 0x" << setw(2) << setfill('0') << value << " -> 0x" + << setw(2) << setfill('0') << burst_value << endl; + return value; +} + unsigned DatabaseExperiment::injectBitFlip(address_t data_address, unsigned bitpos){ unsigned int value, injectedval; @@ -92,8 +104,9 @@ bool DatabaseExperiment::run() unsigned injection_instr = fsppilot->injection_instr(); address_t data_address = fsppilot->data_address(); unsigned width = fsppilot->data_width(); + unsigned injection_width = fsppilot->inject_bursts() ? 8 : 1; - for (unsigned bit_offset = 0; bit_offset < width * 8; ++bit_offset) { + for (unsigned bit_offset = 0; bit_offset < width * 8; bit_offset += injection_width) { // 8 results in one job Message *outer_result = cb_new_result(param); m_current_result = outer_result; @@ -157,8 +170,14 @@ bool DatabaseExperiment::run() simulator.clearListeners(); - /// INJECT BITFLIP: - result->set_original_value(injectBitFlip(data_address, bit_offset)); + if (fsppilot->inject_bursts()) { + /// INJECT BURST: + result->set_original_value(injectBurst((data_address+bit_offset/8))); + } else { + /// INJECT BITFLIP: + result->set_original_value(injectBitFlip(data_address, bit_offset)); + } + result->set_injection_width(injection_width); if (!this->cb_before_resume()) { continue; // Continue to next experiment diff --git a/src/core/efw/DatabaseExperiment.hpp b/src/core/efw/DatabaseExperiment.hpp index f60ddf9a..71fae098 100644 --- a/src/core/efw/DatabaseExperiment.hpp +++ b/src/core/efw/DatabaseExperiment.hpp @@ -15,6 +15,7 @@ class DatabaseExperiment : public fail::ExperimentFlow { fail::JobClient *m_jc; unsigned injectBitFlip(fail::address_t data_address, unsigned bitpos); + unsigned injectBurst(fail::address_t data_address); /** The current experiment data as returned by the job client. This From d46b81eb3deea340bc55fb214eaeed4052a2ee96 Mon Sep 17 00:00:00 2001 From: Michael Lenz Date: Wed, 10 Feb 2016 12:15:01 +0100 Subject: [PATCH 04/23] GenericTracing/-Experiment: add SDC detection This change adds detection of SDCs to GenericTracing and GenericExperiment via Bochs's I/O port E9. Change-Id: Ie036aa97468b45cad94b6c8f73d1ef2d227547b2 --- .../generic-experiment/experiment.cc | 48 ++++++++++++++++++- .../generic-experiment/experiment.hpp | 6 +++ .../generic-experiment.proto | 4 +- src/experiments/generic-tracing/experiment.cc | 27 +++++++++++ .../generic-tracing/experiment.hpp | 2 + 5 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/experiments/generic-experiment/experiment.cc b/src/experiments/generic-experiment/experiment.cc index 496df53e..680d233f 100644 --- a/src/experiments/generic-experiment/experiment.cc +++ b/src/experiments/generic-experiment/experiment.cc @@ -42,6 +42,23 @@ google::protobuf::Message* GenericExperiment::cb_new_result(ExperimentData* data return result; } +std::vector loadFile(std::string filename) +{ + std::vector data; + FILE *f = fopen(filename.c_str(), "rb"); + if (!f) { + return data; + } + fseek(f, 0, SEEK_END); + long len = ftell(f); + fseek(f, 0, SEEK_SET); + if (len > 0) { + data.resize(len); + fread(&data[0], len, 1, f); + } + fclose(f); + return data; +} void handleEvent(GenericExperimentMessage_Result& result, GenericExperimentMessage_Result_ResultType restype, @@ -95,6 +112,9 @@ bool GenericExperiment::cb_start_experiment() { CommandLine::option_handle TIMEOUT = cmd.addOption("", "timeout", Arg::Required, "--timeout \t Experiment Timeout in uS"); + CommandLine::option_handle E9_FILE = cmd.addOption("", "e9-file", Arg::Required, + "--e9-file FILE \t data logged via port 0xE9 in golden run"); + std::map option_handles; for (std::map::iterator it = end_marker_groups.begin(); @@ -152,6 +172,12 @@ bool GenericExperiment::cb_start_experiment() { } } + if (cmd[E9_FILE]) { + m_log << "enabled logging on port E9 for SDC-detection" << std::endl; + enabled_e9_sol = true; + e9_file = std::string(cmd[E9_FILE].first()->arg); + } + if (cmd[WRITE_MEM_TEXT]) { m_log << "Catch writes to text segment from " << hex << minimal_ip << " to " << maximal_ip << std::endl; enabled_mem_text = true; @@ -229,6 +255,10 @@ bool GenericExperiment::cb_before_resume() { simulator.addListener(*it); } + if (enabled_e9_sol) { + simulator.addFlow(&e9_sol); + } + return true; // everything OK } @@ -238,7 +268,6 @@ void GenericExperiment::cb_after_resume(fail::BaseListener *event) { // Record the crash time result->set_crash_time(simulator.getTimerTicks()); - if (event == &l_timeout) { handleEvent(*result, result->TIMEOUT, m_Timeout); } else if (event == &l_trap) { @@ -258,6 +287,17 @@ void GenericExperiment::cb_after_resume(fail::BaseListener *event) { const ElfSymbol *symbol = listener_to_symbol[event]; handleEvent(*result, result->OK_MARKER, symbol->getAddress()); + // check experiment's data for SDC + if (enabled_e9_sol) { + // compare golden run to experiment + std::vector e9_goldenrun = loadFile(e9_file); + std::string e9_experiment = e9_sol.getOutput(); + if ( ! (e9_experiment.size() == e9_goldenrun.size() + && equal(e9_experiment.begin(), e9_experiment.end(), e9_goldenrun.begin())) ) { + handleEvent(*result, result->SDC, 0); + } + } + } else if (FAIL_marker.find(event) != FAIL_marker.end()) { const ElfSymbol *symbol = listener_to_symbol[event]; handleEvent(*result, result->FAIL_MARKER, symbol->getAddress()); @@ -285,4 +325,10 @@ void GenericExperiment::cb_after_resume(fail::BaseListener *event) { } else { handleEvent(*result, result->UNKNOWN, 0); } + + // remove and reset 0xE9 logger even if this run was not "OK" + if (enabled_e9_sol) { + simulator.removeFlow(&e9_sol); + e9_sol.resetOutput(); + } } diff --git a/src/experiments/generic-experiment/experiment.hpp b/src/experiments/generic-experiment/experiment.hpp index ae63e9bb..81358b0a 100644 --- a/src/experiments/generic-experiment/experiment.hpp +++ b/src/experiments/generic-experiment/experiment.hpp @@ -7,6 +7,7 @@ #include "efw/JobClient.hpp" #include "util/Logger.hpp" #include "util/ElfReader.hpp" +#include "../plugins/serialoutput/SerialOutputLogger.hpp" #include #include #include @@ -19,6 +20,10 @@ class GenericExperiment : public fail::DatabaseExperiment { std::string m_state_dir; + bool enabled_e9_sol; + std::string e9_file; + SerialOutputLogger e9_sol; + bool enabled_mem_text; fail::MemAccessListener l_mem_text; @@ -52,6 +57,7 @@ class GenericExperiment : public fail::DatabaseExperiment { public: GenericExperiment() : DatabaseExperiment("GenericExperiment"), m_state_dir("state"), + e9_sol(0xE9), l_trap(fail::ANY_TRAP), l_timeout(0) { enabled_mem_text = false; enabled_mem_outerspace = false; diff --git a/src/experiments/generic-experiment/generic-experiment.proto b/src/experiments/generic-experiment/generic-experiment.proto index 09b25fc6..9baaf4a4 100644 --- a/src/experiments/generic-experiment/generic-experiment.proto +++ b/src/experiments/generic-experiment/generic-experiment.proto @@ -13,7 +13,7 @@ message GenericExperimentMessage { OK_MARKER = 1; FAIL_MARKER = 2; DETECTED_MARKER = 3; - + GROUP1_MARKER = 4; GROUP2_MARKER = 5; GROUP3_MARKER = 6; @@ -24,6 +24,8 @@ message GenericExperimentMessage { WRITE_TEXTSEGMENT = 10; WRITE_OUTERSPACE = 11; + SDC = 12; + UNKNOWN = 100; } // result type, see above diff --git a/src/experiments/generic-tracing/experiment.cc b/src/experiments/generic-tracing/experiment.cc index 7ce02d6f..4e3f450a 100644 --- a/src/experiments/generic-tracing/experiment.cc +++ b/src/experiments/generic-tracing/experiment.cc @@ -67,6 +67,8 @@ void GenericTracing::parseOptions() { "--serial-port \tListen to a given I/O address (default: 0x3F8)"); CommandLine::option_handle SERIAL_FILE = cmd.addOption("", "serial-file", Arg::Required, "--serial-file \tSave the serial output to file"); + CommandLine::option_handle E9_FILE = cmd.addOption("", "e9-file", Arg::Required, + "--e9-file FILE \tData logged via port 0xE9 is stored in this file"); if (!cmd.parse()) { cerr << "Error parsing arguments." << endl; @@ -228,6 +230,14 @@ void GenericTracing::parseOptions() { serial_file = ""; } + if (cmd[E9_FILE]) { + e9_file = std::string(cmd[E9_FILE].first()->arg); + m_log << "port E9 output is written to: " << e9_file << std::endl; + } else { + e9_file = ""; + } + + if (m_elf != NULL) { m_log << "start/save symbol: " << start_symbol << " 0x" << std::hex << start_address << std::endl; m_log << "stop symbol: " << stop_symbol << " 0x" << std::hex << stop_address << std::endl; @@ -287,6 +297,12 @@ bool GenericTracing::run() simulator.addFlow(&sol); } + SerialOutputLogger e9_sol(0xE9); + if (e9_file != "") { + simulator.addFlow(&e9_sol); + } + + //////////////////////////////////////////////////////////////// // Step 2: Continue to the stop point simulator.addListener(&l_stop_symbol); @@ -314,6 +330,17 @@ bool GenericTracing::run() of_serial.close(); } + if (e9_file != "") { + simulator.removeFlow(&e9_sol); + ofstream of_e9(e9_file.c_str(), ios::out|ios::binary); + if (!of_e9.fail()) { + of_e9 << e9_sol.getOutput(); + } else { + m_log << "failed to write " << e9_file << endl; + } + of_e9.close(); + } + simulator.clearListeners(); simulator.terminate(); diff --git a/src/experiments/generic-tracing/experiment.hpp b/src/experiments/generic-tracing/experiment.hpp index e605cf0b..4b2364e0 100644 --- a/src/experiments/generic-tracing/experiment.hpp +++ b/src/experiments/generic-tracing/experiment.hpp @@ -28,6 +28,8 @@ class GenericTracing : public fail::ExperimentFlow { fail::guest_address_t serial_port; std::string serial_file; + std::string e9_file; + fail::Logger m_log; fail::ElfReader *m_elf; From 806c71580fe9cd4d9653f549ba2decf1b06f8f5d Mon Sep 17 00:00:00 2001 From: Michael Lenz Date: Thu, 11 Feb 2016 09:23:20 +0100 Subject: [PATCH 05/23] import-trace: add import of ELF symbols This change adds the capability to import an ELF's symbols into the database. The functionality is implemented via a shell script and will be merged into "import-trace", when it's being cleaned up sometime in the near future, but for now this suffices. Change-Id: I933783659674fcf31f5181fc13661fe10f5b9fe8 --- tools/import-trace/CMakeLists.txt | 1 + tools/import-trace/import-symbols.sh | 68 ++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100755 tools/import-trace/import-symbols.sh diff --git a/tools/import-trace/CMakeLists.txt b/tools/import-trace/CMakeLists.txt index b8a04e49..9e9d3a30 100644 --- a/tools/import-trace/CMakeLists.txt +++ b/tools/import-trace/CMakeLists.txt @@ -42,3 +42,4 @@ if (BUILD_LLVM_DISASSEMBLER) endif (BUILD_LLVM_DISASSEMBLER) install(TARGETS import-trace RUNTIME DESTINATION bin) +install(PROGRAMS import-symbols.sh DESTINATION bin) diff --git a/tools/import-trace/import-symbols.sh b/tools/import-trace/import-symbols.sh new file mode 100755 index 00000000..6fb80f59 --- /dev/null +++ b/tools/import-trace/import-symbols.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# TODO: make this part of import-trace +set -e + +# handle command line arguments +if [ ! $# -eq 4 ]; then + echo "usage: $0 DATABASE VARIANT BENCHMARK ELF" >&2 + exit 1 +fi + +DATABASE=$1 +VARIANT=$2 +BENCHMARK=$3 +ELF=$4 +TABLE=symbol +MYSQL="mysql -B --quick $DATABASE" + + +# check if ELF exists +if [ ! -e $ELF ]; then + echo "$ELF not found" >&2 + exit 1 +fi +echo "importing $VARIANT/$BENCHMARK symbols from $ELF ..." + + +# get fail*'s variant_id +ID=$(echo "SELECT id FROM variant WHERE variant='$VARIANT' AND benchmark='$BENCHMARK'" | $MYSQL -N) +if [ -z $ID ]; then + echo "no such variant/benchmark!" >&2 + exit 1 +fi + + +# generate huge SQL statement and execute +$MYSQL < Date: Thu, 11 Feb 2016 09:41:18 +0100 Subject: [PATCH 06/23] data-aggregator This change introduces a loose collection of scripts for analysis/aggregation of FAIL*'s collected data. It's going to be developed into a proper tool in the future. Change-Id: I63f14d87dd86b62817ec3d8089079d70f58c89c9 --- tools/CMakeLists.txt | 5 +++ tools/analysis/data-aggregator/CMakeLists.txt | 1 + .../data-aggregator/resulttype-occurrences.sh | 28 +++++++++++++ .../resulttype-occurrences_coverage.sh | 40 +++++++++++++++++++ .../data-aggregator/symbol-occurrences.sh | 26 ++++++++++++ .../symbol-occurrences_coverage.sh | 37 +++++++++++++++++ 6 files changed, 137 insertions(+) create mode 100644 tools/analysis/data-aggregator/CMakeLists.txt create mode 100755 tools/analysis/data-aggregator/resulttype-occurrences.sh create mode 100755 tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh create mode 100755 tools/analysis/data-aggregator/symbol-occurrences.sh create mode 100755 tools/analysis/data-aggregator/symbol-occurrences_coverage.sh diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 3f0b2f58..3a4198cc 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -7,6 +7,7 @@ option(BUILD_COMPUTE_HOPS "Build the compute hops tool?" OFF) option(BUILD_DUMP_HOPS "Build the hops dump tool?" OFF) option(BUILD_FAULTSPACEPLOT "Build the faultspace plotting tool?" OFF) +option(BUILD_DATA_AGGREGATOR "Build the data aggregation tools?" OFF) ### Setup search paths for headers ## include_directories(${CMAKE_CURRENT_BINARY_DIR}/../src/core) @@ -39,3 +40,7 @@ endif(BUILD_DUMP_HOPS) if(BUILD_FAULTSPACEPLOT) add_subdirectory(analysis/faultspaceplot) endif(BUILD_FAULTSPACEPLOT) + +if(BUILD_DATA_AGGREGATOR) + add_subdirectory(analysis/data-aggregator) +endif(BUILD_DATA_AGGREGATOR) diff --git a/tools/analysis/data-aggregator/CMakeLists.txt b/tools/analysis/data-aggregator/CMakeLists.txt new file mode 100644 index 00000000..607196dc --- /dev/null +++ b/tools/analysis/data-aggregator/CMakeLists.txt @@ -0,0 +1 @@ +install(PROGRAMS resulttype-occurrences_coverage.sh resulttype-occurrences.sh symbol-occurrences_coverage.sh symbol-occurrences.sh DESTINATION bin) diff --git a/tools/analysis/data-aggregator/resulttype-occurrences.sh b/tools/analysis/data-aggregator/resulttype-occurrences.sh new file mode 100755 index 00000000..45f7f48b --- /dev/null +++ b/tools/analysis/data-aggregator/resulttype-occurrences.sh @@ -0,0 +1,28 @@ +#!/bin/bash +set -e + +if [ ! $# -eq 3 ]; then + echo "usage: $0 DATABASE VARIANT BENCHMARK" >&2 + exit 1 +fi + +DATABASE=$1 +VARIANT=$2 +BENCHMARK=$3 +# add "-t" for more readable output +MYSQL="mysql -B --quick $DATABASE" + +$MYSQL << EOT + SET sql_mode = 'NO_UNSIGNED_SUBTRACTION'; + SELECT r.resulttype, SUM((t.time2-t.time1+1) * t.width) AS occurrences + FROM result_GenericExperimentMessage r + INNER JOIN fspgroup g ON g.pilot_id=r.pilot_id + INNER JOIN trace t ON g.instr2=t.instr2 + AND g.data_address=t.data_address + AND g.variant_id=t.variant_id + INNER JOIN variant v ON t.variant_id=v.id + WHERE v.variant="$VARIANT" + AND v.benchmark="$BENCHMARK" + GROUP BY r.resulttype + ORDER BY r.resulttype ASC; +EOT diff --git a/tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh b/tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh new file mode 100755 index 00000000..d173957b --- /dev/null +++ b/tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh @@ -0,0 +1,40 @@ +#!/bin/bash +set -e + +if [ ! $# -eq 3 ]; then + echo "usage: $0 DATABASE VARIANT BENCHMARK" >&2 + exit 1 +fi + +DATABASE=$1 +VARIANT=$2 +BENCHMARK=$3 +# add "-t" for more readable output +MYSQL="mysql -B --quick $DATABASE" + +$MYSQL << EOT + SET sql_mode = 'NO_UNSIGNED_SUBTRACTION'; + SELECT r.resulttype, + SUM((t.time2-t.time1+1) * t.width) + / + (SELECT SUM(t.time2-t.time1+1)*t.width + FROM result_GenericExperimentMessage r + INNER JOIN fspgroup g ON g.pilot_id=r.pilot_id + INNER JOIN trace t ON g.instr2=t.instr2 + AND g.data_address=t.data_address + AND g.variant_id=t.variant_id + INNER JOIN variant v ON t.variant_id=v.id + WHERE v.variant="$VARIANT" + AND v.benchmark="$BENCHMARK" + ) AS coverage + FROM result_GenericExperimentMessage r + INNER JOIN fspgroup g ON g.pilot_id=r.pilot_id + INNER JOIN trace t ON g.instr2=t.instr2 + AND g.data_address=t.data_address + AND g.variant_id=t.variant_id + INNER JOIN variant v ON t.variant_id=v.id + WHERE v.variant="$VARIANT" + AND v.benchmark="$BENCHMARK" + GROUP BY r.resulttype + ORDER BY r.resulttype ASC; +EOT diff --git a/tools/analysis/data-aggregator/symbol-occurrences.sh b/tools/analysis/data-aggregator/symbol-occurrences.sh new file mode 100755 index 00000000..c6e9a277 --- /dev/null +++ b/tools/analysis/data-aggregator/symbol-occurrences.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set -e + +if [ ! $# -eq 3 ]; then + echo "usage: $0 DATABASE VARIANT BENCHMARK" >&2 + exit 1 +fi + +DATABASE=$1 +VARIANT=$2 +BENCHMARK=$3 +# add "-t" for more readable output +MYSQL="mysql -B --quick $DATABASE" + +$MYSQL << EOT + SELECT v.benchmark, v.variant, s.name, s.size, r.resulttype, SUM(t.time2-t.time1+1) AS occurrences + FROM variant v + INNER JOIN symbol s ON v.id = s.variant_id + INNER JOIN trace t ON t.variant_id = v.id AND t.data_address BETWEEN s.address AND s.address + s.size - 1 + INNER JOIN fspgroup g ON t.variant_id = g.variant_id AND t.data_address = g.data_address AND t.instr2 = g.instr2 + INNER JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id + WHERE v.variant="$VARIANT" + AND v.benchmark="$BENCHMARK" + GROUP BY v.benchmark, v.variant, s.name, r.resulttype + ORDER BY v.benchmark, v.variant, s.name, r.resulttype; +EOT diff --git a/tools/analysis/data-aggregator/symbol-occurrences_coverage.sh b/tools/analysis/data-aggregator/symbol-occurrences_coverage.sh new file mode 100755 index 00000000..45a70de9 --- /dev/null +++ b/tools/analysis/data-aggregator/symbol-occurrences_coverage.sh @@ -0,0 +1,37 @@ +#!/bin/bash +set -e + +if [ ! $# -eq 3 ]; then + echo "usage: $0 DATABASE VARIANT BENCHMARK" >&2 + exit 1 +fi + +DATABASE=$1 +VARIANT=$2 +BENCHMARK=$3 +# add "-t" for more readable output +MYSQL="mysql -B --quick $DATABASE" + +$MYSQL << EOT + SELECT v.benchmark, v.variant, s.name, s.size, r.resulttype, + SUM(t.time2-t.time1+1) + / + (SELECT SUM(t.time2-t.time1+1) + FROM variant v + INNER JOIN symbol s ON v.id = s.variant_id + INNER JOIN trace t ON t.variant_id = v.id AND t.data_address BETWEEN s.address AND s.address + s.size - 1 + INNER JOIN fspgroup g ON t.variant_id = g.variant_id AND t.data_address = g.data_address AND t.instr2 = g.instr2 + INNER JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id + WHERE v.variant="$VARIANT" + AND v.benchmark="$BENCHMARK" + ) AS coverage + FROM variant v + INNER JOIN symbol s ON v.id = s.variant_id + INNER JOIN trace t ON t.variant_id = v.id AND t.data_address BETWEEN s.address AND s.address + s.size - 1 + INNER JOIN fspgroup g ON t.variant_id = g.variant_id AND t.data_address = g.data_address AND t.instr2 = g.instr2 + INNER JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id + WHERE v.variant="$VARIANT" + AND v.benchmark="$BENCHMARK" + GROUP BY v.benchmark, v.variant, s.name, r.resulttype + ORDER BY v.benchmark, v.variant, s.name, r.resulttype; +EOT From cae6860e4e1ac27c0195294a5b9d860bee410e1c Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sat, 13 Feb 2016 22:17:07 +0100 Subject: [PATCH 07/23] generic-tracing typo Change-Id: Ie642487f3c30ec2b99d0d4ee469acb6a987e17c3 --- src/experiments/generic-tracing/experiment.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/experiments/generic-tracing/experiment.cc b/src/experiments/generic-tracing/experiment.cc index 4e3f450a..233a885f 100644 --- a/src/experiments/generic-tracing/experiment.cc +++ b/src/experiments/generic-tracing/experiment.cc @@ -62,7 +62,7 @@ void GenericTracing::parseOptions() { CommandLine::option_handle START_ADDRESS = cmd.addOption("B", "start-address", Arg::Required, "-B,--start-address \tStart Address to start tracing"); CommandLine::option_handle STOP_ADDRESS = cmd.addOption("E", "end-address",Arg::Required, - "-E--end-address \tEnd Address to end tracing"); + "-E,--end-address \tEnd Address to end tracing"); CommandLine::option_handle SERIAL_PORT = cmd.addOption("", "serial-port", Arg::Required, "--serial-port \tListen to a given I/O address (default: 0x3F8)"); CommandLine::option_handle SERIAL_FILE = cmd.addOption("", "serial-file", Arg::Required, From 927d6a5103b5f5719abb2b3db2b9a4baba7c4cab Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 14 Feb 2016 14:41:10 +0100 Subject: [PATCH 08/23] import-trace: import symbol size if available Instead of using the address difference between two neighboring symbols as an indication for the symbol's size, import the size as reported by `nm -S'. Additionally, this change fixes an off-by-one, which had the effect that the last symbol in the list was not imported at all. Change-Id: I3c8e139b788018702526bb968e36d248dc3fe8fc --- tools/import-trace/import-symbols.sh | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/tools/import-trace/import-symbols.sh b/tools/import-trace/import-symbols.sh index 6fb80f59..4cdb27ec 100755 --- a/tools/import-trace/import-symbols.sh +++ b/tools/import-trace/import-symbols.sh @@ -48,10 +48,20 @@ EOT LAST_ADDR= LAST_SYMBOL= - nm -n -C $ELF | egrep '^[0-9a-fA-F]' | while read line + + # The "dummy" entry at the end makes sure the last real symbol from the + # nm output makes it into the database. + (nm -n -S -C $ELF; echo ffffffff a dummy) \ + | egrep '^[0-9a-fA-F]' | while read line do ADDR=$(echo "$line"|awk '{print $1}') - SYMBOL=$(echo "$line"|awk '{for (i=1; i<=NF-2; i++) $i = $(i+2); NF-=2; print}') + SIZE=$(echo "$line"|awk '{print $2}') + if echo $SIZE | egrep -q '^[0-9a-fA-F]{8}'; then + SYMBOL=$(echo "$line"|awk '{for (i=1; i<=NF-3; i++) $i = $(i+3); NF-=3; print}') + else + SIZE=unknown + SYMBOL=$(echo "$line"|awk '{for (i=1; i<=NF-2; i++) $i = $(i+2); NF-=2; print}') + fi if [ $LAST_ADDR ]; then # only create INSERT-line, if $ADDR is new to us @@ -60,8 +70,16 @@ EOT echo "($ID, cast(0x$LAST_ADDR AS UNSIGNED), CAST(0x$ADDR AS UNSIGNED)-CAST(0x$LAST_ADDR AS UNSIGNED), '$LAST_SYMBOL');" fi fi - LAST_ADDR=$ADDR - LAST_SYMBOL=$SYMBOL + + if [ $SIZE != unknown ]; then + echo "INSERT INTO $TABLE (variant_id, address, size, name) VALUES " + echo "($ID, cast(0x$ADDR AS UNSIGNED), CAST(0x$SIZE AS UNSIGNED), '$SYMBOL');" + LAST_ADDR= + LAST_SYMBOL= + else + LAST_ADDR=$ADDR + LAST_SYMBOL=$SYMBOL + fi done ) | $MYSQL From 5851f5d8486b39a65117d3d6782e776cbec68e8e Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 14 Feb 2016 14:42:25 +0100 Subject: [PATCH 09/23] data-aggregator: add aggregate per translation unit Change-Id: Ibd141eccb2549dfad64e8daf35a16e3461a07f9f --- tools/analysis/data-aggregator/CMakeLists.txt | 2 +- .../translation-unit-occurrences.sh | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100755 tools/analysis/data-aggregator/translation-unit-occurrences.sh diff --git a/tools/analysis/data-aggregator/CMakeLists.txt b/tools/analysis/data-aggregator/CMakeLists.txt index 607196dc..6eab3d4f 100644 --- a/tools/analysis/data-aggregator/CMakeLists.txt +++ b/tools/analysis/data-aggregator/CMakeLists.txt @@ -1 +1 @@ -install(PROGRAMS resulttype-occurrences_coverage.sh resulttype-occurrences.sh symbol-occurrences_coverage.sh symbol-occurrences.sh DESTINATION bin) +install(PROGRAMS resulttype-occurrences_coverage.sh resulttype-occurrences.sh symbol-occurrences_coverage.sh symbol-occurrences.sh translation-unit-occurrences.sh DESTINATION bin) diff --git a/tools/analysis/data-aggregator/translation-unit-occurrences.sh b/tools/analysis/data-aggregator/translation-unit-occurrences.sh new file mode 100755 index 00000000..c4727bf3 --- /dev/null +++ b/tools/analysis/data-aggregator/translation-unit-occurrences.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -e + +if [ ! $# -eq 3 ]; then + echo "usage: $0 DATABASE VARIANT BENCHMARK" >&2 + exit 1 +fi + +DATABASE=$1 +VARIANT=$2 +BENCHMARK=$3 +# add "-t" for more readable output +MYSQL="mysql -B --quick $DATABASE" + +$MYSQL << EOT +SELECT v.benchmark, v.variant, f.path, r.resulttype, SUM(t.time2-t.time1+1) AS occurrences +FROM variant v +JOIN dbg_filename f + ON f.variant_id = v.id +JOIN dbg_mapping m + ON f.variant_id = m.variant_id AND f.file_id = m.file_id +JOIN trace t + ON t.variant_id = m.variant_id AND t.instr2_absolute BETWEEN m.instr_absolute AND m.instr_absolute + m.line_range_size - 1 +JOIN fspgroup g + ON g.variant_id = t.variant_id AND g.data_address = t.data_address AND g.instr2 = t.instr2 +JOIN result_GenericExperimentMessage r + ON r.pilot_id = g.pilot_id +WHERE v.variant="$VARIANT" + AND v.benchmark="$BENCHMARK" +GROUP BY v.id, f.file_id, r.resulttype +ORDER BY v.benchmark, v.variant, f.path, r.resulttype +; +EOT From 584ef57aab9e172ee1ef7cb24a99d93bc098f64b Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 14 Feb 2016 17:29:07 +0100 Subject: [PATCH 10/23] data-aggregator: allow resulttype aggregation for all benchmarks This change additionally allows to create a resulttype/occurrences summary over all benchmarks in the database, instead of specifying a single one. Change-Id: I4fc7fd735300168f1e4f9e24a51aba469a7269a8 --- .../data-aggregator/resulttype-occurrences.sh | 19 ++++++++-- .../resulttype-occurrences_coverage.sh | 35 +++++++++++++++---- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/tools/analysis/data-aggregator/resulttype-occurrences.sh b/tools/analysis/data-aggregator/resulttype-occurrences.sh index 45f7f48b..2d451ff7 100755 --- a/tools/analysis/data-aggregator/resulttype-occurrences.sh +++ b/tools/analysis/data-aggregator/resulttype-occurrences.sh @@ -1,8 +1,8 @@ #!/bin/bash set -e -if [ ! $# -eq 3 ]; then - echo "usage: $0 DATABASE VARIANT BENCHMARK" >&2 +if [ $# -ne 3 -a $# -ne 1 ]; then + echo "usage: $0 DATABASE [ VARIANT BENCHMARK ]" >&2 exit 1 fi @@ -12,6 +12,20 @@ BENCHMARK=$3 # add "-t" for more readable output MYSQL="mysql -B --quick $DATABASE" +if [ -z "$VARIANT" ]; then +$MYSQL << EOT + SET sql_mode = 'NO_UNSIGNED_SUBTRACTION'; + SELECT v.benchmark, v.variant, r.resulttype, SUM((t.time2-t.time1+1) * t.width) AS occurrences + FROM result_GenericExperimentMessage r + INNER JOIN fspgroup g ON g.pilot_id=r.pilot_id + INNER JOIN trace t ON g.instr2=t.instr2 + AND g.data_address=t.data_address + AND g.variant_id=t.variant_id + INNER JOIN variant v ON t.variant_id=v.id + GROUP BY v.id, r.resulttype + ORDER BY v.benchmark, v.variant, r.resulttype; +EOT +else $MYSQL << EOT SET sql_mode = 'NO_UNSIGNED_SUBTRACTION'; SELECT r.resulttype, SUM((t.time2-t.time1+1) * t.width) AS occurrences @@ -26,3 +40,4 @@ $MYSQL << EOT GROUP BY r.resulttype ORDER BY r.resulttype ASC; EOT +fi diff --git a/tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh b/tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh index d173957b..66ca2253 100755 --- a/tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh +++ b/tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh @@ -1,8 +1,8 @@ #!/bin/bash set -e -if [ ! $# -eq 3 ]; then - echo "usage: $0 DATABASE VARIANT BENCHMARK" >&2 +if [ $# -ne 3 -a $# -ne 1 ]; then + echo "usage: $0 DATABASE [ VARIANT BENCHMARK ]" >&2 exit 1 fi @@ -12,6 +12,30 @@ BENCHMARK=$3 # add "-t" for more readable output MYSQL="mysql -B --quick $DATABASE" +if [ -z "$VARIANT" ]; then +$MYSQL << EOT + SET sql_mode = 'NO_UNSIGNED_SUBTRACTION'; + SELECT v.benchmark, v.variant, r.resulttype, + SUM((t.time2-t.time1+1) * t.width) + / + (SELECT SUM(t.time2-t.time1+1)*t.width + FROM result_GenericExperimentMessage r + INNER JOIN fspgroup g ON g.pilot_id=r.pilot_id + INNER JOIN trace t ON g.instr2=t.instr2 + AND g.data_address=t.data_address + AND g.variant_id=t.variant_id + WHERE t.variant_id = v.id -- refers to parent query + ) AS coverage + FROM result_GenericExperimentMessage r + INNER JOIN fspgroup g ON g.pilot_id=r.pilot_id + INNER JOIN trace t ON g.instr2=t.instr2 + AND g.data_address=t.data_address + AND g.variant_id=t.variant_id + INNER JOIN variant v ON t.variant_id=v.id + GROUP BY v.id, r.resulttype + ORDER BY v.benchmark, v.variant, r.resulttype; +EOT +else $MYSQL << EOT SET sql_mode = 'NO_UNSIGNED_SUBTRACTION'; SELECT r.resulttype, @@ -23,9 +47,7 @@ $MYSQL << EOT INNER JOIN trace t ON g.instr2=t.instr2 AND g.data_address=t.data_address AND g.variant_id=t.variant_id - INNER JOIN variant v ON t.variant_id=v.id - WHERE v.variant="$VARIANT" - AND v.benchmark="$BENCHMARK" + WHERE t.variant_id = v.id -- refers to parent query ) AS coverage FROM result_GenericExperimentMessage r INNER JOIN fspgroup g ON g.pilot_id=r.pilot_id @@ -36,5 +58,6 @@ $MYSQL << EOT WHERE v.variant="$VARIANT" AND v.benchmark="$BENCHMARK" GROUP BY r.resulttype - ORDER BY r.resulttype ASC; + ORDER BY r.resulttype; EOT +fi From dd7ad77731f01402229eb4492c510b71d6774fbd Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Mon, 15 Feb 2016 01:04:39 +0100 Subject: [PATCH 11/23] data-aggregator: add -t for table output By default, the data-aggregator scripts create machine-readable, tab-separated output. The optional "-t" switch (passed to the internally used `mysql' command-line client) creates human-readable table output instead. Change-Id: Ie448c21a4e82dea83f3e43e6642e67eb85f8b8e9 --- .../data-aggregator/resulttype-occurrences.sh | 13 ++++++++++--- .../resulttype-occurrences_coverage.sh | 13 ++++++++++--- .../analysis/data-aggregator/symbol-occurrences.sh | 13 ++++++++++--- .../data-aggregator/symbol-occurrences_coverage.sh | 13 ++++++++++--- .../data-aggregator/translation-unit-occurrences.sh | 13 ++++++++++--- 5 files changed, 50 insertions(+), 15 deletions(-) diff --git a/tools/analysis/data-aggregator/resulttype-occurrences.sh b/tools/analysis/data-aggregator/resulttype-occurrences.sh index 2d451ff7..1c93900c 100755 --- a/tools/analysis/data-aggregator/resulttype-occurrences.sh +++ b/tools/analysis/data-aggregator/resulttype-occurrences.sh @@ -1,16 +1,23 @@ #!/bin/bash set -e +if [ "$1" = -t ]; then + FORMAT=-t + shift +else + FORMAT=-B +fi + if [ $# -ne 3 -a $# -ne 1 ]; then - echo "usage: $0 DATABASE [ VARIANT BENCHMARK ]" >&2 + echo "usage: $0 [ -t ] DATABASE [ VARIANT BENCHMARK ]" >&2 + echo " -t Display output in table format (tab-separated CSV otherwise)" >&2 exit 1 fi DATABASE=$1 VARIANT=$2 BENCHMARK=$3 -# add "-t" for more readable output -MYSQL="mysql -B --quick $DATABASE" +MYSQL="mysql $FORMAT $DATABASE" if [ -z "$VARIANT" ]; then $MYSQL << EOT diff --git a/tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh b/tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh index 66ca2253..5fa7c2c3 100755 --- a/tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh +++ b/tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh @@ -1,16 +1,23 @@ #!/bin/bash set -e +if [ "$1" = -t ]; then + FORMAT=-t + shift +else + FORMAT=-B +fi + if [ $# -ne 3 -a $# -ne 1 ]; then - echo "usage: $0 DATABASE [ VARIANT BENCHMARK ]" >&2 + echo "usage: $0 [ -t ] DATABASE [ VARIANT BENCHMARK ]" >&2 + echo " -t Display output in table format (tab-separated CSV otherwise)" >&2 exit 1 fi DATABASE=$1 VARIANT=$2 BENCHMARK=$3 -# add "-t" for more readable output -MYSQL="mysql -B --quick $DATABASE" +MYSQL="mysql $FORMAT $DATABASE" if [ -z "$VARIANT" ]; then $MYSQL << EOT diff --git a/tools/analysis/data-aggregator/symbol-occurrences.sh b/tools/analysis/data-aggregator/symbol-occurrences.sh index c6e9a277..f430fd0d 100755 --- a/tools/analysis/data-aggregator/symbol-occurrences.sh +++ b/tools/analysis/data-aggregator/symbol-occurrences.sh @@ -1,16 +1,23 @@ #!/bin/bash set -e +if [ "$1" = -t ]; then + FORMAT=-t + shift +else + FORMAT=-B +fi + if [ ! $# -eq 3 ]; then - echo "usage: $0 DATABASE VARIANT BENCHMARK" >&2 + echo "usage: $0 [ -t ] DATABASE VARIANT BENCHMARK" >&2 + echo " -t Display output in table format (tab-separated CSV otherwise)" >&2 exit 1 fi DATABASE=$1 VARIANT=$2 BENCHMARK=$3 -# add "-t" for more readable output -MYSQL="mysql -B --quick $DATABASE" +MYSQL="mysql $FORMAT $DATABASE" $MYSQL << EOT SELECT v.benchmark, v.variant, s.name, s.size, r.resulttype, SUM(t.time2-t.time1+1) AS occurrences diff --git a/tools/analysis/data-aggregator/symbol-occurrences_coverage.sh b/tools/analysis/data-aggregator/symbol-occurrences_coverage.sh index 45a70de9..8335482c 100755 --- a/tools/analysis/data-aggregator/symbol-occurrences_coverage.sh +++ b/tools/analysis/data-aggregator/symbol-occurrences_coverage.sh @@ -1,16 +1,23 @@ #!/bin/bash set -e +if [ "$1" = -t ]; then + FORMAT=-t + shift +else + FORMAT=-B +fi + if [ ! $# -eq 3 ]; then - echo "usage: $0 DATABASE VARIANT BENCHMARK" >&2 + echo "usage: $0 [ -t ] DATABASE VARIANT BENCHMARK" >&2 + echo " -t Display output in table format (tab-separated CSV otherwise)" >&2 exit 1 fi DATABASE=$1 VARIANT=$2 BENCHMARK=$3 -# add "-t" for more readable output -MYSQL="mysql -B --quick $DATABASE" +MYSQL="mysql $FORMAT $DATABASE" $MYSQL << EOT SELECT v.benchmark, v.variant, s.name, s.size, r.resulttype, diff --git a/tools/analysis/data-aggregator/translation-unit-occurrences.sh b/tools/analysis/data-aggregator/translation-unit-occurrences.sh index c4727bf3..2427706b 100755 --- a/tools/analysis/data-aggregator/translation-unit-occurrences.sh +++ b/tools/analysis/data-aggregator/translation-unit-occurrences.sh @@ -1,16 +1,23 @@ #!/bin/bash set -e +if [ "$1" = -t ]; then + FORMAT=-t + shift +else + FORMAT=-B +fi + if [ ! $# -eq 3 ]; then - echo "usage: $0 DATABASE VARIANT BENCHMARK" >&2 + echo "usage: $0 [ -t ] DATABASE VARIANT BENCHMARK" >&2 + echo " -t Display output in table format (tab-separated CSV otherwise)" >&2 exit 1 fi DATABASE=$1 VARIANT=$2 BENCHMARK=$3 -# add "-t" for more readable output -MYSQL="mysql -B --quick $DATABASE" +MYSQL="mysql $FORMAT $DATABASE" $MYSQL << EOT SELECT v.benchmark, v.variant, f.path, r.resulttype, SUM(t.time2-t.time1+1) AS occurrences From 2bed7c124ac93b067f25b016fe70ce8b203f9555 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Mon, 15 Feb 2016 15:23:24 +0100 Subject: [PATCH 12/23] data-aggregator: per-function + durations Change-Id: I1dc7791fe9af7f848f56093e0554c61973b7a1f3 --- tools/analysis/data-aggregator/CMakeLists.txt | 2 +- .../data-aggregator/function-occurrences.sh | 38 ++++++++++++++++ .../data-aggregator/variant-durations.sh | 44 +++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100755 tools/analysis/data-aggregator/function-occurrences.sh create mode 100755 tools/analysis/data-aggregator/variant-durations.sh diff --git a/tools/analysis/data-aggregator/CMakeLists.txt b/tools/analysis/data-aggregator/CMakeLists.txt index 6eab3d4f..2b91f10b 100644 --- a/tools/analysis/data-aggregator/CMakeLists.txt +++ b/tools/analysis/data-aggregator/CMakeLists.txt @@ -1 +1 @@ -install(PROGRAMS resulttype-occurrences_coverage.sh resulttype-occurrences.sh symbol-occurrences_coverage.sh symbol-occurrences.sh translation-unit-occurrences.sh DESTINATION bin) +install(PROGRAMS function-occurrences.sh resulttype-occurrences.sh resulttype-occurrences_coverage.sh symbol-occurrences.sh symbol-occurrences_coverage.sh translation-unit-occurrences.sh variant-durations.sh DESTINATION bin) diff --git a/tools/analysis/data-aggregator/function-occurrences.sh b/tools/analysis/data-aggregator/function-occurrences.sh new file mode 100755 index 00000000..65e2367b --- /dev/null +++ b/tools/analysis/data-aggregator/function-occurrences.sh @@ -0,0 +1,38 @@ +#!/bin/bash +set -e + +if [ "$1" = -t ]; then + FORMAT=-t + shift +else + FORMAT=-B +fi + +if [ ! $# -eq 3 ]; then + echo "usage: $0 [ -t ] DATABASE VARIANT BENCHMARK" >&2 + echo " -t Display output in table format (tab-separated CSV otherwise)" >&2 + exit 1 +fi + +DATABASE=$1 +VARIANT=$2 +BENCHMARK=$3 +MYSQL="mysql $FORMAT $DATABASE" + +$MYSQL << EOT +SELECT s.name, s.address, r.resulttype, SUM(t.time2-t.time1+1) AS occurrences +FROM variant v +JOIN symbol s + ON s.variant_id = v.id +JOIN trace t + ON t.variant_id = s.variant_id AND t.instr2_absolute BETWEEN s.address AND s.address + s.size - 1 +JOIN fspgroup g + ON g.variant_id = t.variant_id AND g.data_address = t.data_address AND g.instr2 = t.instr2 +JOIN result_GenericExperimentMessage r + ON r.pilot_id = g.pilot_id +WHERE v.variant="$VARIANT" + AND v.benchmark="$BENCHMARK" +GROUP BY s.variant_id, s.address, r.resulttype +ORDER BY s.address, r.resulttype +; +EOT diff --git a/tools/analysis/data-aggregator/variant-durations.sh b/tools/analysis/data-aggregator/variant-durations.sh new file mode 100755 index 00000000..818c7516 --- /dev/null +++ b/tools/analysis/data-aggregator/variant-durations.sh @@ -0,0 +1,44 @@ +#!/bin/bash +set -e + +if [ "$1" = -t ]; then + FORMAT=-t + shift +else + FORMAT=-B +fi + +if [ $# -ne 3 -a $# -ne 1 ]; then + echo "usage: $0 [ -t ] DATABASE [ VARIANT BENCHMARK ]" >&2 + echo " -t Display output in table format (tab-separated CSV otherwise)" >&2 + exit 1 +fi + +DATABASE=$1 +VARIANT=$2 +BENCHMARK=$3 +MYSQL="mysql $FORMAT $DATABASE" + +if [ -z "$VARIANT" ]; then +$MYSQL << EOT + SET sql_mode = 'NO_UNSIGNED_SUBTRACTION'; + SELECT v.benchmark, v.variant, + MAX(t.time2)-MIN(t.time1)+1 AS duration, + MAX(t.instr2)-MIN(t.instr1)+1 AS dyn_instr + FROM trace t + JOIN variant v ON t.variant_id = v.id + GROUP BY v.id + ORDER BY v.benchmark, v.variant; +EOT +else +$MYSQL << EOT + SET sql_mode = 'NO_UNSIGNED_SUBTRACTION'; + SELECT + MAX(t.time2)-MIN(t.time1)+1 AS duration, + MAX(t.instr2)-MIN(t.instr1)+1 AS dyn_instr + FROM trace t + JOIN variant v ON t.variant_id = v.id + WHERE v.variant = "$VARIANT" + AND v.benchmark = "$BENCHMARK" +EOT +fi From 3dd7c9cb48cb59ffa371a5ecb8003ad7d187ae88 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 14 Feb 2016 15:21:05 +0100 Subject: [PATCH 13/23] faultspaceplot: plot burst faults correctly + remove "old matplotlib" warning Change-Id: I47dec1cc6bf6dd86216cd6d373174d4c70556f63 --- tools/analysis/faultspaceplot/faultspaceplot.sh | 2 +- tools/analysis/faultspaceplot/fsp.plot.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/analysis/faultspaceplot/faultspaceplot.sh b/tools/analysis/faultspaceplot/faultspaceplot.sh index 168ea168..3730a44e 100755 --- a/tools/analysis/faultspaceplot/faultspaceplot.sh +++ b/tools/analysis/faultspaceplot/faultspaceplot.sh @@ -17,7 +17,7 @@ echo "getting faultspace data.." $MYSQL < "$VARIANT"_"$BENCHMARK"-raw.csv SELECT t.time1 - (SELECT MIN(t2.time1) FROM trace t2 WHERE t.variant_id = t2.variant_id) AS time1, t.time2 - (SELECT MIN(t2.time1) FROM trace t2 WHERE t.variant_id = t2.variant_id) AS time2, - t.data_address, r.bitoffset, 1, + t.data_address, r.bitoffset, r.injection_width, CASE WHEN r.resulttype = 'OK_MARKER' THEN '#FFFFFF' WHEN r.resulttype = 'FAIL_MARKER' THEN '#EE0000' diff --git a/tools/analysis/faultspaceplot/fsp.plot.py b/tools/analysis/faultspaceplot/fsp.plot.py index 510b1eed..a772f69d 100755 --- a/tools/analysis/faultspaceplot/fsp.plot.py +++ b/tools/analysis/faultspaceplot/fsp.plot.py @@ -45,8 +45,6 @@ if sys.argv[1] == '-h': print "plot (not implemented yet)." # TODO: be more precise here exit(0) -print "WARNING: This script needs a newer version of Matplotlib for axis label rotation; run this on Ubuntu 12.10 or alike." - print "Opening and processing \"" + sys.argv[1] + "\"..." file = open(sys.argv[1], "r") dialect = csv.Sniffer().sniff(file.read(1024)) From ea0a5f90e2fc9816ba19d5f9e1853adcc2ec8358 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 14 Feb 2016 16:20:23 +0100 Subject: [PATCH 14/23] faultspaceplot: add ticks for symbols if available + use helper scripts from the same dir, not from $PATH Change-Id: I7aba773c8dbff5f8643a39fa1ed8d26867f3a86d --- .../analysis/faultspaceplot/faultspaceplot.sh | 30 +++++++++- tools/analysis/faultspaceplot/fsp.plot.py | 60 ++++++++++++++++++- 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/tools/analysis/faultspaceplot/faultspaceplot.sh b/tools/analysis/faultspaceplot/faultspaceplot.sh index 3730a44e..db4425aa 100755 --- a/tools/analysis/faultspaceplot/faultspaceplot.sh +++ b/tools/analysis/faultspaceplot/faultspaceplot.sh @@ -9,9 +9,17 @@ fi DATABASE=$1 VARIANT=$2 BENCHMARK=$3 -# add "-t" for more readable output MYSQL="mysql -B --quick $DATABASE" +MYDIR=$(dirname $0) + +function table_exists() +{ + N=$(echo "SHOW TABLES LIKE '$1'" | $MYSQL $DATABASE | wc -l) + [ $N -gt 0 ] + return +} + # get data echo "getting faultspace data.." $MYSQL < "$VARIANT"_"$BENCHMARK"-raw.csv @@ -44,8 +52,24 @@ EOT # compact data echo "compacting data.." -fsp.compact.sh "$VARIANT"_"$BENCHMARK"-raw.csv "$VARIANT"_"$BENCHMARK"-plot.csv +"$MYDIR"/fsp.compact.sh "$VARIANT"_"$BENCHMARK"-raw.csv "$VARIANT"_"$BENCHMARK"-plot.csv + +# fetch symbols if available +if table_exists symbol; then + echo "getting symbol information ..." + $MYSQL < "$VARIANT"_"$BENCHMARK"-symbols.csv + SELECT s.address, s.size, s.name + FROM variant v + JOIN symbol s ON s.variant_id = v.id + WHERE v.variant = '$VARIANT' AND v.benchmark = '$BENCHMARK' + ORDER BY s.address +EOT +fi # plot data echo "plotting.." -fsp.plot.py "$VARIANT"_"$BENCHMARK"-plot.csv +if [ -e "$VARIANT"_"$BENCHMARK"-symbols.csv -a $(wc -l < "$VARIANT"_"$BENCHMARK"-symbols.csv) -gt 1 ]; then + "$MYDIR"/fsp.plot.py "$VARIANT"_"$BENCHMARK"-plot.csv "$VARIANT"_"$BENCHMARK"-symbols.csv +else + "$MYDIR"/fsp.plot.py "$VARIANT"_"$BENCHMARK"-plot.csv +fi diff --git a/tools/analysis/faultspaceplot/fsp.plot.py b/tools/analysis/faultspaceplot/fsp.plot.py index a772f69d..26ef91bb 100755 --- a/tools/analysis/faultspaceplot/fsp.plot.py +++ b/tools/analysis/faultspaceplot/fsp.plot.py @@ -42,7 +42,7 @@ if sys.argv[1] == '-h': print "DATA_FILE is a CSV-file, storing the tab-separated values" print "retrieved by the experiment run. USER_TAG_FILE is an optional" print "CSV-file which can be used to add user-specific marks to the" - print "plot (not implemented yet)." # TODO: be more precise here + print "plot." # TODO: be more precise here exit(0) print "Opening and processing \"" + sys.argv[1] + "\"..." @@ -52,6 +52,17 @@ file.seek(0) reader = csv.reader(file, dialect) reader.next() # Move down a line to skip the header +if len(sys.argv) >= 3: + print "Opening and processing \"" + sys.argv[2] + "\"..." + symbolfile = open(sys.argv[2], "r") + dialect = csv.Sniffer().sniff(symbolfile.read(1024)) + symbolfile.seek(0) + symbolreader = csv.reader(symbolfile, dialect) + symbolreader.next() # Move down a line to skip the header + have_symbols = True +else: + have_symbols = False + fig = plt.figure() xmin = 99999999 @@ -104,5 +115,52 @@ plt.ylim(ymin, ymax) plt.ylabel('Data Memory (RAM)') plt.xlabel('Time (Cycles)') +# show symbols +if have_symbols: + # Adding 2nd y-axis for object names + ax1 = fig.add_subplot(111) + ax2 = ax1.twinx() + ax2.set_ylabel('Symbols') + + # necessary for proper symbol placement + plt.ylim(ymin, ymax) + + ticks = [] + symbols = [] + + IDX_SYMBOL_ADDRESS = 0; IDX_SYMBOL_SIZE = 1; IDX_SYMBOL_NAME = 2; + + for row in symbolreader: + # TODO: somehow plot size as well + address = int(row[IDX_SYMBOL_ADDRESS]) + size = int(row[IDX_SYMBOL_SIZE]) + if (address >= ymin) and (address <= ymax): + ticks.append(address) + symbols.append(row[IDX_SYMBOL_NAME]) + #print "symbol: " + str(address) + " " + str(size) + " " + row[IDX_SYMBOL_NAME] + elif (address < ymin) and (address + size >= ymin): + ticks.append(ymin) + symbols.append("(" + row[IDX_SYMBOL_NAME] + ")") + #print "partial symbol: " + str(address) + " " + str(size) + " " + row[IDX_SYMBOL_NAME] + else: + #print "skipped symbol: " + str(address) + " " + str(size) + " " + row[IDX_SYMBOL_NAME] + pass + + # list of interesting addresses + ax2.yaxis.set_ticks(ticks) + ax2.yaxis.grid(b=True, color='gray') + + # create minor ticks centered between major tick marks + centered_ticks = [] + major_locator = ax2.yaxis.get_major_locator() + major_locs = major_locator() + for i in range(1,len(major_locs)): + y_last,y = major_locs[i-1],major_locs[i] + centered_ticks.append(0.5*(y+y_last)) + ax2.yaxis.set_ticks(centered_ticks, minor=True) + + # list of corresponding symbol names + ax2.set_yticklabels(symbols, minor=False, rotation=0, rotation_mode='anchor') + plt.show() #pylab.savefig('baseline.pdf', bbox_inches='tight') From 915a3442238b9ebbe4cf062e38f9ed349a3de12a Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 14 Feb 2016 18:39:39 +0100 Subject: [PATCH 15/23] faultspaceplot: better distinguishable colors Change-Id: I49517fd104394e598937ab1c8970c739e41993b7 --- tools/analysis/faultspaceplot/faultspaceplot.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/analysis/faultspaceplot/faultspaceplot.sh b/tools/analysis/faultspaceplot/faultspaceplot.sh index db4425aa..cd5ff299 100755 --- a/tools/analysis/faultspaceplot/faultspaceplot.sh +++ b/tools/analysis/faultspaceplot/faultspaceplot.sh @@ -34,8 +34,8 @@ $MYSQL < "$VARIANT"_"$BENCHMARK"-raw.csv WHEN r.resulttype = 'GROUP1_MARKER' THEN '#EBEBEB' WHEN r.resulttype = 'GROUP2_MARKER' THEN '#ECECEC' WHEN r.resulttype = 'GROUP3_MARKER' THEN '#EDEDED' - WHEN r.resulttype = 'TIMEOUT' THEN '#00EE00' - WHEN r.resulttype = 'TRAP' THEN '#00DD00' + WHEN r.resulttype = 'TIMEOUT' THEN '#CCCC00' + WHEN r.resulttype = 'TRAP' THEN '#00CCCC' WHEN r.resulttype = 'WRITE_TEXTSEGMENT' THEN '#0000AA' WHEN r.resulttype = 'WRITE_OUTERSPACE' THEN '#0000BB' WHEN r.resulttype = 'SDC' THEN '#FF0000' From e8ca3ba6ea62a04e4159d2d5e2097311843a3eca Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 14 Feb 2016 17:29:23 +0100 Subject: [PATCH 16/23] faultspaceplot: don't plot OK_MARKER In the current configuration, OK_MARKER would be plotted in white color and be indistinguishable from the background. Not plotting these areas at all reduces output-file size. As a side effect, the initial Y-axis zoom level (ymin, ymax) can change. Change-Id: Ic7b1a22a5a6f58e4df0849bca5262c646051ae2c --- tools/analysis/faultspaceplot/faultspaceplot.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/analysis/faultspaceplot/faultspaceplot.sh b/tools/analysis/faultspaceplot/faultspaceplot.sh index cd5ff299..9c3d844d 100755 --- a/tools/analysis/faultspaceplot/faultspaceplot.sh +++ b/tools/analysis/faultspaceplot/faultspaceplot.sh @@ -47,6 +47,7 @@ $MYSQL < "$VARIANT"_"$BENCHMARK"-raw.csv JOIN result_GenericExperimentMessage r ON r.pilot_id=g.pilot_id WHERE v.variant = '$VARIANT' AND v.benchmark = '$BENCHMARK' + AND r.resulttype != 'OK_MARKER' AND t.accesstype = 'R'; EOT From ee8759f6b8d95acce14932029ef03cbd87ce7dbe Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Mon, 15 Feb 2016 00:31:36 +0100 Subject: [PATCH 17/23] faultspaceplot: don't round down ymin Before this change, ymin was rounded down to the nearest Y value divisible by 1000, showing an empty, white area in the lower part of the plot. With this change, the initial Y-axis zoom level is maximized to exactly show all non-white areas. Change-Id: I1aea52a3afc331e7f11fe76ff2c5de3c71c61c71 --- tools/analysis/faultspaceplot/fsp.plot.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/analysis/faultspaceplot/fsp.plot.py b/tools/analysis/faultspaceplot/fsp.plot.py index 26ef91bb..25d9f8a3 100755 --- a/tools/analysis/faultspaceplot/fsp.plot.py +++ b/tools/analysis/faultspaceplot/fsp.plot.py @@ -106,7 +106,8 @@ for row in reader: pass #break -ymin = int(ymin / 1000) * 1000 +# round down to nearest 1000 +#ymin = int(ymin / 1000) * 1000 file.close() plt.xlim(xmin, xmax) From 7168566ef5e48f140f64d26a874f9a3fe855cf24 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Tue, 16 Feb 2016 22:59:37 +0100 Subject: [PATCH 18/23] faultspaceplot: -k -- keep CSVs only optionally Change-Id: I5900c53b81d15d5262420afbf636444af31b00f1 --- .../analysis/faultspaceplot/faultspaceplot.sh | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/tools/analysis/faultspaceplot/faultspaceplot.sh b/tools/analysis/faultspaceplot/faultspaceplot.sh index 9c3d844d..b7366cbc 100755 --- a/tools/analysis/faultspaceplot/faultspaceplot.sh +++ b/tools/analysis/faultspaceplot/faultspaceplot.sh @@ -1,8 +1,16 @@ #!/bin/bash set -e +if [ "$1" = -k ]; then + KEEPCSV=yes + shift +else + KEEPCSV=no +fi + if [ ! $# -eq 3 ]; then - echo "usage: $0 DATABASE VARIANT BENCHMARK" >&2 + echo "usage: $0 [ -k ] DATABASE VARIANT BENCHMARK" >&2 + echo " -k Keep compacted plot (and symbols) CSV" >&2 exit 1 fi @@ -21,8 +29,9 @@ function table_exists() } # get data +RAWCSV=$(mktemp) echo "getting faultspace data.." -$MYSQL < "$VARIANT"_"$BENCHMARK"-raw.csv +$MYSQL < $RAWCSV SELECT t.time1 - (SELECT MIN(t2.time1) FROM trace t2 WHERE t.variant_id = t2.variant_id) AS time1, t.time2 - (SELECT MIN(t2.time1) FROM trace t2 WHERE t.variant_id = t2.variant_id) AS time2, t.data_address, r.bitoffset, r.injection_width, @@ -53,12 +62,16 @@ EOT # compact data echo "compacting data.." -"$MYDIR"/fsp.compact.sh "$VARIANT"_"$BENCHMARK"-raw.csv "$VARIANT"_"$BENCHMARK"-plot.csv +COMPACTCSV=$(mktemp) +"$MYDIR"/fsp.compact.sh $RAWCSV $COMPACTCSV +rm $RAWCSV # fetch symbols if available +SYMBOLCSV= if table_exists symbol; then + SYMBOLCSV=$(mktemp) echo "getting symbol information ..." - $MYSQL < "$VARIANT"_"$BENCHMARK"-symbols.csv + $MYSQL < $SYMBOLCSV SELECT s.address, s.size, s.name FROM variant v JOIN symbol s ON s.variant_id = v.id @@ -69,8 +82,20 @@ fi # plot data echo "plotting.." -if [ -e "$VARIANT"_"$BENCHMARK"-symbols.csv -a $(wc -l < "$VARIANT"_"$BENCHMARK"-symbols.csv) -gt 1 ]; then - "$MYDIR"/fsp.plot.py "$VARIANT"_"$BENCHMARK"-plot.csv "$VARIANT"_"$BENCHMARK"-symbols.csv -else - "$MYDIR"/fsp.plot.py "$VARIANT"_"$BENCHMARK"-plot.csv +if [ $KEEPCSV = yes ]; then + KEPT="$VARIANT"_"$BENCHMARK"-plot.csv + mv "$COMPACTCSV" "$KEPT" + COMPACTCSV=$KEPT fi +if [ ! -z "$SYMBOLCSV" -a $(wc -l < $SYMBOLCSV) -gt 1 ]; then + if [ $KEEPCSV = yes ]; then + KEPT="$VARIANT"_"$BENCHMARK"-symbols.csv + mv "$SYMBOLCSV" "$KEPT" + SYMBOLCSV=$KEPT + fi + "$MYDIR"/fsp.plot.py "$COMPACTCSV" "$SYMBOLCSV" + [ $KEEPCSV = no ] && rm "$SYMBOLCSV" +else + "$MYDIR"/fsp.plot.py "$COMPACTCSV" +fi +[ $KEEPCSV = no ] && rm "$COMPACTCSV" From e08deef9d5d66453d8b0224ae2be1512b3cbabc1 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 14 Feb 2016 17:25:35 +0100 Subject: [PATCH 19/23] GenericExperiment: prevent integer overflow This change prevents an integer overflow in the memory-access listener for WRITE_OUTERSPACE. Instead of matching all addresses above maxima_data, l_mem_outerspace never matched in the generic-experiment's "--catch-write-outerspace" mode. Change-Id: I8f4ee4515af3998b7c2a8e83c7a18306c26d8d66 --- src/experiments/generic-experiment/experiment.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/experiments/generic-experiment/experiment.cc b/src/experiments/generic-experiment/experiment.cc index 680d233f..b590c750 100644 --- a/src/experiments/generic-experiment/experiment.cc +++ b/src/experiments/generic-experiment/experiment.cc @@ -193,7 +193,7 @@ bool GenericExperiment::cb_start_experiment() { l_mem_outerspace.setWatchAddress(maximal_data); l_mem_outerspace.setTriggerAccessType(MemAccessEvent::MEM_WRITE); - l_mem_outerspace.setWatchWidth(0xfffffff0); + l_mem_outerspace.setWatchWidth(0xfffffff0 - maximal_data); } if (cmd[TRAP]) { From 5bd7c4a9c568605da538d12548e9438110b8d39c Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Fri, 26 Feb 2016 09:43:14 +0100 Subject: [PATCH 20/23] GenericExperiment: limit output logger buffer Limit the serial-output logger buffer to prevent overly large memory consumption in case the target system ends up, e.g., in an endless loop. The buffer is limited to (golden-run output size)+1 to be able to detect the case when the target system makes a correct output but faultily adds extra characters afterwards. Change-Id: I50c082f8fb09a702d87ab83732ca3e3463c46597 --- src/experiments/generic-experiment/experiment.cc | 9 ++++++++- src/experiments/generic-experiment/experiment.hpp | 1 + src/plugins/serialoutput/SerialOutputLogger.hpp | 5 +++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/experiments/generic-experiment/experiment.cc b/src/experiments/generic-experiment/experiment.cc index b590c750..54b5278f 100644 --- a/src/experiments/generic-experiment/experiment.cc +++ b/src/experiments/generic-experiment/experiment.cc @@ -176,6 +176,14 @@ bool GenericExperiment::cb_start_experiment() { m_log << "enabled logging on port E9 for SDC-detection" << std::endl; enabled_e9_sol = true; e9_file = std::string(cmd[E9_FILE].first()->arg); + e9_goldenrun = loadFile(e9_file); + + // Limit the serial-output logger buffer to prevent overly large memory + // consumption in case the target system ends up, e.g., in an endless + // loop. "+ 1" to be able to detect the case when the target system + // makes a correct output but faultily adds extra characters + // afterwards. + e9_sol.setLimit(e9_goldenrun.size() + 1); } if (cmd[WRITE_MEM_TEXT]) { @@ -290,7 +298,6 @@ void GenericExperiment::cb_after_resume(fail::BaseListener *event) { // check experiment's data for SDC if (enabled_e9_sol) { // compare golden run to experiment - std::vector e9_goldenrun = loadFile(e9_file); std::string e9_experiment = e9_sol.getOutput(); if ( ! (e9_experiment.size() == e9_goldenrun.size() && equal(e9_experiment.begin(), e9_experiment.end(), e9_goldenrun.begin())) ) { diff --git a/src/experiments/generic-experiment/experiment.hpp b/src/experiments/generic-experiment/experiment.hpp index 81358b0a..ef6218e4 100644 --- a/src/experiments/generic-experiment/experiment.hpp +++ b/src/experiments/generic-experiment/experiment.hpp @@ -23,6 +23,7 @@ class GenericExperiment : public fail::DatabaseExperiment { bool enabled_e9_sol; std::string e9_file; SerialOutputLogger e9_sol; + std::vector e9_goldenrun; bool enabled_mem_text; fail::MemAccessListener l_mem_text; diff --git a/src/plugins/serialoutput/SerialOutputLogger.hpp b/src/plugins/serialoutput/SerialOutputLogger.hpp index 19e4f6f1..a2d85c35 100644 --- a/src/plugins/serialoutput/SerialOutputLogger.hpp +++ b/src/plugins/serialoutput/SerialOutputLogger.hpp @@ -40,6 +40,11 @@ public: * Returns the output variable. */ std::string getOutput(); + /** + * Sets the character limit. Does not truncate the stored data if it + * already exceeds the new limit. 0 = unlimited. + */ + void setLimit(unsigned char_limit) { m_limit = char_limit; } }; #endif // __SERIAL_OUTPUT_LOGGER_HPP__ From 39b120f7ca2eeb9f5f01e61743b63889a231997e Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Fri, 26 Feb 2016 09:50:28 +0100 Subject: [PATCH 21/23] GenericExperiment: record output during complete runtime Before this change, the GenericExperiment only recorded port 0xe9 output *after* the fault was injected. When a fault was injected during the workload's output loop, the output data before that point in time was missing, and the experiment outcome was wrongly classified as SDC. This change moves the logging activation to before the fast-forwarding step (DatabaseExperiment::cb_before_fast_forward). It also makes sure the DatabaseExperiment only clears its own listeners instead of also touching the SerialOutputLogger's one. Change-Id: I66bda4ee318d271ddda6f7ade4e817bf9d14cf46 --- src/core/efw/DatabaseExperiment.cc | 6 +++--- src/experiments/generic-experiment/experiment.cc | 13 +++++++++---- src/experiments/generic-experiment/experiment.hpp | 8 ++++++++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/core/efw/DatabaseExperiment.cc b/src/core/efw/DatabaseExperiment.cc index 7a2bf6d4..a9c6bc3e 100644 --- a/src/core/efw/DatabaseExperiment.cc +++ b/src/core/efw/DatabaseExperiment.cc @@ -120,7 +120,7 @@ bool DatabaseExperiment::run() m_log << "Trying to inject @ instr #" << dec << injection_instr << endl; - simulator.clearListeners(); + simulator.clearListeners(this); if (!this->cb_before_fast_forward()) { continue; @@ -168,7 +168,7 @@ bool DatabaseExperiment::run() simulator.terminate(1); } - simulator.clearListeners(); + simulator.clearListeners(this); if (fsppilot->inject_bursts()) { /// INJECT BURST: @@ -194,7 +194,7 @@ bool DatabaseExperiment::run() m_log << "Resume done" << std::endl; this->cb_after_resume(listener); - simulator.clearListeners(); + simulator.clearListeners(this); } m_jc->sendResult(*param); this->cb_free_experiment_data(param); diff --git a/src/experiments/generic-experiment/experiment.cc b/src/experiments/generic-experiment/experiment.cc index 54b5278f..4183dd66 100644 --- a/src/experiments/generic-experiment/experiment.cc +++ b/src/experiments/generic-experiment/experiment.cc @@ -243,6 +243,15 @@ bool GenericExperiment::cb_start_experiment() { } +bool GenericExperiment::cb_before_fast_forward() +{ + if (enabled_e9_sol) { + // output may already appear *before* FI + simulator.addFlow(&e9_sol); + } + return true; +} + bool GenericExperiment::cb_before_resume() { if (enabled_trap) simulator.addListener(&l_trap); @@ -263,10 +272,6 @@ bool GenericExperiment::cb_before_resume() { simulator.addListener(*it); } - if (enabled_e9_sol) { - simulator.addFlow(&e9_sol); - } - return true; // everything OK } diff --git a/src/experiments/generic-experiment/experiment.hpp b/src/experiments/generic-experiment/experiment.hpp index ef6218e4..46f28187 100644 --- a/src/experiments/generic-experiment/experiment.hpp +++ b/src/experiments/generic-experiment/experiment.hpp @@ -98,6 +98,14 @@ public: */ virtual bool cb_start_experiment(); + /** + * Callback that is called before the fast forward is done. This + * can be used to add additional event listeners during the fast + * forward phase. If returning false, the experiment is canceled. + * @return \c true on success, \c false otherwise + */ + virtual bool cb_before_fast_forward(); + /** * Callback that is called before the resuming till crash has * started. This is called after the fault was injected. Here the From 449ac1a692146e39af7d38fd41766bc923a070be Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 14 Feb 2016 22:40:28 +0100 Subject: [PATCH 22/23] DatabaseExperiment: local debug helper code Change-Id: Ibf42c93df26f6123edc867147621a011665e9c43 --- src/core/efw/DatabaseExperiment.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/core/efw/DatabaseExperiment.cc b/src/core/efw/DatabaseExperiment.cc index a9c6bc3e..9342708e 100644 --- a/src/core/efw/DatabaseExperiment.cc +++ b/src/core/efw/DatabaseExperiment.cc @@ -13,6 +13,7 @@ #include #include +//#define LOCAL using namespace std; using namespace fail; @@ -91,16 +92,26 @@ bool DatabaseExperiment::run() while (executed_jobs < 25 || m_jc->getNumberOfUndoneJobs() > 0) { m_log << "asking jobserver for parameters" << endl; ExperimentData * param = this->cb_allocate_experiment_data(); +#ifndef LOCAL if (!m_jc->getParam(*param)){ m_log << "Dying." << endl; // We were told to die. simulator.terminate(1); } +#endif m_current_param = param; DatabaseCampaignMessage * fsppilot = protobufFindSubmessageByTypename(¶m->getMessage(), "DatabaseCampaignMessage"); assert (fsppilot != 0); +#ifdef LOCAL + fsppilot->set_injection_instr(0); + fsppilot->set_injection_instr_absolute(1048677); + fsppilot->set_data_address(2101240); + fsppilot->set_data_width(1); + fsppilot->set_inject_bursts(true); +#endif + unsigned injection_instr = fsppilot->injection_instr(); address_t data_address = fsppilot->data_address(); unsigned width = fsppilot->data_width(); @@ -196,7 +207,11 @@ bool DatabaseExperiment::run() simulator.clearListeners(this); } +#ifndef LOCAL m_jc->sendResult(*param); +#else + break; +#endif this->cb_free_experiment_data(param); } // Explicitly terminate, or the simulator will continue to run. From de8598ab83c2e30e3104ceec11fca3c2bcb3cbc3 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Mon, 15 Feb 2016 14:53:52 +0100 Subject: [PATCH 23/23] cmake: prefer LLVM 3.4 over system-wide default FindLLVM.cmake now starts searching for specific "llvm-config-x.y" versions instead of using the system-wide default "llvm-config" first. This avoids breaking builds on Debian 8, where LLVM 3.5 is the (yet unsupported) default, but 3.4 is still installable. Change-Id: I6fd577f515a233e30c6f803f87b9a680b5515a5b --- cmake/FindLLVM.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindLLVM.cmake b/cmake/FindLLVM.cmake index e13cda05..3379368e 100644 --- a/cmake/FindLLVM.cmake +++ b/cmake/FindLLVM.cmake @@ -1,4 +1,4 @@ -find_program(LLVMCONFIG NAMES llvm-config llvm-config-3.4 llvm-config-3.3 llvm-config-3.2 llvm-config-3.1) +find_program(LLVMCONFIG NAMES llvm-config-3.4 llvm-config-3.3 llvm-config-3.2 llvm-config-3.1 llvm-config) if( NOT LLVMCONFIG ) message(FATAL_ERROR "llvm-config not found, try installing llvm-dev llvm")