diff options
-rwxr-xr-x | lib/automata.py | 26 | ||||
-rwxr-xr-x | test/test_pta.py | 106 |
2 files changed, 132 insertions, 0 deletions
diff --git a/lib/automata.py b/lib/automata.py index 3bba65c..0cc7143 100755 --- a/lib/automata.py +++ b/lib/automata.py @@ -1,6 +1,7 @@ """Classes and helper functions for PTA and other automata.""" from functions import AnalyticFunction, NormalizationFunction +from utils import is_numeric import itertools import numpy as np @@ -604,6 +605,31 @@ class PTA: for transition in self.transitions: transition.set_random_energy_model(static_model) + def shrink_argument_values(self): + """ + Throw away all but two values for each numeric argument of each transition. + + This is meant to speed up an initial PTA-based benchmark by + reducing the parameter space while still gaining insights in the + effect (or nop) or individual parameters on hardware behaviour. + + Parameters with non-numeric values (anything containing neither + numbers nor enums) are left as-is, as they may be distinct + toggles whose effect cannot be estimated when they are left out. + """ + for transition in self.transitions: + for i, argument in enumerate(transition.arguments): + if len(transition.argument_values[i]) <= 2: + continue + if transition.argument_combination == 'zip': + continue + values_are_numeric = True + for value in transition.argument_values[i]: + if not is_numeric(self.normalize_parameter(transition.arg_to_param_map[i], value)): + values_are_numeric = False + if values_are_numeric and len(transition.argument_values[i]) > 2: + transition.argument_values[i] = [transition.argument_values[i][0], transition.argument_values[i][-1]] + def _dfs_with_param(self, generator, param_dict): for trace in generator: param = param_dict.copy() diff --git a/test/test_pta.py b/test/test_pta.py index c41f6a3..3584f93 100755 --- a/test/test_pta.py +++ b/test/test_pta.py @@ -171,6 +171,97 @@ transition: is_interrupt: true """) +example_yaml_3 = yaml.safe_load(""" +codegen: + instance: nrf24l01 + includes: ['driver/nrf24l01.h'] + flags: ['drivers=nrf24l01', 'arch_drivers=spi_b'] + +parameters: + - auto_ack! + - payload_size + - dynamic_payloads_enabled! + - max_retry_count + - retry_count + - retry_delay + - tx_power + - datarate + - channel + +parameter_normalization: + tx_power: + unit: dBm + enum: + Nrf24l01::RF24_PA_MIN: 0 + Nrf24l01::RF24_PA_LOW: 6 + Nrf24l01::RF24_PA_HIGH: 12 + Nrf24l01::RF24_PA_MAX: 18 + datarate: + unit: 'kbit/s' + enum: + Nrf24l01::RF24_1MBPS: 1000 + Nrf24l01::RF24_2MBPS: 2000 + Nrf24l01::RF24_250KBPS: 250 + retry_delay: + unit: us + formula: '250 * param + 250' + +states: + - UNINITIALIZED + - STANDBY1 + +transition: + setup: + src: [UNINITIALIZED, STANDBY1] + dst: STANDBY1 + set_param: + 'auto_ack!': 1 + 'dynamic_payloads_enabled!': 0 + max_retry_count: 10 + retry_delay: 5 + datarate: 'Nrf24l01::RF24_1MBPS' + tx_power: 'Nrf24l01::RF24_PA_MAX' + channel: 76 + setAutoAck: + src: [STANDBY1] + dst: STANDBY1 + arguments: + - name: enable + values: [0, 1] + parameter: 'auto_ack!' + setPALevel: + src: [STANDBY1] + dst: STANDBY1 + arguments: + - name: palevel + values: ['Nrf24l01::RF24_PA_MIN', 'Nrf24l01::RF24_PA_LOW', 'Nrf24l01::RF24_PA_HIGH', 'Nrf24l01::RF24_PA_MAX'] + parameter: tx_power + setRetries: + src: [STANDBY1] + dst: STANDBY1 + arguments: + - name: delay + values: [0, 5, 10, 15] + parameter: retry_delay + - name: count + values: [0, 5, 10, 15] + parameter: max_retry_count + write: + src: [STANDBY1] + dst: STANDBY1 + arguments: + - name: buf + values: ['"foo"', '"foo"', '"foofoofoo"', '"foofoofoo"', '"123456789012345678901234567890"', '"123456789012345678901234567890"'] + - name: len + values: [3, 3, 9, 9, 30, 30] + parameter: payload_size + - name: await_ack + values: [0, 1, 0, 1, 0, 1] + - name: blocking + values: [1, 1, 1, 1, 1, 1] + argument_combination: zip +""") + def dfs_tran_to_name(runs: list, with_args: bool = False, with_param: bool = False) -> list: if with_param: return list(map(lambda run: list(map(lambda x: (x[0].name, x[1], x[2]), run)), runs)) @@ -426,6 +517,21 @@ class TestPTA(unittest.TestCase): ] ) + def test_shrink(self): + pta = PTA.from_yaml(example_yaml_3) + pta.shrink_argument_values() + self.assertEqual(pta.transitions[0].name, 'setAutoAck') + self.assertEqual(pta.transitions[1].name, 'setPALevel') + self.assertEqual(pta.transitions[2].name, 'setRetries') + self.assertEqual(pta.transitions[3].name, 'setup') + self.assertEqual(pta.transitions[4].name, 'setup') + self.assertEqual(pta.transitions[5].name, 'write') + self.assertEqual(pta.transitions[0].argument_values, [[0, 1]]) + self.assertEqual(pta.transitions[1].argument_values, [['Nrf24l01::RF24_PA_MIN', 'Nrf24l01::RF24_PA_MAX']]) + self.assertEqual(pta.transitions[2].argument_values, [[0, 15], [0, 15]]) + self.assertEqual(pta.transitions[5].argument_values, [['"foo"', '"foo"', '"foofoofoo"', '"foofoofoo"', '"123456789012345678901234567890"', + '"123456789012345678901234567890"'], [3, 3, 9, 9, 30, 30], [0, 1, 0, 1, 0, 1], [1, 1, 1, 1, 1, 1]]) + def test_simulation(self): pta = PTA() pta.add_state('IDLE', power = 5) |