summaryrefslogtreecommitdiffstats
path: root/rtemsspec
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-04-13 10:07:12 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-04-13 10:24:16 +0200
commit9e7ee2687d8f0189564b9e72a2d598444a8433d2 (patch)
tree427955f68e9a72eeb2fd86aaaf48c25cc01deea3 /rtemsspec
parentspec: New cases for /rtems/sem/req/obtain (diff)
downloadrtems-central-9e7ee2687d8f0189564b9e72a2d598444a8433d2.tar.bz2
validation: Add get_post_conditions()
Diffstat (limited to 'rtemsspec')
-rw-r--r--rtemsspec/tests/spec-validation/action2.yml10
-rw-r--r--rtemsspec/tests/test_validation.py19
-rw-r--r--rtemsspec/validation.py49
3 files changed, 76 insertions, 2 deletions
diff --git a/rtemsspec/tests/spec-validation/action2.yml b/rtemsspec/tests/spec-validation/action2.yml
index 822a4701..8c269a12 100644
--- a/rtemsspec/tests/spec-validation/action2.yml
+++ b/rtemsspec/tests/spec-validation/action2.yml
@@ -272,4 +272,14 @@ transition-map:
- B0
C:
- C0
+- enabled-by: BOOM
+ post-conditions:
+ A: N/A
+ B: B0
+ pre-conditions:
+ A: N/A
+ B:
+ - B0
+ C:
+ - C0
type: requirement
diff --git a/rtemsspec/tests/test_validation.py b/rtemsspec/tests/test_validation.py
index 938762c3..a35ff371 100644
--- a/rtemsspec/tests/test_validation.py
+++ b/rtemsspec/tests/test_validation.py
@@ -49,8 +49,13 @@ def test_validation(tmpdir):
assert len(list(transition_map.get_variants([]))) == 36
assert len(list(transition_map.get_variants(["RTEMS_MULTIPROCESSING"
]))) == 36
+ assert len(list(transition_map.get_post_conditions([]))) == 4
+ assert len(
+ list(transition_map.get_post_conditions(["RTEMS_MULTIPROCESSING"
+ ]))) == 5
transition_map = TransitionMap(item_cache["/action2"])
assert transition_map.skip_idx_to_name(1) == "SkipReason"
+ assert len(list(transition_map.get_post_conditions(["BOOM"]))) == 6
generate(validation_config, item_cache)
@@ -2109,14 +2114,24 @@ static const Action2_Entry
Action2_Entries[] = {
{ 0, 1, 0, 0, Action2_Post_A_A1, Action2_Post_B_NA },
{ 0, 0, 0, 0, Action2_Post_A_A2, Action2_Post_B_B0 },
- { 0, 0, 0, 0, Action2_Post_A_A1, Action2_Post_B_B0 },
{ 1, 0, 0, 0, Action2_Post_A_NA, Action2_Post_B_NA },
+ { 0, 0, 0, 0, Action2_Post_A_A1, Action2_Post_B_B0 },
+#if defined(BOOM)
+ { 0, 1, 0, 0, Action2_Post_A_NA, Action2_Post_B_B0 },
+#else
+ { 0, 0, 0, 0, Action2_Post_A_A1, Action2_Post_B_B0 },
+#endif
+#if defined(BOOM)
+ { 0, 1, 0, 0, Action2_Post_A_NA, Action2_Post_B_B0 },
+#else
+ { 0, 0, 0, 0, Action2_Post_A_A2, Action2_Post_B_B0 },
+#endif
{ 0, 0, 0, 0, Action2_Post_A_A3, Action2_Post_B_B0 }
};
static const uint8_t
Action2_Map[] = {
- 2, 2, 2, 0, 0, 0, 1, 1, 1, 1, 1, 4, 0, 0, 0, 3, 3, 3
+ 4, 3, 3, 0, 0, 0, 1, 1, 1, 5, 1, 6, 0, 0, 0, 2, 2, 2
};
static size_t Action2_Scope( void *arg, char *buf, size_t n )
diff --git a/rtemsspec/validation.py b/rtemsspec/validation.py
index 944764f6..baff5305 100644
--- a/rtemsspec/validation.py
+++ b/rtemsspec/validation.py
@@ -615,6 +615,10 @@ _POST_COND_OP = {
"specified-by": _post_cond_specified_by,
}
+PostCond = Tuple[int, ...]
+
+PreCondsOfPostCond = List[Tuple[List[int], ...]]
+
class TransitionMap:
""" Representation of an action requirement transition map. """
@@ -677,6 +681,51 @@ class TransitionMap:
variant = transitions[0]
yield map_idx, variant
+ def get_post_conditions(
+ self, enabled: List[str]
+ ) -> Iterator[Tuple[PostCond, PreCondsOfPostCond]]:
+ """
+ Yields tuples of post-condition variants and the corresponding
+ pre-condition variants which are enabled by the enabled list.
+
+ The first entry of the post-condition variant is the skip index. The
+ remaining entries are post-condition indices. The pre-condition
+ variants are a list of tuples. Each tuple entry corresponds to a
+ pre-condition and provides a list of corresponding pre-condition state
+ indices.
+ """
+ entries = {} # type: Dict[PostCond, PreCondsOfPostCond]
+ for map_idx, variant in self.get_variants(enabled):
+ key = (variant.skip, ) + variant.post_cond
+ entry = entries.setdefault(key, [])
+ entry.append(
+ tuple([state] for state in self.map_idx_to_pre_co_states(
+ map_idx, variant.pre_cond_na)))
+ for post_cond, pre_conds in sorted(entries.items(),
+ key=lambda x: (x[0][0], len(x[1]))):
+ while True:
+ last = pre_conds[0]
+ combined_pre_conds = [last]
+ combined_count = 0
+ for row in pre_conds[1:]:
+ if row == last:
+ continue
+ diff = [
+ index for index, states in enumerate(last)
+ if states != row[index]
+ ]
+ if len(diff) == 1:
+ index = diff[0]
+ combined_count += 1
+ last[index].extend(row[index])
+ else:
+ combined_pre_conds.append(row)
+ last = row
+ pre_conds = combined_pre_conds
+ if combined_count == 0:
+ break
+ yield post_cond, pre_conds
+
def _post_process(self) -> None:
for map_idx, transitions in enumerate(self):
if not transitions or not isinstance(