Analysis Example ================ The directory ``sample`` contains a working example of the energy analysis. The file ``run.py`` provides a complete example of ScEpTIC configuration:: import ScEpTIC from ScEpTIC.config import ScEpTICConfig from ScEpTIC.analysis.options import AnalysisResultFormat from ScEpTIC.emulator.energy.buffer.capacitor import CapacitorModel from ScEpTIC.emulator.energy.energy_harvester.charge_booster import ChargeBoosterEnergyHarvester from ScEpTIC.emulator.energy.energy_source.time_series_energy_source import TimeSeriesEnergySource from ScEpTIC.emulator.energy.mcu.msp430fr import MSP430FREnergyModel from ScEpTIC.emulator.energy.mcu.options import MCUPowerState, ADCPowerState from ScEpTIC.emulator.energy.mcu_peripheral.camera_0V7620 import Camera0V7620Model from ScEpTIC.emulator.energy.mcu_peripheral.cc1101 import CC1101Model from ScEpTIC.emulator.energy.options import ComponentVoltageSource from ScEpTIC.emulator.energy.options import PowerOffCondition from ScEpTIC.emulator.energy.power_state_event import PowerStateEvent from ScEpTIC.emulator.energy.state_retention.internal_checkpoint import InternalNVMCheckpointEnergyModel from ScEpTIC.emulator.energy.system_energy_model import SystemEnergyModel from ScEpTIC.emulator.energy.timekeeper import TimekeeperModel from ScEpTIC.emulator.energy.voltage_regulator.MAX20361 import MAX20361 # Configuration params config = { 'capacitance': '10u', 'cap_v_max': 5.0, 'mcu_v_on': 3.6, 'mcu_model': 'msp430fr5969', 'mcu_cache_hit': 0.85, 'mcu_lpm': 'LPM4', 'mcu_clock_frequency': '16MHz', 'energy_source': 'rf_mementos', 'load_resistance': '30K', 'harvester_resistance': '1', } # RF Energy Source energy_source = TimeSeriesEnergySource(config['energy_source']) energy_source.set_load_resistance(config['load_resistance']) energy_source.restart_on_trace_end = True # Charge Booster Energy Harvester charge_booster = MAX20361() # Voltage 1.5% higher than MCU Von to ensure power on charge_booster.set_output_voltage(config['mcu_v_on'] * 1.015) energy_harvester = ChargeBoosterEnergyHarvester(charge_booster, config['harvester_resistance']) energy_harvester.attach_energy_source(energy_source) # Energy buffer energy_buffer = CapacitorModel(config['capacitance'], config['cap_v_max'], None) # Start with full energy buffer energy_buffer.set_voltage(config['mcu_v_on']) # MCU mcu = MSP430FREnergyModel(config['mcu_model'], instruction_cache_hit_ratio=config['mcu_cache_hit']) mcu.set_frequency(config['mcu_clock_frequency']) mcu.set_target_lpm(config['mcu_lpm']) mcu.set_v_on(config['mcu_v_on']) mcu.set_mcu_state(MCUPowerState.ON) mcu.set_adc_state(ADCPowerState.OFF) # Timekeeper timekeeper = TimekeeperModel() # Peripherals radio = CC1101Model() camera = Camera0V7620Model() # System model system_model = SystemEnergyModel() system_model.attach_energy_buffer(energy_buffer) system_model.set_power_off_condition(PowerOffCondition.POWER_STATE_EVENT) system_model.add_power_off_event(PowerStateEvent.MCU_OFF) system_model.attach_energy_source_model(energy_source) system_model.attach_energy_harvester(energy_harvester) system_model.attach_mcu(mcu) # Do not use a voltage regulator for the system system_model.attach_voltage_regulator(None) system_model.attach_timekeeper(timekeeper) system_model.attach_component('cc1101', radio, ComponentVoltageSource.ENERGY_BUFFER) system_model.attach_component('0V7620', camera, ComponentVoltageSource.ENERGY_BUFFER) # State retention model state_retention = InternalNVMCheckpointEnergyModel() system_model.attach_state_retention_model(state_retention) config = ScEpTICConfig() # Volatile Memory config.memory.volatile.set_config('enabled', True) config.memory.volatile.set_config('contains_stack', True) config.memory.volatile.set_config('contains_heap', True) config.memory.volatile.set_config('contains_gst', True) # Non-volatile memory config.memory.non_volatile.set_config('enabled', True) config.memory.non_volatile.set_config('contains_stack', False) config.memory.non_volatile.set_config('contains_heap', False) config.memory.non_volatile.set_config('contains_gst', True) config.memory.set_config("gst_default_memory", "volatile") # State-retention config.state_retention.set_config('type', 'checkpoint') config.state_retention.set_config('state_save_strategy', 'static_placement') config.state_retention.set_config('restore_stack', True) config.state_retention.set_config('restore_heap', True) config.state_retention.set_config('restore_volatile_gst', True) config.state_retention.set_config('restore_non_volatile_gst', False) config.state_retention.set_config('restore_register_file', True) # Memory check config.memory.set_config("check_memory_size", False) # Program config.program.set_config('file', "source.ll") # Results output config.result_output.set_config("save_directory", "analysis_results/") config.result_output.set_config("test_name", "sceptic_example") config.result_output.set_config("dir_append_datetime", False) config.analysis.add_config("enabled_analysis", "energy") config.analysis.energy.set_config("system_model", system_model) config.analysis.set_config('save_results', True) config.analysis.add_config('results_formats', AnalysisResultFormat.TEXT) config.custom_metrics.add_custom_metric(0, 'APP_START', True, True, True) config.custom_metrics.add_custom_metric(1, 'APP_END', True, True, True) vm = ScEpTIC.init(config) vm.execute_analysis() The code we are going to execute is the following:: int i; // NVM var int res[100] __attribute__((section(".DATA,.NVM"))); void main() { // Limit to 20s of simulated time while(sceptic_get_simulation_time() < 20) { // Metric to track starts sceptic_increment_custom_metric(0); // Simulate sensor read sceptic_camera_read_data(2); checkpoint(); // Simulate workload for(int i = 0; i < 100; i++) { res[i] = rand() * rand() * rand() * 1000; } checkpoint(); // Send data sceptic_cc1101_transmit(64, 2); checkpoint(); // Metric to track finishes sceptic_increment_custom_metric(1); } } The corresponding LLVM IR is available in ``source.ll``. To run the analysis, you need to execute:: pypy3 run.py Once the analysis terminates, ScEpTIC writes the analysis results inside a new directory, called ``analysis_results``. The results of our analysis are located inside ``analysis_results/sceptic_example``:: . ├── analysis │ ├── energy │ │ ├── energy_analysis.txt │ │ └── termination_reason.json │ └── energy_custom_metrics.txt ├── code │ ├── main.txt │ ├── rand.txt │ ├── sceptic_camera_read_data.txt │ ├── sceptic_cc1101_transmit.txt │ └── sceptic_get_simulation_time.txt └── states └── energy.txt Inside ``analysis/energy/`` there are two files: ``energy_analysis.txt`` contains system timing and energy consumption metrics, whereas ``termination_reason.json`` contains information on the simulation termination reason. Instead, ``analysis/energy_custom_metrics.txt`` contains the value of the custom metrics we incremented using ``sceptic_increment_custom_metrics``. We can check that the outer loop started and terminated its execution 18 times. The ``code/`` directory contains the ScEpTIC AST of every function used in ``source.c``. Finally, ``states/energy.txt`` provides a dump of the register file, main memory, and system state.