class EnergyCalculator: """ Skeleton for energy calculator class A class needs to expose the following attributes: - voltage: nominal operating voltage - frequency: nominal operating frequency - nvm_extra_cycles: number of wait cycles for NVM accesses - energy_clock_cycle: energy consumption per clock cycle - energy_volatile_memory_access: extra energy consumption per clock cycle for volatile memory accesses - energy_non_volatile_memory_access: extra energy consumption per clock cycle for non-volatile memory accesses - non_volatile_increase: % increase in energy of a single clock cycle accessing non-volatile memory vs volatile memory note: must not to account for nvm_extra_cycles - adc_active_cycles: number of clock cycles while the ADC is active for checkpoint trigger calls - energy_clock_cycle_adc: extra energy consumption per cycle due to ADC on - adc_instructions: number of instructions executed to initialize, query, and power off the ADC The class needs to expose the following method: - n_min_function(n_writes): function to calculate the n_min parameter for applying the read consolidaton for the virtual_memory trasformation """ multipliers = {'G': 1000000000.0, 'M': 1000000.0, 'K': 1000.0, 'm': 0.001, 'u': 0.000001, 'n': 0.000000001} def __init__(self, datasheet, n_registers, adc_datasheet): raise NotImplementedError(f"{self.__class__.__name__} needs to overwrite the init method!") def n_min_function(self, n_writes): """ Function to calculate the minimum number of read instructions required to create a volatile copy of a memory location. Necessary for virtual_memory transformation :param n_writes: number of writes required for creating a volatile copy :return: number of minimum reads """ raise NotImplementedError(f"{self.__class__.__name__} does not implement n_min_function(self, n_writes)") def _str_to_float(self, value): """ Converts a string to a float, accounting for unit multipliers such as M/k/m/u """ multiplier = value[-1] # account for multiplier if multiplier in self.multipliers: number = float(value[:-1]) multiplier = float(self.multipliers[multiplier]) value = number * multiplier return float(value) def _str_to_int(self, value): """ Converts a string to an int, accounting for unit multipliers such as M/k/m/u """ multiplier = value[-1] # account for multiplier if multiplier in self.multipliers: number = float(value[:-1]) multiplier = float(self.multipliers[multiplier]) value = number * multiplier return int(value) @staticmethod def _I_to_e(I, V, f): """ Converts current consumption I to energy consumption """ return (float(V) * float(I)) / float(f) def __str__(self): retstr = f"{self.__class__.__name__}():\n" elements = { "voltage": {"name": "Voltage", "unit": "V"}, "frequency": {"name": "MCU Frequency", "unit": "Hz"}, "nvm_extra_cycles": {"name": "NVM Wait Cycles", "unit": "clock cycles"}, "energy_clock_cycle": {"name": "Energy consumption", "unit": "J/clock cycle"}, "energy_volatile_memory_access": {"name": "Extra energy consumption for volatile accesses", "unit": "J/clock cycle"}, "energy_non_volatile_memory_access": {"name": "Extra energy consumption for non-volatile accesses", "unit": "J/clock cycle"}, } for element in dir(self): if element in elements: value = getattr(self, element) name = elements[element]["name"] unit = elements[element]["unit"] retstr += f" - {name}: {value} {unit}\n" return retstr