summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Friesel <daniel.friesel@uos.de>2020-12-15 18:56:35 +0100
committerDaniel Friesel <daniel.friesel@uos.de>2020-12-15 18:56:35 +0100
commita1e3ca835f8acfda2aa2c5502da5c1d305d59b03 (patch)
tree30f242ba7438d4fb8e37d2a2f56147b7ba6740df /lib
parent383cf6c3fd40c015776fc888f4304cf9cfff88fe (diff)
add proof of concept for EnergyTrace++ based drift compensation
Diffstat (limited to 'lib')
-rw-r--r--lib/lennart/DataProcessor.py37
-rw-r--r--lib/loader.py28
2 files changed, 61 insertions, 4 deletions
diff --git a/lib/lennart/DataProcessor.py b/lib/lennart/DataProcessor.py
index dd45996..e2cfbd2 100644
--- a/lib/lennart/DataProcessor.py
+++ b/lib/lennart/DataProcessor.py
@@ -8,7 +8,9 @@ logger = logging.getLogger(__name__)
class DataProcessor:
- def __init__(self, sync_data, et_timestamps, et_power):
+ def __init__(
+ self, sync_data, et_timestamps, et_power, hw_statechange_indexes=list()
+ ):
"""
Creates DataProcessor object.
@@ -22,6 +24,7 @@ class DataProcessor:
self.et_timestamps = et_timestamps
# energytrace power values
self.et_power_values = et_power
+ self.hw_statechange_indexes = hw_statechange_indexes
self.sync_data = sync_data
self.start_offset = 0
@@ -140,7 +143,10 @@ class DataProcessor:
# As the start and stop timestamps have already been synchronized, we only adjust
# actual transition timestamps here.
if os.getenv("DFATOOL_COMPENSATE_DRIFT"):
- with_drift_compensation = self.compensateDrift(with_drift[4:-8])
+ if len(self.hw_statechange_indexes):
+ with_drift_compensation = self.compensateDriftPlusplus(with_drift[4:-8])
+ else:
+ with_drift_compensation = self.compensateDrift(with_drift[4:-8])
self.sync_timestamps[4:-8] = with_drift_compensation
def addDrift(self, input_timestamps, end_timestamp, end_offset, start_timestamp):
@@ -163,6 +169,33 @@ class DataProcessor:
) * endFactor + start_timestamp
return sync_timestamps_with_drift
+ def compensateDriftPlusplus(self, sync_timestamps):
+ expected_transition_start_timestamps = sync_timestamps[::2]
+ compensated_timestamps = list()
+ drift = 0
+ for i, expected_start_ts in enumerate(expected_transition_start_timestamps):
+ expected_end_ts = sync_timestamps[i * 2 + 1]
+ et_timestamps_start = bisect_left(
+ self.et_timestamps, expected_start_ts - 5e-3
+ )
+ et_timestamps_end = bisect_right(
+ self.et_timestamps, expected_start_ts + 5e-3
+ )
+
+ candidate_indexes = list()
+ for index in self.hw_statechange_indexes:
+ if et_timestamps_start <= index <= et_timestamps_end:
+ candidate_indexes.append(index)
+
+ if len(candidate_indexes) >= 2:
+ drift = self.et_timestamps[candidate_indexes[0]] - expected_start_ts
+
+ compensated_timestamps.append(expected_start_ts + drift)
+ compensated_timestamps.append(expected_end_ts + drift)
+ print(drift)
+
+ return compensated_timestamps
+
def compensateDrift(self, sync_timestamps):
from dfatool.pelt import PELT
diff --git a/lib/loader.py b/lib/loader.py
index 7a0fc4e..b5cfa97 100644
--- a/lib/loader.py
+++ b/lib/loader.py
@@ -1244,13 +1244,14 @@ def _load_energytrace(data_string):
data_lines = filter(lambda x: len(x) > 0 and x[0] != "#", lines)
data = np.empty((data_count, 4))
+ hardware_states = [None for i in range(data_count)]
for i, line in enumerate(data_lines):
fields = line.split(" ")
if len(fields) == 4:
timestamp, current, voltage, total_energy = map(int, fields)
elif len(fields) == 5:
- # cpustate = fields[0]
+ hardware_states[i] = fields[0]
timestamp, current, voltage, total_energy = map(int, fields[1:])
else:
raise RuntimeError('cannot parse line "{}"'.format(line))
@@ -1264,13 +1265,32 @@ def _load_energytrace(data_string):
sample_rate = data_count / (m_duration_us * 1e-6)
+ hardware_state_changes = list()
+ if hardware_states[0]:
+ prev_state = hardware_states[0]
+ for i, state in enumerate(hardware_states):
+ if (
+ state != prev_state
+ and state != "0000000000000000"
+ and prev_state != "0000000000000000"
+ ):
+ hardware_state_changes.append(i)
+ if state != "0000000000000000":
+ prev_state = state
+
logger.debug(
"got {} samples with {} seconds of log data ({} Hz)".format(
data_count, m_duration_us * 1e-6, sample_rate
)
)
- return (interval_start_timestamp, interval_duration, interval_power, sample_rate)
+ return (
+ interval_start_timestamp,
+ interval_duration,
+ interval_power,
+ sample_rate,
+ hardware_state_changes,
+ )
class EnergyTraceWithBarcode:
@@ -1343,6 +1363,7 @@ class EnergyTraceWithBarcode:
self.interval_duration,
self.interval_power,
self.sample_rate,
+ self.hw_statechange_indexes,
) = _load_energytrace(log_data[0])
def ts_to_index(self, timestamp):
@@ -1723,6 +1744,7 @@ class EnergyTraceWithLogicAnalyzer:
self.interval_duration,
self.interval_power,
self.sample_rate,
+ self.hw_statechange_indexes,
) = _load_energytrace(log_data[1])
def analyze_states(self, traces, offline_index: int):
@@ -1761,6 +1783,7 @@ class EnergyTraceWithLogicAnalyzer:
sync_data=self.sync_data,
et_timestamps=self.interval_start_timestamp,
et_power=self.interval_power,
+ hw_statechange_indexes=self.hw_statechange_indexes,
)
dp.run()
energy_trace_new = dp.getStatesdfatool(
@@ -1838,6 +1861,7 @@ class EnergyTraceWithTimer(EnergyTraceWithLogicAnalyzer):
self.interval_duration,
self.interval_power,
self.sample_rate,
+ self.hw_statechange_indexes,
) = _load_energytrace(log_data[0])
def analyze_states(self, traces, offline_index: int):