13     Module::Module(NetlistInternalManager* internal_manager, EventHandler* event_handler, 
u32 id, Module* parent, 
const std::string& 
name)
 
   15         m_internal_manager = internal_manager;
 
   21         m_next_pin_group_id = 1;
 
   23         m_event_handler = event_handler;
 
   30             log_debug(
"module", 
"the modules with IDs {} and {} are not equal due to an unequal ID, name, or type.", m_id, other.
get_id());
 
   38             if (
const auto it = m_submodules_map.find(other_module->get_id()); it == m_submodules_map.end() || *it->second != *other_module)
 
   40                 log_debug(
"module", 
"the modules with IDs {} and {} are not equal due to an unequal submodules.", m_id, other.
get_id());
 
   47             if (
const auto it = m_gates_map.find(other_gate->get_id()); it == m_gates_map.end() || *it->second != *other_gate)
 
   49                 log_debug(
"module", 
"the modules with IDs {} and {} are not equal due to an unequal gates.", m_id, other.
get_id());
 
   56             if (
const auto other_pin_group_res = other.
get_pin_group_by_id(pin_group->get_id()); other_pin_group_res == 
nullptr || *other_pin_group_res != *pin_group)
 
   58                 log_debug(
"module", 
"the modules with IDs {} and {} are not equal due to an unequal pin group.", m_id, other.
get_id());
 
   63         if (!DataContainer::operator==(other))
 
   65             log_debug(
"module", 
"the modules with IDs {} and {} are not equal due to unequal data.", m_id, other.
get_id());
 
   79         return (uintptr_t)
this;
 
   96             log_warning(
"module", 
"module name cannot be empty.");
 
  132         std::vector<Module*> res;
 
  133         if (m_parent == 
nullptr)
 
  140             res.push_back(m_parent);
 
  144             if (filter(m_parent))
 
  146                 res.push_back(m_parent);
 
  153             res.reserve(res.size() + more.size());
 
  154             res.insert(res.end(), more.begin(), more.end());
 
  172         if (new_parent == 
this)
 
  174             log_error(
"module", 
"module '{}' with ID {} in netlist with ID {} cannot be its own parent module.", m_name, m_id, m_internal_manager->m_netlist->
get_id());
 
  178         if (m_parent == 
nullptr)
 
  180             log_error(
"module", 
"no parent module can be assigned to top module '{}' with ID {} in netlist with ID {}.", m_name, m_id, m_internal_manager->m_netlist->
get_id());
 
  184         if (new_parent == 
nullptr)
 
  186             log_error(
"module", 
"module '{}' with ID {} in netlist with ID {} cannot be assigned to be the top module.", m_name, m_id, m_internal_manager->m_netlist->
get_id());
 
  190         if (!
get_netlist()->is_module_in_netlist(new_parent))
 
  192             log_error(
"module", 
"module '{}' with ID {} is not contained in netlist with ID {}.", new_parent->
get_name(), new_parent->
get_id(), m_internal_manager->m_netlist->
get_id());
 
  197         if (std::find(children.begin(), children.end(), new_parent) != children.end())
 
  202         m_parent->m_submodules_map.erase(m_id);
 
  203         m_parent->m_submodules.erase(std::find(m_parent->m_submodules.begin(), m_parent->m_submodules.end(), 
this));
 
  205         if (m_internal_manager->m_net_checks_enabled)
 
  209                 if (
auto res = m_parent->check_net(
net, 
true); res.is_error())
 
  211                     log_error(
"module", 
"{}", res.get_error().get());
 
  218         m_parent = new_parent;
 
  220         m_parent->m_submodules_map[m_id] = 
this;
 
  221         m_parent->m_submodules.push_back(
this);
 
  223         if (m_internal_manager->m_net_checks_enabled)
 
  227                 if (
auto res = m_parent->check_net(
net, 
true); res.is_error())
 
  229                     log_error(
"module", 
"{}", res.get_error().get());
 
  246         for (
auto sm : m_submodules)
 
  252             else if (recursive && sm->is_parent_module_of(
module, 
true))
 
  263         std::vector<Module*> res;
 
  270             for (
auto sm : m_submodules)
 
  281             for (
auto sm : m_submodules)
 
  283                 auto more = sm->get_submodules(filter, 
true);
 
  284                 res.reserve(res.size() + more.size());
 
  285                 res.insert(res.end(), more.begin(), more.end());
 
  316         return m_parent == 
