diff --git a/c_common/models/chip_power_monitor/src/chip_power_monitor.c b/c_common/models/chip_power_monitor/src/chip_power_monitor.c index 4e8cb863b..1646fa2e3 100644 --- a/c_common/models/chip_power_monitor/src/chip_power_monitor.c +++ b/c_common/models/chip_power_monitor/src/chip_power_monitor.c @@ -181,10 +181,8 @@ static void sample_in_slot(UNUSED uint unused0, UNUSED uint unused1) { recording_finalise(); - // Subtract 1 from the time so this tick gets done again on the next - // run - time--; - + // Invert the time calculation so that any time read is correct + time = (time * sample_frequency) / timer; simulation_ready_to_read(); return; diff --git a/spinn_front_end_common/utility_models/chip_power_monitor_machine_vertex.py b/spinn_front_end_common/utility_models/chip_power_monitor_machine_vertex.py index e9eefb1c1..c7bc3776e 100644 --- a/spinn_front_end_common/utility_models/chip_power_monitor_machine_vertex.py +++ b/spinn_front_end_common/utility_models/chip_power_monitor_machine_vertex.py @@ -44,6 +44,8 @@ locate_memory_region_for_placement) from spinn_front_end_common.interface.simulation.simulation_utilities import ( get_simulation_header_array) +from spinn_front_end_common.interface.provenance import ( + AbstractProvidesProvenanceDataFromMachine) logger = FormatAdapter(logging.getLogger(__name__)) BINARY_FILE_NAME = "chip_power_monitor.aplx" @@ -57,7 +59,8 @@ class ChipPowerMonitorMachineVertex( MachineVertex, AbstractHasAssociatedBinary, - AbstractGeneratesDataSpecification, AbstractReceiveBuffersToHost): + AbstractGeneratesDataSpecification, AbstractReceiveBuffersToHost, + AbstractProvidesProvenanceDataFromMachine): """ Machine vertex for C code representing functionality to record idle times in a machine graph. @@ -249,15 +252,23 @@ def get_recorded_data(self, placement: Placement) -> numpy.ndarray: logger.warning( "Chip Power monitor has lost data on chip({}, {})", placement.x, placement.y) + results = numpy.frombuffer(record_raw, dtype="uint32").reshape(-1, 19) + return results - time_for_recorded_sample_s = ( - self._sampling_frequency * - self.__n_samples_per_recording) / 1000000 - results = ( - numpy.frombuffer(record_raw, dtype="uint32").reshape(-1, 19) / - self.__n_samples_per_recording) * time_for_recorded_sample_s + @overrides(AbstractProvidesProvenanceDataFromMachine + .get_provenance_data_from_machine) + def get_provenance_data_from_machine(self, placement: Placement): + # We do this to make sure we actually store the data + results = self.get_recorded_data(placement) + # Get record times in milliseconds record_times = results[:, 0] * self._sampling_frequency / 1000 activity = results[:, 1:].astype("float") + physical_p = FecDataView().get_physical_core_id( + placement.xy, placement.p) + # Set the activity of *this* core to 0, as we don't want to measure + # that! + activity[:, physical_p] = 0 + time_for_recorded_sample_s = self._sampling_frequency / 1000000 activity_times = activity * time_for_recorded_sample_s for checkpoint in FecDataView().iterate_energy_checkpoints(): # Find all activity up to the check point @@ -270,7 +281,6 @@ def get_recorded_data(self, placement: Placement) -> numpy.ndarray: db.insert_monitor( placement.x, placement.y, f"{PROVENANCE_TIME_KEY}_{checkpoint}", activity_time) - FecDataView().clear_energy_checkpoints() activity_count = activity.sum() activity_time = activity_times.sum() with ProvenanceWriter() as db: @@ -278,4 +288,3 @@ def get_recorded_data(self, placement: Placement) -> numpy.ndarray: placement.x, placement.y, PROVENANCE_COUNT_KEY, activity_count) db.insert_monitor( placement.x, placement.y, PROVENANCE_TIME_KEY, activity_time) - return results