Coverage for hdl_registers/generator/vhdl/test/test_register_vhdl_generator.py: 100%
88 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-28 20:51 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-28 20:51 +0000
1# --------------------------------------------------------------------------------------------------
2# Copyright (c) Lukas Vik. All rights reserved.
3#
4# This file is part of the hdl-registers project, an HDL register generator fast enough to run
5# in real time.
6# https://hdl-registers.com
7# https://github.com/hdl-registers/hdl-registers
8# --------------------------------------------------------------------------------------------------
10"""
11Some limited unit tests that check the generated code.
12Note that the generated VHDL code is also simulated in a functional test.
13"""
15# Standard libraries
16from pathlib import Path
18# Third party libraries
19from tsfpga.system_utils import read_file
21# First party libraries
22from hdl_registers.generator.vhdl.axi_lite.wrapper import VhdlAxiLiteWrapperGenerator
23from hdl_registers.generator.vhdl.record_package import VhdlRecordPackageGenerator
24from hdl_registers.generator.vhdl.register_package import VhdlRegisterPackageGenerator
25from hdl_registers.generator.vhdl.simulation.check_package import (
26 VhdlSimulationCheckPackageGenerator,
27)
28from hdl_registers.generator.vhdl.simulation.read_write_package import (
29 VhdlSimulationReadWritePackageGenerator,
30)
31from hdl_registers.generator.vhdl.simulation.wait_until_package import (
32 VhdlSimulationWaitUntilPackageGenerator,
33)
34from hdl_registers.register_list import RegisterList
35from hdl_registers.register_modes import REGISTER_MODES
38def generate_all_vhdl_artifacts(register_list: RegisterList, output_folder: Path) -> None:
39 VhdlRegisterPackageGenerator(
40 register_list=register_list, output_folder=output_folder
41 ).create_if_needed()
43 VhdlRecordPackageGenerator(
44 register_list=register_list, output_folder=output_folder
45 ).create_if_needed()
47 VhdlAxiLiteWrapperGenerator(
48 register_list=register_list, output_folder=output_folder
49 ).create_if_needed()
51 VhdlSimulationReadWritePackageGenerator(
52 register_list=register_list, output_folder=output_folder
53 ).create_if_needed()
55 VhdlSimulationCheckPackageGenerator(
56 register_list=register_list, output_folder=output_folder
57 ).create_if_needed()
59 VhdlSimulationWaitUntilPackageGenerator(
60 register_list=register_list, output_folder=output_folder
61 ).create_if_needed()
64def generate_strange_register_maps(output_path):
65 """
66 Generate register VHDL artifacts for some strange niche cases.
67 """
69 def create_packages(direction, mode):
70 def append_register(data, name):
71 """
72 Append a register with some fields.
73 """
74 register = data.append_register(
75 name=f"{name}_{mode.shorthand}", mode=mode, description=""
76 )
78 register.append_integer(
79 name="integer", description="", min_value=-10, max_value=10, default_value=3
80 )
81 register.append_enumeration(
82 name="enumeration", description="", elements=dict(a="", b=""), default_value="b"
83 )
85 def append_registers(data):
86 """
87 Append some registers with some fields, either to a RegisterList or a RegisterArray.
88 """
89 append_register(data=data, name="first")
90 append_register(data=data, name="second")
92 # Some plain registers, in one direction only.
93 register_list = RegisterList(name=f"plain_only_{direction}")
94 append_registers(data=register_list)
95 generate_all_vhdl_artifacts(register_list=register_list, output_folder=output_path)
97 # Some register arrays, in one direction only.
98 register_list = RegisterList(name=f"array_only_{direction}")
99 register_array = register_list.append_register_array(name="apa", length=5, description="")
100 append_registers(data=register_array)
101 register_array = register_list.append_register_array(name="hest", length=10, description="")
102 append_registers(data=register_array)
103 generate_all_vhdl_artifacts(register_list=register_list, output_folder=output_path)
105 # Plain registers and some register arrays, in one direction only.
106 register_list = RegisterList(name=f"plain_and_array_only_{direction}")
107 append_registers(data=register_list)
108 register_array = register_list.append_register_array(name="apa", length=5, description="")
109 append_registers(data=register_array)
110 register_array = register_list.append_register_array(name="hest", length=10, description="")
111 append_registers(data=register_array)
112 generate_all_vhdl_artifacts(register_list=register_list, output_folder=output_path)
114 # Mode 'Read only' should give registers only in the 'up' direction'
115 create_packages(direction="up", mode=REGISTER_MODES["r"])
116 # Mode 'Write only' should give registers only in the 'down' direction'
117 create_packages(direction="down", mode=REGISTER_MODES["w"])
119 register_list = RegisterList(name="only_constants")
120 register_list.add_constant(name="first", value=123, description="")
121 register_list.add_constant(name="second", value=True, description="")
122 register_list.add_constant(name="third", value=5e30, description="")
123 register_list.add_constant(name="fourth", value=1e-12, description="")
124 generate_all_vhdl_artifacts(register_list=register_list, output_folder=output_path)
126 register_list = RegisterList(name="empty")
127 generate_all_vhdl_artifacts(register_list=register_list, output_folder=output_path)
130def _get_register_arrays_record_string(direction):
131 return (
132 f"records for the registers of each register array the are in the '{direction}' direction"
133 )
136def test_registers_only_in_up_direction_should_give_no_down_type_or_port(tmp_path):
137 generate_strange_register_maps(output_path=tmp_path)
139 for file_name in ["array_only_up", "plain_and_array_only_up", "plain_only_up"]:
140 vhd = read_file(tmp_path / f"{file_name}_register_record_pkg.vhd")
142 assert f"{file_name}_regs_up_t" in vhd
143 assert f"{file_name}_regs_down_t" not in vhd
145 # If there are no arrays there should be no records for arrays, and this comment shall not
146 # be present.
147 string = _get_register_arrays_record_string("up")
148 if "array" in file_name:
149 assert string in vhd
150 else:
151 assert string not in vhd
153 # The 'down' comment shall never be present since we have no 'down' registers.
154 string = _get_register_arrays_record_string("down")
155 assert string not in vhd
157 vhd = read_file(tmp_path / f"{file_name}_register_file_axi_lite.vhd")
159 assert "regs_up : in" in vhd
160 assert "regs_down : out" not in vhd
162 assert "reg_was_read : out" in vhd
163 assert "reg_was_written : out" not in vhd
166def test_registers_only_in_down_direction_should_give_no_down_type_or_port(tmp_path):
167 generate_strange_register_maps(output_path=tmp_path)
169 for file_name in ["array_only_down", "plain_and_array_only_down", "plain_only_down"]:
170 vhd = read_file(tmp_path / f"{file_name}_register_record_pkg.vhd")
172 assert f"{file_name}_regs_up_t" not in vhd
173 assert f"{file_name}_regs_down_t" in vhd
175 # If there are no arrays there should be no records for arrays, and this comment shall not
176 # be present.
177 string = _get_register_arrays_record_string("down")
178 if "array" in file_name:
179 assert string in vhd
180 else:
181 assert string not in vhd
183 # The 'up' comment shall never be present since we have no 'up' registers.
184 string = _get_register_arrays_record_string("up")
185 assert string not in vhd
187 vhd = read_file(tmp_path / f"{file_name}_register_file_axi_lite.vhd")
189 assert "regs_up : in" not in vhd
190 assert "regs_down : out" in vhd
192 assert "reg_was_read : out" not in vhd
193 assert "reg_was_written : out" in vhd