nullptr;
 
  321         return m_internal_manager->m_netlist;
 
  326         return m_internal_manager->module_assign_gates(
this, {gate});
 
  331         return m_internal_manager->module_assign_gates(
this, gates);
 
  341         for (
Gate* gate : gates)
 
  349         return m_internal_manager->module_assign_gates(m_internal_manager->m_netlist->
get_top_module(), gates);
 
  358         bool success = std::find(m_gates.begin(), m_gates.end(), gate) != m_gates.end();
 
  359         if (!success && recursive)
 
  361             for (
auto sm : m_submodules)
 
  363                 if (sm->contains_gate(gate, 
true))
 
  374         auto it = m_gates_map.find(gate_id);
 
  375         if (it == m_gates_map.end())
 
  379                 for (
auto sm : m_submodules)
 
  381                     auto res = sm->get_gate_by_id(gate_id, 
true);
 
  400         std::vector<Gate*> res;
 
  407             for (
auto g : m_gates)
 
  419             for (
auto sm : m_submodules)
 
  421                 auto more = sm->get_gates(filter, 
true);
 
  422                 res.reserve(res.size() + more.size());
 
  423                 res.insert(res.end(), more.begin(), more.end());
 
  439         m_input_nets.clear();
 
  440         m_output_nets.clear();
 
  441         m_internal_nets.clear();
 
  443         std::unordered_set<Net*> net_cache;
 
  446             for (
Net* 
net : gate->get_fan_in_nets())
 
  448                 net_cache.insert(
net);
 
  450             for (
Net* 
net : gate->get_fan_out_nets())
 
  452                 net_cache.insert(
net);
 
  456         for (
Net* 
net : net_cache)
 
  458             NetConnectivity con = check_net_endpoints(
net);
 
  459             if (con.has_internal_source || con.has_internal_destination)
 
  463                 if (con.has_internal_source && con.has_internal_destination)
 
  465                     m_internal_nets.insert(
net);
 
  468                 if (con.has_internal_source && con.has_internal_destination && con.has_external_source && con.has_external_destination)
 
  470                     m_input_nets.insert(
net);
 
  471                     m_output_nets.insert(
net);
 
  473                 else if (con.has_external_source && con.has_internal_destination)
 
  475                     m_input_nets.insert(
net);
 
  477                 else if (con.has_internal_source && con.has_external_destination)
 
  479                     m_output_nets.insert(
net);
 
  491         bool success = m_nets.find(
net) != m_nets.end();
 
  492         if (!success && recursive)
 
  494             for (
auto sm : m_submodules)
 
  496                 if (sm->contains_net(
net, 
true))
 
  512         std::unordered_set<Net*> res;
 
  519             for (
Net* 
n : m_nets)
 
  531             for (
auto sm : m_submodules)
 
  533                 auto more = sm->get_nets(filter, 
true);
 
  534                 res.reserve(res.size() + more.size());
 
  535                 res.insert(more.begin(), more.end());
 
  549         return m_output_nets;
 
  554         return m_internal_nets;
 
  564         return m_input_nets.find(
net) != m_input_nets.end();
 
  574         return m_output_nets.find(
net) != m_output_nets.end();
 
  584         return m_internal_nets.find(
net) != m_internal_nets.end();
 
  587     Module::NetConnectivity Module::check_net_endpoints(
const Net* 
net)
 const 
  589         std::vector<Endpoint*> sources      = 
net->get_sources();
 
  590         std::vector<Endpoint*> destinations = 
net->get_destinations();
 
  593         res.has_external_source      = 
net->is_global_input_net();
 
  594         res.has_internal_source      = 
false;
 
  595         res.has_external_destination = 
net->is_global_output_net();
 
  596         res.has_internal_destination = 
false;
 
  602                 res.has_external_source = 
true;
 
  606                 res.has_internal_source = 
true;
 
  609             if (res.has_external_source && res.has_internal_source)
 
  615         for (Endpoint* ep : destinations)
 
  617             if (Module* mod = ep->get_gate()->get_module(); 
this != mod && !
is_parent_module_of(mod, 
true))
 
  619                 res.has_external_destination = 
true;
 
  623                 res.has_internal_destination = 
