summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-05-03 10:36:15 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-07-21 16:27:58 +0200
commit72508ab04e1008d9afe278a44b688c692199f5bb (patch)
tree6f885658b0147638c23799b672adb3cc556c97a9
parentvalidation: Support test cases in build objects (diff)
downloadrtems-central-72508ab04e1008d9afe278a44b688c692199f5bb.tar.bz2
interface: Add register-block support
-rw-r--r--rtemsspec/interface.py191
-rw-r--r--rtemsspec/tests/spec-interface/c/if/uint32_t.yml17
-rw-r--r--rtemsspec/tests/spec-interface/irqamp-timestamp.yml123
-rw-r--r--rtemsspec/tests/spec-interface/irqamp.yml72
-rw-r--r--rtemsspec/tests/spec/interface-more.yml4
-rw-r--r--rtemsspec/tests/test_interface.py192
-rw-r--r--spec/spec/interface-register-block.yml26
7 files changed, 619 insertions, 6 deletions
diff --git a/rtemsspec/interface.py b/rtemsspec/interface.py
index 61335562..4a637cf6 100644
--- a/rtemsspec/interface.py
+++ b/rtemsspec/interface.py
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: BSD-2-Clause
""" This module provides functions for the generation of interfaces. """
-# Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+# Copyright (C) 2020, 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
@@ -24,13 +24,18 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
+import collections
from contextlib import contextmanager
+import functools
+import itertools
import os
-from typing import Any, Callable, Dict, Iterator, List, Optional, Union, Set
+from typing import Any, Callable, Dict, Iterator, List, NamedTuple, Optional, \
+ Union, Set, Tuple
from rtemsspec.content import CContent, CInclude, enabled_by_to_exp, \
ExpressionMapper, get_value_double_colon, get_value_doxygen_function, \
- get_value_doxygen_group, get_value_hash, get_value_params, get_value_plural
+ get_value_doxygen_group, get_value_hash, get_value_params, \
+ get_value_plural, to_camel_case
from rtemsspec.items import Item, ItemCache, ItemGetValueContext, \
ItemGetValueMap, ItemMapper
@@ -182,6 +187,35 @@ def _add_definition(node: "Node", item: Item, prefix: str,
return content
+class _RegisterMemberContext(NamedTuple):
+ sizes: Dict[int, int]
+ regs: Dict[str, Any]
+ reg_counts: Dict[str, int]
+ reg_indices: Dict[str, int]
+
+
+def _add_register_padding(content: CContent, new_offset: int, old_offset: int,
+ default_padding: int) -> None:
+ delta = new_offset - old_offset
+ if delta > 0:
+ padding = default_padding
+ while delta % padding != 0:
+ padding //= 2
+ count = delta // padding
+ array = f"[ {count} ]" if count > 1 else ""
+ content.add(f"uint{padding * 8}_t "
+ f"reserved_{old_offset:x}_{new_offset:x}{array};")
+
+
+def _get_register_name(definition: Dict[str, Any]) -> Tuple[str, str]:
+ name = definition["name"]
+ try:
+ name, alias = name.split(":")
+ except ValueError:
+ alias = name
+ return name, alias
+
+
class Node:
""" Nodes of a header file. """
@@ -297,6 +331,105 @@ class Node:
""" Generates a macro. """
self._add_generic_definition(Node._get_macro_definition)
+ def _add_register_bits(self, group: str) -> _RegisterMemberContext:
+ ctx = _RegisterMemberContext({}, {}, collections.defaultdict(int),
+ collections.defaultdict(int))
+ for index, register in enumerate(self.item["registers"]):
+ name = register["name"]
+ group_ident = group + to_camel_case(name)
+ ctx.regs[name] = {}
+ width = register["width"]
+ assert width in [8, 16, 32, 64]
+ ctx.regs[name]["size"] = width // 8
+ ctx.regs[name]["type"] = f"uint{width}_t"
+ ctx.regs[name]["group"] = group_ident
+ with self.content.defgroup_block(group_ident, name):
+ self.content.add_brief_description(
+ self.substitute_text(register["brief"]))
+ self.content.doxyfy(
+ self.substitute_text(register["description"]))
+ self.content.add("@{")
+ for index_2, bits in enumerate(register["bits"]):
+ self.content.add(
+ _add_definition(
+ self, self.item, f"registers[{index}]/bits[{index_2}]",
+ bits,
+ functools.partial(Node._get_register_bits_definition,
+ reg_name=name)))
+ self.content.close_add_to_group()
+ return ctx
+
+ def _add_register_block_includes(self,
+ ctx: _RegisterMemberContext) -> None:
+ for link in self.item.links_to_parents("register-block-include"):
+ name = link["name"]
+ ctx.regs[name] = {}
+ ctx.regs[name]["size"] = link.item["register-block-size"]
+ ctx.regs[name]["type"] = link.item["name"]
+ ctx.regs[name]["group"] = link.item["identifier"]
+
+ def _get_register_member_info(self, ctx: _RegisterMemberContext) -> None:
+ offset = -1
+ for index, member in enumerate(self.item["definition"]):
+ assert member["offset"] > offset
+ offset = member["offset"]
+ default = [member["default"]] if member["default"] else []
+ for index_2, definition in enumerate(
+ itertools.chain(default,
+ (variant["definition"]
+ for variant in member["variants"]))):
+ name, alias = _get_register_name(definition)
+ assert name.lower() != "reserved"
+ count = definition["count"]
+ if index_2 == 0:
+ ctx.sizes[index] = ctx.regs[name]["size"] * count
+ else:
+ assert ctx.sizes[index] == ctx.regs[name]["size"] * count
+ ctx.reg_counts[alias] += 1
+
+ def _add_register_members(self, ctx: _RegisterMemberContext) -> None:
+ default_padding = min(ctx.sizes.values())
+ with self.content.doxygen_block():
+ self.content.add_brief_description(
+ self.substitute_text(self.item["brief"]))
+ self.content.doxyfy(self.substitute_text(self.item["description"]))
+ self.content.append(f"typedef struct {self.item['name']} {{")
+ offset = 0
+ with self.content.indent():
+ for index, member in enumerate(self.item["definition"]):
+ member_offset = member["offset"]
+ _add_register_padding(self.content, member_offset, offset,
+ default_padding)
+ self.content.add(
+ _add_definition(
+ self, self.item, f"definition[{index}]", member,
+ functools.partial(Node._get_register_member_definition,
+ ctx=ctx)))
+ offset = member_offset + ctx.sizes[index]
+ size = self.item["register-block-size"]
+ assert offset <= size
+ _add_register_padding(self.content, size, offset, default_padding)
+ self.content.add(f"}} {self.item['name']};")
+
+ def generate_register_block(self) -> None:
+ """ Generates a register block. """
+ self.header_file.add_includes(self.item.map("/c/if/uint32_t"))
+ for parent in self.item.parents("register-block-include"):
+ self.header_file.add_includes(parent)
+ self.header_file.add_dependency(self, parent)
+ group = self.item["identifier"]
+ name = self.item["register-block-group"]
+ with self.content.defgroup_block(group, name):
+ self.content.add_ingroup(_get_group_identifiers(self.ingroups))
+ self.content.add_brief_description(
+ f"This group contains the {name} interfaces.")
+ self.content.add("@{")
+ ctx = self._add_register_bits(group)
+ self._add_register_block_includes(ctx)
+ self._get_register_member_info(ctx)
+ self._add_register_members(ctx)
+ self.content.close_add_to_group()
+
def generate_typedef(self) -> None:
""" Generates a typedef. """
self._add_generic_definition(Node._get_typedef_definition)
@@ -400,6 +533,54 @@ class Node:
body += " \\\n ".join(body_lines)
return line + body
+ def _get_register_bits_definition(self, _item: Item, definition: Any,
+ reg_name: str) -> Lines:
+ lines = [] # List[str]
+ prefix = self.item["register-prefix"]
+ if prefix is None:
+ prefix = self.item["name"]
+ prefix = f"{prefix}_{reg_name}_" if prefix else f"{reg_name}_"
+ for index, bit in enumerate(definition):
+ start = bit["start"]
+ width = bit["width"]
+ end = start + width
+ sfx = "ULL" if end > 32 else "U"
+ define = f"#define {prefix.upper()}{bit['name'].upper()}"
+ if index != 0:
+ lines.append("")
+ if width == 1:
+ val = 1 << start
+ lines.append(f"{define} {val:#x}{sfx}")
+ else:
+ mask = ((1 << width) - 1) << start
+ get = (1 << width) - 1
+ lines.extend([
+ f"{define}_SHIFT {start}", f"{define}_MASK {mask:#x}{sfx}",
+ f"{define}_GET( _reg ) \\",
+ f" ( ( ( _reg ) >> {start} ) & {get:#x}{sfx} )",
+ f"{define}( _val ) ( ( _val ) << {start} )"
+ ])
+ return lines
+
+ def _get_register_member_definition(self, _item: Item, definition: Any,
+ ctx: _RegisterMemberContext) -> Lines:
+ # pylint: disable=no-self-use
+ name, alias = _get_register_name(definition)
+ count = definition["count"]
+ array = f"[ {count} ]" if count > 1 else ""
+ if ctx.reg_counts[alias] > 1:
+ index = ctx.reg_indices[alias]
+ ctx.reg_indices[alias] = index + 1
+ idx = f"_{index}"
+ else:
+ idx = ""
+ content = CContent()
+ with content.doxygen_block():
+ content.add(f"@brief See @ref {ctx.regs[name]['group']}.")
+ content.append(
+ f"{ctx.regs[name]['type']} {alias.lower()}{idx}{array};")
+ return content.lines
+
def _get_typedef_definition(self, _item: Item, definition: Any) -> Lines:
return f"typedef {self.substitute_code(definition)};"
@@ -450,6 +631,7 @@ _NODE_GENERATORS = {
"function": Node.generate_function,
"group": Node.generate_group,
"macro": Node.generate_macro,
+ "register-block": Node.generate_register_block,
"struct": Node.generate_compound,
"typedef": Node.generate_typedef,
"union": Node.generate_compound,
@@ -585,8 +767,7 @@ class _HeaderFile:
includes.extend([
CInclude(link.item["path"],
enabled_by_to_exp(link["enabled-by"], exp_mapper))
- for link in self._item.links_to_parents()
- if link.role == "interface-include"
+ for link in self._item.links_to_parents("interface-include")
])
self._content.add_includes(includes)
with self._content.extern_c():
diff --git a/rtemsspec/tests/spec-interface/c/if/uint32_t.yml b/rtemsspec/tests/spec-interface/c/if/uint32_t.yml
new file mode 100644
index 00000000..ce9cd90d
--- /dev/null
+++ b/rtemsspec/tests/spec-interface/c/if/uint32_t.yml
@@ -0,0 +1,17 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+brief: null
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+definition:
+ default: unsigned
+ variants: []
+description: null
+enabled-by: true
+index-entries: []
+interface-type: define
+links:
+- role: interface-placement
+ uid: ../../stdint
+name: uint32_t
+notes: null
+type: interface
diff --git a/rtemsspec/tests/spec-interface/irqamp-timestamp.yml b/rtemsspec/tests/spec-interface/irqamp-timestamp.yml
new file mode 100644
index 00000000..9ec01ead
--- /dev/null
+++ b/rtemsspec/tests/spec-interface/irqamp-timestamp.yml
@@ -0,0 +1,123 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+brief: |
+ This structure defines the ${.:/register-block-group} register block memory
+ map.
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+description: null
+enabled-by: true
+identifier: IrqampTimestamp
+index-entries: []
+interface-type: register-block
+links:
+- role: interface-placement
+ uid: h
+definition:
+- default:
+ count: 1
+ name: ITCNT
+ offset: 0x0
+ variants: []
+- default:
+ count: 1
+ name: ITSTMPC
+ offset: 0x4
+ variants: []
+- default:
+ count: 1
+ name: ITSTMPAS
+ offset: 0x8
+ variants: []
+- default:
+ count: 1
+ name: ITSTMPAC
+ offset: 0xc
+ variants: []
+register-prefix: IRQAMP
+register-block-group: IRQ(A)MP Timestamp
+register-block-size: 16
+register-block-type: memory
+registers:
+- bits:
+ - default:
+ - access: [r]
+ brief: null
+ description: null
+ name: 'TCNT'
+ start: 0
+ width: 32
+ variants: []
+ brief: |
+ Interrupt timestamp counter n register
+ description: null
+ name: ITCNT
+ width: 32
+- bits:
+ - default:
+ - access: [r]
+ brief: null
+ description: null
+ name: 'TSTAMP'
+ start: 27
+ width: 5
+ - access: [r, w1c]
+ brief: null
+ description: null
+ name: 'S1'
+ start: 26
+ width: 1
+ - access: [r, w1c]
+ brief: null
+ description: null
+ name: 'S2'
+ start: 25
+ width: 1
+ - access: [r, w]
+ brief: null
+ description: null
+ name: 'KS'
+ start: 5
+ width: 1
+ - access: [r, w]
+ brief: null
+ description: null
+ name: 'TSISEL'
+ start: 0
+ width: 5
+ variants: []
+ brief: |
+ Interrupt timestamp n control register
+ description: null
+ name: ITSTMPC
+ width: 32
+- bits:
+ - default:
+ - access: [r]
+ brief: null
+ description: null
+ name: 'TASSERTION'
+ start: 0
+ width: 32
+ variants: []
+ brief: |
+ Interrupt Assertion Timestamp n register
+ description: null
+ name: ITSTMPAS
+ width: 32
+- bits:
+ - default:
+ - access: [r]
+ brief: null
+ description: null
+ name: 'TACKNOWLEDGE'
+ start: 0
+ width: 32
+ variants: []
+ brief: |
+ Interrupt Acknowledge Timestamp n register
+ description: null
+ name: ITSTMPAC
+ width: 32
+name: irqamp_timestamp
+notes: null
+type: interface
diff --git a/rtemsspec/tests/spec-interface/irqamp.yml b/rtemsspec/tests/spec-interface/irqamp.yml
new file mode 100644
index 00000000..beccec9a
--- /dev/null
+++ b/rtemsspec/tests/spec-interface/irqamp.yml
@@ -0,0 +1,72 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+brief: |
+ This structure defines the ${.:/register-block-group} register block memory
+ map.
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+description: null
+enabled-by: true
+identifier: Irqamp
+index-entries: []
+interface-type: register-block
+links:
+- role: interface-placement
+ uid: h
+- name: ITSTMP
+ role: register-block-include
+ uid: irqamp-timestamp
+definition:
+- default:
+ count: 1
+ name: ILEVEL:FOOBAR
+ offset: 0x0
+ variants: []
+- default:
+ count: 1
+ name: ILEVEL:FOOBAR
+ offset: 0x4
+ variants:
+ - definition:
+ count: 4
+ name: IPEND8
+ enabled-by: defined(RTEMS_SMP)
+- default:
+ count: 4
+ name: IPEND8
+ offset: 0x9
+ variants: []
+- default:
+ count: 16
+ name: ITSTMP
+ offset: 0x100
+ variants: []
+register-prefix: null
+register-block-group: IRQ(A)MP
+register-block-size: 1024
+register-block-type: memory
+registers:
+- bits:
+ - default:
+ - access: [r, w]
+ brief: null
+ description: null
+ name: 'IL_15_1'
+ start: 1
+ width: 15
+ variants: []
+ brief: |
+ Interrupt level register
+ description: null
+ name: ILEVEL
+ width: 32
+- bits:
+ - default: []
+ variants: []
+ brief: |
+ Interrupt pending register
+ description: null
+ name: IPEND8
+ width: 8
+name: irqamp
+notes: null
+type: interface
diff --git a/rtemsspec/tests/spec/interface-more.yml b/rtemsspec/tests/spec/interface-more.yml
index 9c7917ec..aff1b49a 100644
--- a/rtemsspec/tests/spec/interface-more.yml
+++ b/rtemsspec/tests/spec/interface-more.yml
@@ -59,6 +59,10 @@ links:
uid: interface
- role: spec-refinement
spec-key: interface-type
+ spec-value: register-block
+ uid: interface
+- role: spec-refinement
+ spec-key: interface-type
spec-value: typedef
uid: interface
- role: spec-refinement
diff --git a/rtemsspec/tests/test_interface.py b/rtemsspec/tests/test_interface.py
index b7b0feea..9e23bb39 100644
--- a/rtemsspec/tests/test_interface.py
+++ b/rtemsspec/tests/test_interface.py
@@ -61,7 +61,7 @@ def test_interface(tmpdir):
*/
/*
- * Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+ * Copyright (C) 2020, 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
@@ -242,6 +242,196 @@ void Function(
/* Generated from spec:/func6 */
void Function6( int Param0 );
+/* Generated from spec:/irqamp-timestamp */
+
+/**
+ * @defgroup IrqampTimestamp IRQ(A)MP Timestamp
+ *
+ * @brief This group contains the IRQ(A)MP Timestamp interfaces.
+ *
+ * @{
+ */
+
+/**
+ * @defgroup IrqampTimestampITCNT ITCNT
+ *
+ * @brief Interrupt timestamp counter n register
+ *
+ * @{
+ */
+
+#define IRQAMP_ITCNT_TCNT_SHIFT 0
+#define IRQAMP_ITCNT_TCNT_MASK 0xffffffffU
+#define IRQAMP_ITCNT_TCNT_GET( _reg ) \\
+ ( ( ( _reg ) >> 0 ) & 0xffffffffU )
+#define IRQAMP_ITCNT_TCNT( _val ) ( ( _val ) << 0 )
+
+/** @} */
+
+/**
+ * @defgroup IrqampTimestampITSTMPC ITSTMPC
+ *
+ * @brief Interrupt timestamp n control register
+ *
+ * @{
+ */
+
+#define IRQAMP_ITSTMPC_TSTAMP_SHIFT 27
+#define IRQAMP_ITSTMPC_TSTAMP_MASK 0xf8000000U
+#define IRQAMP_ITSTMPC_TSTAMP_GET( _reg ) \\
+ ( ( ( _reg ) >> 27 ) & 0x1fU )
+#define IRQAMP_ITSTMPC_TSTAMP( _val ) ( ( _val ) << 27 )
+
+#define IRQAMP_ITSTMPC_S1 0x4000000U
+
+#define IRQAMP_ITSTMPC_S2 0x2000000U
+
+#define IRQAMP_ITSTMPC_KS 0x20U
+
+#define IRQAMP_ITSTMPC_TSISEL_SHIFT 0
+#define IRQAMP_ITSTMPC_TSISEL_MASK 0x1fU
+#define IRQAMP_ITSTMPC_TSISEL_GET( _reg ) \\
+ ( ( ( _reg ) >> 0 ) & 0x1fU )
+#define IRQAMP_ITSTMPC_TSISEL( _val ) ( ( _val ) << 0 )
+
+/** @} */
+
+/**
+ * @defgroup IrqampTimestampITSTMPAS ITSTMPAS
+ *
+ * @brief Interrupt Assertion Timestamp n register
+ *
+ * @{
+ */
+
+#define IRQAMP_ITSTMPAS_TASSERTION_SHIFT 0
+#define IRQAMP_ITSTMPAS_TASSERTION_MASK 0xffffffffU
+#define IRQAMP_ITSTMPAS_TASSERTION_GET( _reg ) \\
+ ( ( ( _reg ) >> 0 ) & 0xffffffffU )
+#define IRQAMP_ITSTMPAS_TASSERTION( _val ) ( ( _val ) << 0 )
+
+/** @} */
+
+/**
+ * @defgroup IrqampTimestampITSTMPAC ITSTMPAC
+ *
+ * @brief Interrupt Acknowledge Timestamp n register
+ *
+ * @{
+ */
+
+#define IRQAMP_ITSTMPAC_TACKNOWLEDGE_SHIFT 0
+#define IRQAMP_ITSTMPAC_TACKNOWLEDGE_MASK 0xffffffffU
+#define IRQAMP_ITSTMPAC_TACKNOWLEDGE_GET( _reg ) \\
+ ( ( ( _reg ) >> 0 ) & 0xffffffffU )
+#define IRQAMP_ITSTMPAC_TACKNOWLEDGE( _val ) ( ( _val ) << 0 )
+
+/** @} */
+
+/**
+ * @brief This structure defines the IRQ(A)MP Timestamp register block memory
+ * map.
+ */
+typedef struct irqamp_timestamp {
+ /**
+ * @brief See @ref IrqampTimestampITCNT.
+ */
+ uint32_t itcnt;
+
+ /**
+ * @brief See @ref IrqampTimestampITSTMPC.
+ */
+ uint32_t itstmpc;
+
+ /**
+ * @brief See @ref IrqampTimestampITSTMPAS.
+ */
+ uint32_t itstmpas;
+
+ /**
+ * @brief See @ref IrqampTimestampITSTMPAC.
+ */
+ uint32_t itstmpac;
+} irqamp_timestamp;
+
+/** @} */
+
+/* Generated from spec:/irqamp */
+
+/**
+ * @defgroup Irqamp IRQ(A)MP
+ *
+ * @brief This group contains the IRQ(A)MP interfaces.
+ *
+ * @{
+ */
+
+/**
+ * @defgroup IrqampILEVEL ILEVEL
+ *
+ * @brief Interrupt level register
+ *
+ * @{
+ */
+
+#define IRQAMP_ILEVEL_IL_15_1_SHIFT 1
+#define IRQAMP_ILEVEL_IL_15_1_MASK 0xfffeU
+#define IRQAMP_ILEVEL_IL_15_1_GET( _reg ) \\
+ ( ( ( _reg ) >> 1 ) & 0x7fffU )
+#define IRQAMP_ILEVEL_IL_15_1( _val ) ( ( _val ) << 1 )
+
+/** @} */
+
+/**
+ * @defgroup IrqampIPEND8 IPEND8
+ *
+ * @brief Interrupt pending register
+ *
+ * @{
+ */
+
+/** @} */
+
+/**
+ * @brief This structure defines the IRQ(A)MP register block memory map.
+ */
+typedef struct irqamp {
+ /**
+ * @brief See @ref IrqampILEVEL.
+ */
+ uint32_t foobar_0;
+
+ #if defined(RTEMS_SMP)
+ /**
+ * @brief See @ref IrqampIPEND8.
+ */
+ uint8_t ipend8_0[ 4 ];
+ #else
+ /**
+ * @brief See @ref IrqampILEVEL.
+ */
+ uint32_t foobar_1;
+ #endif
+
+ uint8_t reserved_8_9;
+
+ /**
+ * @brief See @ref IrqampIPEND8.
+ */
+ uint8_t ipend8_1[ 4 ];
+
+ uint8_t reserved_d_100[ 243 ];
+
+ /**
+ * @brief See @ref IrqampTimestamp.
+ */
+ irqamp_timestamp itstmp[ 16 ];
+
+ uint32_t reserved_200_400[ 128 ];
+} irqamp;
+
+/** @} */
+
/* Generated from spec:/macro */
/**
diff --git a/spec/spec/interface-register-block.yml b/spec/spec/interface-register-block.yml
new file mode 100644
index 00000000..23f3ef4e
--- /dev/null
+++ b/spec/spec/interface-register-block.yml
@@ -0,0 +1,26 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: spec-member
+ uid: root
+- role: spec-refinement
+ spec-key: interface-type
+ spec-value: register-block
+ uid: interface
+spec-description: null
+spec-example: null
+spec-info:
+ dict:
+ attributes: {}
+ description: |
+ This set of attributes defines a register block.
+ generic-attributes:
+ description: null
+ key-spec-type: name
+ value-spec-type: any
+ mandatory-attributes: all
+spec-name: Interface Register Block Item Type
+spec-type: interface-register-block
+type: spec