From 98c0a3f5de0c16c0e4c1ec3a147e11ab32e7b878 Mon Sep 17 00:00:00 2001 From: "julian.speith" Date: Tue, 4 Jun 2024 11:53:54 +0200 Subject: [PATCH 1/3] added optional flag to store whether pin group is ordered or not --- include/hal_core/netlist/pins/pin_group.h | 43 ++++++++++++++----- .../include/hgl_parser/hgl_parser.h | 2 +- plugins/hgl_parser/src/hgl_parser.cpp | 8 +++- .../include/hgl_writer/hgl_writer.h | 2 +- plugins/hgl_writer/src/hgl_writer.cpp | 1 + src/netlist/persistent/netlist_serializer.cpp | 14 +++++- .../bindings/gate_pin_group.cpp | 20 +++++++-- .../bindings/module_pin_group.cpp | 22 +++++++++- 8 files changed, 90 insertions(+), 22 deletions(-) diff --git a/include/hal_core/netlist/pins/pin_group.h b/include/hal_core/netlist/pins/pin_group.h index 30abc056440..1348a731c73 100644 --- a/include/hal_core/netlist/pins/pin_group.h +++ b/include/hal_core/netlist/pins/pin_group.h @@ -26,8 +26,8 @@ #pragma once #include "hal_core/defines.h" -#include "hal_core/utilities/result.h" #include "hal_core/utilities/log.h" +#include "hal_core/utilities/result.h" #include #include @@ -57,9 +57,10 @@ namespace hal * @param[in] type - The type of the pin group. * @param[in] ascending - Set `true` for ascending pin order (from 0 to n-1), `false` otherwise (from n-1 to 0). Defaults to `true`. * @param[in] start_index - The start index of the pin group. Defaults to `0`. + * @param[in] ordered - Set `true` if the pin group features an inherent order, `false` otherwise. Defaults to `false`. */ - PinGroup(const u32 id, const std::string& name, PinDirection direction, PinType type, bool ascending = true, u32 start_index = 0) - : m_id(id), m_name(name), m_direction(direction), m_type(type), m_ascending(ascending), m_start_index(start_index), m_next_index(start_index) + PinGroup(const u32 id, const std::string& name, PinDirection direction, PinType type, bool ascending = true, u32 start_index = 0, bool ordered = false) + : m_id(id), m_name(name), m_direction(direction), m_type(type), m_ascending(ascending), m_start_index(start_index), m_next_index(start_index), m_ordered(ordered) { } @@ -74,7 +75,7 @@ namespace hal bool operator==(const PinGroup& other) const { if (m_id != other.get_id() || m_name != other.get_name() || m_direction != other.get_direction() || m_type != other.get_type() || m_start_index != other.get_start_index() - || m_ascending != other.is_ascending()) + || m_ascending != other.is_ascending() || m_is_ordered != other.is_ordered()) { return false; } @@ -270,7 +271,7 @@ namespace hal /** * Check whether the pin order of a pin group comprising n pins is ascending (from 0 to n-1) or descending (from n-1 to 0). * - * @returns True for ascending bit order, false otherwise. + * @returns `true` for ascending bit order, `false` otherwise. */ bool is_ascending() const { @@ -289,6 +290,26 @@ namespace hal return m_start_index; } + /** + * Check whether the pin group features an inherent order. + * + * @returns `true` if the pin group is inherently ordered, `false` otherwise. + */ + bool is_ordered() const + { + return m_ordered; + } + + /** + * Set whether the pin group features an inherent order. + * + * @param[in] ordered - Set `true` if the pin group is inherently ordered, `false` otherwise. Defaults to `true`. + */ + void set_ordered(bool ordered = true) const + { + m_ordered = ordered; + } + /** * Check whether the pin group is empty, i.e., contains no pins. * @@ -319,8 +340,7 @@ namespace hal { if (pin == nullptr) { - log_warning("pin_group", "'nullptr' given instead of a pin when trying to assign a pin to pin group '{}' with ID {}", - m_name, m_id); + log_warning("pin_group", "'nullptr' given instead of a pin when trying to assign a pin to pin group '{}' with ID {}", m_name, m_id); return false; } @@ -336,7 +356,7 @@ namespace hal { // special case empty pin group index = m_start_index; - -- m_next_index; + --m_next_index; } else { @@ -456,7 +476,7 @@ namespace hal } else { - if (m_pins.size()==1) + if (m_pins.size() == 1) { m_pins.clear(); m_next_index++; @@ -464,14 +484,14 @@ namespace hal else { auto it = m_pins.begin(); - for (int i=m_start_index; i>index;i--) + for (int i = m_start_index; i > index; i--) { std::get<1>((*(it++))->m_group)--; } m_pins.erase(it); --m_start_index; } - } + } return true; } @@ -506,6 +526,7 @@ namespace hal bool m_ascending; i32 m_start_index; i32 m_next_index; + bool m_ordered; PinGroup(const PinGroup&) = delete; PinGroup(PinGroup&&) = delete; diff --git a/plugins/hgl_parser/include/hgl_parser/hgl_parser.h b/plugins/hgl_parser/include/hgl_parser/hgl_parser.h index 7b35b6414ed..a126395165b 100644 --- a/plugins/hgl_parser/include/hgl_parser/hgl_parser.h +++ b/plugins/hgl_parser/include/hgl_parser/hgl_parser.h @@ -55,7 +55,7 @@ namespace hal Result> parse(const std::filesystem::path& file_path) override; private: - const u32 HGL_FORMAT_VERSION = 3; + const u32 HGL_FORMAT_VERSION = 4; u32 file_version = 1; struct PinCtx diff --git a/plugins/hgl_parser/src/hgl_parser.cpp b/plugins/hgl_parser/src/hgl_parser.cpp index bdb0397a919..7a8b41d9ba1 100644 --- a/plugins/hgl_parser/src/hgl_parser.cpp +++ b/plugins/hgl_parser/src/hgl_parser.cpp @@ -253,6 +253,12 @@ namespace hal } bool ascending = pg_val["ascending"].GetBool(); + bool ordered = false; + if (pg_val.HasMember("ordered") && pg_val["ordered"].IsBool()) + { + ordered = pg_val["ordered"].GetBool(); + } + if (!pg_val.HasMember("start_index") || !pg_val["start_index"].IsUint()) { return ERR("could not parse pin group '" + pg_name + "': missing or start index"); @@ -354,7 +360,7 @@ namespace hal } } - auto pg_res = gt->create_pin_group(pg_name, pins, pg_direction, pg_type, ascending, start_index); + auto pg_res = gt->create_pin_group(pg_name, pins, pg_direction, pg_type, ascending, start_index, ordered); if (pg_res.is_error()) { return ERR_APPEND(pg_res.get_error(), diff --git a/plugins/hgl_writer/include/hgl_writer/hgl_writer.h b/plugins/hgl_writer/include/hgl_writer/hgl_writer.h index b18783c238f..5a68efc5ef6 100644 --- a/plugins/hgl_writer/include/hgl_writer/hgl_writer.h +++ b/plugins/hgl_writer/include/hgl_writer/hgl_writer.h @@ -60,7 +60,7 @@ namespace hal bool write(const GateLibrary* gate_lib, const std::filesystem::path& file_path) override; private: - const u32 HGL_FORMAT_VERSION = 3; + const u32 HGL_FORMAT_VERSION = 4; struct PinCtx { diff --git a/plugins/hgl_writer/src/hgl_writer.cpp b/plugins/hgl_writer/src/hgl_writer.cpp index 8e736202dc8..1fb8d5a8a2b 100644 --- a/plugins/hgl_writer/src/hgl_writer.cpp +++ b/plugins/hgl_writer/src/hgl_writer.cpp @@ -277,6 +277,7 @@ namespace hal pg_val.AddMember("type", enum_to_string(group->get_type()), allocator); pg_val.AddMember("ascending", group->is_ascending(), allocator); pg_val.AddMember("start_index", group->get_start_index(), allocator); + pg_val.AddMember("ordered", group->is_ordered(), allocator); // pins of group rapidjson::Value p_array(rapidjson::kArrayType); diff --git a/src/netlist/persistent/netlist_serializer.cpp b/src/netlist/persistent/netlist_serializer.cpp index 52d3b12f77c..9844c81b7cf 100644 --- a/src/netlist/persistent/netlist_serializer.cpp +++ b/src/netlist/persistent/netlist_serializer.cpp @@ -34,7 +34,7 @@ namespace hal // serializing functions namespace { - const int SERIALIZATION_FORMAT_VERSION = 13; + const int SERIALIZATION_FORMAT_VERSION = 14; int encoded_format_version; // Ver 12 : location of gates @@ -66,6 +66,7 @@ namespace hal std::vector pins; bool ascending = false; u32 start_index = 0; + bool ordered = false; }; } // namespace @@ -443,6 +444,7 @@ namespace hal json_pin_group.AddMember("direction", enum_to_string(pin_group->get_direction()), allocator); json_pin_group.AddMember("type", enum_to_string(pin_group->get_type()), allocator); json_pin_group.AddMember("ascending", pin_group->is_ascending(), allocator); + json_pin_group.AddMember("ordered", pin_group->is_ordered(), allocator); json_pin_group.AddMember("start_index", pin_group->get_start_index(), allocator); rapidjson::Value json_pins(rapidjson::kArrayType); for (const ModulePin* pin : pin_group->get_pins()) @@ -544,6 +546,14 @@ namespace hal { pin_group.type = PinType::none; } + if (json_pin_group.HasMember("ordered")) + { + pin_group.ordered = json_pin_group["ordered"].GetBool(); + } + else + { + pin_group.type = PinType::none; + } pin_group.ascending = json_pin_group["ascending"].GetBool(); pin_group.start_index = json_pin_group["start_index"].GetUint(); @@ -616,7 +626,7 @@ namespace hal } } u32 pgid = (pg.id > 0) ? (u32)pg.id : sm->get_unique_pin_group_id(); - if (auto res = sm->create_pin_group(pgid, pg.name, pins, pg.direction, pg.type, pg.ascending, pg.start_index); res.is_error()) + if (auto res = sm->create_pin_group(pgid, pg.name, pins, pg.direction, pg.type, pg.ascending, pg.start_index, pg.ordered); res.is_error()) { log_error("netlist_persistent", "could not deserialize pin group '" + pg.name + "' of module '" + sm->get_name() + "' with ID " + std::to_string(sm->get_id()) diff --git a/src/python_bindings/bindings/gate_pin_group.cpp b/src/python_bindings/bindings/gate_pin_group.cpp index 32c4847e2e3..d669e8bc9ab 100644 --- a/src/python_bindings/bindings/gate_pin_group.cpp +++ b/src/python_bindings/bindings/gate_pin_group.cpp @@ -81,8 +81,7 @@ namespace hal :rtype: hal_py.PinType )"); - py_gate_pin_group.def_property_readonly( - "pins", [](const PinGroup& self) -> std::vector { return self.get_pins(nullptr); }, R"( + py_gate_pin_group.def_property_readonly("pins", [](const PinGroup& self) -> std::vector { return self.get_pins(nullptr); }, R"( The (ordered) pins of the pin groups. :type: list[hal_py.GatePin] @@ -152,7 +151,7 @@ namespace hal )"); py_gate_pin_group.def_property_readonly("ascending", &PinGroup::is_ascending, R"( - True if the pin order of a pin group comprising n pins is ascending (from 0 to n-1), False if it is descending (from n-1 to 0). + ``True`` if the pin order of a pin group comprising n pins is ascending (from 0 to n-1), ``False`` if it is descending (from n-1 to 0). :type: bool )"); @@ -160,7 +159,7 @@ namespace hal py_gate_pin_group.def("is_ascending", &PinGroup::is_ascending, R"( Check whether the pin order of a pin group comprising n pins is ascending (from 0 to n-1) or descending (from n-1 to 0). - :returns: True for ascending bit order, False otherwise. + :returns: ``True`` for ascending bit order, ``False`` otherwise. :rtype: bool )"); @@ -181,6 +180,19 @@ namespace hal :rtype: int )"); + py_gate_pin_group.def_property_readonly("ordered", &PinGroup::is_ordered, R"( + ``True`` if the pin group is inherently ordered, ``False`` otherwise. + + :type: bool + )"); + + py_gate_pin_group.def("is_ordered", &PinGroup::is_ordered, R"( + Check whether the pin group features an inherent order. + + :returns: ``True`` if the pin group is inherently ordered, ``False`` otherwise. + :rtype: bool + )"); + py_gate_pin_group.def("empty", &PinGroup::empty, R"( Check whether the pin group is empty, i.e., contains no pins. diff --git a/src/python_bindings/bindings/module_pin_group.cpp b/src/python_bindings/bindings/module_pin_group.cpp index fa4a60a04b8..294ea8e561a 100644 --- a/src/python_bindings/bindings/module_pin_group.cpp +++ b/src/python_bindings/bindings/module_pin_group.cpp @@ -81,8 +81,7 @@ namespace hal :rtype: hal_py.PinType )"); - py_module_pin_group.def_property_readonly( - "pins", [](const PinGroup& self) -> std::vector { return self.get_pins(nullptr); }, R"( + py_module_pin_group.def_property_readonly("pins", [](const PinGroup& self) -> std::vector { return self.get_pins(nullptr); }, R"( The (ordered) pins of the pin groups. :type: list[hal_py.ModulePin] @@ -181,6 +180,25 @@ namespace hal :rtype: int )"); + py_module_pin_group.def_property_readonly("ordered", &PinGroup::is_ordered, R"( + ``True`` if the pin group is inherently ordered, ``False`` otherwise. + + :type: bool + )"); + + py_module_pin_group.def("is_ordered", &PinGroup::is_ordered, R"( + Check whether the pin group features an inherent order. + + :returns: ``True`` if the pin group is inherently ordered, ``False`` otherwise. + :rtype: bool + )"); + + py_module_pin_group.def("set_ordered", &PinGroup::set_ordered, py::arg("ordered") = true, R"( + Set whether the pin group features an inherent order. + + :param bool ordered: Set ``True`` if the pin group is inherently ordered, ``False`` otherwise. Defaults to ``True``. + )"); + py_module_pin_group.def("empty", &PinGroup::empty, R"( Check whether the pin group is empty, i.e., contains no pins. From cbc4ff0072791c1ca378a0813e17d70ad5abf608 Mon Sep 17 00:00:00 2001 From: "julian.speith" Date: Tue, 4 Jun 2024 11:59:41 +0200 Subject: [PATCH 2/3] updated changelog --- CHANGELOG.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e150b7a3ac2..fce09ec5b1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,19 +42,23 @@ All notable changes to this project will be documented in this file. * extended maximum line with the CSV parser can handle * changed warning messages for waveform parsing and made them more specific * changed policy toward 'dangling' wires, they are no longer ignored but considered as global inputs or outputs -* netlist - * module pins - * added qualifier for `pin_changed` core events telling receiver details about the recent modification - * added event scope and stacking classes so that `pin_changed` events can be collected and prioritized - * added specific GUI handler for every `pin_changed` event thus replacing the reload-entire-pingroup-tree policy +* core + * pin (groups) + * added optional flag to determine whether a pin group has an inherent order (defaults to `false`) + * added `GateType::delete_pin_group` and `GateType::assign_pin_to_group` to enable more operations on pin groups of gate pins + * added parameter `force_name` to enforce pin (group) renaming to `Module::set_pin_name`, `Module::set_pin_group_name`, `Module::create_pin`, and `Module::create_pin_group` + * added pin types `status`, `error`, `error_detection`, `done`, and `control` + * added qualifier for module `pin_changed` core events telling receiver details about the recent modification + * added event scope and stacking classes so that module `pin_changed` events can be collected and prioritized + * added specific GUI handler for every module `pin_changed` event thus replacing the reload-entire-pingroup-tree policy * added class `ActionPingroup` so that UNDO function works for all pin / pin group actions issued from GUI -* decorators - * added `NetlistTraversalDecorator` to ease exploration of a netlist - * added `get_next_matching_gates` to get successor/predecessor gates matching a certain condition - * added `get_next_matching_gates_until` to get successor/predecessor gates until a certain condition is fulfilled - * added `get_next_matching_gates_until_depth` to get successor/predecessor gates up to a certain depth - * added `get_next_sequential_gates` and `get_next_sequential_gates_map` to get the next layer of sequential successors/predecessors - * added `get_next_combinational_gates` to get all combinational gates until the next non-combinational gates are reached + * decorators + * added `NetlistTraversalDecorator` to ease exploration of a netlist + * added `get_next_matching_gates` to get successor/predecessor gates matching a certain condition + * added `get_next_matching_gates_until` to get successor/predecessor gates until a certain condition is fulfilled + * added `get_next_matching_gates_until_depth` to get successor/predecessor gates up to a certain depth + * added `get_next_sequential_gates` and `get_next_sequential_gates_map` to get the next layer of sequential successors/predecessors + * added `get_next_combinational_gates` to get all combinational gates until the next non-combinational gates are reached * miscellaneous * added support for Ubuntu 24.04 LTS * added INIT field declaration to FF-gate-types in example library @@ -64,12 +68,9 @@ All notable changes to this project will be documented in this file. * added GUI PluginParameter types `Module` and `Gated` for parameters that can be requested from plugin * added `Show content` button to `Groupings` widget to show content of grouping as a list * added flag which Python editor tab is active when serializing project - * added `GateType::delete_pin_group` and `GateType::assign_pin_to_group` to enable more operations on pin groups of gate pins * added extended gate library picker when importing a netlist * added keyboard shortcut for delete-item action from toolbar - * added parameter `force_name` to enforce pin (group) renaming to `Module::set_pin_name`, `Module::set_pin_group_name`, `Module::create_pin`, and `Module::create_pin_group` * added gate type properties `fifo` and `shift_register` - * added pin types `status`, `error`, `error_detection`, `done`, and `control` * added optional filter to `Net::get_num_of_sources` and `Net::get_num_of_destinations` * added function `unify_ff_outputs` to netlist preprocessing plugin * changed supported input file formats for import from hard coded list to list provided by loadable parser plugins From bf39d60be76385fc3fcb8fae08f2d73b85531a48 Mon Sep 17 00:00:00 2001 From: "julian.speith" Date: Tue, 4 Jun 2024 12:13:09 +0200 Subject: [PATCH 3/3] fixed compile errors --- include/hal_core/netlist/pins/pin_group.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/hal_core/netlist/pins/pin_group.h b/include/hal_core/netlist/pins/pin_group.h index 1348a731c73..9696aa2fa88 100644 --- a/include/hal_core/netlist/pins/pin_group.h +++ b/include/hal_core/netlist/pins/pin_group.h @@ -75,7 +75,7 @@ namespace hal bool operator==(const PinGroup& other) const { if (m_id != other.get_id() || m_name != other.get_name() || m_direction != other.get_direction() || m_type != other.get_type() || m_start_index != other.get_start_index() - || m_ascending != other.is_ascending() || m_is_ordered != other.is_ordered()) + || m_ascending != other.is_ascending() || m_ordered != other.is_ordered()) { return false; } @@ -305,7 +305,7 @@ namespace hal * * @param[in] ordered - Set `true` if the pin group is inherently ordered, `false` otherwise. Defaults to `true`. */ - void set_ordered(bool ordered = true) const + void set_ordered(bool ordered = true) { m_ordered = ordered; }