true;
 
  626             if (res.has_external_destination && res.has_internal_destination)
 
  635     Result<std::monostate> Module::check_net(Net* 
net, 
bool recursive)
 
  637         NetConnectivity con = check_net_endpoints(
net);
 
  638         if (con.has_internal_source && con.has_internal_destination)
 
  640             m_internal_nets.insert(
net);
 
  644             m_internal_nets.erase(
net);
 
  647         if (con.has_internal_source || con.has_internal_destination)
 
  656         if (con.has_internal_source && con.has_internal_destination && con.has_external_source && con.has_external_destination)
 
  663                     m_output_nets.insert(
net);
 
  669                     m_input_nets.insert(
net);
 
  678                     return ERR(
"could not assign inout pin to net ID " + std::to_string(
net->get_id()) + 
": failed to create pin");
 
  682         else if (con.has_external_source && con.has_internal_destination)
 
  686                 const auto direction = pin->get_direction();
 
  689                     m_input_nets.insert(
net);
 
  690                     m_output_nets.erase(
net);
 
  697                 m_input_nets.insert(
net);
 
  700                     return ERR(
"could not assign input pin to net ID " + std::to_string(
net->get_id()) + 
": failed to create pin");
 
  704         else if (con.has_internal_source && con.has_external_destination)
 
  708                 const auto direction = pin->get_direction();
 
  711                     m_output_nets.insert(
net);
 
  712                     m_input_nets.erase(
net);
 
  719                 m_output_nets.insert(
net);
 
  722                     return ERR(
"could not assign output pin to net ID " + std::to_string(
net->get_id()) + 
": failed to create pin");
 
  733                     m_input_nets.erase(
net);
 
  737                     m_output_nets.erase(
net);
 
  739                 if (!remove_pin_net(
net))
 
  741                     return ERR(
"Remove pin net failed");
 
  746         if (m_internal_manager->m_net_checks_enabled && recursive && m_parent != 
nullptr)
 
  748             if (
auto res = m_parent->check_net(
net, 
true); res.is_error())
 
  765         if (!m_free_pin_ids.empty())
 
  767             return *(m_free_pin_ids.begin());
 
  769         while (m_used_pin_ids.find(m_next_pin_id) != m_used_pin_ids.end())
 
  773         return m_next_pin_id;
 
  778         if (!m_free_pin_group_ids.empty())
 
  780             return *(m_free_pin_group_ids.begin());
 
  782         while (m_used_pin_group_ids.find(m_next_pin_group_id) != m_used_pin_group_ids.end())
 
  784             m_next_pin_group_id++;
 
  786         return m_next_pin_group_id;
 
  793             return ERR(
"could not create pin for module '" + m_name + 
"' with ID " + std::to_string(m_id) + 
": empty string passed as name");
 
  796         if (m_internal_manager->m_net_checks_enabled)
 
  798             return ERR(
"could not create pin '" + 
name + 
"' for module '" + m_name + 
"' with ID " + std::to_string(m_id)
 
  799                        + 
": unable to manually assign pin as automatic net checks are enabled. Disable these checks using 'Netlist::enable_automatic_net_checks(false)' in case you " 
  800                          "want to manage pins manually.");
 
  805             return ERR(
"could not create pin '" + 
name + 
"' for module '" + m_name + 
"' with ID " + std::to_string(m_id) + 
": net is a 'nullptr'");
 
  812         if (is_input && is_output)
 
  826             return ERR(
"could not create pin '" + 
name + 
"' for module '" + m_name + 
"' with ID " + std::to_string(m_id) + 
": net '" + 
net->get_name() + 
"' with ID " + std::to_string(
net->get_id())
 
  827                        + 
" is neither an input nor an output");
 
  830         if (
auto pin_res = create_pin_internal(
id, 
name, 
net, 
direction, 
type, force_name); pin_res.is_error())
 
  832             return ERR_APPEND(pin_res.get_error(), 
"could not create pin '" + 
name + 
"' for module '" + m_name + 
"' with ID " + std::to_string(m_id));
 
  841                     assert(delete_pin_internal(pin_res.get()));
 
  842                     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");
 
  847                     if (!group_res.get()->assign_pin(pin_res.get()))
 
  849                         assert(delete_pin_internal(pin_res.get()));
 
  850                         assert(delete_pin_group_internal(group_res.get()));
 
  851                         return ERR(
"could not create pin '" + 
name + 
"' for module '" + m_name + 
"' with ID " + std::to_string(m_id) + 
": failed to assign pin to pin group");
 
  875         std::vector<ModulePin*> res;
 
  878             res.reserve(m_pins.size());
 
  879             for (
const auto& group : m_pin_groups_ordered)
 
  881                 std::vector<ModulePin*> 
pins = group->get_pins();
 
  882                 res.insert(res.end(), 
pins.begin(), 
pins.end());
 
  903         std::vector<std::string> res;
 
  906             res.reserve(m_pins.size());
 
  907             for (
const auto& group : m_pin_groups_ordered)
 
  909                 std::vector<ModulePin*> 
