From 8a2485ee289a2b278eb6e66bab13758023e8fb96 Mon Sep 17 00:00:00 2001 From: Simon Klix Date: Fri, 8 Nov 2024 14:15:30 +0100 Subject: [PATCH] added missing python bindings and fixed bug in netlist preprocessing --- .../machine_learning/labels/gate_pair_label.h | 105 +++++- .../python/python_bindings.cpp | 315 ++++++++++++------ .../src/labels/gate_pair_label.cpp | 7 +- .../src/netlist_preprocessing.cpp | 12 +- 4 files changed, 337 insertions(+), 102 deletions(-) diff --git a/plugins/machine_learning/include/machine_learning/labels/gate_pair_label.h b/plugins/machine_learning/include/machine_learning/labels/gate_pair_label.h index b3c39a52bf0..dc5a48d1ff9 100644 --- a/plugins/machine_learning/include/machine_learning/labels/gate_pair_label.h +++ b/plugins/machine_learning/include/machine_learning/labels/gate_pair_label.h @@ -1,3 +1,8 @@ +/** + * @file gate_pair_label.h + * @brief This file contains classes and functions for labeling pairs of gates within a machine learning context. + */ + #pragma once #include "hal_core/defines.h" @@ -9,7 +14,7 @@ namespace hal { - /* Forward declaration */ + /* Forward declarations */ class Gate; class Netlist; @@ -17,55 +22,145 @@ namespace hal { namespace gate_pair_label { + /** + * @struct MultiBitInformation + * @brief Holds mappings between word labels and gates, and gates and word labels. + * + * This struct provides a bi-directional mapping between specific word pairs and their corresponding gates, + * as well as between gates and associated word pairs. + */ struct MultiBitInformation { + /** + * @brief Maps word pairs to corresponding gates. + */ std::map, std::vector> word_to_gates; + + /** + * @brief Maps gates to associated word pairs. + */ std::map>> gate_to_words; }; + /** + * @struct LabelContext + * @brief Provides context for gate-pair labeling within a netlist. + * + * This struct is initialized with a reference to the netlist and the gates involved in the labeling. + * It also provides access to multi-bit information for use in labeling calculations. + */ struct LabelContext { + /** + * @brief Deleted default constructor to enforce initialization with parameters. + */ LabelContext() = delete; + + /** + * @brief Constructs a `LabelContext` with the specified netlist and gates. + * @param[in] netlist - The netlist to which the gates belong. + * @param[in] gates - The gates to be labeled. + */ LabelContext(const Netlist* netlist, const std::vector& gates) : nl(netlist), gates{gates} {}; + /** + * @brief Retrieves the multi-bit information, initializing it if not already done. + * @returns A constant reference to the `MultiBitInformation` object. + */ const MultiBitInformation& get_multi_bit_information(); + /** + * @brief The netlist to which the gates belong. + */ const Netlist* nl; + + /** + * @brief The gates that are part of this labeling context. + */ const std::vector gates; + + /** + * @brief Optional storage for multi-bit information, initialized on demand. + */ std::optional mbi; }; + /** + * @class GatePairLabel + * @brief Base class for calculating gate pairs and labels for machine learning models. + * + * This abstract class provides methods for calculating gate pairs and labels based on various criteria. + */ class GatePairLabel { public: + /** + * @brief Calculate gate pairs based on the provided labeling context and netlist. + * @param[in] lc - The labeling context. + * @param[in] nl - The netlist to operate on. + * @param[in] gates - The gates to be paired. + * @returns A vector of gate pairs on success, an error otherwise. + */ virtual std::vector> calculate_gate_pairs(LabelContext& lc, const Netlist* nl, const std::vector& gates) const = 0; - virtual std::vector calculate_label(LabelContext& lc, const Gate* g_a, const Gate* g_b) const = 0; - virtual std::vector> calculate_labels(LabelContext& lc, const std::vector>& gate_pairs) const = 0; + /** + * @brief Calculate labels for a given gate pair. + * @param[in] lc - The labeling context. + * @param[in] g_a - The first gate in the pair. + * @param[in] g_b - The second gate in the pair. + * @returns A vector of labels on success, an error otherwise. + */ + virtual std::vector calculate_label(LabelContext& lc, const Gate* g_a, const Gate* g_b) const = 0; + + /** + * @brief Calculate labels for multiple gate pairs. + * @param[in] lc - The labeling context. + * @param[in] gate_pairs - The gate pairs to label. + * @returns A vector of label vectors for each pair on success, an error otherwise. + */ + virtual std::vector> calculate_labels(LabelContext& lc, const std::vector>& gate_pairs) const = 0; + + /** + * @brief Calculate both gate pairs and their labels within the labeling context. + * @param[in] lc - The labeling context. + * @returns A pair containing gate pairs and corresponding labels on success, an error otherwise. + */ virtual std::pair>, std::vector>> calculate_labels(LabelContext& lc) const = 0; }; + /** + * @class SharedSignalGroup + * @brief Labels gate pairs based on shared signal groups. + */ class SharedSignalGroup : public GatePairLabel { public: + /** + * @brief Default constructor. + */ SharedSignalGroup() {}; std::vector> calculate_gate_pairs(LabelContext& lc, const Netlist* nl, const std::vector& gates) const override; std::vector calculate_label(LabelContext& lc, const Gate* g_a, const Gate* g_b) const override; std::vector> calculate_labels(LabelContext& lc, const std::vector>& gate_pairs) const override; - std::pair>, std::vector>> calculate_labels(LabelContext& lc) const override; }; + /** + * @class SharedConnection + * @brief Labels gate pairs based on shared connections. + */ class SharedConnection : public GatePairLabel { public: + /** + * @brief Default constructor. + */ SharedConnection() {}; std::vector> calculate_gate_pairs(LabelContext& lc, const Netlist* nl, const std::vector& gates) const override; std::vector calculate_label(LabelContext& lc, const Gate* g_a, const Gate* g_b) const override; std::vector> calculate_labels(LabelContext& lc, const std::vector>& gate_pairs) const override; - std::pair>, std::vector>> calculate_labels(LabelContext& lc) const override; }; } // namespace gate_pair_label diff --git a/plugins/machine_learning/python/python_bindings.cpp b/plugins/machine_learning/python/python_bindings.cpp index e10ff8be015..654d7c7daa1 100644 --- a/plugins/machine_learning/python/python_bindings.cpp +++ b/plugins/machine_learning/python/python_bindings.cpp @@ -609,152 +609,277 @@ namespace hal )"); // machine_learning::labels::gate_pair_label - py::class_ py_multi_bit_information(py_gate_pair_label, "MultiBitInformation", R"( - Holds information about multi-bit labels, mapping word pairs to gates and gates to word pairs. - )"); + // MultiBitInformation + py::class_ py_multi_bit_information( + py_gate_pair_label, "MultiBitInformation", R"( + Holds mappings between word labels and gates, and gates and word labels. + + This struct provides a bi-directional mapping between specific word pairs and their corresponding gates, + as well as between gates and associated word pairs. + )"); py_multi_bit_information.def_readwrite("word_to_gates", &hal::machine_learning::gate_pair_label::MultiBitInformation::word_to_gates, R"( - Maps word pairs to lists of gates. + Maps word pairs to corresponding gates. :type: dict[tuple[str, str], list[hal_py.Gate]] )"); py_multi_bit_information.def_readwrite("gate_to_words", &hal::machine_learning::gate_pair_label::MultiBitInformation::gate_to_words, R"( - Maps gates to lists of word pairs. + Maps gates to associated word pairs. :type: dict[hal_py.Gate, list[tuple[str, str]]] )"); - py::class_ py_label_context(py_gate_pair_label, "LabelContext", R"( - Provides context for labeling gates within a netlist. - )"); + // LabelContext + py::class_ py_label_context( + py_gate_pair_label, "LabelContext", R"( + Provides context for gate-pair labeling within a netlist. - py_label_context.def(py::init&>(), py::arg("netlist"), py::arg("gates"), R"( - Initialize a LabelContext with a netlist and a set of gates. + This struct is initialized with a reference to the netlist and the gates involved in the labeling. + It also provides access to multi-bit information for use in labeling calculations. + )"); - :param hal_py.Netlist netlist: The netlist for analysis. - :param list[hal_py.Gate] gates: The gates for labeling. - )"); + py_label_context.def( + py::init&>(), + py::arg("netlist"), + py::arg("gates"), + R"( + Constructs a `LabelContext` with the specified netlist and gates. - py_label_context.def("get_multi_bit_information", &hal::machine_learning::gate_pair_label::LabelContext::get_multi_bit_information, R"( - Retrieve multi-bit information for the current context. + :param hal_py.Netlist netlist: The netlist to which the gates belong. + :param list[hal_py.Gate] gates: The gates to be labeled. + )"); - :returns: Multi-bit information. - :rtype: gate_pair_label.MultiBitInformation - )"); + py_label_context.def( + "get_multi_bit_information", + &hal::machine_learning::gate_pair_label::LabelContext::get_multi_bit_information, + R"( + Retrieves the multi-bit information, initializing it if not already done. + + :returns: The MultiBitInformation object. + :rtype: hal_py.machine_learning.gate_pair_label.MultiBitInformation + )"); py_label_context.def_readonly("nl", &hal::machine_learning::gate_pair_label::LabelContext::nl, R"( - The netlist associated with the LabelContext. + The netlist to which the gates belong. :type: hal_py.Netlist )"); py_label_context.def_readonly("gates", &hal::machine_learning::gate_pair_label::LabelContext::gates, R"( - The gates within the context. + The gates that are part of this labeling context. :type: list[hal_py.Gate] )"); - py_label_context.def_readonly("mbi", &hal::machine_learning::gate_pair_label::LabelContext::mbi, R"( - Multi-bit information if available. + py_label_context.def_readwrite("mbi", &hal::machine_learning::gate_pair_label::LabelContext::mbi, R"( + Optional storage for multi-bit information, initialized on demand. - :type: Optional[gate_pair_label.MultiBitInformation] + :type: Optional[hal_py.machine_learning.gate_pair_label.MultiBitInformation] )"); - py::class_> py_gate_pair_label_class( + // GatePairLabel + py::class_ py_gatepairlabel( py_gate_pair_label, "GatePairLabel", R"( - Base class for gate-pair labeling implementations. - )"); + Base class for calculating gate pairs and labels for machine learning models. - // py_gate_pair_label_class.def("calculate_gate_pairs", &hal::machine_learning::gate_pair_label::GatePairLabel::calculate_gate_pairs, py::arg("lc"), py::arg("netlist"), py::arg("gates"), R"( - // Calculate gate pairs based on the provided label context, netlist, and gates. + This abstract class provides methods for calculating gate pairs and labels based on various criteria. + )"); - // :param gate_pair_label.LabelContext lc: The labeling context. - // :param hal_py.Netlist netlist: The netlist. - // :param list[hal_py.Gate] gates: The gates to analyze. - // :returns: List of gate pairs. - // :rtype: list[tuple[hal_py.Gate, hal_py.Gate]] - // )"); + py_gatepairlabel.def( + "calculate_gate_pairs", + &hal::machine_learning::gate_pair_label::GatePairLabel::calculate_gate_pairs, + py::arg("lc"), + py::arg("nl"), + py::arg("gates"), + R"( + Calculate gate pairs based on the provided labeling context and netlist. - // py_gate_pair_label_class.def("calculate_label", &hal::machine_learning::gate_pair_label::GatePairLabel::calculate_label, py::arg("lc"), py::arg("g_a"), py::arg("g_b"), R"( - // Calculate the label for a given pair of gates. + :param hal_py.machine_learning.gate_pair_label.LabelContext lc: The labeling context. + :param hal_py.Netlist nl: The netlist to operate on. + :param list[hal_py.Gate] gates: The gates to be paired. + :returns: A list of gate pairs. + :rtype: list[tuple[hal_py.Gate, hal_py.Gate]] + )"); - // :param gate_pair_label.LabelContext lc: The labeling context. - // :param hal_py.Gate g_a: The first gate. - // :param hal_py.Gate g_b: The second gate. - // :returns: List of labels. - // :rtype: list[int] - // )"); + py_gatepairlabel.def( + "calculate_label", + &hal::machine_learning::gate_pair_label::GatePairLabel::calculate_label, + py::arg("lc"), + py::arg("g_a"), + py::arg("g_b"), + R"( + Calculate labels for a given gate pair. - // py_gate_pair_label_class.def("calculate_labels", &hal::machine_learning::gate_pair_label::GatePairLabel::calculate_labels, py::arg("lc"), py::arg("gate_pairs"), R"( - // Calculate labels for a set of gate pairs. + :param hal_py.machine_learning.gate_pair_label.LabelContext lc: The labeling context. + :param hal_py.Gate g_a: The first gate in the pair. + :param hal_py.Gate g_b: The second gate in the pair. + :returns: A list of labels. + :rtype: list[int] + )"); - // :param gate_pair_label.LabelContext lc: The labeling context. - // :param list[tuple[hal_py.Gate, hal_py.Gate]] gate_pairs: The gate pairs. - // :returns: List of labels for each gate pair. - // :rtype: list[list[int]] - // )"); + py_gatepairlabel.def( + "calculate_labels", + py::overload_cast>&>(&hal::machine_learning::gate_pair_label::GatePairLabel::calculate_labels, py::const_), + py::arg("lc"), + py::arg("gate_pairs"), + R"( + Calculate labels for multiple gate pairs. - // py_gate_pair_label_class.def("calculate_labels", &hal::machine_learning::gate_pair_label::GatePairLabel::calculate_labels, py::arg("lc"), R"( - // Calculate labels for all gate pairs in the context. + :param hal_py.machine_learning.gate_pair_label.LabelContext lc: The labeling context. + :param list[tuple[hal_py.Gate, hal_py.Gate]] gate_pairs: The gate pairs to label. + :returns: A list of label vectors for each pair. + :rtype: list[list[int]] + )"); - // :param gate_pair_label.LabelContext lc: The labeling context. - // :returns: Tuple of gate pairs and corresponding labels. - // :rtype: tuple[list[tuple[hal_py.Gate, hal_py.Gate]], list[list[int]]] - // )"); + py_gatepairlabel.def( + "calculate_labels", + py::overload_cast(&hal::machine_learning::gate_pair_label::GatePairLabel::calculate_labels, py::const_), + py::arg("lc"), + R"( + Calculate both gate pairs and their labels within the labeling context. - py::class_> - py_shared_signal_group(py_gate_pair_label, "SharedSignalGroup", R"( - Labeling strategy based on shared signals between gate pairs. - )"); + :param hal_py.machine_learning.gate_pair_label.LabelContext lc: The labeling context. + :returns: A pair containing gate pairs and corresponding labels. + :rtype: tuple[list[tuple[hal_py.Gate, hal_py.Gate]], list[list[int]]] + )"); + + // SharedSignalGroup + py::class_ py_sharedsignalgroup( + py_gate_pair_label, "SharedSignalGroup", R"( + Labels gate pairs based on shared signal groups. + )"); - py_shared_signal_group.def(py::init<>(), R"( - Constructs a SharedSignalGroup labeling strategy. + py_sharedsignalgroup.def(py::init<>(), R"( + Default constructor. )"); - py_shared_signal_group.def("calculate_gate_pairs", &hal::machine_learning::gate_pair_label::SharedSignalGroup::calculate_gate_pairs, py::arg("lc"), py::arg("netlist"), py::arg("gates"), R"( - Calculate gate pairs based on shared signals. + py_sharedsignalgroup.def( + "calculate_gate_pairs", + &hal::machine_learning::gate_pair_label::SharedSignalGroup::calculate_gate_pairs, + py::arg("lc"), + py::arg("nl"), + py::arg("gates"), + R"( + Calculate gate pairs based on the provided labeling context and netlist. - :param gate_pair_label.LabelContext lc: The labeling context. - :param hal_py.Netlist netlist: The netlist. - :param list[hal_py.Gate] gates: The gates to analyze. - :returns: List of gate pairs. - :rtype: list[tuple[hal_py.Gate, hal_py.Gate]] - )"); + :param hal_py.machine_learning.gate_pair_label.LabelContext lc: The labeling context. + :param hal_py.Netlist nl: The netlist to operate on. + :param list[hal_py.Gate] gates: The gates to be paired. + :returns: A list of gate pairs. + :rtype: list[tuple[hal_py.Gate, hal_py.Gate]] + )"); - py_shared_signal_group.def("calculate_label", &hal::machine_learning::gate_pair_label::SharedSignalGroup::calculate_label, py::arg("lc"), py::arg("g_a"), py::arg("g_b"), R"( - Calculate the label for a given pair of gates based on shared signals. + py_sharedsignalgroup.def( + "calculate_label", + &hal::machine_learning::gate_pair_label::SharedSignalGroup::calculate_label, + py::arg("lc"), + py::arg("g_a"), + py::arg("g_b"), + R"( + Calculate labels for a given gate pair. - :param gate_pair_label.LabelContext lc: The labeling context. - :param hal_py.Gate g_a: The first gate. - :param hal_py.Gate g_b: The second gate. - :returns: List of labels. - :rtype: list[int] - )"); + :param hal_py.machine_learning.gate_pair_label.LabelContext lc: The labeling context. + :param hal_py.Gate g_a: The first gate in the pair. + :param hal_py.Gate g_b: The second gate in the pair. + :returns: A vector of labels. + :rtype: list[int] + )"); - py::class_> - py_shared_connection(py_gate_pair_label, "SharedConnection", R"( - Labeling strategy based on shared connections between gate pairs. - )"); + py_sharedsignalgroup.def( + "calculate_labels", + py::overload_cast>&>(&hal::machine_learning::gate_pair_label::SharedSignalGroup::calculate_labels, py::const_), + py::arg("lc"), + py::arg("gate_pairs"), + R"( + Calculate labels for multiple gate pairs. - py_shared_connection.def(py::init<>(), R"( - Constructs a SharedConnection labeling strategy. - )"); + :param hal_py.machine_learning.gate_pair_label.LabelContext lc: The labeling context. + :param list[tuple[hal_py.Gate, hal_py.Gate]] gate_pairs: The gate pairs to label. + :returns: A vector of label vectors for each pair. + :rtype: list[list[int]] + )"); - py_shared_connection.def("calculate_gate_pairs", &hal::machine_learning::gate_pair_label::SharedConnection::calculate_gate_pairs, py::arg("lc"), py::arg("netlist"), py::arg("gates"), R"( - Calculate gate pairs based on shared connections. + py_sharedsignalgroup.def( + "calculate_labels", + py::overload_cast(&hal::machine_learning::gate_pair_label::SharedSignalGroup::calculate_labels, py::const_), + py::arg("lc"), + R"( + Calculate both gate pairs and their labels within the labeling context. - :param gate_pair_label.LabelContext lc: The labeling context. - :param hal_py.Netlist netlist: The netlist. - :param list[hal_py.Gate] gates: The gates to analyze. - :returns: List of gate pairs. - :rtype: list[tuple[hal_py.Gate, hal_py.Gate]] + :param hal_py.machine_learning.gate_pair_label.LabelContext lc: The labeling context. + :returns: A pair containing gate pairs and corresponding labels. + :rtype: tuple[list[tuple[hal_py.Gate, hal_py.Gate]], list[list[int]]] + )"); + + // SharedConnection + py::class_ py_sharedconnection( + py_gate_pair_label, "SharedConnection", R"( + Labels gate pairs based on shared connections. + )"); + + py_sharedconnection.def(py::init<>(), R"( + Default constructor. )"); + py_sharedconnection.def( + "calculate_gate_pairs", + &hal::machine_learning::gate_pair_label::SharedConnection::calculate_gate_pairs, + py::arg("lc"), + py::arg("nl"), + py::arg("gates"), + R"( + Calculate gate pairs based on the provided labeling context and netlist. + + :param hal_py.machine_learning.gate_pair_label.LabelContext lc: The labeling context. + :param hal_py.Netlist nl: The netlist to operate on. + :param list[hal_py.Gate] gates: The gates to be paired. + :returns: A list of gate pairs. + :rtype: list[tuple[hal_py.Gate, hal_py.Gate]] + )"); + + py_sharedconnection.def( + "calculate_label", + &hal::machine_learning::gate_pair_label::SharedConnection::calculate_label, + py::arg("lc"), + py::arg("g_a"), + py::arg("g_b"), + R"( + Calculate labels for a given gate pair. + + :param hal_py.machine_learning.gate_pair_label.LabelContext lc: The labeling context. + :param hal_py.Gate g_a: The first gate in the pair. + :param hal_py.Gate g_b: The second gate in the pair. + :returns: A vector of labels. + :rtype: list[int] + )"); + + py_sharedconnection.def( + "calculate_labels", + py::overload_cast>&>(&hal::machine_learning::gate_pair_label::SharedConnection::calculate_labels, py::const_), + py::arg("lc"), + py::arg("gate_pairs"), + R"( + Calculate labels for multiple gate pairs. + + :param hal_py.machine_learning.gate_pair_label.LabelContext lc: The labeling context. + :param list[tuple[hal_py.Gate, hal_py.Gate]] gate_pairs: The gate pairs to label. + :returns: A vector of label vectors for each pair. + :rtype: list[list[int]] + )"); + + py_sharedconnection.def( + "calculate_labels", + py::overload_cast(&hal::machine_learning::gate_pair_label::SharedConnection::calculate_labels, py::const_), + py::arg("lc"), + R"( + Calculate both gate pairs and their labels within the labeling context. + + :param hal_py.machine_learning.gate_pair_label.LabelContext lc: The labeling context. + :returns: A pair containing gate pairs and corresponding labels. + :rtype: tuple[list[tuple[hal_py.Gate, hal_py.Gate]], list[list[int]]] + )"); + #ifndef PYBIND11_MODULE return m.ptr(); #endif // PYBIND11_MODULE diff --git a/plugins/machine_learning/src/labels/gate_pair_label.cpp b/plugins/machine_learning/src/labels/gate_pair_label.cpp index c15c8ef4d1a..ada1be4a263 100644 --- a/plugins/machine_learning/src/labels/gate_pair_label.cpp +++ b/plugins/machine_learning/src/labels/gate_pair_label.cpp @@ -130,7 +130,7 @@ namespace hal if (mbi.gate_to_words.find(g) == mbi.gate_to_words.end()) { // gate is only in a group with itself - pairs.push_back({g, g}); + // pairs.push_back({g, g}); pos_gates.insert(g); } else @@ -141,6 +141,11 @@ namespace hal const auto& gates = mbi.word_to_gates.at(name_direction); for (const auto g_i : gates) { + if (g == g_i) + { + continue; + } + pairs.push_back({g, g_i}); pos_gates.insert(g); } diff --git a/plugins/netlist_preprocessing/src/netlist_preprocessing.cpp b/plugins/netlist_preprocessing/src/netlist_preprocessing.cpp index b45e1efb17a..d6e2830b2f9 100644 --- a/plugins/netlist_preprocessing/src/netlist_preprocessing.cpp +++ b/plugins/netlist_preprocessing/src/netlist_preprocessing.cpp @@ -1955,7 +1955,7 @@ namespace hal { struct indexed_identifier { - indexed_identifier(const std::string& identifier, const u32 index, const std::string& origin, const PinDirection& direction) : identifier{identifier}, index{index}, origin{origin} + indexed_identifier(const std::string& identifier, const u32 index, const std::string& origin, const PinDirection& direction) : identifier{identifier}, index{index}, origin{origin}, direction{direction} { } @@ -2059,8 +2059,18 @@ namespace hal for (const auto& pin : typed_pins) { + if (pin->get_direction() != PinDirection::output && pin->get_direction() != PinDirection::input) + { + continue; + } + const auto typed_net = (pin->get_direction() == PinDirection::output) ? gate->get_fan_out_net(pin) : gate->get_fan_in_net(pin); + if (typed_net == nullptr) + { + continue; + } + // 1) search the net name itself const auto net_name_index = extract_index(typed_net->get_name(), net_index_pattern, "net_name", pin->get_direction()); if (net_name_index.has_value())