diff options
author | Daniel Friesel <daniel.friesel@uos.de> | 2020-12-15 18:56:35 +0100 |
---|---|---|
committer | Daniel Friesel <daniel.friesel@uos.de> | 2020-12-15 18:56:35 +0100 |
commit | a1e3ca835f8acfda2aa2c5502da5c1d305d59b03 (patch) | |
tree | 30f242ba7438d4fb8e37d2a2f56147b7ba6740df | |
parent | 383cf6c3fd40c015776fc888f4304cf9cfff88fe (diff) |
add proof of concept for EnergyTrace++ based drift compensation
-rw-r--r-- | lib/lennart/DataProcessor.py | 37 | ||||
-rw-r--r-- | lib/loader.py | 28 |
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): |