pins = group->get_pins();
 
  910                 for (
const auto pin : group->get_pins())
 
  912                     res.push_back(pin->get_name());
 
  924                         res.push_back(pin->get_name());
 
  966         std::vector<PinGroup<ModulePin>*> res;
 
  969             res.reserve(m_pin_groups_ordered.size());
 
  970             res.insert(res.end(), m_pin_groups_ordered.begin(), m_pin_groups_ordered.end());
 
  978                     res.push_back(group);
 
  989             log_warning(
"module", 
"could not get pin by ID for module '{}' with ID {}: ID 0 is invalid", m_name, m_id);
 
  993         if (
const auto it = m_pins_map.find(
id); it != m_pins_map.end())
 
  998         log_warning(
"module", 
"could not get pin by ID for module '{}' with ID {}: no pin with ID {} exists", m_name, m_id, 
id);
 
 1006             log_warning(
"module", 
"could not get pin by ID for module '{}' with ID {}: empty string provided as name", m_name, m_id);
 
 1010         if (
const auto it = m_pin_names_map.find(
name); it != m_pin_names_map.end())
 
 1015         log_warning(
"module", 
"could not get pin by ID for module '{}' with ID {}: no pin with name '{}' exists", m_name, m_id, 
name);
 
 1023             log_warning(
"module", 
"could not get pin by net for module '{}' with ID {}: net is a 'nullptr'", m_name, m_id);
 
 1027         if (
const auto it = std::find_if(m_pins.begin(), m_pins.end(), [
net](
const std::unique_ptr<ModulePin>& pin) { return pin->get_net() == net; }); it != m_pins.end())
 
 1032         log_debug(
"module", 
"could not get pin by net for module '{}' with ID {}: no pin belongs to net '{}' with ID {}", m_name, m_id, 
net->get_name(), 
net->get_id());
 
 1040             log_warning(
"module", 
"could not get pin group by ID for module '{}' with ID {}: ID 0 is invalid", m_name, m_id);
 
 1044         if (
const auto it = m_pin_groups_map.find(
id); it != m_pin_groups_map.end())
 
 1049         log_warning(
"module", 
"could not get pin group by ID for module '{}' with ID {}: no pin group with ID {} exists", m_name, m_id, 
id);
 
 1057             log_warning(
"module", 
"could not get pin group by name for module '{}' with ID {}: empty string provided as name", m_name, m_id);
 
 1061         if (
const auto it = m_pin_group_names_map.find(
name); it != m_pin_group_names_map.end())
 
 1066         log_warning(
"module", 
"could not get pin group by name for module '{}' with ID {}: no pin group with name '{}' exists", m_name, m_id, 
name);
 
 1074             log_warning(
"module", 
"could not set name for pin of module '{}' with ID {}: pin is a 'nullptr'", m_name, m_id);
 
 1078         if (new_name.empty())
 
 1080             log_warning(
"module", 
"could not set name for pin '{}' with ID {} of module '{}' with ID {}: empty string passed as new name", pin->
get_name(), pin->
get_id(), m_name, m_id);
 
 1084         if (
const auto it = m_pins_map.find(pin->
get_id()); it == m_pins_map.end() || it->second != pin)
 
 1086             log_warning(
"module", 
"could not set name for pin '{}' with ID {} of module '{}' with ID {}: pin does not belong to module", pin->
get_name(), pin->
get_id(), m_name, m_id);
 
 1090         if (
const auto pin_it = m_pin_names_map.find(new_name); pin_it != m_pin_names_map.end())
 
 1095                 while (!this->
set_pin_name(pin_it->second, new_name + 
"__" + std::to_string(ctr) + 
"__"))
 
 1103                             "could not set name for pin '{}' with ID {} of module '{}' with ID {}: a pin with name '{}' already exists within the module",
 
 1113         if (
const std::string& old_name = pin->
get_name(); old_name != new_name)
 
 1115             m_pin_names_map.erase(old_name);
 
 1117             m_pin_names_map[new_name] = pin;
 
 1128             log_warning(
"module", 
"could not set type for pin of module '{}' with ID {}: pin is a 'nullptr'", m_name, m_id);
 
 1132         if (
const auto it = m_pins_map.find(pin->
get_id()); it == m_pins_map.end() || it->second != pin)
 
 1134             log_warning(
"module", 
"could not set type for pin '{}' with ID {} of module '{}' with ID {}: pin does not belong to module", pin->
get_name(), pin->
get_id(), m_name, m_id);
 
 1149         if (pin_group == 
nullptr)
 
 1151             log_warning(
"module", 
"could not set name for pin group of module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id);
 
 1155         if (new_name.empty())
 
 1158                 "module", 
"could not set name for pin group '{}' with ID {} of module '{}' with ID {}: empty string passed as new name", pin_group->
get_name(), pin_group->
get_id(), m_name, m_id);
 
 1162         if (
const auto it = m_pin_groups_map.find(pin_group->
get_id()); it == m_pin_groups_map.end() || it->second != pin_group)
 
 1165                 "module", 
