[rtems-central commit] membench: New module

Sebastian Huber sebh at rtems.org
Wed Mar 10 09:02:05 UTC 2021


Module:    rtems-central
Branch:    master
Commit:    577769120f4b527e973f248d4641a700125834d4
Changeset: http://git.rtems.org/rtems-central/commit/?id=577769120f4b527e973f248d4641a700125834d4

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon Mar  8 17:23:24 2021 +0100

membench: New module

---

 rtemsspec/membench.py                        | 160 +++++++++++++++++++++++++++
 rtemsspec/tests/spec-membench/r0.yml         |  13 +++
 rtemsspec/tests/spec-membench/r1.yml         |  15 +++
 rtemsspec/tests/spec-membench/t0.yml         |  20 ++++
 rtemsspec/tests/spec-membench/t1.yml         |  20 ++++
 rtemsspec/tests/spec/non-functional-more.yml |   4 +
 rtemsspec/tests/test_membench.py             |  87 +++++++++++++++
 7 files changed, 319 insertions(+)

diff --git a/rtemsspec/membench.py b/rtemsspec/membench.py
new file mode 100644
index 0000000..a8bc670
--- /dev/null
+++ b/rtemsspec/membench.py
@@ -0,0 +1,160 @@
+# SPDX-License-Identifier: BSD-2-Clause
+"""
+This module provides functions for the generation of memory benchmark
+documentation.
+"""
+
+# Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import re
+from typing import Dict, List, Tuple
+
+from rtemsspec.items import Item, ItemMapper
+from rtemsspec.sphinxcontent import get_label, get_reference, SphinxContent
+from rtemsspec.util import run_command
+
+_SECTION = re.compile(
+    r"^\s*\d+\s+(\S+)\s+([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+[0-9a-fA-F]+"
+    r"\s+[0-9a-fA-F]+\s+.*$")
+
+_SECTION_MAP = {
+    ".ARM.attributes": None,
+    ".ARM.exidx": ".rodata",
+    ".bss": ".bss",
+    ".comment": None,
+    ".data": ".data",
+    ".debug_abbrev": None,
+    ".debug_aranges": None,
+    ".debug_frame": None,
+    ".debug_info": None,
+    ".debug_line": None,
+    ".debug_loc": None,
+    ".debug_ranges": None,
+    ".debug_str": None,
+    ".eh_frame": ".rodata",
+    ".fini": ".text",
+    ".fini_array": ".rodata",
+    ".init": ".text",
+    ".init_array": ".rodata",
+    ".nocachenoload": None,
+    ".robarrier": None,
+    ".rodata": ".rodata",
+    ".rtemsroset": ".rodata",
+    ".rtemsrwset": ".data",
+    ".rtemsstack": ".rtemsstack",
+    ".rwbarrier": None,
+    ".stack": None,
+    ".start": ".text",
+    ".text": ".text",
+    ".vector": ".vector",
+    ".work": None,
+    ".xbarrier": None,
+}
+
+
+def _do_gather_items(items: List[Item], item: Item) -> None:
+    if item.type == "test-suite":
+        items.append(item)
+    for child in item.children("validation"):
+        _do_gather_items(items, child)
+    for child in item.children("requirement-refinement"):
+        _do_gather_items(items, child)
+
+
+def _gather_items(root: Item) -> List[Item]:
+    items = []  # type: List[Item]
+    _do_gather_items(items, root)
+    return items
+
+
+def _get_sections(item: Item, path: str) -> Dict[str, Tuple[int, int]]:
+    name = os.path.basename(item.uid).replace("mem-", "")
+    module = os.path.basename(os.path.dirname(os.path.dirname(item.uid)))
+    elf = f"{path}/mem-{module}-{name}.norun.exe"
+    stdout = []  # type: List[str]
+    status = run_command(["objdump", "-h", elf], stdout=stdout)
+    assert status == 0
+    sections = {}  # type: Dict[str, Tuple[int, int]]
+    for line in stdout:
+        match = _SECTION.search(line)
+        if match:
+            name = match.group(1)
+            size = int(match.group(2), 16)
+            section = _SECTION_MAP[name]
+            if size != 0 and section:
+                start = int(match.group(3), 16)
+                end = start + size
+                info = sections.get(section, (2**64, 0))
+                sections[section] = (min(info[0], start), max(info[1], end))
+    return sections
+
+
+def _get_label(item: Item) -> str:
+    return get_label(f"MemBenchmark {item.uid[1:]}")
+
+
+def _generate_table(content: SphinxContent, items: List[Item],
+                    path: str) -> None:
+    rows = []  # type: List[Tuple[str, ...]]
+    for index, item in enumerate(items):
+        sections = _get_sections(item, path)
+        name = (get_reference(_get_label(item), item.uid), )
+        if index == 0:
+            keys = ("spec", ) + tuple(sections.keys())
+            base = {key: info[1] - info[0] for key, info in sections.items()}
+            rows.append(keys)
+            rows.append(name + tuple(map(str, base.values())))
+        else:
+            rows.append(name + tuple(f"{info[1] - info[0] - base[key]:+}"
+                                     for key, info in sections.items()))
+
+    pivot = items[0]
+    section = f"Benchmarks Based on: {pivot.spec}"
+    with content.section(section):
+        content.wrap(f"""The following memory benchmarks are based on the
+memory benchmark defined by {get_reference(_get_label(pivot), pivot.spec)}.""")
+        content.add_simple_table(rows)
+
+
+def _generate_paragraphs(content: SphinxContent, items: List[Item],
+                         mapper: ItemMapper) -> None:
+    for item in items:
+        section = f"Benchmark: {item.spec}"
+        with content.section(section, label=_get_label(item)):
+            content.wrap(mapper.substitute(item["test-brief"], item))
+            content.wrap(mapper.substitute(item["test-description"], item))
+
+
+def generate(content: SphinxContent, root: Item, mapper: ItemMapper,
+             table_pivots: List[str], path: str) -> None:
+    """
+    Generates memory benchmark documentation for items dependent on the root
+    item and executables in the path.
+    """
+    for pivot in table_pivots:
+        items = _gather_items(root.map(pivot))
+        _generate_table(content, items, path)
+    items = _gather_items(root)
+    _generate_paragraphs(content, items, mapper)
diff --git a/rtemsspec/tests/spec-membench/r0.yml b/rtemsspec/tests/spec-membench/r0.yml
new file mode 100644
index 0000000..763d498
--- /dev/null
+++ b/rtemsspec/tests/spec-membench/r0.yml
@@ -0,0 +1,13 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de
+enabled-by: true
+links: []
+non-functional-type: quality
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+  The system shall provide benchmark programs to show the static memory usage
+  of features.
+type: requirement
diff --git a/rtemsspec/tests/spec-membench/r1.yml b/rtemsspec/tests/spec-membench/r1.yml
new file mode 100644
index 0000000..62ee344
--- /dev/null
+++ b/rtemsspec/tests/spec-membench/r1.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: r0
+non-functional-type: quality
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+  The system shall provide a benchmark program to show the static memory usage
+  of a basic application configuration.
+type: requirement
diff --git a/rtemsspec/tests/spec-membench/t0.yml b/rtemsspec/tests/spec-membench/t0.yml
new file mode 100644
index 0000000..e489255
--- /dev/null
+++ b/rtemsspec/tests/spec-membench/t0.yml
@@ -0,0 +1,20 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+code: |
+  /* Blue green code */
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+description: The Blue Green description.
+enabled-by: true
+links:
+- role: validation
+  uid: r1
+test-brief: The Blue Green brief description.
+test-code: |
+  /* Blue green code */
+test-description: The Blue Green description.
+test-includes:
+- blue.h
+test-local-includes:
+- green.h
+test-target: t0.c
+type: test-suite
diff --git a/rtemsspec/tests/spec-membench/t1.yml b/rtemsspec/tests/spec-membench/t1.yml
new file mode 100644
index 0000000..e489255
--- /dev/null
+++ b/rtemsspec/tests/spec-membench/t1.yml
@@ -0,0 +1,20 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+code: |
+  /* Blue green code */
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+description: The Blue Green description.
+enabled-by: true
+links:
+- role: validation
+  uid: r1
+test-brief: The Blue Green brief description.
+test-code: |
+  /* Blue green code */
+test-description: The Blue Green description.
+test-includes:
+- blue.h
+test-local-includes:
+- green.h
+test-target: t0.c
+type: test-suite
diff --git a/rtemsspec/tests/spec/non-functional-more.yml b/rtemsspec/tests/spec/non-functional-more.yml
index ba081e3..33c5b5d 100644
--- a/rtemsspec/tests/spec/non-functional-more.yml
+++ b/rtemsspec/tests/spec/non-functional-more.yml
@@ -9,6 +9,10 @@ links:
   spec-key: non-functional-type
   spec-value: performance-runtime
   uid: non-functional
