summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-09-21 20:15:58 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-09-22 09:28:20 +0200
commit3756347e83f7e7a2cb7863849fa13a96c7b68acc (patch)
treea68c8d8e5d7c6fc248ed8eccd3ebfea574862fc2
parentspec: Add missing file (diff)
downloadrtems-central-3756347e83f7e7a2cb7863849fa13a96c7b68acc.tar.bz2
validation: Fix skipping of transition variants
-rw-r--r--rtemsspec/content.py9
-rw-r--r--rtemsspec/tests/test_validation.py45
-rw-r--r--rtemsspec/transitionmap.py7
-rw-r--r--rtemsspec/validation.py70
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)