"could not set name for pin group '{}' with ID {} of module '{}' with ID {}: pin group does not belong to module", pin_group->
get_name(), pin_group->
get_id(), m_name, m_id);
 
 1169         if (
const auto pin_group_it = m_pin_group_names_map.find(new_name); pin_group_it != m_pin_group_names_map.end())
 
 1174                 while (!this->
set_pin_group_name(pin_group_it->second, new_name + 
"__" + std::to_string(ctr) + 
"__"))
 
 1182                             "could not set name for pin group '{}' with ID {} of module '{}' with ID {}: a pin group with name '{}' already exists within the module",
 
 1192         if (
const std::string& old_name = pin_group->
get_name(); old_name != new_name)
 
 1194             m_pin_group_names_map.erase(old_name);
 
 1196             m_pin_group_names_map[new_name] = pin_group;
 
 1205         if (pin_group == 
nullptr)
 
 1207             log_warning(
"module", 
"could not set type for pin group of module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id);
 
 1211         if (
const auto it = m_pin_groups_map.find(pin_group->
get_id()); it == m_pin_groups_map.end() || it->second != pin_group)
 
 1214                 "module", 
"could not set type for pin group '{}' with ID {} of module '{}' with ID {}: pin group does not belong to module", pin_group->
get_name(), pin_group->
get_id(), m_name, m_id);
 
 1218         if (pin_group->
get_type() != new_type)
 
 1228         if (pin_group == 
nullptr)
 
 1230             log_warning(
"module", 
"could not set direction for pin group of module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id);
 
 1234         if (
const auto it = m_pin_groups_map.find(pin_group->
get_id()); it == m_pin_groups_map.end() || it->second != pin_group)
 
 1237                         "could not set direction for pin group '{}' with ID {} of module '{}' with ID {}: pin group does not belong to module",
 
 1254                                                           const std::string& 
name,
 
 1255                                                           const std::vector<ModulePin*> 
pins,
 
 1260                                                           bool delete_empty_groups,
 
 1267             return ERR(
"could not create pin group for module '" + m_name + 
"' with ID " + std::to_string(m_id) + 
": empty string passed as name");
 
 1279             return ERR_APPEND(res.get_error(), 
"could not create pin group '" + 
name + 
"' for module '" + m_name + 
"' with ID " + std::to_string(m_id));
 
 1283             pin_group = res.get();
 
 1288             for (
auto it = 
pins.begin(); it != 
pins.end(); ++it)
 
 1293                     return ERR(
"Assign pin to group failed.");
 
 1299             for (
auto it = 
pins.rbegin(); it != 
pins.rend(); ++it)
 
 1304                     return ERR(
"Assign pin to group failed.");
 
 1311         return OK(pin_group);
 
 1315                                                           const std::vector<ModulePin*> 
pins,
 
 1320                                                           bool delete_empty_groups,
 
 1329         if (pin_group == 
nullptr)
 
 1331             log_warning(
"module", 
"could not delete pin group from module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id);
 
 1335         if (
const auto it = m_pin_groups_map.find(pin_group->
get_id()); it == m_pin_groups_map.end() || it->second != pin_group)
 
 1338                 "module", 
"could not delete pin group '{}' with ID {} from module '{}' with ID {}: pin group does not belong to module", pin_group->
get_name(), pin_group->
get_id(), m_name, m_id);
 
 1342         std::vector<ModulePin*> pins_copy = pin_group->
get_pins();
 
 1345             auto res = 
create_pin_group(pin->get_name(), {pin}, pin->get_direction(), pin->get_type(), 
true, 0, 
false);
 
 1354         u32 pin_group_id_to_delete = pin_group->
get_id();
 
 1356         if (!delete_pin_group_internal(pin_group))
 
 1368         if (pin_group == 
nullptr)
 
 1370             log_warning(
"module", 
"could not move pin group of module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id);
 
 1374         if (
const auto it = m_pin_groups_map.find(pin_group->
get_id()); it == m_pin_groups_map.end() || it->second != pin_group)
 
 1377                 "module", 
"could not move pin group '{}' with ID {} within module '{}' with ID {}: pin group does not belong to module", pin_group->
get_name(), pin_group->
get_id(), m_name, m_id);
 
 1381         if (new_index >= m_pin_groups_ordered.size())
 
 1383             log_warning(
"module", 
"could not move pin group '{}' with ID {} of module '{}' with ID {}: index {} is out of bounds", pin_group->
get_name(), pin_group->
get_id(), m_name, m_id, new_index);
 
 1387         auto src_it = std::find(m_pin_groups_ordered.begin(), m_pin_groups_ordered.end(), pin_group);
 
 1388         auto dst_it = m_pin_groups_ordered.begin();
 
 1389         std::advance(dst_it, new_index);
 
 1390         if (src_it == dst_it)
 
 1394         else if (std::distance(m_pin_groups_ordered.begin(), src_it) < std::distance(m_pin_groups_ordered.begin(), dst_it))
 
 1396             std::advance(dst_it, 1);
 
 1397             m_pin_groups_ordered.splice(dst_it, m_pin_groups_ordered, src_it);
 
 1401             m_pin_groups_ordered.splice(dst_it, m_pin_groups_ordered, src_it);
 
 1412         if (pin_group == 
nullptr)
 
 1414             log_warning(
"module", 
"could not assign pin to pin group of module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id);
 
 1420             log_warning(
"module", 
"could not assign pin to pin group '{}' with ID {} of module '{}' with ID {}: pin is a 'nullptr'", pin_group->
get_name(), pin_group->
get_id(), m_name, m_id);
 
 1424         if (
const auto it = m_pin_groups_map.find(pin_group->
get_id()); it == m_pin_groups_map.end() || it->second != pin_group)
 
 1427                         "could not assign pin '{}' with ID {} to pin group '{}' with ID {} of module '{}' with ID {}: pin group does not belong to module",
 
 1437         if (
const auto it = m_pins_map.find(pin->
get_id()); it == m_pins_map.end() || it->second != pin)
 
 1440                         "could not assign pin '{}' with ID {} to pin group '{}' with ID {} of module '{}' with ID {}: pin does not belong to module",
 
 1458             if (!pg->remove_pin(pin))
 
 1461                             "could not assign pin '{}' with ID {} to pin group '{}' with ID {} of module '{}' with ID {}: unable to remove pin from pin group '{}' with ID {}",
 
 1473             if (delete_empty_groups && pg->empty())
 
 1476                 if (!delete_pin_group_internal(pg))
 
 1479                                 "could not assign pin '{}' with ID {} to pin group '{}' with ID {} of module '{}' with ID {}: unable to delete pin group '{}' with ID {}",
 
 1496                         "could not assign pin '{}' with ID {} to pin group '{}' with ID {} of module '{}' with ID {}",
 
 1514         if (pin_group == 
nullptr)
 
 1516             log_warning(
"module", 
"could not move pin within pin group of module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id);
 
 1522             log_warning(
"module", 
"could not move pin within pin group '{}' with ID {} of module '{}' with ID {}: pin is a 'nullptr'", pin_group->
get_name(), pin_group->
get_id(), m_name, m_id);
 
 1526         if (
const auto it = m_pin_groups_map.find(pin_group->
get_id()); it == m_pin_groups_map.end() || it->second != pin_group)
 
 1529                         "could not move pin '{}' with ID {} within pin group '{}' with ID {} of module '{}' with ID {}: pin group does not belong to module",
 
 1539         if (
const auto it = m_pins_map.find(pin->
get_id()); it == m_pins_map.end() || it->second != pin)
 
 1542                         "could not move pin '{}' with ID {} within pin group '{}' with return ERRID {} of module '{}' with ID {}: pin does not belong to module",
 
 1552         if (
auto res = pin_group->
move_pin(pin, new_index); res.is_error())
 
 1555                         "could not move pin '{}' with ID {} within pin group '{}' with ID {} of module '{}' with ID {}",
 
 1571         if (pin_group == 
nullptr)
 
 1573             log_warning(
"module", 
"could not remove pin from pin group of module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id);
 
 1579             log_warning(
"module", 
"could not remove pin from pin group '{}' with ID {} of module '{}' with ID {}: pin is a 'nullptr'", pin_group->
get_name(), pin_group->
get_id(), m_name, m_id);
 
 1583         if (
const auto it = m_pin_groups_map.find(pin_group->
get_id()); it == m_pin_groups_map.end() || it->second != pin_group)
 
 1586                         "could not remove pin '{}' with ID {} from pin group '{}' with ID {} of module '{}' with ID {}: pin group does not belong to module",
 
 1596         if (
const auto it = m_pins_map.find(pin->
get_id()); it == m_pins_map.end() || it->second != pin)
 
 1599                         "could not remove pin '{}' with ID {} from pin group '{}' with ID {} of module '{}' with ID {}: pin does not belong to module",
 
 1612                         "could not remove pin '{}' with ID {} from pin group '{}' with ID {} of module '{}' with ID : unable to create new pin group for pin",
 
 1628         std::string port_prefix;
 
 1646         std::string name_internal;
 
 1649             name_internal = port_prefix + 
"(" + std::to_string(ctr) + 
")";
 
 1651         } 
while (m_pin_names_map.find(name_internal) != m_pin_names_map.end() || m_pin_group_names_map.find(name_internal) != m_pin_group_names_map.end());
 
 1657             log_warning(
"module", 
"could not assign pin '{}' to net: failed to create pin", name_internal);
 
 1666         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())
 
 1668             log_warning(
"module", 
"could not assign pin '{}' to net: failed to create pin group", name_internal);
 
 1674             if (!group_res.get()->assign_pin(pin))
 
 1676                 log_warning(
"module", 
"could not assign pin '{}' to net: failed to assign pin to pin group", name_internal);
 
 1685         scope.send_events();
 
 1689     bool Module::remove_pin_net(Net* 
net)
 
 1691         PinChangedEventScope scope(
this);
 
 1695             log_warning(
"module", 
"could not remove pin from net: failed to get pin corresponding to net");
 
 1699         PinGroup<ModulePin>* pin_group = pin->get_group().first;
 
 1700         assert(pin_group != 
nullptr);
 
 1702         if (!pin_group->remove_pin(pin))
 
 1705                         "could not remove pin '{}' with ID {} from net '{}' with ID {}: failed to remove pin from pin group '{}' with ID {}",
 
 1710                         pin_group->get_name(),
 
 1711                         pin_group->get_id());
 
 1715         if (pin_group->empty())
 
 1718             if (!delete_pin_group_internal(pin_group))
 
 1721                             "could not remove pin '{}' with ID {} from net '{}' with ID {}: failed to delete pin group '{}' with ID {}",
 
 1726                             pin_group->get_name(),
 
 1727                             pin_group->get_id());
 
 1732         u32 pin_id_to_delete = pin->get_id();
 
 1734         if (!delete_pin_internal(pin))
 
 1737                         "could not remove pin '{}' with ID {} from net '{}' with ID {}: failed to delete pin '{}' with ID {}",
 
 1748         scope.send_events();
 
 1757             return ERR(
"could not create pin '" + 
name + 
"' for module '" + m_name + 
"' with ID " + std::to_string(m_id) + 
": ID 0 is invalid");
 
 1759         if (m_used_pin_ids.find(
id) != m_used_pin_ids.end())
 
 1761             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");
 
 1763         if (
const auto pin_it = m_pin_names_map.find(
name); pin_it != m_pin_names_map.end())
 
 1768                 while (!this->
set_pin_name(pin_it->second, 
name + 
"__" + std::to_string(ctr) + 
"__"))
 
 1775                 return ERR(
"could not create pin '" + 
name + 
"' for module '" + m_name + 
"' with ID " + std::to_string(m_id) + 
": name '" + 
name + 
"' is already taken");
 
 1780             return ERR(
"could not create pin '" + 
name + 
"' for gate type '" + m_name + 
"' with ID " + std::to_string(m_id) + 
": net is a 'nullptr'");
 
 1784             return ERR(
"could not create pin '" + 
name + 
"' for module '" + m_name + 
"' with " + std::to_string(m_id) + 
": direction '" + 
enum_to_string(
direction) + 
"' is invalid");
 
 1789         ModulePin* pin = pin_owner.get();
 
 1790         m_pins.push_back(std::move(pin_owner));
 
 1791         m_pins_map[
id]        = pin;
 
 1792         m_pin_names_map[
name] = pin;
 
 1795         if (
auto free_id_it = m_free_pin_ids.find(
id); free_id_it != m_free_pin_ids.end())
 
 1797             m_free_pin_ids.erase(free_id_it);
 
 1799         m_used_pin_ids.insert(
id);
 
 1804     bool Module::delete_pin_internal(ModulePin* pin)
 
 1809             log_warning(
"module", 
"could not delete pin of gate type '{}' with ID {}: pin is a 'nullptr'", m_name, m_id);
 
 1812         if (
const auto it = m_pins_map.find(pin->get_id()); it == m_pins_map.end() || it->second != pin)
 
 1814             log_warning(
"module", 
"could not delete pin '{}' with ID {} of module '{}' with ID {}: pin does not belong to module", pin->get_name(), pin->get_id(), m_name, m_id);
 
 1819         u32 del_id                  = pin->get_id();
 
 1820         const std::string& del_name = pin->get_name();
 
 1821         m_pins_map.erase(del_id);
 
 1822         m_pin_names_map.erase(del_name);
 
 1823         m_pins.erase(std::find_if(m_pins.begin(), m_pins.end(), [pin](
const auto& p) { return p.get() == pin; }));
 
 1826         m_free_pin_ids.insert(del_id);
 
 1827         m_used_pin_ids.erase(del_id);
 
 1837             return ERR(
"could not create pin group '" + 
name + 
"' for module '" + m_name + 
"' with ID " + std::to_string(m_id) + 
": ID 0 is invalid");
 
 1839         if (m_used_pin_group_ids.find(
id) != m_used_pin_group_ids.end())
 
 1841             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");
 
 1843         if (
const auto pin_group_it = m_pin_group_names_map.find(
name); pin_group_it != m_pin_group_names_map.end())
 
 1856                 return ERR(
"could not create pin group '" + 
name + 
"' for module '" + m_name + 
"' with ID " + std::to_string(m_id) + 
": name '" + 
name + 
"' is already taken");
 
 1862         m_pin_groups.push_back(std::move(pin_group_owner));
 
 1863         PinGroup<ModulePin>* pin_group = m_pin_groups.back().get();
 
 1864         m_pin_groups_ordered.push_back(pin_group);
 
 1865         m_pin_groups_map[
id]        = pin_group;
 
 1866         m_pin_group_names_map[
name] = pin_group;
 
 1869         if (
auto free_id_it = m_free_pin_group_ids.find(
id); free_id_it != m_free_pin_group_ids.end())
 
 1871             m_free_pin_group_ids.erase(free_id_it);
 
 1873         m_used_pin_group_ids.insert(
id);
 
 1875         return OK(pin_group);
 
 1878     bool Module::delete_pin_group_internal(PinGroup<ModulePin>* pin_group)
 
 1881         if (pin_group == 
nullptr)
 
 1883             log_warning(
"module", 
"could not delete pin group of module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id);
 
 1886         if (
const auto it = m_pin_groups_map.find(pin_group->get_id()); it == m_pin_groups_map.end() || it->second != pin_group)
 
 1889                 "module", 
"could not delete pin group '{}' with ID {} of module '{}' with ID {}: pin group does not belong to module", pin_group->get_name(), pin_group->get_id(), m_name, m_id);
 
 1894         u32 del_id                  = pin_group->get_id();
 
 1895         const std::string& del_name = pin_group->get_name();
 
 1896         m_pin_groups_map.erase(del_id);
 
 1897         m_pin_group_names_map.erase(del_name);
 
 1898         m_pin_groups_ordered.erase(std::find(m_pin_groups_ordered.begin(), m_pin_groups_ordered.end(), pin_group));
 
 1899         m_pin_groups.erase(std::find_if(m_pin_groups.begin(), m_pin_groups.end(), [pin_group](
const auto& pg) { return pg.get() == pin_group; }));
 
 1902         m_free_pin_group_ids.insert(del_id);
 
 1903         m_used_pin_group_ids.erase(del_id);
 
 1910         return m_event_handler;
 