+- role: spec-refinement
+  spec-key: non-functional-type
+  spec-value: quality
+  uid: non-functional
 spec-description: null
 spec-example: null
 spec-info:
diff --git a/rtemsspec/tests/test_membench.py b/rtemsspec/tests/test_membench.py
new file mode 100644
index 0000000..3bc5ecb
--- /dev/null
+++ b/rtemsspec/tests/test_membench.py
@@ -0,0 +1,87 @@
+# SPDX-License-Identifier: BSD-2-Clause
+""" Unit tests for the rtemsspec.membench module. """
+
+# Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+from rtemsspec.membench import generate
+from rtemsspec.items import ItemCache, ItemMapper
+from rtemsspec.sphinxcontent import SphinxContent
+from rtemsspec.tests.util import create_item_cache_config_and_copy_spec
+
+
+def run_command(args, cwd=None, stdout=None):
+    stdout.extend([
+        "  0 .start        00000708  00100000  00100000  00010000  2**2",
+        "                  CONTENTS, ALLOC, LOAD, READONLY, CODE",
+        "  2 .text         000090bc  00100740  00100740  00010740  2**6",
+        "                  CONTENTS, ALLOC, LOAD, READONLY, CODE",
+        " 22 .debug_aranges 000011d8  00000000  00000000  000202e8  2**3"
+    ])
+    return 0
+
+
+def test_membench(tmpdir, monkeypatch):
+    monkeypatch.setattr("rtemsspec.membench.run_command", run_command)
+    item_cache_config = create_item_cache_config_and_copy_spec(
+        tmpdir, "spec-membench", with_spec_types=True)
+    item_cache = ItemCache(item_cache_config)
+    root = item_cache["/r0"]
+    content = SphinxContent()
+    generate(content, root, ItemMapper(root), ["/r0"], "path")
+    assert str(content) == """.. _SectionBenchmarksBasedOnSpecT0:
+
+Benchmarks Based on: spec:/t0
+=============================
+
+The following memory benchmarks are based on the memory benchmark defined by
+:ref:`spec:/t0 <MemBenchmarkT0>`.
+
+.. table::
+    :class: longtable
+
+    =========================== =====
+    spec                        .text
+    =========================== =====
+    :ref:`/t0 <MemBenchmarkT0>` 38908
+    :ref:`/t1 <MemBenchmarkT1>` +0
+    =========================== =====
+
+.. _MemBenchmarkT0:
+
+Benchmark: spec:/t0
+===================
+
+The Blue Green brief description.
+
+The Blue Green description.
+
+.. _MemBenchmarkT1:
+
+Benchmark: spec:/t1
+===================
+
+The Blue Green brief description.
+
+The Blue Green description.
+"""



More information about the vc mailing list