481 lines
17 KiB
Python
481 lines
17 KiB
Python
import math
|
|
|
|
from ScEpTIC.AST.builtins.builtin import Builtin
|
|
from ScEpTIC.AST.elements.value import Value
|
|
from ScEpTIC.emulator.energy.mcu import ADCPowerState
|
|
from ScEpTIC.emulator.energy.mcu.options import MCUClockCycleAction
|
|
from ScEpTIC.emulator.energy.options import OpModeName
|
|
|
|
class voc_read_data(Builtin):
|
|
"""
|
|
voc_read_data() builtin that reads voc from SGP40 sensor
|
|
"""
|
|
def get_val(self):
|
|
try:
|
|
sgp40 = self._vmstate.config.analysis.energy.system_model.get_component('SGP40')
|
|
except BaseException:
|
|
raise Exception("SystemModel not attached to ScEpTIC")
|
|
|
|
if sgp40 is None:
|
|
raise Exception("SHT85 not attached to ScEpTIC")
|
|
|
|
# read
|
|
self._vmstate.global_clock += sgp40.simulate_read()
|
|
|
|
|
|
class temperature_read_data(Builtin):
|
|
"""
|
|
temperature_read_data() builtin that reads temperature from SHT85 sensor
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
sht85 = self._vmstate.config.analysis.energy.system_model.get_component('SHT85')
|
|
except BaseException:
|
|
raise Exception("SystemModel not attached to ScEpTIC")
|
|
|
|
if sht85 is None:
|
|
raise Exception("SHT85 not attached to ScEpTIC")
|
|
|
|
# read
|
|
self._vmstate.global_clock += sht85.simulate_read()
|
|
|
|
|
|
class camera_read_data(Builtin):
|
|
"""
|
|
camera_read_data() builtin that reads a camera
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
camera = self._vmstate.config.analysis.energy.system_model.get_component('0V7620')
|
|
except BaseException:
|
|
raise Exception("SystemModel not attached to ScEpTIC")
|
|
|
|
if camera is None:
|
|
raise Exception("Camera not attached to ScEpTIC")
|
|
|
|
# word size
|
|
self._vmstate.global_clock += camera.simulate_read(int(self.args[0]))
|
|
|
|
|
|
class generic_adc_sensor_read(Builtin):
|
|
"""
|
|
generic_adc_sensor_read() builtin that reads a generic ADC sensor
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
generic_sensor = self._vmstate.config.analysis.energy.system_model.get_component('generic_sensor')
|
|
except BaseException:
|
|
raise Exception("SystemModel not attached to ScEpTIC")
|
|
|
|
if generic_sensor is None:
|
|
raise Exception("GenericADCSensor not attached to ScEpTIC")
|
|
|
|
self._vmstate.global_clock += generic_sensor.simulate_read(int(self.args[0]))
|
|
|
|
class cc1101_set_state(Builtin):
|
|
"""
|
|
cc1101_set_state() builtin that sets the state of cc1101
|
|
"""
|
|
|
|
states = {0: 'off', 1: 'inactive', 2: 'active'}
|
|
|
|
def get_val(self):
|
|
try:
|
|
cc1101 = self._vmstate.config.analysis.energy.system_model.get_component('cc1101')
|
|
except BaseException:
|
|
raise Exception("SystemModel not attached to ScEpTIC")
|
|
|
|
if cc1101 is None:
|
|
raise Exception("CC1101 not attached to ScEpTIC")
|
|
|
|
self._vmstate.global_clock += cc1101.simulate_set_state(self.states[int(self.args[0])])
|
|
|
|
|
|
class cc1101_transmit(Builtin):
|
|
"""
|
|
cc1101_transmit() builtin that turns on the cc1101, transmit data, and turns it off
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
cc1101 = self._vmstate.config.analysis.energy.system_model.get_component('cc1101')
|
|
except BaseException:
|
|
raise Exception("SystemModel not attached to ScEpTIC")
|
|
|
|
if cc1101 is None:
|
|
raise Exception("CC1101 not attached to ScEpTIC")
|
|
|
|
# args: bytes, word_size
|
|
self._vmstate.global_clock += cc1101.simulate_transmit(int(self.args[0]), int(self.args[1]))
|
|
|
|
class adc_off(Builtin):
|
|
"""
|
|
adc_off() builtin that turns off the ADCon
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
system_model = self._vmstate.config.analysis.energy.system_model
|
|
except BaseException:
|
|
raise Exception("SystemModel not attached to ScEpTIC")
|
|
|
|
# Turn off ADC
|
|
self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, OpModeName.SIMULATE_ADC)
|
|
system_model.mcu.set_adc_state(ADCPowerState.OFF)
|
|
|
|
class adc_on(Builtin):
|
|
"""
|
|
adc_on() builtin that turns on the ADC
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
system_model = self._vmstate.config.analysis.energy.system_model
|
|
except BaseException:
|
|
raise Exception("SystemModel not attached to ScEpTIC")
|
|
|
|
# Turn on ADC
|
|
# - Run instructions
|
|
# - ADCPowerState -> ON
|
|
for _ in range(system_model.mcu.adc_instructions['on']):
|
|
self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, OpModeName.SIMULATE_ADC)
|
|
|
|
system_model.mcu.set_adc_state(ADCPowerState.ON)
|
|
|
|
class adc_read(Builtin):
|
|
"""
|
|
adc_read() builtin that reads data from ADC
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
system_model = self._vmstate.config.analysis.energy.system_model
|
|
except BaseException:
|
|
raise Exception("SystemModel not attached to ScEpTIC")
|
|
|
|
# Wait for startup and data to be ready
|
|
for _ in range(system_model.mcu.get_ADC_wait_cycles()):
|
|
self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name)
|
|
|
|
# Transfer
|
|
for _ in range(system_model.mcu.adc_instructions['transfer']):
|
|
self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name)
|
|
|
|
|
|
class adc_get_data(Builtin):
|
|
"""
|
|
adc_get_data(n_samples, wait_between_samples) builtin that turns the ADC on, collects n_samples (one every wait_between_samples ms), and turns the ADC off.
|
|
"""
|
|
op_mode_name = OpModeName.SIMULATE_ADC
|
|
|
|
def __adc_on(self, system_model):
|
|
# Turn on ADC
|
|
# - Run instructions
|
|
# - ADCPowerState -> ON
|
|
for _ in range(system_model.mcu.adc_instructions['on']):
|
|
self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name)
|
|
|
|
system_model.mcu.set_adc_state(ADCPowerState.ON)
|
|
|
|
def __adc_off(self, system_model):
|
|
# Turn off ADC
|
|
self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name)
|
|
system_model.mcu.set_adc_state(ADCPowerState.OFF)
|
|
|
|
def __adc_transfer_data(self, system_model):
|
|
# Wait for startup and data to be ready
|
|
for _ in range(system_model.mcu.get_ADC_wait_cycles()):
|
|
self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name)
|
|
|
|
# Transfer
|
|
for _ in range(system_model.mcu.adc_instructions['transfer']):
|
|
self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name)
|
|
|
|
def __wait_cycles(self, system_model, wait_cycles):
|
|
if wait_cycles <= 0:
|
|
return
|
|
|
|
for _ in range(wait_cycles):
|
|
self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, self.op_mode_name)
|
|
|
|
def __adc_get_samples_on_off(self, system_model, n_samples, wait_cycles):
|
|
for i in range(n_samples):
|
|
self.__adc_on(system_model)
|
|
self.__adc_transfer_data(system_model)
|
|
self.__adc_off(system_model)
|
|
|
|
if i < (n_samples - 1):
|
|
self.__wait_cycles(system_model, wait_cycles)
|
|
|
|
def __adc_get_samples(self, system_model, n_samples, wait_cycles):
|
|
self.__adc_on(system_model)
|
|
|
|
for i in range(n_samples):
|
|
self.__adc_transfer_data(system_model)
|
|
if i < (n_samples - 1):
|
|
self.__wait_cycles(system_model, wait_cycles)
|
|
|
|
self.__adc_off(system_model)
|
|
|
|
def get_val(self):
|
|
try:
|
|
system_model = self._vmstate.config.analysis.energy.system_model
|
|
except BaseException:
|
|
raise Exception("SystemModel not attached to ScEpTIC")
|
|
|
|
# Samples to collect
|
|
n_samples = self.args[0]
|
|
|
|
# ms to wait between samples
|
|
samples_s_wait = float(self.args[1]) / 1000.0
|
|
|
|
frequency = system_model.mcu.get_frequency()
|
|
sample_wait_cycles = max(0, math.ceil(samples_s_wait*frequency) - system_model.mcu.get_ADC_wait_cycles())
|
|
|
|
wait_cycles = sample_wait_cycles - system_model.mcu.adc_instructions['on'] - 1
|
|
|
|
if self.args[2] == 0:
|
|
self.__adc_get_samples(system_model, n_samples, sample_wait_cycles)
|
|
else:
|
|
self.__adc_get_samples_on_off(system_model, n_samples, wait_cycles)
|
|
|
|
class timekeeper_get_time_us(Builtin):
|
|
"""
|
|
timekeeper_get_time_us() builtin that returns timekeeper power-off time in us
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
return self._vmstate.config.analysis.energy.system_model.timekeeper.get_time() * 1000000.0
|
|
except BaseException:
|
|
raise Exception("SystemModel/Timekeeper not attached to ScEpTIC")
|
|
|
|
class timekeeper_get_time(Builtin):
|
|
"""
|
|
timekeeper_get_time() builtin that returns timekeeper power-off time
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
return self._vmstate.config.analysis.energy.system_model.timekeeper.get_time()
|
|
except BaseException:
|
|
raise Exception("SystemModel/Timekeeper not attached to ScEpTIC")
|
|
|
|
class set_mcu_power_on_voltage(Builtin):
|
|
"""
|
|
set_mcu_power_on_voltage() builtin that sets the power on voltage of the MCU
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
voltage = self.args[0]
|
|
#print(f"Set MCU Von={voltage}V")
|
|
return self._vmstate.config.analysis.energy.system_model.mcu.set_v_on(voltage)
|
|
except BaseException:
|
|
raise Exception("SystemModel/MCU not attached to ScEpTIC")
|
|
|
|
class get_mcu_time(Builtin):
|
|
"""
|
|
get_mcu_time() builtin that returns the mcu time
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
#t = self._vmstate.config.analysis.energy.system_model.mcu.get_time()
|
|
#print(f"Time: {t}")
|
|
return self._vmstate.config.analysis.energy.system_model.mcu.get_time()
|
|
except BaseException:
|
|
raise Exception("SystemModel/MCU not attached to ScEpTIC")
|
|
|
|
class get_mcu_time_us(Builtin):
|
|
"""
|
|
get_mcu_time_us() builtin that returns the mcu time in us
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
return self._vmstate.config.analysis.energy.system_model.mcu.get_time() * 1000000
|
|
except BaseException:
|
|
raise Exception("SystemModel/MCU not attached to ScEpTIC")
|
|
|
|
class set_mcu_time(Builtin):
|
|
"""
|
|
set_mcu_time() builtin that sets the mcu time
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
t = float(self.args[0])
|
|
self._vmstate.config.analysis.energy.system_model.mcu.set_time(t)
|
|
except BaseException:
|
|
raise Exception("SystemModel/MCU not attached to ScEpTIC")
|
|
|
|
class set_mcu_time_us(Builtin):
|
|
"""
|
|
set_mcu_time_us() builtin that sets the mcu time in us
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
t = float(self.args[0]) / 1000000.0
|
|
self._vmstate.config.analysis.energy.system_model.mcu.set_time(t)
|
|
except BaseException as e:
|
|
print(self.args)
|
|
print(e)
|
|
raise Exception("SystemModel/MCU not attached to ScEpTIC")
|
|
|
|
class get_simulation_time(Builtin):
|
|
"""
|
|
get_simulation_time() builtin that returns the simulation time
|
|
"""
|
|
print_enabled = False
|
|
|
|
def get_val(self):
|
|
try:
|
|
t = self._vmstate.config.analysis.energy.system_model.get_simulation_time()
|
|
if self.print_enabled:
|
|
t_us = t * 1000000.0
|
|
print(f"Time (us): {round(t_us, 2)}")
|
|
return t
|
|
except BaseException:
|
|
raise Exception("SystemModel/MCU not attached to ScEpTIC")
|
|
|
|
class reset_simulation_time(Builtin):
|
|
"""
|
|
reset_simulation_time() builtin that resets the simulation time
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
self._vmstate.config.analysis.energy.system_model.reset_simulation_time()
|
|
except BaseException:
|
|
raise Exception("SystemModel/MCU not attached to ScEpTIC")
|
|
|
|
class get_mcu_clock_cycles(Builtin):
|
|
"""
|
|
get_mcu_clock_cycles() builtin that returns the number of clock cycles in the latest active cycle
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
return self._vmstate.config.analysis.energy.system_model.mcu.get_clock_cycles()
|
|
except BaseException:
|
|
raise Exception("SystemModel/MCU not attached to ScEpTIC")
|
|
|
|
class get_used_energy(Builtin):
|
|
"""
|
|
get_used_energy() builtin that returns the used energy
|
|
"""
|
|
print_enabled = False
|
|
|
|
def get_val(self):
|
|
try:
|
|
e = self._vmstate.config.analysis.energy.system_model.get_used_energy()
|
|
if self.print_enabled:
|
|
e_uj = e * 1000000.0
|
|
print(f"Energy consumption (uJ): {round(e_uj, 2)}")
|
|
return e
|
|
except BaseException:
|
|
raise Exception("SystemModel/MCU not attached to ScEpTIC")
|
|
|
|
class set_capacitor_voltage(Builtin):
|
|
"""
|
|
set_voltage() bultin that sets the energy buffer voltage
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
system_model = self._vmstate.config.analysis.energy.system_model
|
|
except BaseException:
|
|
raise Exception("SystemModel not attached to ScEpTIC")
|
|
|
|
system_model.energy_buffer.set_voltage(self.args[0])
|
|
|
|
class reset_used_energy(Builtin):
|
|
"""
|
|
reset_energy() builtin that resets the energy consumption
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
self._vmstate.config.analysis.energy.system_model.reset_used_energy()
|
|
except BaseException:
|
|
raise Exception("SystemModel/MCU not attached to ScEpTIC")
|
|
|
|
class get_capacitor_voltage(Builtin):
|
|
"""
|
|
get_voltage() builtin that returns capacitor voltage
|
|
"""
|
|
|
|
def get_val(self):
|
|
try:
|
|
system_model = self._vmstate.config.analysis.energy.system_model
|
|
except BaseException:
|
|
raise Exception("SystemModel not attached to ScEpTIC")
|
|
|
|
op_mode_name = OpModeName.PROBE_ENERGY_BUFFER
|
|
|
|
# Turn on ADC
|
|
# - Run instructions
|
|
# - ADCPowerState -> ON
|
|
for _ in range(system_model.mcu.adc_instructions['on']):
|
|
self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, op_mode_name)
|
|
|
|
system_model.mcu.set_adc_state(ADCPowerState.ON)
|
|
# Wait for startup and data to be ready
|
|
for _ in range(system_model.mcu.get_ADC_wait_cycles()):
|
|
self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, op_mode_name, True)
|
|
|
|
# Transfer data to reg
|
|
for _ in range(system_model.mcu.adc_instructions['transfer']):
|
|
self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, op_mode_name)
|
|
|
|
v = system_model.energy_buffer.get_voltage()
|
|
|
|
# Turn off ADC
|
|
self._vmstate.global_clock += system_model.run_step(MCUClockCycleAction.NO_MEMORY_ACCESS, op_mode_name)
|
|
system_model.mcu.set_adc_state(ADCPowerState.OFF)
|
|
|
|
return v
|
|
|
|
get_capacitor_voltage.define_builtin('sceptic_get_capacitor_voltage', '', 'double')
|
|
set_capacitor_voltage.define_builtin('sceptic_set_capacitor_voltage', 'double', 'void')
|
|
get_mcu_clock_cycles.define_builtin('sceptic_get_mcu_clock_cycles', '', 'i32')
|
|
get_mcu_time.define_builtin('sceptic_get_mcu_time', '', 'double')
|
|
get_mcu_time_us.define_builtin('sceptic_get_mcu_time_us', '', 'double')
|
|
get_used_energy.define_builtin('sceptic_get_used_energy', '', 'double')
|
|
reset_used_energy.define_builtin('sceptic_reset_used_energy', '', 'void')
|
|
get_simulation_time.define_builtin('sceptic_get_simulation_time', '', 'double')
|
|
set_mcu_time.define_builtin('sceptic_set_mcu_time', 'double', 'void')
|
|
set_mcu_time_us.define_builtin('sceptic_set_mcu_time_us', 'double', 'void')
|
|
reset_simulation_time.define_builtin('sceptic_reset_simulation_time', '', 'void')
|
|
# voltage
|
|
set_mcu_power_on_voltage.define_builtin('sceptic_set_mcu_power_on_voltage', 'double', 'void')
|
|
timekeeper_get_time.define_builtin('sceptic_timekeeper_get_time', '', 'double')
|
|
timekeeper_get_time_us.define_builtin('sceptic_timekeeper_get_time_us', '', 'double')
|
|
|
|
# n_samples, t_wait (ms), on_off
|
|
adc_get_data.define_builtin('sceptic_adc_get_data', 'i32, double, i32', 'void')
|
|
adc_on.define_builtin('sceptic_adc_on', '', 'void')
|
|
adc_off.define_builtin('sceptic_adc_off', '', 'void')
|
|
adc_read.define_builtin('sceptic_adc_read', '', 'void')
|
|
|
|
# bytes, word_size
|
|
cc1101_transmit.define_builtin('sceptic_cc1101_transmit', 'i32, i32', 'void')
|
|
|
|
# state_id
|
|
cc1101_set_state.define_builtin('sceptic_cc1101_set_state', 'i32', 'void')
|
|
|
|
# n_samples
|
|
generic_adc_sensor_read.define_builtin('sceptic_generic_adc_sensor_read', 'i32', 'void')
|
|
|
|
# word size
|
|
camera_read_data.define_builtin('sceptic_camera_read_data', 'i32', 'void')
|
|
|
|
temperature_read_data.define_builtin('sceptic_read_temperature', '', 'void')
|
|
voc_read_data.define_builtin('sceptic_read_voc', '', 'void')
|
|
|