void set_name(const std::string &name)
 
const std::string & get_name() const
 
void set_type(PinType type)
 
const std::pair< PinGroup< T > *, i32 > & get_group() const
 
PinDirection get_direction() const
 
NETLIST_API void notify(NetlistEvent::event ev, Netlist *netlist, u32 associated_data=0xFFFFFFFF)
 
@ submodule_removed
associated_data = id of removed module
 
@ type_changed
no associated_data
 
@ submodule_added
associated_data = id of added module
 
@ parent_changed
no associated_data
 
@ name_changed
no associated_data
 
bool is_input_net(Net *net) const
 
void set_name(const std::string &name)
 
const std::unordered_set< Net * > & get_nets() const
 
std::vector< std::string > get_pin_names(const std::function< bool(ModulePin *)> &filter=nullptr) const
 
PinGroup< ModulePin > * get_pin_group_by_name(const std::string &name) const
 
bool move_pin_within_group(PinGroup< ModulePin > *pin_group, ModulePin *pin, u32 new_index)
 
Module * get_parent_module() const
 
bool is_parent_module_of(const Module *module, bool recursive=false) const
 
std::vector< ModulePin * > get_output_pins() const
 
bool set_parent_module(Module *new_parent)
 
bool remove_gate(Gate *gate)
 
