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.