sceptic-biomem/ScEpTIC/analysis/utils/max_state_identifier.py
2026-07-10 10:38:57 +02:00

96 lines
3.1 KiB
Python

from ScEpTIC.AST.elements.instructions.other_operations import CallOperation
from ScEpTIC.analysis.utils.saved_state_calculator import SavedStateCalculator
from ScEpTIC.analysis.utils.settings_cache import SettingsCache
class MaxStateIdentifier:
"""
Utility that identifies the volatile state maximum size.
"""
cache_element = "max_state"
def __init__(self, vm):
"""
:param vm: ScEpTIC vm
"""
self.vm = vm
self.n_registers = 0
self.n_memory_cells = 0
self.save_only_pc = True
self.has_static_placement = self.vm.state_retention.static_placement
self.state_calc = SavedStateCalculator(self.vm)
# Cache
file_name = self.vm.state.config.program.file
cache_target = "{}_{}".format(file_name, 'static' if self.has_static_placement else 'interrupt')
self._cache = SettingsCache(self.cache_element, cache_target)
def _load_cache(self):
"""
Load data from the cache file
"""
self._cache.load()
try:
self.n_registers = self._cache.data['n_registers']
self.n_memory_cells = self._cache.data['n_memory_cells']
self.save_only_pc = self._cache.data['save_only_pc']
print(f"Max state loaded - Regs: {self.n_registers}; Memory: {self.n_memory_cells}; Save only pc: {self.save_only_pc}")
return True
except KeyError:
return False
def _save_cache(self):
"""
Save data into the cache file
"""
self._cache.data = {
'n_registers': self.n_registers,
'n_memory_cells': self.n_memory_cells,
'save_only_pc': self.save_only_pc
}
self._cache.save()
def identify(self):
"""
Identifies the maximum state to be saved
"""
if self._load_cache():
return
print(f"Identifying maximum state")
self.vm.reset()
state_save_function_name = self.vm.state_retention.routine_names['save']
while not self.vm.state.program_end_reached:
current_instruction = self.vm.state.current_instruction
self.vm.state.run_step()
# Static placement -> state saved only when state-save operation reached
if self.has_static_placement:
# Skip calc if state-saving operation not reached
if not isinstance(current_instruction, CallOperation) or current_instruction.resolve_function_name() != state_save_function_name:
continue
save_only_pc, n_registers = self.state_calc.get_saved_registers(current_instruction)
n_memory_cells = self.state_calc.get_saved_memory_cells(current_instruction)
self.n_registers = max(self.n_registers, n_registers)
self.n_memory_cells = max(self.n_memory_cells, n_memory_cells)
self.save_only_pc = self.save_only_pc & save_only_pc
self._save_cache()
print(f" -> Regs: {self.n_registers}; Memory: {self.n_memory_cells}; Save only pc: {self.save_only_pc}")
self.vm.reset()