summaryrefslogtreecommitdiff
path: root/lib/loader.py
diff options
context:
space:
mode:
authorDaniel Friesel <daniel.friesel@uos.de>2020-10-13 15:20:21 +0200
committerDaniel Friesel <daniel.friesel@uos.de>2020-10-13 15:20:21 +0200
commitf5125e191ab1db62e4167b00f809dba20bc54b6f (patch)
tree312ed18c55e42bd90abd98426e899ff1dd582a8c /lib/loader.py
parentc3958b67834268792235faef7cfca86f1d8e8195 (diff)
parentf8cf50af8564094e145124af08e5e12e13ed352f (diff)
merge
Diffstat (limited to 'lib/loader.py')
-rw-r--r--lib/loader.py176
1 files changed, 167 insertions, 9 deletions
diff --git a/lib/loader.py b/lib/loader.py
index 57b3d30..fcd5490 100644
--- a/lib/loader.py
+++ b/lib/loader.py
@@ -11,6 +11,7 @@ import struct
import tarfile
import hashlib
from multiprocessing import Pool
+
from .utils import running_mean, soft_cast_int
logger = logging.getLogger(__name__)
@@ -107,7 +108,14 @@ def _preprocess_mimosa(measurement):
def _preprocess_etlog(measurement):
setup = measurement["setup"]
- etlog = EnergyTraceLog(
+
+ energytrace_class = EnergyTraceWithBarcode
+ if measurement["sync_mode"] == "la":
+ energytrace_class = EnergyTraceWithLogicAnalyzer
+ elif measurement["sync_mode"] == "timer":
+ energytrace_class = EnergyTraceWithTimer
+
+ etlog = energytrace_class(
float(setup["voltage"]),
int(setup["state_duration"]),
measurement["transition_names"],
@@ -406,7 +414,7 @@ class RawData:
processed_data["error"] = "; ".join(processed_data["datasource_errors"])
return False
- # Note that the low-level parser (EnergyTraceLog) already checks
+ # Note that the low-level parser (EnergyTraceWithBarcode) already checks
# whether the transition count is correct
return True
@@ -909,6 +917,10 @@ class RawData:
new_filenames = list()
with tarfile.open(filename) as tf:
ptalog = self.ptalog
+ if "sync" in ptalog["opt"]["energytrace"]:
+ sync_mode = ptalog["opt"]["energytrace"]["sync"]
+ else:
+ sync_mode = "bar"
# Benchmark code may be too large to be executed in a single
# run, so benchmarks (a benchmark is basically a list of DFA runs)
@@ -963,13 +975,16 @@ class RawData:
"state_duration": ptalog["opt"]["sleep"],
}
)
- for repeat_id, etlog_file in enumerate(ptalog["files"][j]):
- member = tf.getmember(etlog_file)
+ for repeat_id, etlog_files in enumerate(ptalog["files"][j]):
+ members = list(map(tf.getmember, etlog_files))
offline_data.append(
{
- "content": tf.extractfile(member).read(),
+ "content": list(
+ map(lambda f: tf.extractfile(f).read(), members)
+ ),
+ "sync_mode": sync_mode,
"fileno": j,
- "info": member,
+ "info": members[0],
"setup": self.setup_by_fileno[j],
"repeat_id": repeat_id,
"expected_trace": ptalog["traces"][j],
@@ -1161,7 +1176,7 @@ def pta_trace_to_aggregate(traces, ignore_trace_indexes=[]):
return by_name, parameter_names, arg_count
-class EnergyTraceLog:
+class EnergyTraceWithBarcode:
"""
EnergyTrace log loader for DFA traces.
@@ -1184,7 +1199,7 @@ class EnergyTraceLog:
with_traces=False,
):
"""
- Create a new EnergyTraceLog object.
+ Create a new EnergyTraceWithBarcode object.
:param voltage: supply voltage [V], usually 3.3 V
:param state_duration: state duration [ms]
@@ -1226,7 +1241,7 @@ class EnergyTraceLog:
)
return list()
- lines = log_data.decode("ascii").split("\n")
+ lines = log_data[0].decode("ascii").split("\n")
data_count = sum(map(lambda x: len(x) > 0 and x[0] != "#", lines))
data_lines = filter(lambda x: len(x) > 0 and x[0] != "#", lines)
@@ -1599,6 +1614,149 @@ class EnergyTraceLog:
return None, None, None, None
+class EnergyTraceWithLogicAnalyzer:
+ def __init__(
+ self,
+ voltage: float,
+ state_duration: int,
+ transition_names: list,
+ with_traces=False,
+ ):
+
+ """
+ Create a new EnergyTraceWithLogicAnalyzer object.
+
+ :param voltage: supply voltage [V], usually 3.3 V
+ :param state_duration: state duration [ms]
+ :param transition_names: list of transition names in PTA transition order.
+ Needed to map barcode synchronization numbers to transitions.
+ """
+ self.voltage = voltage
+ self.state_duration = state_duration * 1e-3
+ self.transition_names = transition_names
+ self.with_traces = with_traces
+ self.errors = list()
+
+ def load_data(self, log_data):
+ from data.timing.SigrokInterface import SigrokResult
+ from data.energy.EnergyInterface import EnergyInterface
+
+ # Daten laden
+ self.sync_data = SigrokResult.fromString(log_data[0])
+ self.energy_data = EnergyInterface.getDataFromString(str(log_data[1]))
+
+ pass
+
+ def analyze_states(self, traces, offline_index: int):
+ u"""
+ Split log data into states and transitions and return duration, energy, and mean power for each element.
+
+ :param traces: expected traces, needed to synchronize with the measurement.
+ traces is a list of runs, traces[*]['trace'] is a single run
+ (i.e. a list of states and transitions, starting with a transition
+ and ending with a state).
+ :param offline_index: This function uses traces[*]['trace'][*]['online_aggregates']['duration'][offline_index] to find sync codes
+
+ :param charges: raw charges (each element describes the charge in pJ transferred during 10 µs)
+ :param trigidx: "charges" indexes corresponding to a trigger edge, see `trigger_edges`
+ :param ua_func: charge(pJ) -> current(µA) function as returned by `calibration_function`
+
+ :returns: returns list of states and transitions, starting with a transition and ending with astate
+ Each element is a dict containing:
+ * `isa`: 'state' or 'transition'
+ * `W_mean`: Mittelwert der Leistungsaufnahme
+ * `W_std`: Standardabweichung der Leistungsaufnahme
+ * `s`: Dauer
+ if isa == 'transition, it also contains:
+ * `W_mean_delta_prev`: Differenz zwischen W_mean und W_mean des vorherigen Zustands
+ * `W_mean_delta_next`: Differenz zwischen W_mean und W_mean des Folgezustands
+ """
+
+ names = []
+ for trace_number, trace in enumerate(traces):
+ for state_or_transition in trace["trace"]:
+ names.append(state_or_transition["name"])
+ # print(names[:15])
+ from data.processing.DataProcessor import DataProcessor
+
+ dp = DataProcessor(sync_data=self.sync_data, energy_data=self.energy_data)
+ dp.run()
+ energy_trace_new = list()
+ energy_trace_new.extend(dp.getStatesdfatool(state_sleep=self.state_duration))
+ dp.plot()
+ # dp.plot(names)
+ energy_trace_new = energy_trace_new[4:]
+
+ energy_trace = list()
+ expected_transitions = list()
+
+ # Print for debug purposes
+ # for number, name in enumerate(names):
+ # if "P15_8MW" in name:
+ # print(name, energy_trace_new[number]["W_mean"])
+
+ # add next/prev state W_mean_delta
+ for number, item in enumerate(energy_trace_new):
+ if item["isa"] == "transition" and 0 < number < len(energy_trace_new) - 1:
+ item["W_mean_delta_prev"] = energy_trace_new[number - 1]
+ item["W_mean_delta_next"] = energy_trace_new[number + 1]
+
+ # st = ""
+ # for i, x in enumerate(energy_trace_new[-10:]):
+ # #st += "(%s|%s|%s)" % (energy_trace[i-10]["name"],x['W_mean'],x['s'])
+ # st += "(%s|%s|%s)\n" % (energy_trace[i-10]["s"], x['s'], x['W_mean'])
+
+ # print(st, "\n_______________________")
+ # print(len(self.sync_data.timestamps), " - ", len(energy_trace_new), " - ", len(energy_trace), " - ", ",".join([str(x["s"]) for x in energy_trace_new[-6:]]), " - ", ",".join([str(x["s"]) for x in energy_trace[-6:]]))
+ # if len(energy_trace_new) < len(energy_trace):
+ # return None
+
+ return energy_trace_new
+
+
+class EnergyTraceWithTimer(EnergyTraceWithLogicAnalyzer):
+ def __init__(
+ self,
+ voltage: float,
+ state_duration: int,
+ transition_names: list,
+ with_traces=False,
+ ):
+
+ """
+ Create a new EnergyTraceWithLogicAnalyzer object.
+
+ :param voltage: supply voltage [V], usually 3.3 V
+ :param state_duration: state duration [ms]
+ :param transition_names: list of transition names in PTA transition order.
+ Needed to map barcode synchronization numbers to transitions.
+ """
+
+ self.voltage = voltage
+ self.state_duration = state_duration * 1e-3
+ self.transition_names = transition_names
+ self.with_traces = with_traces
+ self.errors = list()
+
+ super().__init__(voltage, state_duration, transition_names, with_traces)
+
+ def load_data(self, log_data):
+ from data.timing.SigrokInterface import SigrokResult
+ from data.energy.EnergyInterface import EnergyInterface
+
+ # Daten laden
+ self.sync_data = None
+ self.energy_data = EnergyInterface.getDataFromString(str(log_data[0]))
+
+ pass
+
+ def analyze_states(self, traces, offline_index: int):
+ from data.timing.SigrokInterface import SigrokResult
+
+ self.sync_data = SigrokResult.fromTraces(traces)
+ return super().analyze_states(traces, offline_index)
+
+
class MIMOSA:
"""
MIMOSA log loader for DFA traces with auto-calibration.