std::vector< ModulePin * > get_pins(const std::function< bool(ModulePin *)> &filter=nullptr) const
 
std::vector< ModulePin * > get_input_pins() const
 
bool assign_gates(const std::vector< Gate * > &gates)
 
bool contains_net(Net *net, bool recursive=false) const
 
bool operator==(const Module &other) const
 
Gate * get_gate_by_id(const u32 id, bool recursive=false) const
 
const std::unordered_set< Net * > & get_internal_nets() const
 
ModulePin * get_pin_by_name(const std::string &name) const
 
bool assign_pin_to_group(PinGroup< ModulePin > *pin_group, ModulePin *pin, bool delete_empty_groups=true)
 
int get_submodule_depth() const
 
bool remove_pin_from_group(PinGroup< ModulePin > *pin_group, ModulePin *pin, bool delete_empty_groups=true)
 
bool is_top_module() const
 
bool remove_gates(const std::vector< Gate * > &gates)
 
ModulePin * get_pin_by_id(const u32 id) const
 
bool set_pin_group_type(PinGroup< ModulePin > *pin_group, PinType new_type)
 
bool set_pin_type(ModulePin *pin, PinType new_type)
 
bool assign_gate(Gate *gate)
 
bool is_output_net(Net *net) const
 
bool delete_pin_group(PinGroup< ModulePin > *pin_group)
 
