diff --git a/src/peakrdl_cheader/__peakrdl__.py b/src/peakrdl_cheader/__peakrdl__.py index 00134c7..bcf6a28 100644 --- a/src/peakrdl_cheader/__peakrdl__.py +++ b/src/peakrdl_cheader/__peakrdl__.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Union from peakrdl.plugins.exporter import ExporterSubcommandPlugin #pylint: disable=import-error from peakrdl.config import schema #pylint: disable=import-error @@ -76,8 +76,8 @@ def add_exporter_arguments(self, arg_group: 'argparse._ActionsContainer') -> Non ) # Wrap constructor to allow hex strings - def integer(n): - return int(n, 0) + def integer(n: Union[int, str]) -> int: + return int(n, 0) # type: ignore # bogus error arg_group.add_argument( "--inst-offset", diff --git a/src/peakrdl_cheader/design_scanner.py b/src/peakrdl_cheader/design_scanner.py index 74a62a4..8d15268 100644 --- a/src/peakrdl_cheader/design_scanner.py +++ b/src/peakrdl_cheader/design_scanner.py @@ -10,7 +10,7 @@ def __init__(self, ds: DesignState) -> None: self.ds = ds self.msg = ds.top_node.env.msg - self.prev_reg_stack: List[RegNode] + self.prev_reg_stack: List[Optional[RegNode]] self.prev_reg_stack = [] @property @@ -83,7 +83,7 @@ def enter_Reg(self, node: RegNode) -> Optional[WalkerAction]: self.ds.overlapping_reg_pairs[prev_reg.get_path()] = node.inst_name # Check for sparse register arrays - if node.is_array and node.array_stride > node.size: + if node.is_array and node.array_stride > node.size: # type: ignore # is_array implies array_stride is not none self.msg.error( "C header export does not support sparse arrays of registers. " f"See register: '{node.inst_name}.'", diff --git a/src/peakrdl_cheader/header_generator.py b/src/peakrdl_cheader/header_generator.py index 769bbdc..ba41a4f 100644 --- a/src/peakrdl_cheader/header_generator.py +++ b/src/peakrdl_cheader/header_generator.py @@ -1,15 +1,18 @@ -from typing import TextIO, Set, Optional, List +from typing import TextIO, Set, Optional, List, Union import os import re from systemrdl.walker import RDLListener, RDLWalker, WalkerAction -from systemrdl.node import AddrmapNode, AddressableNode, RegNode, FieldNode, Node, MemNode +from systemrdl.node import AddrmapNode, AddressableNode, RegNode, FieldNode, Node, MemNode, RegfileNode from .design_state import DesignState from .identifier_filter import kw_filter as kwf from . import utils class HeaderGenerator(RDLListener): + root_node: Union[AddrmapNode, MemNode, RegfileNode] + f: TextIO + def __init__(self, ds: DesignState) -> None: self.ds = ds @@ -17,13 +20,7 @@ def __init__(self, ds: DesignState) -> None: self.defined_namespace = set() self.indent_level = 0 - self.root_node: AddrmapNode - self.root_node = None - - self.f: TextIO - self.f = None # type: ignore - - def run(self, path: str, top_nodes: List[AddrmapNode]) -> None: + def run(self, path: str, top_nodes: List[Union[AddrmapNode, MemNode, RegfileNode]]) -> None: with open(path, "w", encoding='utf-8') as f: self.f = f @@ -36,7 +33,7 @@ def run(self, path: str, top_nodes: List[AddrmapNode]) -> None: # Stream header via jinja template = self.ds.jj_env.get_template("header.h") - template.stream(context).dump(f) + template.stream(context).dump(f) # type: ignore # jinja incorrectly typed f.write("\n") # Generate definitions @@ -50,7 +47,7 @@ def run(self, path: str, top_nodes: List[AddrmapNode]) -> None: for node in top_nodes: addr = node.raw_absolute_address + self.ds.inst_offset type_name = utils.get_struct_name(self.ds, node, node) - if node.is_array: + if node.array_dimensions: if len(node.array_dimensions) > 1: node.env.msg.fatal( f"C header generator does not support instance defines for multi-dimensional arrays: {node.inst_name}{node.array_dimensions}", @@ -62,7 +59,7 @@ def run(self, path: str, top_nodes: List[AddrmapNode]) -> None: # Stream footer via jinja template = self.ds.jj_env.get_template("footer.h") - template.stream(context).dump(f) + template.stream(context).dump(f) # type: ignore # jinja incorrectly typed # Ensure newline before EOF f.write("\n") @@ -281,11 +278,14 @@ def write_block(self, node: AddressableNode) -> None: # Check if register is overlapping first partner_reg_name = self.ds.overlapping_reg_pairs.get(child.get_path(), None) if partner_reg_name: + partner_reg = node.get_child_by_name(partner_reg_name) + assert isinstance(partner_reg, RegNode) + # Two registers occupy the same space self.write("union {\n") self.push_indent() self.write_reg_struct_member(child) - self.write_reg_struct_member(node.get_child_by_name(partner_reg_name)) + self.write_reg_struct_member(partner_reg) self.pop_indent() if self.ds.std.anon_unions: self.write("};\n") @@ -301,6 +301,7 @@ def write_block(self, node: AddressableNode) -> None: # Write end padding as needed if node.is_array: + assert node.array_stride is not None padding = node.array_stride - current_offset else: padding = node.size - current_offset @@ -316,7 +317,7 @@ def write_byte_padding(self, start_offset: int, size: int) -> None: def write_reg_struct_member(self, node: RegNode) -> None: - if node.is_array: + if node.array_dimensions: array_suffix = "".join(f"[{dim}]" for dim in node.array_dimensions) else: array_suffix = "" @@ -336,7 +337,7 @@ def write_reg_struct_member(self, node: RegNode) -> None: def write_group_struct_member(self, node: AddressableNode) -> None: - if node.is_array: + if node.array_dimensions: array_suffix = "".join(f"[{dim}]" for dim in node.array_dimensions) else: array_suffix = "" diff --git a/src/peakrdl_cheader/testcase_generator.py b/src/peakrdl_cheader/testcase_generator.py index 1515101..ff1d1a9 100644 --- a/src/peakrdl_cheader/testcase_generator.py +++ b/src/peakrdl_cheader/testcase_generator.py @@ -1,9 +1,9 @@ -from typing import List, TextIO, Set, Match +from typing import List, TextIO, Set, Match, Union import os import re from systemrdl.walker import RDLListener, RDLWalker -from systemrdl.node import AddrmapNode, RegNode, AddressableNode +from systemrdl.node import AddrmapNode, RegNode, AddressableNode, MemNode, RegfileNode from .design_state import DesignState from . import utils @@ -13,7 +13,7 @@ class TestcaseGenerator: def __init__(self, ds: DesignState) -> None: self.ds = ds - def run(self, header_path: str, top_nodes: List[AddrmapNode]) -> None: + def run(self, header_path: str, top_nodes: List[Union[AddrmapNode, MemNode, RegfileNode]]) -> None: testcase_path = header_path + ".test.c" with open(testcase_path, "w", encoding='utf-8') as f: @@ -24,7 +24,7 @@ def run(self, header_path: str, top_nodes: List[AddrmapNode]) -> None: # Stream header via jinja template = self.ds.jj_env.get_template("test_header.c") - template.stream(context).dump(f) + template.stream(context).dump(f) # type: ignore # jinja incorrectly typed f.write("\n\n") OffsetTestsGenerator(self.ds).run(f, top_nodes) @@ -36,24 +36,21 @@ def run(self, header_path: str, top_nodes: List[AddrmapNode]) -> None: class OffsetTestsGenerator(RDLListener): + root_node: Union[AddrmapNode, MemNode, RegfileNode] + f: TextIO + def __init__(self, ds: DesignState) -> None: self.ds = ds self.indent_level = 0 - self.root_node: AddrmapNode - self.root_node = None - self.root_struct_name: str self.root_struct_name = "" - self.f: TextIO - self.f = None # type: ignore - self.overlap_pair_stack: List[List[str]] self.overlap_pair_stack = [] - def run(self, f: TextIO, top_nodes: List[AddrmapNode]) -> None: + def run(self, f: TextIO, top_nodes: List[Union[AddrmapNode, MemNode, RegfileNode]]) -> None: self.f = f f.write("static void test_offsets(void){\n") @@ -138,6 +135,9 @@ def kwrepl(m: Match) -> str: class BitfieldTestsGenerator(RDLListener): + root_node: Union[AddrmapNode, MemNode, RegfileNode] + f: TextIO + def __init__(self, ds: DesignState) -> None: self.ds = ds @@ -146,13 +146,8 @@ def __init__(self, ds: DesignState) -> None: self.defined_namespace: Set[str] self.defined_namespace = set() - self.root_node: AddrmapNode - self.root_node = None - - self.f: TextIO - self.f = None # type: ignore - def run(self, f: TextIO, top_nodes: List[AddrmapNode]) -> None: + def run(self, f: TextIO, top_nodes: List[Union[AddrmapNode, MemNode, RegfileNode]]) -> None: self.f = f f.write("static void test_bitfields(void){\n") diff --git a/src/peakrdl_cheader/utils.py b/src/peakrdl_cheader/utils.py index aabf29e..2c8272c 100644 --- a/src/peakrdl_cheader/utils.py +++ b/src/peakrdl_cheader/utils.py @@ -1,7 +1,9 @@ -from systemrdl.node import AddressableNode, AddrmapNode, Node +from typing import Union + +from systemrdl.node import AddressableNode, AddrmapNode, Node, MemNode, RegfileNode from .design_state import DesignState -def get_node_prefix(ds: DesignState, root_node: AddrmapNode, node: AddressableNode) -> str: +def get_node_prefix(ds: DesignState, root_node: Union[AddrmapNode, MemNode, RegfileNode], node: AddressableNode) -> str: if ds.reuse_typedefs: prefix = node.get_global_type_name("__") if prefix is None: @@ -23,8 +25,8 @@ def get_node_prefix(ds: DesignState, root_node: AddrmapNode, node: AddressableNo return prefix -def get_struct_name(ds: DesignState, root_node: AddrmapNode, node: AddressableNode) -> str: - if node.is_array and node.array_stride > node.size: +def get_struct_name(ds: DesignState, root_node: Union[AddrmapNode, MemNode, RegfileNode], node: AddressableNode) -> str: + if node.is_array and node.array_stride > node.size: # type: ignore # is_array implies array_stride is not none # Stride is larger than size of actual element. # Struct will be padded up, and therefore needs a unique name pad_suffix = f"__stride{node.array_stride:x}" @@ -34,7 +36,7 @@ def get_struct_name(ds: DesignState, root_node: AddrmapNode, node: AddressableNo return get_node_prefix(ds, root_node, node) + pad_suffix + "_t" -def get_friendly_name(ds: DesignState, root_node: AddrmapNode, node: Node) -> str: +def get_friendly_name(ds: DesignState, root_node: Union[AddrmapNode, MemNode, RegfileNode], node: Node) -> str: """ Returns a useful string that helps identify the typedef in a comment diff --git a/tests/mypy.ini b/tests/mypy.ini index f061b14..052d30e 100644 --- a/tests/mypy.ini +++ b/tests/mypy.ini @@ -1,11 +1,7 @@ [mypy] -namespace_packages = True -explicit_package_bases = True - -[mypy-systemrdl.*] -# Ignore missing py.typed in release -ignore_missing_imports = True - -[mypy-peakrdl.*] -# Ignore missing py.typed in release -ignore_missing_imports = True +disallow_incomplete_defs = True +disallow_untyped_defs = True +warn_unused_configs = True +warn_unused_ignores = True +warn_unreachable = True +disallow_untyped_calls = True diff --git a/tests/run.sh b/tests/run.sh index c4d6315..f3e8af0 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -17,9 +17,6 @@ pip install -r requirements.txt pip install -U ../ # Run unit tests -export SKIP_SYNTH_TESTS=1 -#export STUB_SIMULATOR=1 -export NO_XSIM=1 pytest -n auto --cov=peakrdl_cheader # Generate coverage report