diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-09-21 20:15:58 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-09-22 09:28:20 +0200 |
commit | 3756347e83f7e7a2cb7863849fa13a96c7b68acc (patch) | |
tree | a68c8d8e5d7c6fc248ed8eccd3ebfea574862fc2 | |
parent | spec: Add missing file (diff) | |
download | rtems-central-3756347e83f7e7a2cb7863849fa13a96c7b68acc.tar.bz2 |
validation: Fix skipping of transition variants
-rw-r--r-- | rtemsspec/content.py | 9 | ||||
-rw-r--r-- | rtemsspec/tests/test_validation.py | 45 | ||||
-rw-r--r-- | rtemsspec/transitionmap.py | 7 | ||||
-rw-r--r-- | rtemsspec/validation.py | 70 |
4 files changed, 91 insertions, 40 deletions
diff --git a/rtemsspec/content.py b/rtemsspec/content.py index 5d6711ce..a7430985 100644 --- a/rtemsspec/content.py +++ b/rtemsspec/content.py @@ -29,6 +29,7 @@ from contextlib import contextmanager import collections import itertools +import math import os import re import sys @@ -1162,3 +1163,11 @@ def to_camel_case(name: str) -> str: return name[0].upper() + _CAMEL_CASE_TO_UPPER.sub( lambda match: match.group(1).upper(), _CAMEL_CASE_DISCARD.sub(" ", name[1:].replace("+", "X"))) + + +def get_integer_type(value: int) -> str: + """ + Returns an unsigned integer type which is large enough to store the value. + """ + power = 2**max(math.ceil(math.log2(math.floor(math.log2(value)) + 1)), 3) + return f"uint{power}_t" diff --git a/rtemsspec/tests/test_validation.py b/rtemsspec/tests/test_validation.py index 2bc8b934..fc1bdc4e 100644 --- a/rtemsspec/tests/test_validation.py +++ b/rtemsspec/tests/test_validation.py @@ -2233,36 +2233,44 @@ static T_fixture Action2_Fixture = { .initial_context = &Action2_Instance }; -static inline Action2_Entry Action2_PopEntry( Action2_Context *ctx ) -{ - size_t index; - - index = ctx->Map.index; - ctx->Map.index = index + 1; - return Action2_Entries[ - Action2_Map[ index ] - ]; -} +static const uint8_t Action2_Weights[] = { + 9, 3, 1 +}; static void Action2_Skip( Action2_Context *ctx, size_t index ) { - size_t increment; - - ctx->Map.skip = false; - increment = 1; - switch ( index + 1 ) { case 1: - increment *= Action2_Pre_B_NA - ctx->Map.pci[ 1 ]; ctx->Map.pci[ 1 ] = Action2_Pre_B_NA - 1; /* Fall through */ case 2: - increment *= Action2_Pre_C_NA - ctx->Map.pci[ 2 ]; ctx->Map.pci[ 2 ] = Action2_Pre_C_NA - 1; break; } +} + +static inline Action2_Entry Action2_PopEntry( Action2_Context *ctx ) +{ + size_t index; + + if ( ctx->Map.skip ) { + size_t i; + + ctx->Map.skip = false; + index = 0; + + for ( i = 0; i < 3; ++i ) { + index += Action2_Weights[ i ] * ctx->Map.pci[ i ]; + } + } else { + index = ctx->Map.index; + } + + ctx->Map.index = index + 1; - ctx->Map.index += increment - 1; + return Action2_Entries[ + Action2_Map[ index ] + ]; } static void Action2_SetPreConditionStates( Action2_Context *ctx ) @@ -2307,6 +2315,7 @@ void Action2_Run( int *a, int b, int *c ) ctx = T_push_fixture( &Action2_Node, &Action2_Fixture ); ctx->Map.in_action_loop = true; ctx->Map.index = 0; + ctx->Map.skip = false; for ( ctx->Map.pci[ 0 ] = Action2_Pre_A_A0; diff --git a/rtemsspec/transitionmap.py b/rtemsspec/transitionmap.py index 9d6ab8a3..f3ad3988 100644 --- a/rtemsspec/transitionmap.py +++ b/rtemsspec/transitionmap.py @@ -32,7 +32,8 @@ import math import textwrap from typing import Any, Dict, Iterator, List, NamedTuple, Optional, Tuple -from rtemsspec.content import CContent, enabled_by_to_exp, ExpressionMapper +from rtemsspec.content import CContent, enabled_by_to_exp, ExpressionMapper, \ + get_integer_type from rtemsspec.items import is_enabled, Item @@ -663,9 +664,9 @@ class TransitionMap: content.add([f"static const {ident}_Entry", f"{ident}_Entries[] = {{"]) entries[-1] = entries[-1].replace("},", "}") content.append(entries) - bits = max(8, math.ceil(math.log2(len(self._entries)) / 8) * 8) + integer_type = get_integer_type(len(self._entries)) content.append( - ["};", "", f"static const uint{bits}_t", f"{ident}_Map[] = {{"]) + ["};", "", f"static const {integer_type}", f"{ident}_Map[] = {{"]) text = ", ".join( str(self._entries[transitions.key][1]) for transitions in self._map) diff --git a/rtemsspec/validation.py b/rtemsspec/validation.py index a4d284f5..0a218089 100644 --- a/rtemsspec/validation.py +++ b/rtemsspec/validation.py @@ -27,12 +27,13 @@ # pylint: disable=too-many-lines import itertools +import functools import os import re from typing import Any, Dict, List, Optional, Tuple from rtemsspec.content import CContent, CInclude, \ - GenericContent, get_value_params, get_value_plural, \ + GenericContent, get_integer_type, get_value_params, get_value_plural, \ get_value_doxygen_group, get_value_doxygen_function, to_camel_case from rtemsspec.items import Item, ItemCache, \ ItemGetValueContext, ItemMapper @@ -601,25 +602,32 @@ class _ActionRequirementTestItem(_TestItem): content.call_function(None, f"{self.ident}_{name}", ["ctx"]) def _add_skip(self, content: CContent) -> Any: + state_counts = [len(enum) - 2 for enum in self._pre_co_idx_to_enum] + weigths = [ + str( + functools.reduce((lambda x, y: x * y), + state_counts[index + 1:], 1)) + for index in range(self._pre_co_count) + ] + integer_type = get_integer_type(int(weigths[0])) + content.add(f"static const {integer_type} {self.ident}_Weights[] = {{") + with content.indent(): + content.wrap(", ".join(weigths)) + content.add("};") with content.function("static void", f"{self.ident}_Skip", [f"{self.context} *ctx", "size_t index"]): - content.append([ - "size_t increment;", "", "ctx->Map.skip = false;", - "increment = 1;", "", "switch ( index + 1 ) {" - ]) + content.append("switch ( index + 1 ) {") fall_through = "/* Fall through */" with content.indent(): for index, enum in enumerate(self._pre_co_idx_to_enum[1:], 1): content.add(f"case {index}:") with content.indent(): pci = f"ctx->Map.{self._pci}[ {index} ]" - content.append([ - f"increment *= {enum[-1]} - {pci};", - f"{pci} = {enum[-1]} - 1;", fall_through - ]) + content.append( + [f"{pci} = {enum[-1]} - 1;", fall_through]) content.lines[-1] = content.lines[-1].replace( fall_through, "break;") - content.append(["}", "", "ctx->Map.index += increment - 1;"]) + content.append("}") def _add_test_variant(self, content: CContent, transition_map: TransitionMap) -> None: @@ -694,19 +702,38 @@ class _ActionRequirementTestItem(_TestItem): gap = False content.add(pcs_pci) - def _add_test_case(self, content: CContent, transition_map: TransitionMap, - header: Dict[str, Any]) -> None: + def _add_pop_entry(self, content: CContent) -> None: ret = f"static inline {self.ident}_Entry" name = f"{self.ident}_PopEntry" params = [f"{self.context} *ctx"] with content.function(ret, name, params, align=True): + content.add("size_t index;") + if self._pre_co_skip: + with content.first_condition("ctx->Map.skip"): + content.add([ + "size_t i;", "", "ctx->Map.skip = false;", "index = 0;" + ]) + with content.for_loop("i = 0", f"i < {self._pre_co_count}", + "++i"): + content.append(f"index += {self.ident}_Weights[ i ]" + f" * ctx->Map.{self._pci}[ i ];") + with content.final_condition(): + content.add("index = ctx->Map.index;") + content.add("ctx->Map.index = index + 1;") + else: + content.add( + ["index = ctx->Map.index;", "ctx->Map.index = index + 1;"]) + content.gap = False content.add([ - "size_t index;", "", "index = ctx->Map.index;", - "ctx->Map.index = index + 1;", f"return {self.ident}_Entries[", + f"return {self.ident}_Entries[", f" {self.ident}_Map[ index ]", "];" ]) + + def _add_test_case(self, content: CContent, transition_map: TransitionMap, + header: Dict[str, Any]) -> None: if self._pre_co_skip: self._add_skip(content) + self._add_pop_entry(content) if transition_map.has_pre_co_not_applicable(): self._add_set_pre_co_states(content, transition_map) with content.function("static void", f"{self.ident}_TestVariant", @@ -715,6 +742,11 @@ class _ActionRequirementTestItem(_TestItem): fixture = f"{self.ident}_Fixture" prologue = CContent() epilogue = CContent() + map_members_initialization = [ + "ctx->Map.in_action_loop = true;", "ctx->Map.index = 0;" + ] + if self._pre_co_skip: + map_members_initialization.append("ctx->Map.skip = false;") if header: content.add(f"static T_fixture_node {self.ident}_Node;") ret = "void" @@ -724,8 +756,7 @@ class _ActionRequirementTestItem(_TestItem): self.assign_run_params(prologue, header) prologue.call_function("ctx =", "T_push_fixture", [f"&{self.ident}_Node", f"&{fixture}"]) - prologue.append( - ["ctx->Map.in_action_loop = true;", "ctx->Map.index = 0;"]) + prologue.append(map_members_initialization) epilogue.add("T_pop_fixture();") align = True else: @@ -737,9 +768,10 @@ class _ActionRequirementTestItem(_TestItem): name = "T_TEST_CASE_FIXTURE" params = [f"{self.ident}", f"&{fixture}"] prologue.add([ - f"{self.context} *ctx;", "", "ctx = T_fixture_context();", - "ctx->Map.in_action_loop = true;", "ctx->Map.index = 0;" - ]) + f"{self.context} *ctx;", + "", + "ctx = T_fixture_context();", + ] + map_members_initialization) align = False with content.function(ret, name, params, align=align): content.add(prologue) |