const std::vector< Gate * > & get_gates() const
 
bool move_pin_group(PinGroup< ModulePin > *pin_group, u32 new_index)
 
bool set_pin_name(ModulePin *pin, const std::string &new_name, bool force_name=false)
 
std::string get_name() const
 
Grouping * get_grouping() const
 
const std::unordered_set< Net * > & get_input_nets() const
 
std::vector< std::string > get_input_pin_names() const
 
bool set_pin_group_direction(PinGroup< ModulePin > *pin_group, PinDirection new_direction)
 
void set_type(const std::string &type)
 
bool contains_module(const Module *other, bool recursive=false) const
 
Result< PinGroup< ModulePin > * > create_pin_group(const u32 id, const std::string &name, const std::vector< ModulePin * > pins={}, PinDirection direction=PinDirection::none, PinType type=PinType::none, bool ascending=true, u32 start_index=0, bool delete_empty_groups=true, bool force_name=false)
 
bool operator!=(const Module &other) const
 
std::vector< Module * > get_parent_modules(const std::function< bool(Module *)> &filter=nullptr, bool recursive=true) const
 
Netlist * get_netlist() const
 
ModulePin * get_pin_by_net(Net *net) const
 
bool set_pin_group_name(PinGroup< ModulePin > *pin_group, const std::string &new_name, bool force_name=false)
 
EventHandler * get_event_handler() const
 
std::vector< PinGroup< ModulePin > * > get_pin_groups(const std::function< bool(PinGroup< ModulePin > *)> &filter=nullptr) const
 
Result< ModulePin * > create_pin(const u32 id, const std::string &name, Net *net, PinType type=PinType::none, bool create_group=true, bool force_name=false)
 
PinGroup< ModulePin > * get_pin_group_by_id(const u32 id) const
 
std::vector< Module * > get_submodules(const std::function< bool(Module *)> &filter=nullptr, bool recursive=false) const
 
std::vector< std::string > get_output_pin_names() const
 
bool contains_gate(Gate *gate, bool recursive=false) const
 
std::string get_type() const
 
bool is_internal_net(Net *net) const
 
bool is_submodule_of(const Module *module, bool recursive=false) const
 
const std::unordered_set< Net * > & get_output_nets() const
 
u32 get_unique_pin_group_id()
 
Module * get_top_module() const
 
std::vector< T * > get_pins(const std::function< bool(T *)> &filter=nullptr) const
 
Result< std::monostate > move_pin(T *pin, i32 new_index)
 
void set_direction(PinDirection direction)
 
bool contains_pin(T *pin)
 
const std::string & get_name() const
 
void set_name(const std::string &name)
 
PinDirection get_direction() const
 
void set_type(PinType type)
 
#define log_error(channel,...)
 
#define log_debug(channel,...)
 
#define log_warning(channel,...)
 
#define ERR_APPEND(prev_error, message)
 
const Module * module(const Gate *g, const NodeBoxes &boxes)
 
CORE_API T trim(const T &s, const char *to_remove=" \t\r\n")
 
@ PinTypeChange
pin renamed
 
@ GroupReorder
changed PinDirection attribute of group (like input)
 
@ PinCreate
moved group to a new position within containing module
 
@ GroupTypeChange
pin group renamed
 
@ PinRename
pin assigned to new group
 
@ PinAssignToGroup
new pin created
 
@ PinDelete
moved pin to a new position within containing group
 
@ GroupRename
new pin group created
 
@ PinReorder
changed PinDirection attribute of pin (like input)
 
std::string enum_to_string(T e)
 
std::vector< PinInformation > pins