diff --git a/include/hal_core/netlist/module.h b/include/hal_core/netlist/module.h index 7aabc550d9b..a785ef1eacf 100644 --- a/include/hal_core/netlist/module.h +++ b/include/hal_core/netlist/module.h @@ -339,9 +339,10 @@ namespace hal * @param[in] net - The net that the pin is being assigned to. * @param[in] type - The type of the pin. Defaults to `PinType::none`. * @param[in] create_group - Set `true` to automatically create a pin group and assign the pin, `false` otherwise. Defaults to `true`. + * @param[in] force_name - Set `true` to enforce the name, `false` otherwise. If a pin with the same name already exists, the existing pin will be renamed. Defaults to `false`. * @returns The module pin on success, an error message otherwise. */ - Result create_pin(const u32 id, const std::string& name, Net* net, PinType type = PinType::none, bool create_group = true); + Result create_pin(const u32 id, const std::string& name, Net* net, PinType type = PinType::none, bool create_group = true, bool force_name = false); /** * Manually create a module pin and assign it to a net. @@ -355,9 +356,10 @@ namespace hal * @param[in] net - The net that the pin is being assigned to. * @param[in] type - The type of the pin. Defaults to `PinType::none`. * @param[in] create_group - Set `true` to automatically create a pin group and assign the pin, `false` otherwise. Defaults to `true`. + * @param[in] force_name - Set `true` to enforce the name, `false` otherwise. If a pin with the same name already exists, the existing pin will be renamed. Defaults to `false`. * @returns The module pin on success, an error message otherwise. */ - Result create_pin(const std::string& name, Net* net, PinType type = PinType::none, bool create_group = true); + Result create_pin(const std::string& name, Net* net, PinType type = PinType::none, bool create_group = true, bool force_name = false); /** * Get an ordered vector of all pins of the module. @@ -459,9 +461,10 @@ namespace hal * * @param[in] pin - The pin. * @param[in] new_name - The name to be assigned to the pin. + * @param[in] force_name - Set `true` to enforce the name, `false` otherwise. If a pin with the same name already exists, that existing pin will be renamed. Defaults to `false`. * @returns `true` on success, `false` otherwise. */ - bool set_pin_name(ModulePin* pin, const std::string& new_name); + bool set_pin_name(ModulePin* pin, const std::string& new_name, bool force_name = false); /** * Set the type of the given pin. @@ -483,6 +486,7 @@ namespace hal * @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] delete_empty_groups - Set `true` to delete groups that are empty after the pins have been assigned to the new group, `false` to keep empty groups. Defaults to `true`. + * @param[in] force_name - Set `true` to enforce the name, `false` otherwise. If a pin group with the same name already exists, the existing pin group will be renamed. Defaults to `false`. * @returns The pin group on success, an error message otherwise. */ Result*> create_pin_group(const u32 id, @@ -492,7 +496,8 @@ namespace hal PinType type = PinType::none, bool ascending = true, u32 start_index = 0, - bool delete_empty_groups = true); + bool delete_empty_groups = true, + bool force_name = false); /** * Create a new pin group with the given name. @@ -505,6 +510,7 @@ namespace hal * @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] delete_empty_groups - Set `true` to delete groups that are empty after the pins have been assigned to the new group, `false` to keep empty groups. Defaults to `true`. + * @param[in] force_name - Set `true` to enforce the name, `false` otherwise. If a pin group with the same name already exists, the existing pin group will be renamed. Defaults to `false`. * @returns The pin group on success, an error message otherwise. */ Result*> create_pin_group(const std::string& name, @@ -513,7 +519,8 @@ namespace hal PinType type = PinType::none, bool ascending = true, u32 start_index = 0, - bool delete_empty_groups = true); + bool delete_empty_groups = true, + bool force_name = false); /** * Delete the given pin group. @@ -538,9 +545,10 @@ namespace hal * * @param[in] pin_group - The pin group. * @param[in] new_name - The name to be assigned to the pin group. + * @param[in] force_name - Set `true` to enforce the name, `false` otherwise. If a pin group with the same name already exists, the existing pin group will be renamed. Defaults to `false`. * @returns `true` on success, `false` otherwise. */ - bool set_pin_group_name(PinGroup* pin_group, const std::string& new_name); + bool set_pin_group_name(PinGroup* pin_group, const std::string& new_name, bool force_name = false); /** * Set the type of the given pin group. @@ -735,9 +743,9 @@ namespace hal Result check_net(Net* net, bool recursive = false); Result assign_pin_net(const u32 pin_id, Net* net, PinDirection direction, const std::string& name = "", PinType type = PinType::none); Result remove_pin_net(Net* net); - Result create_pin_internal(const u32 id, const std::string& name, Net* net, PinDirection direction, PinType type); + Result create_pin_internal(const u32 id, const std::string& name, Net* net, PinDirection direction, PinType type, bool force_name); Result delete_pin_internal(ModulePin* pin); - Result*> create_pin_group_internal(const u32 id, const std::string& name, PinDirection direction, PinType type, bool ascending, u32 start_index); + Result*> create_pin_group_internal(const u32 id, const std::string& name, PinDirection direction, PinType type, bool ascending, u32 start_index, bool force_name); Result delete_pin_group_internal(PinGroup* pin_group); }; } // namespace hal diff --git a/plugins/gui/src/graph_widget/graph_context_manager.cpp b/plugins/gui/src/graph_widget/graph_context_manager.cpp index 399759a76ce..4e6b888afda 100644 --- a/plugins/gui/src/graph_widget/graph_context_manager.cpp +++ b/plugins/gui/src/graph_widget/graph_context_manager.cpp @@ -163,16 +163,20 @@ namespace hal void GraphContextManager::handleModuleRemoved(Module* m) { for (GraphContext* context : mContextTableModel->list()) - if (context->modules().contains(m->get_id())) + { + if (context->getExclusiveModuleId() == m->get_id()) + { + context->setExclusiveModuleId(0, false); + deleteGraphContext(context); + } + else if (context->modules().contains(m->get_id())) { - if (context->getExclusiveModuleId() == m->get_id()) - context->setExclusiveModuleId(0, false); - context->remove({m->get_id()}, {}); if (context->empty() || context->willBeEmptied()) deleteGraphContext(context); } + } } void GraphContextManager::handleModuleNameChanged(Module* m) const diff --git a/plugins/gui/src/module_model/module_model.cpp b/plugins/gui/src/module_model/module_model.cpp index 267da560738..d1e02d99baf 100644 --- a/plugins/gui/src/module_model/module_model.cpp +++ b/plugins/gui/src/module_model/module_model.cpp @@ -264,7 +264,7 @@ namespace hal void ModuleModel::remove_module(const u32 id) { assert(id != 1); - assert(gNetlist->get_module_by_id(id)); +// module was most likely already purged from netlist assert(mModuleItems.contains(id)); ModuleItem* item = mModuleItems.value(id); diff --git a/src/netlist/module.cpp b/src/netlist/module.cpp index acbdc8f6a44..b58772e6cfd 100644 --- a/src/netlist/module.cpp +++ b/src/netlist/module.cpp @@ -784,7 +784,7 @@ namespace hal return m_next_pin_group_id; } - Result Module::create_pin(const u32 id, const std::string& name, Net* net, PinType type, bool create_group) + Result Module::create_pin(const u32 id, const std::string& name, Net* net, PinType type, bool create_group, bool force_name) { if (name.empty()) { @@ -825,7 +825,7 @@ namespace hal + " is neither an input nor an output"); } - if (auto pin_res = create_pin_internal(id, name, net, direction, type); pin_res.is_error()) + if (auto pin_res = create_pin_internal(id, name, net, direction, type, force_name); pin_res.is_error()) { return ERR_APPEND(pin_res.get_error(), "could not create pin '" + name + "' for module '" + m_name + "' with ID " + std::to_string(m_id)); } @@ -833,7 +833,7 @@ namespace hal { if (create_group) { - if (const auto group_res = create_pin_group_internal(get_unique_pin_group_id(), name, direction, type, true, 0); group_res.is_error()) + if (const auto group_res = create_pin_group_internal(get_unique_pin_group_id(), name, direction, type, true, 0, force_name); group_res.is_error()) { assert(delete_pin_internal(pin_res.get()).is_ok()); return ERR_APPEND(group_res.get_error(), "could not create pin '" + name + "' for module '" + m_name + "' with ID " + std::to_string(m_id) + ": failed to create pin group"); @@ -854,9 +854,9 @@ namespace hal } } - Result Module::create_pin(const std::string& name, Net* net, PinType type, bool create_group) + Result Module::create_pin(const std::string& name, Net* net, PinType type, bool create_group, bool force_name) { - return create_pin(get_unique_pin_id(), name, net, type, create_group); + return create_pin(get_unique_pin_id(), name, net, type, create_group, force_name); } std::vector Module::get_pins(const std::function& filter) const @@ -1056,7 +1056,7 @@ namespace hal return nullptr; } - bool Module::set_pin_name(ModulePin* pin, const std::string& new_name) + bool Module::set_pin_name(ModulePin* pin, const std::string& new_name, bool force_name) { if (pin == nullptr) { @@ -1076,16 +1076,27 @@ namespace hal return false; } - if (m_pin_names_map.find(new_name) != m_pin_names_map.end()) + if (const auto pin_it = m_pin_names_map.find(new_name); pin_it != m_pin_names_map.end()) { - log_warning("module", - "could not set name for pin '{}' with ID {} of module '{}' with ID {}: a pin with name '{}' already exists within the module", - pin->get_name(), - pin->get_id(), - m_name, - m_id, - new_name); - return false; + if (force_name) + { + u32 ctr = 2; + while (!this->set_pin_name(pin_it->second, new_name + "__" + std::to_string(ctr) + "__")) + { + ctr++; + } + } + else + { + log_warning("module", + "could not set name for pin '{}' with ID {} of module '{}' with ID {}: a pin with name '{}' already exists within the module", + pin->get_name(), + pin->get_id(), + m_name, + m_id, + new_name); + return false; + } } if (const std::string& old_name = pin->get_name(); old_name != new_name) @@ -1122,7 +1133,7 @@ namespace hal return true; } - bool Module::set_pin_group_name(PinGroup* pin_group, const std::string& new_name) + bool Module::set_pin_group_name(PinGroup* pin_group, const std::string& new_name, bool force_name) { if (pin_group == nullptr) { @@ -1144,16 +1155,27 @@ namespace hal return false; } - if (m_pin_group_names_map.find(new_name) != m_pin_group_names_map.end()) + if (const auto pin_group_it = m_pin_group_names_map.find(new_name); pin_group_it != m_pin_group_names_map.end()) { - log_warning("module", - "could not set name for pin group '{}' with ID {} of module '{}' with ID {}: a pin group with name '{}' already exists within the module", - pin_group->get_name(), - pin_group->get_id(), - m_name, - m_id, - new_name); - return false; + if (force_name) + { + u32 ctr = 2; + while (!this->set_pin_group_name(pin_group_it->second, new_name + "__" + std::to_string(ctr) + "__")) + { + ctr++; + } + } + else + { + log_warning("module", + "could not set name for pin group '{}' with ID {} of module '{}' with ID {}: a pin group with name '{}' already exists within the module", + pin_group->get_name(), + pin_group->get_id(), + m_name, + m_id, + new_name); + return false; + } } if (const std::string& old_name = pin_group->get_name(); old_name != new_name) @@ -1224,7 +1246,8 @@ namespace hal PinType type, bool ascending, u32 start_index, - bool delete_empty_groups) + bool delete_empty_groups, + bool force_name) { if (name.empty()) { @@ -1232,7 +1255,7 @@ namespace hal } PinGroup* pin_group; - if (auto res = create_pin_group_internal(id, name, direction, type, ascending, start_index); res.is_error()) + if (auto res = create_pin_group_internal(id, name, direction, type, ascending, start_index, force_name); res.is_error()) { return ERR_APPEND(res.get_error(), "could not create pin group '" + name + "' for module '" + m_name + "' with ID " + std::to_string(m_id)); } @@ -1254,10 +1277,16 @@ namespace hal return OK(pin_group); } - Result*> - Module::create_pin_group(const std::string& name, const std::vector pins, PinDirection direction, PinType type, bool ascending, u32 start_index, bool delete_empty_groups) + Result*> Module::create_pin_group(const std::string& name, + const std::vector pins, + PinDirection direction, + PinType type, + bool ascending, + u32 start_index, + bool delete_empty_groups, + bool force_name) { - return create_pin_group(get_unique_pin_group_id(), name, pins, direction, type, ascending, start_index, delete_empty_groups); + return create_pin_group(get_unique_pin_group_id(), name, pins, direction, type, ascending, start_index, delete_empty_groups, force_name); } Result Module::delete_pin_group(PinGroup* pin_group) @@ -1508,7 +1537,7 @@ namespace hal // create pin ModulePin* pin; - if (auto res = create_pin_internal(pin_id, name_internal, net, direction, type); res.is_error()) + if (auto res = create_pin_internal(pin_id, name_internal, net, direction, type, false); res.is_error()) { return ERR_APPEND(res.get_error(), "could not assign pin '" + name_internal + "' to net: failed to create pin"); } @@ -1517,7 +1546,7 @@ namespace hal pin = res.get(); } - if (const auto group_res = create_pin_group_internal(get_unique_pin_group_id(), name_internal, pin->get_direction(), pin->get_type(), true, 0); group_res.is_error()) + if (const auto group_res = create_pin_group_internal(get_unique_pin_group_id(), name_internal, pin->get_direction(), pin->get_type(), true, 0, false); group_res.is_error()) { return ERR_APPEND(group_res.get_error(), "could not assign pin '" + name_internal + "' to net: failed to create pin group"); } @@ -1572,7 +1601,7 @@ namespace hal return OK({}); } - Result Module::create_pin_internal(const u32 id, const std::string& name, Net* net, PinDirection direction, PinType type) + Result Module::create_pin_internal(const u32 id, const std::string& name, Net* net, PinDirection direction, PinType type, bool force_name) { // some sanity checks if (id == 0) @@ -1583,9 +1612,20 @@ namespace hal { return ERR("could not create pin '" + name + "' for module '" + m_name + "' with ID " + std::to_string(m_id) + ": ID " + std::to_string(id) + " is already taken"); } - if (m_pin_names_map.find(name) != m_pin_names_map.end()) + if (const auto pin_it = m_pin_names_map.find(name); pin_it != m_pin_names_map.end()) { - return ERR("could not create pin '" + name + "' for module '" + m_name + "' with ID " + std::to_string(m_id) + ": name '" + name + "' is already taken"); + if (force_name) + { + u32 ctr = 2; + while (!this->set_pin_name(pin_it->second, name + "__" + std::to_string(ctr) + "__")) + { + ctr++; + } + } + else + { + return ERR("could not create pin '" + name + "' for module '" + m_name + "' with ID " + std::to_string(m_id) + ": name '" + name + "' is already taken"); + } } if (net == nullptr) { @@ -1640,7 +1680,7 @@ namespace hal return OK({}); } - Result*> Module::create_pin_group_internal(const u32 id, const std::string& name, PinDirection direction, PinType type, bool ascending, u32 start_index) + Result*> Module::create_pin_group_internal(const u32 id, const std::string& name, PinDirection direction, PinType type, bool ascending, u32 start_index, bool force_name) { // some sanity checks if (id == 0) @@ -1651,9 +1691,20 @@ namespace hal { return ERR("could not create pin group '" + name + "' for module '" + m_name + "' with ID " + std::to_string(m_id) + ": ID " + std::to_string(id) + " is already taken"); } - if (m_pin_group_names_map.find(name) != m_pin_group_names_map.end()) + if (const auto pin_group_it = m_pin_group_names_map.find(name); pin_group_it != m_pin_group_names_map.end()) { - return ERR("could not create pin group '" + name + "' for module '" + m_name + "' with ID " + std::to_string(m_id) + ": name '" + name + "' is already taken"); + if (force_name) + { + u32 ctr = 2; + while (!this->set_pin_group_name(pin_group_it->second, name + "__" + std::to_string(ctr) + "__")) + { + ctr++; + } + } + else + { + return ERR("could not create pin group '" + name + "' for module '" + m_name + "' with ID " + std::to_string(m_id) + ": name '" + name + "' is already taken"); + } } // create pin group diff --git a/src/python_bindings/bindings/module.cpp b/src/python_bindings/bindings/module.cpp index 101d2047fe7..59f93e59df7 100644 --- a/src/python_bindings/bindings/module.cpp +++ b/src/python_bindings/bindings/module.cpp @@ -423,8 +423,8 @@ namespace hal py_module.def( "create_pin", - [](Module& self, const u32 id, const std::string& name, Net* net, PinType type = PinType::none, bool create_group = true) -> ModulePin* { - auto res = self.create_pin(id, name, net, type, create_group); + [](Module& self, const u32 id, const std::string& name, Net* net, PinType type = PinType::none, bool create_group = true, bool force_name = false) -> ModulePin* { + auto res = self.create_pin(id, name, net, type, create_group, force_name); if (res.is_ok()) { return res.get(); @@ -440,6 +440,7 @@ namespace hal py::arg("net"), py::arg("type") = PinType::none, py::arg("create_group") = true, + py::arg("force_name") = false, R"( Manually assign a module pin to a net. Checks whether the given direction matches the actual properties of the net, i.e., checks whether the net actually is an input and/or output to the module. @@ -453,14 +454,15 @@ namespace hal :param hal_py.Net net: The net that the pin is being assigned to. :param hal_py.PinType type: The type of the pin. Defaults to ``hal_py.PinType.none``. :param bool create_group: Set ``True`` to automatically create a pin group and assign the pin, ``False`` otherwise. Defaults to ``True``. + :param bool force_name: Set ``True`` to enforce the name, ``False`` otherwise. If a pin with the same name already exists, the existing pin will be renamed. Defaults to ``False``. :returns: The module pin on success, ``None`` otherwise. :rtype: hal_py.ModulePin or None )"); py_module.def( "create_pin", - [](Module& self, const std::string& name, Net* net, PinType type = PinType::none, bool create_group = true) -> ModulePin* { - auto res = self.create_pin(name, net, type, create_group); + [](Module& self, const std::string& name, Net* net, PinType type = PinType::none, bool create_group = true, bool force_name = false) -> ModulePin* { + auto res = self.create_pin(name, net, type, create_group, force_name); if (res.is_ok()) { return res.get(); @@ -475,6 +477,7 @@ namespace hal py::arg("net"), py::arg("type") = PinType::none, py::arg("create_group") = true, + py::arg("force_name") = false, R"( Manually assign a module pin to a net. The ID of the pin is set automatically. @@ -488,6 +491,7 @@ namespace hal :param hal_py.Net net: The net that the pin is being assigned to. :param hal_py.PinType type: The type of the pin. Defaults to ``hal_py.PinType.none``. :param bool create_group: Set ``True`` to automatically create a pin group and assign the pin, ``False`` otherwise. Defaults to ``True``. + :param bool force_name: Set ``True`` to enforce the name, ``False`` otherwise. If a pin with the same name already exists, the existing pin will be renamed. Defaults to ``False``. :returns: The module pin on success, ``None`` otherwise. :rtype: hal_py.ModulePin or None )"); @@ -633,20 +637,22 @@ namespace hal :rtype: hal_py.ModulePinGroup or None )"); - py_module.def("set_pin_name", &Module::set_pin_name, py::arg("pin"), py::arg("new_name"), R"( + py_module.def("set_pin_name", &Module::set_pin_name, py::arg("pin"), py::arg("new_name"), py::arg("force_name") = false, R"( Set the name of the given pin. :param hal_py.ModulePin pin: The pin. :param str new_name: The name to be assigned to the pin. + :param bool force_name: Set ``True`` to enforce the name, ``False`` otherwise. If a pin with the same name already exists, the existing pin will be renamed. Defaults to ``False``. :returns: ``True`` on success, ``False`` otherwise. :rtype: bool )"); - py_module.def("set_pin_group_name", &Module::set_pin_group_name, py::arg("pin_group"), py::arg("new_name"), R"( + py_module.def("set_pin_group_name", &Module::set_pin_group_name, py::arg("pin_group"), py::arg("new_name"), py::arg("force_name") = false, R"( Set the name of the given pin group. :param hal_py.ModulePinGroup pin_group: The pin group. :param str new_name: The name to be assigned to the pin group. + :param bool force_name: Set ``True`` to enforce the name, ``False`` otherwise. If a pin group with the same name already exists, the existing pin group will be renamed. Defaults to ``False``. :returns: ``True`` on success, ``False`` otherwise. :rtype: bool )"); @@ -688,8 +694,9 @@ namespace hal PinType type = PinType::none, bool ascending = true, u32 start_index = 0, - bool delete_empty_groups = true) -> PinGroup* { - auto res = self.create_pin_group(id, name, pins, direction, type, ascending, start_index, delete_empty_groups); + bool delete_empty_groups = true, + bool force_name = false) -> PinGroup* { + auto res = self.create_pin_group(id, name, pins, direction, type, ascending, start_index, delete_empty_groups, force_name); if (res.is_ok()) { return res.get(); @@ -708,6 +715,7 @@ namespace hal py::arg("ascending") = true, py::arg("start_index") = 0, py::arg("delete_empty_groups") = true, + py::arg("force_name") = false, R"( Create a new pin group with the given name. All pins to be added to the pin group must have the same direction and type. @@ -720,6 +728,7 @@ namespace hal :param bool ascending: Set ``True`` for ascending pin order (from 0 to n-1), ``False`` otherwise (from n-1 to 0). Defaults to ``True``. :param int start_index: The start index of the pin group. Defaults to ``0``. :param bool delete_empty_groups: Set ``True`` to delete groups that are empty after the pins have been assigned to the new group, ``False`` to keep empty groups. Defaults to ``True``. + :param bool force_name: Set ``True`` to enforce the name, ``False`` otherwise. If a pin group with the same name already exists, the existing pin group will be renamed. Defaults to ``False``. :returns: The pin group on success, ``None`` otherwise. :rtype: hal_py.ModulePinGroup or None )"); @@ -733,8 +742,9 @@ namespace hal PinType type = PinType::none, bool ascending = true, u32 start_index = 0, - bool delete_empty_groups = true) -> PinGroup* { - auto res = self.create_pin_group(name, pins, direction, type, ascending, start_index, delete_empty_groups); + bool delete_empty_groups = true, + bool force_name = false) -> PinGroup* { + auto res = self.create_pin_group(name, pins, direction, type, ascending, start_index, delete_empty_groups, force_name); if (res.is_ok()) { return res.get(); @@ -752,6 +762,7 @@ namespace hal py::arg("ascending") = true, py::arg("start_index") = 0, py::arg("delete_empty_groups") = true, + py::arg("force_name") = false, R"( Create a new pin group with the given name. All pins to be added to the pin group must have the same direction and type. @@ -763,6 +774,7 @@ namespace hal :param bool ascending: Set ``True`` for ascending pin order (from 0 to n-1), ``False`` otherwise (from n-1 to 0). Defaults to ``True``. :param int start_index: The start index of the pin group. Defaults to ``0``. :param bool delete_empty_groups: Set `True`` to delete groups that are empty after the pins have been assigned to the new group, ``False`` to keep empty groups. Defaults to ``True``. + :param bool force_name: Set ``True`` to enforce the name, ``False`` otherwise. If a pin group with the same name already exists, the existing pin group will be renamed. Defaults to ``False``. :returns: The pin group on success, ``None`` otherwise. :rtype: hal_py.ModulePinGroup or None )");