Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: PeakRDL-halcpp test

on:
push:
branches:
- "*"
jobs:
build-and-test:
runs-on: ubuntu-latest
strategy:
matrix:
compiler: [ {cpp: g++, c: gcc}, {cpp: clang++, c: clang} ]

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install dependencies
run: |
sudo apt-get remove --purge man-db -y
sudo apt-get update
sudo apt-get install -y \
build-essential \
cmake \
make \
clang \
lld \
gcc g++ \
tree \
python3 python3-pip
pip install .

- name: Configure CMake
run: |
cmake -S tests -B build \
-DCMAKE_C_COMPILER=${{ matrix.compiler.c }} \
-DCMAKE_CXX_COMPILER=${{ matrix.compiler.cpp }}

- name: Build
run: cmake --build build

- name: Run tests
working-directory: build
run: ctest --output-on-failure
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,4 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
tests/cmake/_deps
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
recursive-include src/peakrdl_halcpp/templates *.j2
recursive-include src/peakrdl_halcpp/include *.h
recursive-include src/peakrdl_halcpp/test_generator_data/test_utils *.h
recursive-include src/peakrdl_halcpp/test_generator_data/test_utils *.txt
21 changes: 20 additions & 1 deletion src/peakrdl_halcpp/__peakrdl__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from typing import TYPE_CHECKING
import pathlib

from peakrdl.plugins.exporter import ExporterSubcommandPlugin # pylint: disable=import-error
from peakrdl.plugins.exporter import ExporterSubcommandPlugin

from peakrdl_halcpp.test_generator import TestGenerator # pylint: disable=import-error

from .exporter import HalExporter

Expand Down Expand Up @@ -42,6 +45,14 @@ def add_exporter_arguments(self, arg_group: 'argparse.ArgumentParser') -> None:
passing --skip-buses flag."
)

arg_group.add_argument(
"--generate-tests",
dest="generate_tests",
default=False,
action="store_true",
help="Generate tests"
)

def do_export(self, top_node: 'AddrmapNode', options: 'argparse.Namespace') -> None:
"""Plugin entry function."""
hal = HalExporter()
Expand All @@ -52,3 +63,11 @@ def do_export(self, top_node: 'AddrmapNode', options: 'argparse.Namespace') -> N
ext_modules=options.ext,
skip_buses=options.skip_buses,
)

if options.generate_tests:
tests = TestGenerator()

test_outdir = pathlib.Path(options.output) / "tests"
test_outdir.mkdir(parents=True, exist_ok=True)
tests.export(node=top_node,
outdir=str(test_outdir))
12 changes: 6 additions & 6 deletions src/peakrdl_halcpp/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,12 @@ def export(self,
text = self.process_template(context)

# Addrmaps for memories use the original type name
if halnode.is_mem_addrmap:
out_file = os.path.join(
outdir, halnode.orig_type_name_hal.lower() + ".h")
else:
out_file = os.path.join(
outdir, halnode.inst_name_hal.lower() + ".h")
# if halnode.is_mem_addrmap:
out_file = os.path.join(
outdir, halnode.orig_type_name_hal.lower() + ".h")
# else:
# out_file = os.path.join(
# outdir, halnode.inst_name_hal.lower() + ".h")

# Generate the files if --list-files parameter is not set
if list_files:
Expand Down
49 changes: 48 additions & 1 deletion src/peakrdl_halcpp/halnode.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ def get_docstring(self) -> str:
def _halfactory(inst: Node, env: 'RDLEnvironment', parent: Optional['Node'] = None) -> Optional['Node']:
"""HAL node factory method adapted from systemrdl Node class."""
if isinstance(inst, FieldNode):
return HalFieldNode(inst)
if inst.get_property("intwidth", default=None) or inst.get_property("fracwidth", default=None):
return HalFixpFieldNode(inst)
else:
return HalFieldNode(inst)
elif isinstance(inst, RegNode):
return HalRegNode(inst)
elif isinstance(inst, RegfileNode):
Expand Down Expand Up @@ -243,6 +246,50 @@ def get_enums(self):

return False, None, None, None, None, None

class HalFixpFieldNode(HalFieldNode, FieldNode):
"""HalFixpFieldNode class inheriting from HalBaseNode class and systemrdl FieldNode class.

Class methods:

- :func:`get_enums`
"""

@property
def fracwidth(self) -> int:
intwidth: int|None = self.get_property("intwidth", default=None)
fracwidth: int|None = self.get_property("fracwidth", default=None)

if fracwidth:
return int(fracwidth)
elif intwidth:
return self.width - intwidth

raise ValueError("One of intwidth or fracwidth properties need to be defined fro FixpFieldNode")

@property
def intwidth(self) -> int:
intwidth: int|None = self.get_property("intwidth", default=None)
fracwidth: int|None = self.get_property("fracwidth", default=None)

if intwidth:
return int(intwidth)
elif fracwidth:
return self.width - fracwidth

raise ValueError("One of intwidth or fracwidth properties need to be defined fro FixpFieldNode")

@property
def cpp_access_type(self) -> str:
"""C++ access right template selection."""
if self.is_sw_readable and self.is_sw_writable:
return "FixpFieldRW"
elif self.is_sw_writable and not self.is_sw_readable:
return "FixpFieldWO"
elif self.is_sw_readable:
return "FixpFieldRO"
else:
raise ValueError(f'Node field access rights are not found \
{self.inst.inst_name}')

class HalRegNode(HalBaseNode, RegNode):
"""HalRegNode class inheriting from HalBaseNode class and systemrdl RegNode class.
Expand Down
19 changes: 15 additions & 4 deletions src/peakrdl_halcpp/include/field_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ namespace halcpp
*/
static constexpr uint32_t get_width() { return width; }

/**
*
* @brief Return the index of first bit of the field in the parent register
*/
static constexpr uint32_t get_start_bit() { return start_bit; }

/**
*
* @brief Return the index of last bit of the field in the parent register
*/
static constexpr uint32_t get_end_bit() { return end_bit; }

/**
* @brief Calculate the field mask.
*
Expand Down Expand Up @@ -125,10 +137,8 @@ namespace halcpp
template <typename BASE_TYPE>
class FieldRdMixin : public BASE_TYPE
{
private:
using parent = typename BASE_TYPE::parent_type;

public:
using parent = typename BASE_TYPE::parent_type;
/**
* @brief Check if the field has a get operation (read capability).
*/
Expand Down Expand Up @@ -249,12 +259,13 @@ namespace halcpp
static_assert(IDX >= -1);
// Calculate the index to be used for accessing the mixin based on the given index
constexpr uint32_t idx = IDX == -1 ? first_mixin::width - 1 : IDX;
constexpr uint32_t start_bit = first_mixin::start_bit;

// Calculate the number of mixins in the tuple
constexpr std::size_t num_of_mixins = sizeof...(FieldMixins);

// Define the base type using the calculated index and parent type
using base_type = FieldBase<idx, idx, parent_type>;
using base_type = FieldBase<start_bit + idx, start_bit + idx, parent_type>;

// Check if there's only one mixin
if constexpr (num_of_mixins == 1)
Expand Down
Loading