diff --git a/CHANGELOG.md b/CHANGELOG.md index ac0e1def95b..384569c1762 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,11 @@ All notable changes to this project will be documented in this file. * boosted performance by using classes with faster memory access * removed layouter code used prior to version 3.1.0 - thus removing the setting option to use that code * added setting option to dump junction layout input data for experts to debug in case of layout errors +* 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 + * added class `ActionPingroup` so that UNDO function works for all pin / pin group actions issued from GUI * miscellaneous * added INIT field declaration to FF-gate-types in example library * added drag'n drop feature allowing to move several nodes in graph view at same time diff --git a/include/hal_core/netlist/event_system/event_handler.h b/include/hal_core/netlist/event_system/event_handler.h index 06c6b13372c..58570fdd81d 100644 --- a/include/hal_core/netlist/event_system/event_handler.h +++ b/include/hal_core/netlist/event_system/event_handler.h @@ -114,7 +114,7 @@ namespace hal gates_remove_begin, ///< associated_data = number of gates to remove gates_remove_end, ///< associated_data = number of removed gates gate_removed, ///< associated_data = id of removed gate - pin_changed, ///< no associated_data + pin_changed, ///< associated_data = [4LSB: type of action] [28HSB: id of pin group or pin] }; }; diff --git a/include/hal_core/netlist/gate_library/enums/pin_event.h b/include/hal_core/netlist/gate_library/enums/pin_event.h new file mode 100644 index 00000000000..7f4b6daf3c8 --- /dev/null +++ b/include/hal_core/netlist/gate_library/enums/pin_event.h @@ -0,0 +1,166 @@ +// MIT License +// +// Copyright (c) 2019 Ruhr University Bochum, Chair for Embedded Security. All Rights reserved. +// Copyright (c) 2019 Marc Fyrbiak, Sebastian Wallat, Max Hoffmann ("ORIGINAL AUTHORS"). All rights reserved. +// Copyright (c) 2021 Max Planck Institute for Security and Privacy. All Rights reserved. +// Copyright (c) 2021 Jörn Langheinrich, Julian Speith, Nils Albartus, René Walendy, Simon Klix ("ORIGINAL AUTHORS"). All Rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "hal_core/utilities/enums.h" +#include "hal_core/defines.h" +#include +#include + +namespace hal +{ + /** + * Spezifies the pin_changed event type + * + * The order of events in enum class defines the order in which events are handled. + * + */ + enum class PinEvent + { + unknown, + GroupCreate, /// new pin group created + GroupRename, /// pin group renamed + GroupTypeChange, /// changed PinType attribute of group (like data) + GroupDirChange, /// changed PinDirection attribute of group (like input) + GroupReorder, /// moved group to a new position within containing module + PinCreate, /// new pin created + PinAssignToGroup, /// pin assigned to new group + PinRename, /// pin renamed + PinTypeChange, /// changed PinType attribute of pin (like data) + PinDirChange, /// changed PinDirection attribute of pin (like input) + PinReorder, /// moved pin to a new position within containing group + PinDelete, /// pin deleted + GroupDelete /// group deleted + }; + + template<> + std::map EnumStrings::data; + + class Module; + + /** + * Wrapper class for core pin_changed events. + * + * Events can be send immediately or stacked and send at according to their priority. + */ + class PinChangedEvent + { + friend bool pin_event_order(const PinChangedEvent& a, const PinChangedEvent& b); + friend class PinChangedEventScope; + + /** + * Subclass for event stack. + */ + class EventStack : public std::vector + { + public: + /** + * Scope count indicates the nesting depth of event-throwing subroutines. + * Only the top level (m_count=0) is allowed to send the events from stack. + */ + int m_count; + + /** + * Construct empty stack + */ + EventStack() : m_count(0) {;} + + /** + * Attempts to send events, typically at the end of a pin-changing subroutine. + * Events will only be send if m_count is zero. + */ + void send_events(Module* m); + }; + + static std::unordered_map s_event_stack; + + Module* m_module; + PinEvent m_event; + u32 m_id; + + public: + /** + * PinChangedEvent class for single event + * @param m - The module comprising pins and pin groups + * @param pev - The pin event enum + * @param id - pin or pin group ID + */ + PinChangedEvent(Module* m, PinEvent pev, u32 id); + + /** + * Returns the module for which pins or pin groups have been changed + * @return The module comprising pins and pin groups + */ + Module* get_module() const; + + /** + * Return bitwise binary encoded PinEvent and ID + * 4LSB = The pin event enum as 4 bit int + * 28HSB = The ID as 28 bit int + * @return The bitcode according to scheme above + */ + u32 associated_data(); + + /** + * Attempts to send event. + * If this routine or any calling routine wants to collect events the event gets written on stack instead. + */ + void send(); + }; + + /** + * By creating an instance of this class a new scope gets created thus collecting events. + */ + class PinChangedEventScope + { + Module* m_module; + public: + + /** + * Constructor for scope instance incrementing scope count + * @param m The module comprising pins and pin groups + */ + PinChangedEventScope(Module* m); + + /** + * Destructor for scope instance decrementing scope count + */ + ~PinChangedEventScope(); + + /** + * Attempts to send all stacked events. Will do nothing if not issued from top-level scope. + */ + void send_events(); + }; + + /** + * Function used by sort algorithm to organize events according to their priority. + * @param a - Pin changed event A + * @param b - Pin changed event B + * @return true if A should be handled before B, false otherwise. + */ + bool pin_event_order(const PinChangedEvent& a, const PinChangedEvent& b); +} diff --git a/include/hal_core/netlist/gate_library/enums/pin_type.h b/include/hal_core/netlist/gate_library/enums/pin_type.h index 295e7d0acbc..b8a35ef1a03 100644 --- a/include/hal_core/netlist/gate_library/enums/pin_type.h +++ b/include/hal_core/netlist/gate_library/enums/pin_type.h @@ -54,4 +54,5 @@ namespace hal template<> std::map EnumStrings::data; -} // namespace hal \ No newline at end of file + +} // namespace hal diff --git a/include/hal_core/netlist/gate_library/gate_type.h b/include/hal_core/netlist/gate_library/gate_type.h index 34399a46661..17fcdf81893 100644 --- a/include/hal_core/netlist/gate_library/gate_type.h +++ b/include/hal_core/netlist/gate_library/gate_type.h @@ -354,9 +354,9 @@ namespace hal * Delete the given pin group. * * @param[in] pin_group - The pin group to be deleted. - * @returns Ok on success, an error message otherwise. + * @returns true on success, false otherwise. */ - Result delete_pin_group(PinGroup* pin_group); + bool delete_pin_group(PinGroup* pin_group); /** * Assign a pin to a pin group. @@ -469,6 +469,6 @@ namespace hal GateType& operator=(const GateType&) = delete; Result*> create_pin_group_internal(const u32 id, const std::string& name, PinDirection direction, PinType type, bool ascending, u32 start_index); - Result delete_pin_group_internal(PinGroup* pin_group); + bool delete_pin_group_internal(PinGroup* pin_group); }; } // namespace hal diff --git a/include/hal_core/netlist/module.h b/include/hal_core/netlist/module.h index a785ef1eacf..0cccca0441e 100644 --- a/include/hal_core/netlist/module.h +++ b/include/hal_core/netlist/module.h @@ -30,6 +30,7 @@ #include "hal_core/netlist/event_system/event_handler.h" #include "hal_core/netlist/gate_library/enums/pin_direction.h" #include "hal_core/netlist/gate_library/enums/pin_type.h" +#include "hal_core/netlist/gate_library/enums/pin_event.h" #include "hal_core/netlist/gate_library/gate_library.h" #include "hal_core/netlist/pins/module_pin.h" #include "hal_core/netlist/pins/pin_group.h" @@ -526,9 +527,9 @@ namespace hal * Delete the given pin group. * * @param[in] pin_group - The pin group to be deleted. - * @returns Ok on success, an error message otherwise. + * @returns true on success, false otherwise. */ - Result delete_pin_group(PinGroup* pin_group); + bool delete_pin_group(PinGroup* pin_group); /** * Move a pin group to another index within the module. @@ -536,9 +537,9 @@ namespace hal * * @param[in] pin_group - The pin group to be moved. * @param[in] new_index - The index to which the pin group is moved. - * @returns Ok on success, an error message otherwise. + * @returns true on success, false message otherwise. */ - Result move_pin_group(PinGroup* pin_group, u32 new_index); + bool move_pin_group(PinGroup* pin_group, u32 new_index); /** * Set the name of the given pin group. @@ -574,9 +575,9 @@ namespace hal * @param[in] pin_group - The new pin group. * @param[in] pin - The pin to be added. * @param[in] delete_empty_groups - Set `true` to delete groups that are empty after the pin has been assigned to the new group, `false` to keep empty groups. Defaults to `true`. - * @returns Ok on success, an error message otherwise. + * @returns `true` on success, `false` otherwise. */ - Result assign_pin_to_group(PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups = true); + bool assign_pin_to_group(PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups = true); /** * Move a pin to another index within the given pin group. @@ -585,9 +586,9 @@ namespace hal * @param[in] pin_group - The pin group. * @param[in] pin - The pin to be moved. * @param[in] new_index - The index to which the pin is moved. - * @returns Ok on success, an error message otherwise. + * @returns `true` on success, `false` otherwise. */ - Result move_pin_within_group(PinGroup* pin_group, ModulePin* pin, u32 new_index); + bool move_pin_within_group(PinGroup* pin_group, ModulePin* pin, u32 new_index); /** * Remove a pin from a pin group. @@ -596,9 +597,9 @@ namespace hal * @param[in] pin_group - The old pin group. * @param[in] pin - The pin to be removed. * @param[in] delete_empty_groups - Set `true` to delete the group of it is empty after the pin has been removed, `false` to keep the empty group. Defaults to `true`. - * @returns Ok on success, an error message otherwise. + * @returns `true` on success, `false` otherwise. */ - Result remove_pin_from_group(PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups = true); + bool remove_pin_from_group(PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups = true); /* * ################################################################ @@ -680,6 +681,12 @@ namespace hal */ std::vector get_gates(const std::function& filter, bool recursive = false) const; + /** + * Get the event handler connected to module + * @return The event handler; + */ + EventHandler* get_event_handler() const; + private: friend class NetlistInternalManager; Module(NetlistInternalManager* internal_manager, EventHandler* event_handler, u32 id, Module* parent, const std::string& name); @@ -741,11 +748,11 @@ namespace hal NetConnectivity check_net_endpoints(const Net* net) const; 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); + bool assign_pin_net(const u32 pin_id, Net* net, PinDirection direction); + bool remove_pin_net(Net* net); 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); + bool 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, bool force_name); - Result delete_pin_group_internal(PinGroup* pin_group); + bool delete_pin_group_internal(PinGroup* pin_group); }; } // namespace hal diff --git a/include/hal_core/netlist/pins/base_pin.h b/include/hal_core/netlist/pins/base_pin.h index 79629f2c34c..855db0470bd 100644 --- a/include/hal_core/netlist/pins/base_pin.h +++ b/include/hal_core/netlist/pins/base_pin.h @@ -187,4 +187,4 @@ namespace hal { } }; -} // namespace hal \ No newline at end of file +} // namespace hal diff --git a/include/hal_core/netlist/pins/pin_group.h b/include/hal_core/netlist/pins/pin_group.h index b036ab682d1..31f0f526cab 100644 --- a/include/hal_core/netlist/pins/pin_group.h +++ b/include/hal_core/netlist/pins/pin_group.h @@ -27,6 +27,7 @@ #include "hal_core/defines.h" #include "hal_core/utilities/result.h" +#include "hal_core/utilities/log.h" #include #include @@ -312,19 +313,39 @@ namespace hal * Assign a pin to the pin group. * * @param[in] pin - The pin to assign. - * @returns Ok on success, an error message otherwise. + * @returns true on success, false otherwise. */ - Result assign_pin(T* pin) + bool assign_pin(T* pin) { if (pin == nullptr) { - return ERR("'nullptr' given instead of a pin when trying to assign a pin to pin group '" + m_name + "' with ID " + std::to_string(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; } - i32 index = m_ascending ? m_next_index++ : m_next_index--; - m_pins.push_back(pin); + i32 index = 0; + if (m_ascending) + { + index = m_next_index++; + m_pins.push_back(pin); + } + else + { + if (m_start_index == m_next_index) + { + // special case empty pin group + index = m_start_index; + -- m_next_index; + } + else + { + index = ++m_start_index; + } + m_pins.push_front(pin); + } pin->m_group = std::make_pair(this, index); - return OK({}); + return true; } /** @@ -405,18 +426,20 @@ namespace hal * Remove a pin from the pin group. * * @param[in] pin - The pin to remove. - * @returns Ok on success, an error message otherwise. + * @returns true on success, false otherwise. */ - Result remove_pin(T* pin) + bool remove_pin(T* pin) { if (pin == nullptr) { - return ERR("'nullptr' given instead of a pin when trying to remove pin from pin group '" + m_name + "' with ID " + std::to_string(m_id)); + log_warning("pin_group", "'nullptr' given instead of a pin when trying to remove pin from pin group '{}' with ID {}.", m_name, m_id); + return false; } if (pin->m_group.first != this) { - return ERR("pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " does not belong to pin group '" + m_name + "' with ID " + std::to_string(m_id)); + log_warning("pin_group", "pin '{}' with ID {} does not belong to pin group '{}' with ID {}.", pin->get_name(), pin->get_id(), m_name, m_id); + return false; } i32 index = pin->m_group.second; @@ -433,16 +456,24 @@ namespace hal } else { - auto it = std::next(m_pins.begin(), m_start_index - index); - it = m_pins.erase(it); - for (; it != m_pins.end(); it++) + if (m_pins.size()==1) { - std::get<1>((*it)->m_group)++; + m_pins.clear(); + m_next_index++; } - m_next_index++; - } + else + { + auto it = m_pins.begin(); + for (int i=m_start_index; i>index;i--) + { + std::get<1>((*(it++))->m_group)--; + } + m_pins.erase(it); + --m_start_index; + } + } - return OK({}); + return true; } /** @@ -481,4 +512,4 @@ namespace hal PinGroup& operator=(const PinGroup&) = delete; PinGroup& operator=(PinGroup&&) = delete; }; -} // namespace hal \ No newline at end of file +} // namespace hal diff --git a/plugins/bitorder_propagation/src/plugin_bitorder_propagation.cpp b/plugins/bitorder_propagation/src/plugin_bitorder_propagation.cpp index 32df78b9850..7e839e0d7ac 100644 --- a/plugins/bitorder_propagation/src/plugin_bitorder_propagation.cpp +++ b/plugins/bitorder_propagation/src/plugin_bitorder_propagation.cpp @@ -928,10 +928,9 @@ namespace hal for (const auto& [index, pin] : index_to_pin) { - auto move_res = m->move_pin_within_group(pg, pin, index); - if (move_res.is_error()) + if (!m->move_pin_within_group(pg, pin, index)) { - return ERR_APPEND(move_res.get_error(), + return ERR( "cannot reorder module pin groups: failed to move pin " + pin->get_name() + " in pin group " + pg->get_name() + " of module with ID " + std::to_string(m->get_id()) + " to new index " + std::to_string(index)); } diff --git a/plugins/dataflow_analysis/src/api/result.cpp b/plugins/dataflow_analysis/src/api/result.cpp index 1aecd57dcaf..d8441ec5c2c 100644 --- a/plugins/dataflow_analysis/src/api/result.cpp +++ b/plugins/dataflow_analysis/src/api/result.cpp @@ -519,9 +519,9 @@ namespace hal } else { - if (const auto res = new_mod->assign_pin_to_group(data_in_group, pin); res.is_error()) + if (!new_mod->assign_pin_to_group(data_in_group, pin)) { - log_warning("dataflow", "{}", res.get_error().get()); + log_warning("dataflow", "Assign pin to group failed."); } } @@ -542,9 +542,9 @@ namespace hal } else { - if (const auto res = new_mod->assign_pin_to_group(data_out_group, pin); res.is_error()) + if (!new_mod->assign_pin_to_group(data_out_group, pin)) { - log_warning("dataflow", "{}", res.get_error().get()); + log_warning("dataflow", "Assign pin to group failed."); } } @@ -588,9 +588,9 @@ namespace hal } else { - if (const auto res = new_mod->assign_pin_to_group(pin_group, pin); res.is_error()) + if (!new_mod->assign_pin_to_group(pin_group, pin)) { - log_warning("dataflow", "{}", res.get_error().get()); + log_warning("dataflow", "Assign pin to group failed."); } } @@ -814,4 +814,4 @@ namespace hal return OK(new_group_ids); } } // namespace dataflow -} // namespace hal \ No newline at end of file +} // namespace hal diff --git a/plugins/gui/include/gui/basic_tree_model/base_tree_item.h b/plugins/gui/include/gui/basic_tree_model/base_tree_item.h index ae9a9efe332..04df7bf683e 100644 --- a/plugins/gui/include/gui/basic_tree_model/base_tree_item.h +++ b/plugins/gui/include/gui/basic_tree_model/base_tree_item.h @@ -35,15 +35,10 @@ namespace hal /** * @brief (Future) Base class for all tree models related to the details widget. * - * This class functions as a generic data container for all tree models. For this - * purpose, it uses QVariants as its main type of storage for its columns. (Note: Perhaps add - * additional data in form of a list or map (split it from "normal" displayed column data) + * This class functions as a generic data container for all tree models. */ class BaseTreeItem { - // maybe add enum type for all possible scenarios? or use additional data with key to access type - // and handle type handling in model...e.g.: item->getAddData("type")(structure, more generalization,...) - private: /** * Copy constructor. Copies the item's data, not the parent/children. @@ -194,31 +189,9 @@ namespace hal */ virtual int getOwnRow(); - /** - * Stores additional data. Can be accessed by getAdditionalData. - * (For example, a menu or color) - * - * @param key - The key to store the data under. - * @param data - The actual data to store. - */ - virtual void setAdditionalData(QString key, QVariant data); - - /** - * Retrieve the data stored under the given key. - * - * @param key - The key for the requested data. - * @return The data if something was stored under the key, empty QVariant otherwise. - */ - virtual QVariant getAdditionalData(QString key) const; - - private: + protected: BaseTreeItem* mParent; QList mChildren; - - // experimental, additional data (for anything) - QMap mAdditionalData; - //QList mAdditionalData; - }; /** diff --git a/plugins/gui/include/gui/content_anchor/content_anchor.h b/plugins/gui/include/gui/content_anchor/content_anchor.h index eefe744c322..8fb03c1c8dd 100644 --- a/plugins/gui/include/gui/content_anchor/content_anchor.h +++ b/plugins/gui/include/gui/content_anchor/content_anchor.h @@ -84,6 +84,11 @@ namespace hal * Destructor that has to be overriden. */ virtual inline ~ContentAnchor() = 0; + + /** + * Returns the number of widgets / buttons as of mDockBar->count() + */ + virtual int count() const = 0; }; ContentAnchor::~ContentAnchor() diff --git a/plugins/gui/include/gui/docking_system/splitter_anchor.h b/plugins/gui/include/gui/docking_system/splitter_anchor.h index 7678f0c01f6..d7bd083c071 100644 --- a/plugins/gui/include/gui/docking_system/splitter_anchor.h +++ b/plugins/gui/include/gui/docking_system/splitter_anchor.h @@ -113,7 +113,7 @@ namespace hal * * @return The number of widgets. */ - int count(); + int count() const override; /** * Removes all buttons from the dockbar and therefore the widgets from the area. The corresponding diff --git a/plugins/gui/include/gui/docking_system/tab_widget.h b/plugins/gui/include/gui/docking_system/tab_widget.h index d5d56f5ea50..9692b36c411 100644 --- a/plugins/gui/include/gui/docking_system/tab_widget.h +++ b/plugins/gui/include/gui/docking_system/tab_widget.h @@ -116,6 +116,12 @@ namespace hal */ void handleNoCurrentWidget(int index); + /** + * Returns the number of widgets / buttons as of mDockBar->count() + * @return - The number of widgets / buttons + */ + int count() const override; + /** * Removes all buttons from the dockbar and therefore the widgets from the area. The corresponding * widgets are not destroyed but hidden. diff --git a/plugins/gui/include/gui/graph_widget/graph_context_manager.h b/plugins/gui/include/gui/graph_widget/graph_context_manager.h index 9e6bec315c1..050df7eb007 100644 --- a/plugins/gui/include/gui/graph_widget/graph_context_manager.h +++ b/plugins/gui/include/gui/graph_widget/graph_context_manager.h @@ -26,6 +26,7 @@ #pragma once #include "hal_core/defines.h" +#include "hal_core/netlist/gate_library/enums/pin_event.h" #include #include @@ -200,7 +201,7 @@ namespace hal * * @param m - The module with the changed port */ - void handleModulePortsChanged(Module* m); + void handleModulePortsChanged(Module* m, PinEvent pev, u32 pgid); /** * Handler to be called after a gate has been removed.
diff --git a/plugins/gui/include/gui/graph_widget/layout_locker.h b/plugins/gui/include/gui/graph_widget/layout_locker.h index ebc6472a05c..34af29617d5 100644 --- a/plugins/gui/include/gui/graph_widget/layout_locker.h +++ b/plugins/gui/include/gui/graph_widget/layout_locker.h @@ -26,6 +26,7 @@ #pragma once #include +#include "hal_core/defines.h" namespace hal { @@ -37,7 +38,7 @@ namespace hal LayoutLockerManager(); int mLockCount; - QSet mWaitingRoom; + QSet mWaitingRoom; public: static LayoutLockerManager* instance(); diff --git a/plugins/gui/include/gui/module_model/module_item.h b/plugins/gui/include/gui/module_model/module_item.h index 49bbdc9288b..f34143e088c 100644 --- a/plugins/gui/include/gui/module_model/module_item.h +++ b/plugins/gui/include/gui/module_model/module_item.h @@ -107,6 +107,13 @@ namespace hal */ bool highlighted() const; + /** + * Checks if this ModuleItem is direct child to mRootItem + * + * @return + */ + bool isToplevelItem() const; + /** * Gets the type of the netlist item this ModuleItem represents. * @@ -121,6 +128,12 @@ namespace hal */ void setName(const QString& name); + /** + * Set the module type name (gate types are immutable) + * @param moduleType + */ + void setModuleType(const QString& moduleType); + /** * Marks/Unmarks this ModuleItem as highlighted. * @@ -131,8 +144,9 @@ namespace hal private: u32 mId; - TreeItemType mType; + TreeItemType mItemType; QString mName; + QString mModuleType; bool mHighlighted; }; diff --git a/plugins/gui/include/gui/module_model/module_model.h b/plugins/gui/include/gui/module_model/module_model.h index 11086efdb05..fd0e5c01755 100644 --- a/plugins/gui/include/gui/module_model/module_model.h +++ b/plugins/gui/include/gui/module_model/module_model.h @@ -36,6 +36,7 @@ #include #include #include +#include namespace hal { @@ -50,6 +51,28 @@ namespace hal { Q_OBJECT + class TempGateAssignment + { + int mAccumulate; + public: + QHash mGateRemove; + QHash mGateAssign; + + TempGateAssignment() : mAccumulate(0) {;} + void removeGateFromModule(u32 gateId, Module* m) + { + if (!mGateRemove.contains(gateId)) + mGateRemove[gateId] = m; + } + void assignGateToModule(u32 gateId, Module* m) + { + mGateAssign[gateId] = m; + } + bool isAccumulate() const { return mAccumulate > 0; } + void beginAccumulate() { mAccumulate++; } + void endAccumulate() { mAccumulate--; } + }; + public: /** * Constructor.
@@ -90,14 +113,6 @@ namespace hal */ ModuleItem* getItem(const QModelIndex& index) const; - /** - * Returns the index where the specified ModuleItem can be found. - * - * @param item - The ModuleItem to search for in the item model - * @returns the model index of the specified ModuleItem - */ - QModelIndex getIndex(const ModuleItem* const item) const; - /** * Returns the ModuleItem for a specified id and type. * @@ -123,7 +138,7 @@ namespace hal * @param id - The id of the module to add. * @param parent_module - The id of the parent module of the module to add. */ - void addModule(const u32 id, const u32 parent_module); + void addModule(const u32 id, const u32 parentId); /** * Add a gate to the item model. For the specified gate a new ModuleItem is created and stored. @@ -131,7 +146,7 @@ namespace hal * @param id - The id of the gate to add. * @param parent_module - The id of the parent module of the gate to add. */ - void addGate(const u32 id, const u32 parent_module); + void addGate(const u32 id, const u32 parentId); /** * Add a net to the item model. For the specified net a new ModuleItem is created and stored. @@ -139,7 +154,7 @@ namespace hal * @param id - The id of the net to add. * @param parent_module - The id of the parent module of the net to add. */ - void addNet(const u32 id, const u32 parent_module); + void addNet(const u32 id, const u32 parentId); /** * Recursively adds the given module with all of its submodules (and their submodules and so on...) @@ -148,7 +163,7 @@ namespace hal * @param module - The module which should be added to the item model together with all its * submodules, gates and nets. */ - void addRecursively(const Module* module); + void addRecursively(const Module* module, BaseTreeItem* parentItem = nullptr); /** * Removes a module from the item model. The specified module MUST be contained in the item model. @@ -172,20 +187,16 @@ namespace hal void removeNet(const u32 id); /** - * Moves the ModuleItem corresponding to the module under it's new parent ModuleItem. - * The items for all nets, that have at least one source or one destination within the module, - * will be updated afterwards. - * - * @param module The module whose parent has changed. + * Handles the assigment of gates to modules. + * If the gate does not yet exist in the item model, a new one is created. */ - void handleModuleParentChanged(const Module* module); + void moduleAssignGate(const u32 moduleId, const u32 gateId); /** - * Handles the assigment of gates to modules. - * If the gate does not yet exist in the item model, a new one is created. - * All nets, that are connected to the gate, will be updated. + * Handles the assigment of nets to modules for nets connected to gates of list. + * If the gate list is empty all nets connected to modules in tree are considered. */ - void handleModuleGateAssinged(const u32 id, const u32 parent_module); + void moduleAssignNets(const QList& gateIds = QList()); /** * Updates the position of a net in the ModuleTree. @@ -195,7 +206,7 @@ namespace hal * * @param net The net whose source or destination might have changed. */ - void updateNet(const Net* net); + void updateNetParent(const Net* net, const QHash* parentAssignment = nullptr); /** * Reattaches the ModuleItem corresponding to the specified module to a new parent item. @@ -235,6 +246,47 @@ namespace hal */ bool isModifying(); + private Q_SLOTS: + void handleModuleNameChanged(Module* mod); + + void handleModuleRemoved(Module* mod); + + void handleModuleCreated(Module* mod); + + /** + * Moves the ModuleItem corresponding to the module under it's new parent ModuleItem. + * The items for all nets, that have at least one source or one destination within the module, + * will be updated afterwards. + * + * @param module The module whose parent has changed. + */ + void handleModuleParentChanged(const Module* mod); + + void handleModuleSubmoduleAdded(Module* mod, u32 submodId); + + void handleModuleSubmoduleRemoved(Module* mod, u32 submodId); + + void handleModuleGateAssigned(Module* mod, u32 gateId); + + void handleModuleGateRemoved(Module* mod, u32 gateId); + + void handleModuleGatesAssignBegin(Module* mod, u32 numberGates); + + void handleModuleGatesAssignEnd(Module* mod, u32 numberGates); + + void handleGateCreated(Gate* gat); + + void handleGateNameChanged(Gate* gat); + + void handleGateRemoved(Gate* gat); + + void handleNetCreated(Net* net); + + void handleNetNameChanged(Net* net); + + void handleNetRemoved(Net* net); + + void handleNetUpdated(Net* net, u32 data); private: /** * Searches for a new parent module, such that it is the deepest module in the hierarchy, that contains all @@ -243,15 +295,41 @@ namespace hal * @param net The net for which a new parent should be searched. * * @return The new parent module, that contains all sources and destinations of net. If no such parent could be found - * (e.g. net has no sources or destinations), nullptr is returned instead. + * (e.g. global input/output, net has no sources or destinations), nullptr is returned instead. */ - Module* findNetParent(const Net* net); + Module* findNetParent(const Net* net) const; + + /** + * Recursion to loop over all modules from (sub-)tree and create a hash assign how internal nets are assigned to module + * @param parent - top tree element + * @param parentAssignment - the resulting net module assignment + * @param assignedNets - nets already assigned (no assignment to module higher up in hierarchy) + */ + void findNetParentRecursion(BaseTreeItem* parent, QHash& parentAssignment, std::unordered_set& assignedNets) const; + + /** + * Factory method to append new tree items. Insert signals are sent to view. New items are put into hash table. + * @param id - ID of new tree item + * @param itemType - Whether new tree item is module, gate, or net + * @param parentItem - Parent to new tree item. Will create top-level item if parent is nullptr + * @return Point to new tree item + */ + ModuleItem* createChildItem(u32 id, ModuleItem::TreeItemType itemType, BaseTreeItem* parentItem = nullptr); + + /** + * Method to remove and delete tree items. Remove signals are sent to view. + * Hash table will _NOT_ be updated since caller can do it more efficiently. + * @param itemToRemove - Item to be removed from tree + * @param parentItem - Parent item. Must be present. + */ + void removeChildItem(ModuleItem* itemToRemove, BaseTreeItem* parentItem); - QMap mModuleMap; - QMap mGateMap; - QMap mNetMap; - std::array*, 3> mModuleItemMaps = {&mModuleMap, &mGateMap, &mNetMap};; + QMultiMap mModuleMap; + QMultiMap mGateMap; + QMultiMap mNetMap; + QMultiMap* mModuleItemMaps[3] = {&mModuleMap, &mGateMap, &mNetMap};; bool mIsModifying; + TempGateAssignment mTempGateAssignment; }; } // namespace hal diff --git a/plugins/gui/include/gui/module_widget/module_widget.h b/plugins/gui/include/gui/module_widget/module_widget.h index fb18026a2c7..115a6e7199c 100644 --- a/plugins/gui/include/gui/module_widget/module_widget.h +++ b/plugins/gui/include/gui/module_widget/module_widget.h @@ -45,6 +45,7 @@ class QTreeView; namespace hal { + class ModuleModel; class ModuleProxyModel; /** @@ -93,6 +94,13 @@ namespace hal */ virtual QList createShortcuts() override; + /** + * Accesses the module model. + * + * @returns the module model + */ + ModuleModel* getModuleModel() const; + /** * Opens a existing view that contains the given module, otherwise creates a new context * and opens it. @@ -268,6 +276,7 @@ namespace hal bool mIgnoreSelectionChange; + ModuleModel* mModuleModel; ModuleProxyModel* mModuleProxyModel; QShortcut* mShortCutDeleteItem; diff --git a/plugins/gui/include/gui/netlist_relay/netlist_relay.h b/plugins/gui/include/gui/netlist_relay/netlist_relay.h index 83085c6b8ae..7e0630d1243 100644 --- a/plugins/gui/include/gui/netlist_relay/netlist_relay.h +++ b/plugins/gui/include/gui/netlist_relay/netlist_relay.h @@ -26,6 +26,7 @@ #pragma once #include "hal_core/netlist/event_system/event_handler.h" +#include "hal_core/netlist/gate_library/enums/pin_event.h" #include "gui/grouping/grouping_color_serializer.h" #include "gui/module_model/module_color_manager.h" #include @@ -34,7 +35,6 @@ namespace hal { class ModuleItem; - class ModuleModel; class ModuleColorManager; class ModuleColorSerializer; class Module; @@ -86,13 +86,6 @@ namespace hal */ QColor getModuleColor(const u32 id); - /** - * Accesses the module model. - * - * @returns the module model - */ - ModuleModel* getModuleModel() const; - /** * Accesses the module color manager * @@ -342,7 +335,7 @@ namespace hal * @param m - The module with the changed port * @param respective_net - The id of the net of the renamed input port */ - void modulePortsChanged(Module* m) const; + void modulePortsChanged(Module* m, PinEvent pev, u32 pgid) const; /** * Q_SIGNAL to notify that the type of a module has been changed.
@@ -614,12 +607,12 @@ namespace hal void relayGateEvent(GateEvent::event ev, Gate* gat, u32 associated_data); void relayNetEvent(NetEvent::event ev, Net* net, u32 associated_data); void relayGroupingEvent(GroupingEvent::event ev, Grouping* grp, u32 associated_data); + static void dumpModuleRecursion(Module* m); void handleNetlistModified(); bool mNotified; QMap mModuleColors; - ModuleModel* mModuleModel; ModuleColorManager* mModuleColorManager; ModuleColorSerializer mColorSerializer; enum ThreadEventType { TetNetlist, TetModule, TetGate, TetNet, TetGrouping }; diff --git a/plugins/gui/include/gui/selection_details_widget/gate_details_widget/gate_pin_tree.h b/plugins/gui/include/gui/selection_details_widget/gate_details_widget/gate_pin_tree.h index 1d23ff76df1..746eb58931e 100644 --- a/plugins/gui/include/gui/selection_details_widget/gate_details_widget/gate_pin_tree.h +++ b/plugins/gui/include/gui/selection_details_widget/gate_details_widget/gate_pin_tree.h @@ -33,7 +33,7 @@ namespace hal { class GatePinsTreeModel; class Gate; - class BaseTreeItem; + class PinTreeItem; class GraphNavigationWidget; /** @@ -98,8 +98,8 @@ namespace hal bool mClearSelection; //helper functions - void buildPythonMenuForPin(QMenu &menu, BaseTreeItem* clickedPinItem); - void buildPythonMenuForPinGroup(QMenu &menu, BaseTreeItem* clickedPinIGrouptem); + void buildPythonMenuForPin(QMenu &menu, PinTreeItem* clickedPinItem); + void buildPythonMenuForPinGroup(QMenu &menu, PinTreeItem* clickedPinIGrouptem); void addSourceOurDestinationToSelection(int netId, bool isInputPin); void handleNavigationCloseRequested(); void handleNavigationJumpRequested(const Node& origin, const u32 via_net, const QSet& to_gates, const QSet& to_modules); diff --git a/plugins/gui/include/gui/selection_details_widget/gate_details_widget/pin_tree_model.h b/plugins/gui/include/gui/selection_details_widget/gate_details_widget/pin_tree_model.h index 142601fa32a..81c06e3f4b2 100644 --- a/plugins/gui/include/gui/selection_details_widget/gate_details_widget/pin_tree_model.h +++ b/plugins/gui/include/gui/selection_details_widget/gate_details_widget/pin_tree_model.h @@ -26,8 +26,10 @@ #pragma once //#include "gui/new_selection_details_widget/models/base_tree_model.h" +#include "hal_core/defines.h" #include "gui/basic_tree_model/base_tree_model.h" #include +#include namespace hal { @@ -36,8 +38,12 @@ namespace hal class PinTreeItem : public BaseTreeItem { + public: + enum Type {None, Pin, Group}; private: + Type mType; + QList mNetIds; std::string mPinName; QString mPinDirection; QString mPinType; @@ -51,6 +57,24 @@ namespace hal void setDataAtIndex(int index, QVariant& data) override; void appendData(QVariant data) override; int getColumnCount() const override; + void setType(Type tp) { mType = tp; } + + /** + * Get the type (enum) of a given item. + * + * @return The item's type. + */ + Type type() const { return mType; } + void setNetIds(const QList& nids) { mNetIds = nids; } + + /** + * Get the connected nets for a given treeitem (represents a pin). If the + * item is grouping type or the pin has no connected net, an empty list + * is returned. In case of an inout pin, even multiple connected nets are possible. + * + * @return A list of net ids. + */ + QList netIds() const { return mNetIds; } }; /** @@ -63,9 +87,6 @@ class GatePinsTreeModel : public BaseTreeModel public: - //metatype declaration at the end of file - enum class itemType {grouping = 0, pin = 1}; - /** * The constructor. * @@ -98,24 +119,6 @@ class GatePinsTreeModel : public BaseTreeModel */ int getCurrentGateID(); - /** - * Get the connected nets for a given treeitem (represents a pin). If the - * item is grouping type or the pin has no connected net, an empty list - * is returned. In case of an inout pin, even multiple connected nets are possible. - * - * @param item - The treeitem from which to get the connected nets. - * @return A list of net ids. - */ - QList getNetIDsOfTreeItem(BaseTreeItem* item); - - /** - * Get the type (enum) of a given item. - * - * @param item - The item for which the type is requested. - * @return The item's type. - */ - itemType getTypeOfItem(BaseTreeItem* item); - /** * Get the number of displayed pins (the number of pins of all types). * @@ -130,16 +133,10 @@ class GatePinsTreeModel : public BaseTreeModel static const int sTypeColumn = 2; static const int sConnectedNetColumn = 3; - //additional data keys - const QString keyType = "type"; - const QString keyRepresentedNetsID = "netID"; //might not be needed - private: int mGateId; - QMap mPinGroupingToTreeItem; + QMap mPinGroupToTreeItem; }; } - -Q_DECLARE_METATYPE(hal::GatePinsTreeModel::itemType) diff --git a/plugins/gui/include/gui/selection_details_widget/module_details_widget/module_tree_model.h b/plugins/gui/include/gui/selection_details_widget/module_details_widget/module_tree_model.h index 0608a6bd89f..81dceaf580a 100644 --- a/plugins/gui/include/gui/selection_details_widget/module_details_widget/module_tree_model.h +++ b/plugins/gui/include/gui/selection_details_widget/module_details_widget/module_tree_model.h @@ -41,19 +41,30 @@ namespace hal class ModuleTreeitem : public BaseTreeItem { + public: + enum ItemType { None, Module, Gate}; private: - std::string mType; + ItemType mItemType; int mId; - std::string mName; + QString mName; + QString mNodeType; public: - ModuleTreeitem(const std::string& name, int id, std::string tp); + ModuleTreeitem(ItemType itp, int id, const QString& name, const QString& ntp); QVariant getData(int column) const override; void setData(QList data) override; void setDataAtIndex(int index, QVariant& data) override; void appendData(QVariant data) override; int getColumnCount() const override; + + /** + * Get the type (enum) of a given item. + * + * @param item - The item for which the type is requested. + * @return The item's type. + */ + ItemType itemType() const { return mItemType; } }; class ModuleTreeModel : public BaseTreeModel @@ -61,9 +72,6 @@ namespace hal Q_OBJECT public: - //metatype declaration at the end of file - enum class itemType {module = 0, gate = 1}; - ModuleTreeModel(QObject* parent = nullptr); ~ModuleTreeModel(); @@ -83,14 +91,6 @@ namespace hal QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; ///@} - /** - * Get the type (enum) of a given item. - * - * @param item - The item for which the type is requested. - * @return The item's type. - */ - itemType getTypeOfItem(BaseTreeItem* item) const; - /** * Disconnects all events from the model. Can be called to increase performance when * no module is displayed. @@ -144,7 +144,7 @@ namespace hal * @param item - The requested item. * @return A module, net, or gate icon depending on the item's type. */ - QIcon getIconFromItem(BaseTreeItem* item) const; + QIcon getIconFromItem(ModuleTreeitem* item) const; void clearOwnStructures(); @@ -167,5 +167,3 @@ namespace hal }; } - -Q_DECLARE_METATYPE(hal::ModuleTreeModel::itemType) diff --git a/plugins/gui/include/gui/selection_details_widget/module_details_widget/netlist_elements_tree_model.h b/plugins/gui/include/gui/selection_details_widget/module_details_widget/netlist_elements_tree_model.h index 5bb90aa7240..b6540d1855e 100644 --- a/plugins/gui/include/gui/selection_details_widget/module_details_widget/netlist_elements_tree_model.h +++ b/plugins/gui/include/gui/selection_details_widget/module_details_widget/netlist_elements_tree_model.h @@ -29,6 +29,7 @@ #include //#include "gui/new_selection_details_widget/models/base_tree_item.h" #include "gui/basic_tree_model/base_tree_model.h" +#include "hal_core/defines.h" namespace hal { @@ -39,19 +40,30 @@ namespace hal class NetlistElementsTreeitem : public BaseTreeItem { + public: + enum ItemType { None, Module, Gate, Net}; private: - QString mType; - int mId; + ItemType mItemType; + u32 mId; QString mName; + QString mNodeType; public: - NetlistElementsTreeitem(const QString& name, int id, QString tp); + NetlistElementsTreeitem(ItemType itp, u32 id_, const QString& name, const QString& ntp = QString()); QVariant getData(int column) const override; void setData(QList data) override; void setDataAtIndex(int index, QVariant& data) override; void appendData(QVariant data) override; int getColumnCount() const override; + + u32 id() const { return mId; } + /** + * Get the type (enum) of a given item. + * + * @return The item's type. + */ + ItemType itemType() const { return mItemType; } }; /** @@ -63,8 +75,6 @@ namespace hal Q_OBJECT public: - //metatype declaration at the end of file - enum class itemType {module = 0, gate = 1, net = 2}; /** * The constructor. @@ -121,14 +131,6 @@ namespace hal */ void setModule(Module* mod, bool showGates = true, bool showNets = true, bool displayModulesRecursive = true); - /** - * Get the type (enum) of a given item. - * - * @param item - The item for which the type is requested. - * @return The item's type. - */ - itemType getTypeOfItem(NetlistElementsTreeitem* item) const; - /** * Get the module/gate/net id that the given item represents. * To know the type of the item, call getTypeOfItem(). @@ -217,5 +219,3 @@ namespace hal }; } - -Q_DECLARE_METATYPE(hal::NetlistElementsTreeModel::itemType) diff --git a/plugins/gui/include/gui/selection_details_widget/module_details_widget/port_tree_model.h b/plugins/gui/include/gui/selection_details_widget/module_details_widget/port_tree_model.h index 5167f9bfc48..d14937a00d7 100644 --- a/plugins/gui/include/gui/selection_details_widget/module_details_widget/port_tree_model.h +++ b/plugins/gui/include/gui/selection_details_widget/module_details_widget/port_tree_model.h @@ -27,6 +27,9 @@ //#include "gui/new_selection_details_widget/models/base_tree_model.h" #include "gui/basic_tree_model/base_tree_model.h" +#include "hal_core/netlist/gate_library/enums/pin_direction.h" +#include "hal_core/netlist/gate_library/enums/pin_event.h" +#include "hal_core/netlist/gate_library/enums/pin_type.h" #include namespace hal @@ -37,21 +40,41 @@ namespace hal class PortTreeItem : public BaseTreeItem { + public: + enum Type {None, Pin, Group}; private: + Type mItemType; + u32 mId; QString mPinName; - QString mPinDirection; - QString mPinType; + PinDirection mPinDirection; + PinType mPinType; QString mNetName; + public: - PortTreeItem(QString pinName, QString pinDirection, QString pinType, QString netName); - PortTreeItem(); + PortTreeItem(Type itype, u32 id_, QString pinName, PinDirection dir, PinType ptype, QString netName = QString()); + PortTreeItem() : mItemType(None), mId(0) {;} QVariant getData(int column) const override; void setData(QList data) override; void setDataAtIndex(int index, QVariant& data) override; void appendData(QVariant data) override; int getColumnCount() const override; + void setItemType(Type tp) { mItemType = tp; } + Type itemType() const { return mItemType; } + QString name() const { return mPinName; } + void setName(const QString& nam) { mPinName = nam; } + void setPinType(PinType ptype) { mPinType = ptype; } + void setPinDirection(PinDirection dir) { mPinDirection = dir; } + + /** + * Returns the pin-id if the item represents a pin or the pingroup-id + * if the item represents a pingroup. + * + * @param item - The item. + * @return The pin- or pingroup-id. + */ + u32 id() const { return mId; } }; /** @@ -62,10 +85,6 @@ namespace hal Q_OBJECT public: - //metatype declaration at the end of file (portSingleBit and portMultiBit are deprecated) - //important now are pins and groups - enum class itemType{portSingleBit = 0, portMultiBit = 1, pin = 2, group = 3}; - /** * The constructor. * @@ -116,27 +135,10 @@ namespace hal */ int getRepresentedModuleId(); - /** - * Get the type (enum) of a given item. - * - * @param item - The item for which the type is requested. - * @return The item's type. - */ - itemType getTypeOfItem(PortTreeItem* item) const; - - /** - * Returns the pin-id if the item represents a pin or the pingroup-id - * if the item represents a pingroup. - * - * @param item - The item. - * @return The pin- or pingroup-id. - */ - int getIdOfItem(BaseTreeItem* item) const; - /** @name Event Handler Functions */ ///@{ - void handleModulePortsChanged(Module* m); + void handleModulePortsChanged(Module* m, PinEvent pev, u32 pgid); ///@} //column identifier @@ -145,10 +147,6 @@ namespace hal static const int sTypeColumn = 2; static const int sNetColumn = 3; - //additional data keys - const QString keyType = "type"; - const QString keyId = "id"; - Q_SIGNALS: /** * Q_SIGNAL that is emitted when the number of the model's port changed. @@ -163,9 +161,8 @@ namespace hal Module* mModule; //name is (hopefully) enough to identify QMap mNameToTreeItem; - QMap mIdToPinItem; - QMap mIdToGroupItem; - bool mIgnoreEventsFlag; + QMap mIdToPinItem; + QMap mIdToGroupItem; void insertItem(PortTreeItem* item, BaseTreeItem* parent, int index); void removeItem(PortTreeItem* item); @@ -178,5 +175,3 @@ namespace hal void dndPinBetweenGroup(PortTreeItem* droppedPin, int row); }; } - -Q_DECLARE_METATYPE(hal::ModulePinsTreeModel::itemType) diff --git a/plugins/gui/include/gui/selection_details_widget/net_details_widget/module_table_model.h b/plugins/gui/include/gui/selection_details_widget/net_details_widget/module_table_model.h index a1b6a8cdf31..cfe0a053e7d 100644 --- a/plugins/gui/include/gui/selection_details_widget/net_details_widget/module_table_model.h +++ b/plugins/gui/include/gui/selection_details_widget/net_details_widget/module_table_model.h @@ -26,6 +26,7 @@ #pragma once #include "hal_core/defines.h" +#include "hal_core/netlist/gate_library/enums/pin_event.h" #include #include @@ -154,7 +155,7 @@ class ModuleTableModel : public QAbstractTableModel /** @name Event Handler Functions */ ///@{ - void handleModulePortsChanged(Module* m); + void handleModulePortsChanged(Module* m, PinEvent pev, u32 pgid); void handleModuleRemoved(Module* m); ///@} diff --git a/plugins/gui/include/gui/selection_details_widget/selection_details_widget.h b/plugins/gui/include/gui/selection_details_widget/selection_details_widget.h index 43f90b100b2..42010ac0807 100644 --- a/plugins/gui/include/gui/selection_details_widget/selection_details_widget.h +++ b/plugins/gui/include/gui/selection_details_widget/selection_details_widget.h @@ -338,6 +338,8 @@ namespace hal */ void selectionToModuleAction(int actionCode); + void showNoSelection(); + QSplitter* mSplitter; SelectionTreeView* mSelectionTreeView; unsigned int mNumberSelectedItems; diff --git a/plugins/gui/include/gui/user_action/action_pingroup.h b/plugins/gui/include/gui/user_action/action_pingroup.h new file mode 100644 index 00000000000..4ab871068f7 --- /dev/null +++ b/plugins/gui/include/gui/user_action/action_pingroup.h @@ -0,0 +1,179 @@ +// MIT License +// +// Copyright (c) 2019 Ruhr University Bochum, Chair for Embedded Security. All Rights reserved. +// Copyright (c) 2019 Marc Fyrbiak, Sebastian Wallat, Max Hoffmann ("ORIGINAL AUTHORS"). All rights reserved. +// Copyright (c) 2021 Max Planck Institute for Security and Privacy. All Rights reserved. +// Copyright (c) 2021 Jörn Langheinrich, Julian Speith, Nils Albartus, René Walendy, Simon Klix ("ORIGINAL AUTHORS"). All Rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once +#include "user_action.h" +#include "hal_core/netlist/module.h" +#include +#include + +namespace hal +{ + class PinActionType : public QObject + { + Q_OBJECT + public: + enum Type { None, GroupCreate, GroupDelete, GroupMoveToRow, GroupRename, GroupTypeChange, GroupDirChange, + PinAsignToGroup, PinRename, PinTypeChange, PinDirChange, PinMoveToRow, MaxAction }; + Q_ENUM(Type); + + public: + static QString toString(Type tp); + static Type fromString(const QString& s); + static bool useExistingGroup(Type tp); + static bool useExistingPin(Type tp); + }; + + int pinGroupIndex(const Module* mod, const PinGroup* pgrp); + + int pinIndex2Row(const ModulePin* pin, int index); + + int pinRow2Index(const ModulePin* pin, int row); + + QString generateGroupName(const Module* mod, const ModulePin* pin); + + void dumpPingroups(Module* m = nullptr); + /** + * @ingroup user_action + * @brief Pingroup user actions + * + * Arguments depends on PinActionType::Type: + * + * GroupCreate: + * ID : ID of group to create + * negative ID: call constructor without ID, however, + * ID will be used internally for subsequent commands related to crated group + * name : name of group + * value : start index, assume ascending + * negative value: descending order starting with (-value-1) + * + * GroupDelete + * ID : ID of group to delete + * + * GroupMoveToRow + * ID : ID of group to move + * value : row to which group get moved within vector of pin groups + * + * GroupRename + * ID : ID of group to rename + * name : new name + * + * GroupTypeChange + * ID : ID of group to modifiy + * value : (int) PinType as of hal_core/netlist/gate_library/enums/pin_type.h + * + * GroupDirChange + * ID : ID of group to modifiy + * value : (int) PinDirection as of hal_core/netlist/gate_library/enums/pin_direction.h + * + * PinAsignToGroup + * ID : ID of pin + * value : ID of group, might be negative if group recently created + * + * PinRename + * ID : ID of pin to rename + * name : new name + * + * PinTypeChange + * ID : ID of pin to modify + * value : (int) PinType + * + * PinDirChange + * ID : ID of pin to modify + * value : (int) PinDirection + * + * PinMoveToRow + * ID : ID of pin + * value : row to which pin gets moved in pingroup + */ + class ActionPingroup : public UserAction + { + private: + class AtomicAction + { + public: + PinActionType::Type mType; + int mId; + QString mName; + int mValue; + AtomicAction(PinActionType::Type tp, int id, const QString& name = QString(), int v=0) : mType(tp), mId(id), mName(name), mValue(v) {;} + }; + + class GroupRestore + { + public: + int mId; + QString mName; + int mRow; + int mStartIndex; + PinDirection mDirection; + PinType mType; + GroupRestore(Module* m, PinGroup* pgroup); + }; + + QHash*> mPinGroups; + QList mPinActions; + Module* mParentModule; + QMap mGroupRestore; + QSet mPinsMoved; + QSet mGroupToRemove; + + PinGroup* getGroup(ModulePin* pin) const; + PinGroup* getGroup(int grpId) const; + void prepareUndoAction(); + void finalizeUndoAction(); + void addUndoAction(PinActionType::Type tp, int id = 0, const QString& name=QString(), int value=0); + static int pinGroupRow(Module* m, PinGroup* pgroup); + public: + ActionPingroup(PinActionType::Type tp = PinActionType::None, int id = 0, const QString& name=QString(), int value=0); + ActionPingroup(const QList& aaList); + bool exec() override; + QString tagname() const override; + void writeToXml(QXmlStreamWriter& xmlOut) const override; + void readFromXml(QXmlStreamReader& xmlIn) override; + void addToHash(QCryptographicHash& cryptoHash) const override; + + static ActionPingroup* addPinsToExistingGroup(const Module* m, u32 grpId, QList pinIds, int pinRow = -1); + static ActionPingroup* addPinToExistingGroup(const Module* m, u32 grpId, u32 pinId, int pinRow = -1); + static ActionPingroup* addPinsToNewGroup(const Module* m, const QString& name, QList pinIds, int grpRow = -1); + static ActionPingroup* addPinToNewGroup(const Module* m, const QString& name, u32 pinId, int grpRow = -1); + static ActionPingroup* removePinsFromGroup(const Module* m, QList pinIds); + static ActionPingroup* deletePinGroup(const Module* m, u32 grpId); + }; + + /** + * @ingroup user_action + * @brief UserActionFactory for ActionPingroup + */ + class ActionPingroupFactory : public UserActionFactory + { + public: + ActionPingroupFactory(); + UserAction* newAction() const; + static ActionPingroupFactory* sFactory; + }; + + uint qHash(PinEvent pev); +} diff --git a/plugins/gui/include/gui/user_action/user_action_object.h b/plugins/gui/include/gui/user_action/user_action_object.h index 572e608de2f..4658b22d8ab 100644 --- a/plugins/gui/include/gui/user_action/user_action_object.h +++ b/plugins/gui/include/gui/user_action/user_action_object.h @@ -54,8 +54,6 @@ namespace hal Grouping, Netlist, Context, - Pin, - PinGroup, MaxObjectType }; Q_ENUM(ObjectType) diff --git a/plugins/gui/src/basic_tree_model/base_tree_item.cpp b/plugins/gui/src/basic_tree_model/base_tree_item.cpp index d0209984816..493a803e68a 100644 --- a/plugins/gui/src/basic_tree_model/base_tree_item.cpp +++ b/plugins/gui/src/basic_tree_model/base_tree_item.cpp @@ -99,16 +99,6 @@ namespace hal return mParent->getRowForChild(this); } - void BaseTreeItem::setAdditionalData(QString key, QVariant data) - { - mAdditionalData.insert(key, data); - } - - QVariant BaseTreeItem::getAdditionalData(QString key) const - { - return mAdditionalData.value(key, QVariant()); - } - QVariant RootTreeItem::getData(int column) const { if (column <= mHeaderLabels.size()) diff --git a/plugins/gui/src/content_layout_area/content_layout_area.cpp b/plugins/gui/src/content_layout_area/content_layout_area.cpp index 8a3ac9b66f2..8dc4d88d102 100644 --- a/plugins/gui/src/content_layout_area/content_layout_area.cpp +++ b/plugins/gui/src/content_layout_area/content_layout_area.cpp @@ -1,5 +1,6 @@ #include "gui/content_layout_area/content_layout_area.h" +#include "hal_core/utilities/log.h" #include "gui/docking_system/dock_bar.h" #include "gui/docking_system/splitter_anchor.h" #include "gui/docking_system/tab_widget.h" @@ -109,6 +110,30 @@ namespace hal void ContentLayoutArea::addContent(ContentWidget* widget, int index, content_anchor anchor) { + int maxIndex = 0; + switch (anchor) + { + case content_anchor::center: + maxIndex = mTabWidget->count(); + break; + case content_anchor::left: + maxIndex = mLeftAnchor->count(); + break; + case content_anchor::right: + maxIndex = mRightAnchor->count(); + break; + case content_anchor::bottom: + maxIndex = mBottomAnchor->count(); + break; + } + + if (index > maxIndex) + { + log_warning("gui", "Cannot insert widget '{}' at index {}, moved to index {}", widget->name().toStdString(), index, maxIndex); + index = maxIndex; + } + + switch (anchor) { case content_anchor::center: diff --git a/plugins/gui/src/content_manager/content_manager.cpp b/plugins/gui/src/content_manager/content_manager.cpp index 8b2d13a7a0a..09fd59069b2 100644 --- a/plugins/gui/src/content_manager/content_manager.cpp +++ b/plugins/gui/src/content_manager/content_manager.cpp @@ -150,10 +150,10 @@ namespace hal void ContentManager::handleOpenDocument(const QString& fileName) { - mExternalIndex = 6; + mExternalIndex = 1; mGraphTabWidget = new GraphTabWidget(); - mMainWindow->addContent(mGraphTabWidget, 2, content_anchor::center); + mMainWindow->addContent(mGraphTabWidget, 0, content_anchor::center); mModuleWidget = new ModuleWidget(); mMainWindow->addContent(mModuleWidget, 0, content_anchor::left); @@ -200,7 +200,7 @@ namespace hal mPythonWidget->open(); mPythonConsoleWidget = new PythonConsoleWidget(); - mMainWindow->addContent(mPythonConsoleWidget, 5, content_anchor::bottom); + mMainWindow->addContent(mPythonConsoleWidget, 2, content_anchor::bottom); mPythonConsoleWidget->open(); mContent.append(mGraphTabWidget); diff --git a/plugins/gui/src/docking_system/splitter_anchor.cpp b/plugins/gui/src/docking_system/splitter_anchor.cpp index 996ef138e21..5500e80a87f 100644 --- a/plugins/gui/src/docking_system/splitter_anchor.cpp +++ b/plugins/gui/src/docking_system/splitter_anchor.cpp @@ -95,7 +95,7 @@ namespace hal mDockBar->uncheckButton(widget); } - int SplitterAnchor::count() + int SplitterAnchor::count() const { return mDockBar->count(); } diff --git a/plugins/gui/src/docking_system/tab_widget.cpp b/plugins/gui/src/docking_system/tab_widget.cpp index 15602f4f18f..1934b53b9ef 100644 --- a/plugins/gui/src/docking_system/tab_widget.cpp +++ b/plugins/gui/src/docking_system/tab_widget.cpp @@ -201,4 +201,9 @@ namespace hal if (mDockBar->unused()) hide(); } + + int TabWidget::count() const + { + return mDockBar->count(); + } } diff --git a/plugins/gui/src/graph_widget/graph_context_manager.cpp b/plugins/gui/src/graph_widget/graph_context_manager.cpp index 254298b236a..846f5194d9b 100644 --- a/plugins/gui/src/graph_widget/graph_context_manager.cpp +++ b/plugins/gui/src/graph_widget/graph_context_manager.cpp @@ -378,8 +378,10 @@ namespace hal xout << "-------\n"; } - void GraphContextManager::handleModulePortsChanged(Module* m) + void GraphContextManager::handleModulePortsChanged(Module* m, PinEvent pev, u32 pgid) { + Q_UNUSED(pev); + Q_UNUSED(pgid); for (GraphContext* context : mContextTableModel->list()) if (context->modules().contains(m->get_id())) { diff --git a/plugins/gui/src/graph_widget/layout_locker.cpp b/plugins/gui/src/graph_widget/layout_locker.cpp index 70082902bdb..e2bf1f46bb2 100644 --- a/plugins/gui/src/graph_widget/layout_locker.cpp +++ b/plugins/gui/src/graph_widget/layout_locker.cpp @@ -1,4 +1,5 @@ #include "gui/graph_widget/layout_locker.h" +#include "gui/gui_globals.h" #include "gui/graph_widget/contexts/graph_context.h" namespace hal { @@ -22,24 +23,29 @@ namespace hal { void LayoutLockerManager::removeLock() { --mLockCount; + if (mLockCount <= 0 && !mWaitingRoom.isEmpty()) { - for (GraphContext* ctx : mWaitingRoom) - ctx->startSceneUpdate(); + for (u32 ctxId : mWaitingRoom) + { + GraphContext* ctx = gGraphContextManager->getContextById(ctxId); + if (ctx) ctx->startSceneUpdate(); + } mWaitingRoom.clear(); } } bool LayoutLockerManager::canUpdate(GraphContext* ctx) { + if (!ctx) return false; if (mLockCount <= 0) return true; - mWaitingRoom.insert(ctx); + mWaitingRoom.insert(ctx->id()); return false; } void LayoutLockerManager::removeWaitingContext(GraphContext* ctx) { - auto it = mWaitingRoom.find(ctx); + auto it = mWaitingRoom.find(ctx->id()); if (it != mWaitingRoom.end()) mWaitingRoom.erase(it); } diff --git a/plugins/gui/src/module_dialog/module_dialog.cpp b/plugins/gui/src/module_dialog/module_dialog.cpp index 369533c3d43..877da5fa2b1 100644 --- a/plugins/gui/src/module_dialog/module_dialog.cpp +++ b/plugins/gui/src/module_dialog/module_dialog.cpp @@ -4,6 +4,7 @@ #include "gui/module_model/module_model.h" #include "gui/module_model/module_proxy_model.h" #include "gui/module_model/module_item.h" +#include "gui/module_widget/module_widget.h" #include "gui/graph_tab_widget/graph_tab_widget.h" #include "gui/searchbar/searchbar.h" #include "gui/content_manager/content_manager.h" @@ -91,7 +92,7 @@ namespace hal { mModuleTreeProxyModel = new ModuleProxyModel(this); mModuleTreeProxyModel->setFilterKeyColumn(-1); mModuleTreeProxyModel->setDynamicSortFilter(true); - mModuleTreeProxyModel->setSourceModel(gNetlistRelay->getModuleModel()); + mModuleTreeProxyModel->setSourceModel(gContentManager->getModuleWidget()->getModuleModel()); mTreeView->setModel(mModuleTreeProxyModel); mTreeView->expandAll(); diff --git a/plugins/gui/src/module_model/module_item.cpp b/plugins/gui/src/module_model/module_item.cpp index cf5a79bcc56..8291ac52b80 100644 --- a/plugins/gui/src/module_model/module_item.cpp +++ b/plugins/gui/src/module_model/module_item.cpp @@ -11,21 +11,35 @@ namespace hal ModuleItem::ModuleItem(const u32 id, const TreeItemType type) : BaseTreeItem(), mId(id), - mType(type), + mItemType(type), mHighlighted(false) { switch(type) { case TreeItemType::Module: - mName = QString::fromStdString(gNetlist->get_module_by_id(id)->get_name()); + { + const Module* m = gNetlist->get_module_by_id(id); + Q_ASSERT(m); + mName = QString::fromStdString(m->get_name()); + mModuleType = QString::fromStdString(m->get_type()); break; + } case TreeItemType::Gate: - mName = QString::fromStdString(gNetlist->get_gate_by_id(id)->get_name()); + { + const Gate* g = gNetlist->get_gate_by_id(id); + Q_ASSERT(g); + mName = QString::fromStdString(g->get_name()); + mModuleType = QString::fromStdString(g->get_type()->get_name()); break; + } case TreeItemType::Net: - mName = QString::fromStdString(gNetlist->get_net_by_id(id)->get_name()); + { + const Net* n = gNetlist->get_net_by_id(id); + Q_ASSERT(n); + mName = QString::fromStdString(n->get_name()); break; } + } } int ModuleItem::row() const @@ -38,7 +52,7 @@ ModuleItem::ModuleItem(const u32 id, const TreeItemType type) : void ModuleItem::appendExistingChildIfAny(const QMap& moduleMap) { - if(mType != TreeItemType::Module) // only module can have children + if(mItemType != TreeItemType::Module) // only module can have children return; Module* m = gNetlist->get_module_by_id(mId); @@ -55,30 +69,25 @@ ModuleItem::ModuleItem(const u32 id, const TreeItemType type) : } } + void ModuleItem::setModuleType(const QString &moduleType) + { + if (mItemType != TreeItemType::Module) return; + Module* module = gNetlist->get_module_by_id(mId); + if (!module) return; + module->set_type(moduleType.toStdString()); + mModuleType = moduleType; + } + QVariant ModuleItem::getData(int column) const { // DEBUG CODE, USE STYLED DELEGATES OR SOMETHING - if(column == 0) + switch (column) { + case 0: return mName; - else if (column == 1) + case 1: return mId; - else if(column == 2) - { - switch(mType) - { - case TreeItemType::Module: - { - Module* module = gNetlist->get_module_by_id(mId); - if(!module) - return QVariant(); - return QString::fromStdString(module->get_type()); - } - case TreeItemType::Gate: - Gate* gate = gNetlist->get_gate_by_id(mId); - if(!gate) - return QVariant(); - return QString::fromStdString(gate->get_type()->get_name()); - } + case 2: + return mModuleType; } return QVariant(); } @@ -86,42 +95,21 @@ ModuleItem::ModuleItem(const u32 id, const TreeItemType type) : void ModuleItem::setData(QList data) { setName(data[0].toString()); - switch(mType) - { - case TreeItemType::Module: - { - Module* module = gNetlist->get_module_by_id(mId); - if(!module) - return; - module->set_type(data[3].toString().toStdString()); - } - case TreeItemType::Gate: - return; - } + if (mItemType == TreeItemType::Module) + setModuleType(data.at(2).toString()); } void ModuleItem::setDataAtIndex(int index, QVariant &data) { - if(index == 0) { + switch (index) { + case 0: setName(data.toString()); return; - } - else if (index == 1) + case 1: + return; + case 2: + setModuleType(data.toString()); return; - else if(index == 2) - { - switch(mType) - { - case TreeItemType::Module: - { - Module* module = gNetlist->get_module_by_id(mId); - if(!module) - return; - module->set_type(data.toString().toStdString()); - } - case TreeItemType::Gate: - return; - } } } @@ -140,8 +128,14 @@ ModuleItem::ModuleItem(const u32 id, const TreeItemType type) : return mHighlighted; } + bool ModuleItem::isToplevelItem() const + { + if (dynamic_cast(mParent)) return true; + return false; + } + ModuleItem::TreeItemType ModuleItem::getType() const{ - return mType; + return mItemType; } void ModuleItem::setName(const QString& name) @@ -159,5 +153,8 @@ ModuleItem::ModuleItem(const u32 id, const TreeItemType type) : return 3; } - void ModuleItem::appendData(QVariant data) {} + void ModuleItem::appendData(QVariant data) + { + Q_UNUSED(data); + } } diff --git a/plugins/gui/src/module_model/module_model.cpp b/plugins/gui/src/module_model/module_model.cpp index 7c645b97364..28e9de94035 100644 --- a/plugins/gui/src/module_model/module_model.cpp +++ b/plugins/gui/src/module_model/module_model.cpp @@ -13,6 +13,24 @@ namespace hal { // use root item to store header information setHeaderLabels(QStringList() << "Name" << "ID" << "Type"); + connect(gNetlistRelay, &NetlistRelay::moduleCreated, this, &ModuleModel::handleModuleCreated); + connect(gNetlistRelay, &NetlistRelay::moduleNameChanged, this, &ModuleModel::handleModuleNameChanged); + connect(gNetlistRelay, &NetlistRelay::moduleParentChanged, this, &ModuleModel::handleModuleParentChanged); + connect(gNetlistRelay, &NetlistRelay::moduleSubmoduleAdded, this, &ModuleModel::handleModuleSubmoduleAdded); + connect(gNetlistRelay, &NetlistRelay::moduleSubmoduleRemoved, this, &ModuleModel::handleModuleSubmoduleRemoved); + connect(gNetlistRelay, &NetlistRelay::moduleGateAssigned, this, &ModuleModel::handleModuleGateAssigned); + connect(gNetlistRelay, &NetlistRelay::moduleGatesAssignBegin, this, &ModuleModel::handleModuleGatesAssignBegin); + connect(gNetlistRelay, &NetlistRelay::moduleGatesAssignEnd, this, &ModuleModel::handleModuleGatesAssignEnd); + connect(gNetlistRelay, &NetlistRelay::moduleGateRemoved, this, &ModuleModel::handleModuleGateRemoved); + connect(gNetlistRelay, &NetlistRelay::moduleRemoved, this, &ModuleModel::handleModuleRemoved); + connect(gNetlistRelay, &NetlistRelay::gateNameChanged, this, &ModuleModel::handleGateNameChanged); + connect(gNetlistRelay, &NetlistRelay::netCreated, this, &ModuleModel::handleNetCreated); + connect(gNetlistRelay, &NetlistRelay::netRemoved, this, &ModuleModel::handleNetRemoved); + connect(gNetlistRelay, &NetlistRelay::netNameChanged, this, &ModuleModel::handleNetNameChanged); + connect(gNetlistRelay, &NetlistRelay::netSourceAdded, this, &ModuleModel::handleNetUpdated); + connect(gNetlistRelay, &NetlistRelay::netSourceRemoved, this, &ModuleModel::handleNetUpdated); + connect(gNetlistRelay, &NetlistRelay::netDestinationAdded, this, &ModuleModel::handleNetUpdated); + connect(gNetlistRelay, &NetlistRelay::netDestinationRemoved, this, &ModuleModel::handleNetUpdated); } QVariant ModuleModel::data(const QModelIndex& index, int role) const @@ -75,335 +93,614 @@ namespace hal return nullptr; } - QModelIndex ModuleModel::getIndex(const ModuleItem* const item) const + void ModuleModel::init() { - assert(item); - - QVector row_numbers; - const ModuleItem* current_item = item; + addRecursively(gNetlist->get_top_module()); + moduleAssignNets(); + } - while (current_item != mRootItem->getChild(0)) - { - row_numbers.append(current_item->row()); - current_item = static_cast(current_item->getParent()); - } + void ModuleModel::clear() + { + beginResetModel(); - QModelIndex model_index = index(0, 0, QModelIndex()); + BaseTreeModel::clear(); + mModuleMap.clear(); + mGateMap.clear(); + mNetMap.clear(); + endResetModel(); + } - for (QVector::const_reverse_iterator i = row_numbers.crbegin(); i != row_numbers.crend(); ++i) - model_index = index(*i, 0, model_index); + void ModuleModel::addModule(u32 id, u32 parentId) + { + Q_ASSERT(gNetlist->get_module_by_id(id)); + Q_ASSERT(gNetlist->get_module_by_id(parentId)); - return model_index; + for (auto it = mModuleMap.lowerBound(parentId); it != mModuleMap.upperBound(parentId); ++it) + { + ModuleItem* parentItem = it.value(); + createChildItem(id, ModuleItem::TreeItemType::Module, parentItem); + } } - void ModuleModel::init() + void ModuleModel::addGate(u32 id, u32 parentId) { - ModuleItem* item = new ModuleItem(1); - mModuleMap.insert(1, item); + Q_ASSERT(gNetlist->get_gate_by_id(id)); + Q_ASSERT(gNetlist->get_module_by_id(parentId)); - beginInsertRows(index(0, 0, QModelIndex()), 0, 0); - mRootItem->appendChild(item); - endInsertRows(); - Module* m = gNetlist->get_top_module(); - addRecursively(m); - for(auto net : gNetlist->get_top_module()->get_internal_nets()) + for (auto it = mModuleMap.lowerBound(parentId); it != mModuleMap.upperBound(parentId); ++it) { - addNet(net->get_id(), m->get_id()); - updateNet(net); + createChildItem(id, ModuleItem::TreeItemType::Gate, it.value()); } } - void ModuleModel::clear() + void ModuleModel::addNet(u32 id, u32 parentId) { - beginResetModel(); + Q_ASSERT(gNetlist->get_net_by_id(id)); + Q_ASSERT(gNetlist->get_module_by_id(parentId)); - BaseTreeModel::clear(); - mModuleMap.clear(); - mGateMap.clear(); - mNetMap.clear(); - //TODO : clear colors - endResetModel(); + for (auto it = mModuleMap.lowerBound(parentId); it != mModuleMap.upperBound(parentId); ++it) + { + createChildItem(id, ModuleItem::TreeItemType::Net, it.value()); + } } - void ModuleModel::addModule(u32 id, u32 parent_module) + void ModuleModel::addRecursively(const Module* module, BaseTreeItem *parentItem) { - assert(gNetlist->get_module_by_id(id)); - assert(gNetlist->get_module_by_id(parent_module)); - assert(!mModuleMap.contains(id)); - assert(mModuleMap.contains(parent_module)); - - ModuleItem* item = new ModuleItem(id); - ModuleItem* parent = mModuleMap.value(parent_module); + Q_ASSERT(module); + ModuleItem* moduleItem = createChildItem(module->get_id(), ModuleItem::TreeItemType::Module, parentItem ? parentItem : mRootItem); + Q_ASSERT(moduleItem); + for(const Module* subModule : module->get_submodules()) + addRecursively(subModule, moduleItem); + + for(const Gate* g : module->get_gates()) + createChildItem(g->get_id(), ModuleItem::TreeItemType::Gate, moduleItem); + } - item->setParent(parent); - mModuleMap.insert(id, item); + void ModuleModel::removeModule(const u32 id) + { + auto it = mModuleMap.lowerBound(id); + while (it != mModuleMap.upperBound(id)) + { + ModuleItem* item = it.value(); + BaseTreeItem* parentItem = item->getParent(); - QModelIndex index = getIndex(parent); + removeChildItem(item,parentItem); - int row = parent->getChildCount(); - mIsModifying = true; - beginInsertRows(index, row, row); - parent->appendChild(item); - mIsModifying = false; - endInsertRows(); + it = mModuleMap.erase(it); + } } - void ModuleModel::addGate(u32 id, u32 parent_module) + void ModuleModel::removeGate(const u32 id) { - assert(gNetlist->get_gate_by_id(id)); - assert(gNetlist->get_module_by_id(parent_module)); - assert(!mGateMap.contains(id)); - assert(mModuleMap.contains(parent_module)); + auto it = mGateMap.lowerBound(id); + while (it != mGateMap.upperBound(id)) + { + ModuleItem* item = it.value(); + BaseTreeItem* parentItem = item->getParent(); - ModuleItem* item = new ModuleItem(id, ModuleItem::TreeItemType::Gate); - ModuleItem* parent = mModuleMap.value(parent_module); + removeChildItem(item, parentItem); - item->setParent(parent); - mGateMap.insert(id, item); + it = mGateMap.erase(it); + } + } - QModelIndex index = getIndex(parent); + void ModuleModel::removeNet(const u32 id) + { + auto it = mNetMap.lowerBound(id); + while (it != mNetMap.upperBound(id)) + { + ModuleItem* item = it.value(); + BaseTreeItem* parentItem = item->getParent(); - int row = parent->getChildCount(); - mIsModifying = true; - beginInsertRows(index, row, row); - parent->appendChild(item); - mIsModifying = false; - endInsertRows(); + removeChildItem(item, parentItem); + + it = mNetMap.erase(it); + } } - void ModuleModel::addNet(u32 id, u32 parent_module) + void ModuleModel::removeChildItem(ModuleItem *itemToRemove, BaseTreeItem *parentItem) { - assert(gNetlist->get_net_by_id(id)); - assert(gNetlist->get_module_by_id(parent_module)); - assert(!mNetMap.contains(id)); - assert(mModuleMap.contains(parent_module)); + Q_ASSERT(itemToRemove); + Q_ASSERT(parentItem); - ModuleItem* item = new ModuleItem(id, ModuleItem::TreeItemType::Net); - ModuleItem* parent = mModuleMap.value(parent_module); + while (itemToRemove->getChildCount()) + { + ModuleItem* childItem = static_cast(itemToRemove->getChildren().at(0)); + int ityp = static_cast(childItem->getType()); + auto it = mModuleItemMaps[ityp]->lowerBound(childItem->id()); + while (it != mModuleItemMaps[ityp]->upperBound(childItem->id())) + { + if (it.value() == childItem) + it = mModuleItemMaps[ityp]->erase(it); + else + ++it; + } + removeChildItem(childItem,itemToRemove); + } - item->setParent(parent); - mNetMap.insert(id, item); + QModelIndex index = getIndexFromItem(parentItem); - QModelIndex index = getIndex(parent); + int row = itemToRemove->row(); - int row = parent->getChildCount(); mIsModifying = true; - beginInsertRows(index, row, row); - parent->appendChild(item); + beginRemoveRows(index, row, row); + parentItem->removeChild(itemToRemove); + endRemoveRows(); mIsModifying = false; - endInsertRows(); + + delete itemToRemove; } - void ModuleModel::addRecursively(const Module* module) + void ModuleModel::handleModuleNameChanged(Module* mod) { - if(!module->is_top_module()) - addModule(module->get_id(), module->get_parent_module()->get_id()); - for(auto &m : module->get_submodules()) - addRecursively(m); + updateModuleName(mod->get_id()); + } - for(auto &g : module->get_gates()) - addGate(g->get_id(), module->get_id()); + void ModuleModel::handleModuleRemoved(Module* mod) + { + removeModule(mod->get_id()); } - void ModuleModel::removeModule(const u32 id) + void ModuleModel::handleModuleCreated(Module* mod) { - assert(id != 1); - // module was most likely already purged from netlist - assert(mModuleMap.contains(id)); + if (mod->get_parent_module() == nullptr) return; + addModule(mod->get_id(), mod->get_parent_module()->get_id()); + } - ModuleItem* item = mModuleMap.value(id); - ModuleItem* parent = static_cast(item->getParent()); - assert(item); - assert(parent); + void ModuleModel::handleModuleGateAssigned(Module* mod, u32 gateId) + { + if (mTempGateAssignment.isAccumulate()) + mTempGateAssignment.assignGateToModule(gateId,mod); + else + { + moduleAssignGate(mod->get_id(), gateId); + moduleAssignNets({gateId}); + } + } - QModelIndex index = getIndex(parent); + void ModuleModel::handleModuleGateRemoved(Module* mod, u32 gateId) + { + if (mTempGateAssignment.isAccumulate()) + mTempGateAssignment.removeGateFromModule(gateId,mod); + else + { + auto it = mGateMap.lowerBound(gateId); + while (it != mGateMap.upperBound(gateId)) + { + ModuleItem* item = it.value(); + if (!item->isToplevelItem()) + { + ModuleItem* parentItem = static_cast(item->getParent()); + if (parentItem->id() == mod->get_id()) + { + removeChildItem(item, parentItem); + it = mGateMap.erase(it); + continue; + } + } + ++it; + } + } + } - int row = item->row(); + void ModuleModel::handleModuleGatesAssignBegin(Module* mod, u32 numberGates) + { + Q_UNUSED(mod); + Q_UNUSED(numberGates); + mTempGateAssignment.beginAccumulate(); + } - mIsModifying = true; - beginRemoveRows(index, row, row); - parent->removeChild(item); - mIsModifying = false; - endRemoveRows(); + void ModuleModel::handleModuleGatesAssignEnd(Module* mod, u32 numberGates) + { + Q_UNUSED(mod); + Q_UNUSED(numberGates); + mTempGateAssignment.endAccumulate(); + if (!mTempGateAssignment.isAccumulate()) + { + for (auto it = mTempGateAssignment.mGateAssign.begin(); it != mTempGateAssignment.mGateAssign.end(); ++it) + { + moduleAssignGate(it.value()->get_id(), it.key()); // moduleId, gateId + } + moduleAssignNets(mTempGateAssignment.mGateAssign.keys()); + mTempGateAssignment.mGateAssign.clear(); + mTempGateAssignment.mGateRemove.clear(); + } + } - mModuleMap.remove(id); - delete item; + void ModuleModel::handleGateRemoved(Gate* gat) + { + removeGate(gat->get_id()); } - void ModuleModel::removeGate(const u32 id) + void ModuleModel::handleGateCreated(Gate* gat) { - //assert(gNetlist->get_gate_by_id(id)); - assert(mGateMap.contains(id)); + Module* mod = gat->get_module(); + if (mod) moduleAssignGate(mod->get_id(), gat->get_id()); + } - ModuleItem* item = mGateMap.value(id); - ModuleItem* parent = static_cast(item->getParent()); - assert(item); - assert(parent); + void ModuleModel::handleGateNameChanged(Gate* gat) + { + updateGateName(gat->get_id()); + } - QModelIndex index = getIndex(parent); + void ModuleModel::handleNetCreated(Net* net) + { + addNet(net->get_id(), gNetlist->get_top_module()->get_id()); + } - int row = item->row(); + void ModuleModel::handleNetRemoved(Net* net) + { + removeNet(net->get_id()); + } - mIsModifying = true; - beginRemoveRows(index, row, row); - parent->removeChild(item); - mIsModifying = false; - endRemoveRows(); + void ModuleModel::handleNetNameChanged(Net* net) + { + updateNetName(net->get_id()); + } - mGateMap.remove(id); - delete item; + void ModuleModel::handleNetUpdated(Net* net, u32 data) + { + Q_UNUSED(data); + updateNetParent(net); } - void ModuleModel::removeNet(const u32 id) + void ModuleModel::handleModuleParentChanged(const Module* mod) { - //assert(gNetlist->get_net_by_id(id)); - if(!mNetMap.contains(id)) // global nets are not contained in the item model - return; + Q_ASSERT(mod); + updateModuleParent(mod); - ModuleItem* item = mNetMap.value(id); - ModuleItem* parent = static_cast(item->getParent()); - assert(item); - assert(parent); + QHash parentAssignment; + std::unordered_set assignedNets; + findNetParentRecursion(mRootItem, parentAssignment, assignedNets); - QModelIndex index = getIndex(parent); + for(Net* net : mod->get_nets()) + updateNetParent(net, &parentAssignment); + } - int row = item->row(); + void ModuleModel::handleModuleSubmoduleAdded(Module* mod, u32 submodId) + { + Q_UNUSED(mod); + Q_UNUSED(submodId); + } - mIsModifying = true; - beginRemoveRows(index, row, row); - parent->removeChild(item); - mIsModifying = false; - endRemoveRows(); + void ModuleModel::handleModuleSubmoduleRemoved(Module* mod, u32 submodId) + { + Q_UNUSED(mod); + Q_UNUSED(submodId); + } - mNetMap.remove(id); - delete item; + void ModuleModel::findNetParentRecursion(BaseTreeItem* parent, QHash &parentAssignment, std::unordered_set& assignedNets) const + { + for (BaseTreeItem* bti : parent->getChildren()) + { + ModuleItem* item = dynamic_cast(bti); + if (!item || item->getType() != ModuleItem::TreeItemType::Module) continue; + findNetParentRecursion(item, parentAssignment, assignedNets); + Module* m = gNetlist->get_module_by_id(item->id()); + Q_ASSERT(m); + std::unordered_set internalNets = m->get_nets(); + if (!internalNets.empty()) + { + for (Net* n : assignedNets) + internalNets.erase(n); + for (Net* n : m->get_input_nets()) + internalNets.erase(n); + for (Net* n : m->get_output_nets()) + internalNets.erase(n); + } + for (Net* n : internalNets) + { + parentAssignment[n] = item; + assignedNets.insert(n); + } + } } - void ModuleModel::handleModuleParentChanged(const Module* module) + Module* ModuleModel::findNetParent(const Net *net) const { - assert(module); - updateModuleParent(module); + QHash modHash; + if (net->is_global_input_net() || net->is_global_output_net()) return nullptr; + int maxDepth = 0; + + for (const Endpoint* ep : net->get_sources()) + { + Module* m = ep->get_gate()->get_module(); + Q_ASSERT(m); + int depth = m->get_submodule_depth(); + if (depth > maxDepth) maxDepth = depth; + modHash.insert(m,depth); + } - for(Net* net : module->get_nets()) - updateNet(net); + for (const Endpoint* ep : net->get_destinations()) + { + Module* m = ep->get_gate()->get_module(); + Q_ASSERT(m); + int depth = m->get_submodule_depth(); + if (depth > maxDepth) maxDepth = depth; + modHash.insert(m,depth); + } + + while (modHash.size() > 1 && maxDepth > 0) + { + auto it = modHash.begin(); + while (it != modHash.end()) + { + if (it.value() == maxDepth) + { + Module* parentMod = it.key()->get_parent_module(); + modHash.erase(it); + if (parentMod) modHash.insert(parentMod,maxDepth-1); + break; + } + ++it; + } + if (it == modHash.end()) + --maxDepth; + } + if (modHash.empty()) return nullptr; + return modHash.begin().key(); } - void ModuleModel::handleModuleGateAssinged(const u32 id, const u32 parent_module) + void ModuleModel::moduleAssignGate(const u32 moduleId, const u32 gateId) { // Don't need new function handleModuleGateRemoved(), because the GateAssinged event always follows GateRemoved // or NetlistInternalManager updates Net connections when a gate is deleted. - if(!mGateMap.contains(id)) - addGate(id, parent_module); - - Gate* gate = gNetlist->get_gate_by_id(id); - for(Net* in_net : gate->get_fan_in_nets()) - updateNet(in_net); - for(Net* in_net : gate->get_fan_out_nets()) - updateNet(in_net); + QSet parentsHandled; + Q_ASSERT(gNetlist->get_gate_by_id(gateId)); + + auto itGat = mGateMap.lowerBound(gateId); + while (itGat != mGateMap.upperBound(gateId)) + { + ModuleItem* gatItem = itGat.value(); + if (gatItem->isToplevelItem()) continue; + ModuleItem* oldParentItem = static_cast(gatItem->getParent()); + Q_ASSERT(oldParentItem); + + if (oldParentItem->id() != moduleId) + { + removeChildItem(gatItem,oldParentItem); + itGat = mGateMap.erase(itGat); + } + else + { + parentsHandled.insert(oldParentItem); + ++itGat; + } + + } + + if (!moduleId) return; + for (auto itMod = mModuleMap.lowerBound(moduleId); itMod != mModuleMap.upperBound(moduleId); ++itMod) + { + ModuleItem* parentItem = itMod.value(); + if (parentsHandled.contains(parentItem)) continue; + createChildItem(gateId, ModuleItem::TreeItemType::Gate, parentItem); + } + } - void ModuleModel::updateNet(const Net* net) + void ModuleModel::moduleAssignNets(const QList& gateIds) { - assert(net); - u32 id = net->get_id(); + QHash parentAssignment; + std::unordered_set assignedNets; + findNetParentRecursion(mRootItem, parentAssignment, assignedNets); + + QSet netsToAssign; + if (gateIds.isEmpty()) + { +#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + QList tempKeys = parentAssignment.keys(); + netsToAssign = QSet(tempKeys.begin(),tempKeys.end()); +#else + netsToAssign = parentAssignment.keys().toSet(); +#endif + } + else + { + for (u32 id : gateIds) + { + Gate* gate = gNetlist->get_gate_by_id(id); + for(Net* in_net : gate->get_fan_in_nets()) + netsToAssign.insert(in_net); + for(Net* out_net : gate->get_fan_out_nets()) + netsToAssign.insert(out_net); + } + } + + for (const Net* n: netsToAssign) + updateNetParent(n, &parentAssignment); + } + + void ModuleModel::updateNetParent(const Net* net, const QHash *parentAssignment) + { + Q_ASSERT(net); + u32 netId = net->get_id(); + + QSet parentsHandled; + u32 newParentId = 0; + if (parentAssignment) + { + ModuleItem* modItem = parentAssignment->value(net); + if (modItem) + newParentId = modItem->id(); + } + else + { + Module* newParentModule = findNetParent(net); + if (newParentModule) + newParentId = newParentModule->get_id(); + } - if(!mNetMap.contains(id)) - return; + auto itNet = mNetMap.lowerBound(netId); + while (itNet != mNetMap.upperBound(netId)) + { + if (itNet.value()->isToplevelItem()) continue; - ModuleItem* item = mNetMap.value(id); - ModuleItem* oldParentItem = static_cast(item->getParent()); - assert(oldParentItem); - - Module* newParentModule = findNetParent(net); - if(newParentModule == nullptr) - newParentModule = gNetlist->get_top_module(); - if(newParentModule->get_id() == oldParentItem->id()) - return; - - assert(mModuleMap.contains(newParentModule->get_id())); - ModuleItem* newParentItem = mModuleMap[newParentModule->get_id()]; - QModelIndex newIndex = getIndex(newParentItem); - QModelIndex oldIndex = getIndex(oldParentItem); - int row = item->row(); + ModuleItem* netItem = itNet.value(); + ModuleItem* oldParentItem = static_cast(netItem->getParent()); + Q_ASSERT(oldParentItem); - mIsModifying = true; - beginMoveRows(oldIndex, row, row, newIndex, newParentItem->getChildCount()); - oldParentItem->removeChild(item); - newParentItem->appendChild(item); - mIsModifying = false; - endMoveRows(); + + if (newParentId == 0 || newParentId != oldParentItem->id()) + { + removeChildItem(netItem,oldParentItem); + itNet = mNetMap.erase(itNet); + } + else + { + parentsHandled.insert(oldParentItem); + ++itNet; + } + } + + if (!newParentId) return; + for (auto itMod = mModuleMap.lowerBound(newParentId); itMod != mModuleMap.upperBound(newParentId); ++itMod) + { + ModuleItem* parentItem = itMod.value(); + if (parentsHandled.contains(parentItem)) continue; + createChildItem(net->get_id(), ModuleItem::TreeItemType::Net, parentItem); + } } - void ModuleModel::updateModuleParent(const Module* module){ - assert(module); + void ModuleModel::updateModuleParent(const Module* module) + { + ModuleItem* moduleItemToBeMoved = nullptr; + bool moduleItemReassigned = false; + + Q_ASSERT(module); u32 id = module->get_id(); - assert(id != 1); - assert(mModuleMap.contains(id)); - ModuleItem* item = mModuleMap.value(id); - ModuleItem* oldParent = static_cast(item->getParent()); - assert(oldParent); + Q_ASSERT(id != 1); - assert(module->get_parent_module()); - if(oldParent->id() == module->get_parent_module()->get_id()) - return; + QSet parentsHandled; + u32 parentId = module->get_parent_module()->get_id(); + Q_ASSERT(parentId > 0); - assert(mModuleMap.contains(module->get_parent_module()->get_id())); - ModuleItem* newParent = mModuleMap.value(module->get_parent_module()->get_id()); + auto itSubm = mModuleMap.lowerBound(id); + while (itSubm != mModuleMap.upperBound(id)) + { + ModuleItem* submItem = itSubm.value(); + if (submItem->isToplevelItem()) continue; + ModuleItem* oldParentItem = static_cast(submItem->getParent()); + Q_ASSERT(oldParentItem); - QModelIndex oldIndex = getIndex(oldParent); - QModelIndex newIndex = getIndex(newParent); - int row = item->row(); + if (oldParentItem->id() != parentId) + { + if (moduleItemToBeMoved) + { + // remove tree item recursively + removeChildItem(submItem,oldParentItem); + itSubm = mModuleMap.erase(itSubm); + } + else + { + // save tree item for reassignment + moduleItemToBeMoved = submItem; + QModelIndex index = getIndexFromItem(oldParentItem); + + int row = submItem->row(); + + mIsModifying = true; + beginRemoveRows(index, row, row); + oldParentItem->removeChild(submItem); + endRemoveRows(); + mIsModifying = false; + ++itSubm; + } + } + else + { + parentsHandled.insert(oldParentItem); + ++itSubm; + } + } + + if (!parentId) return; + for (auto itMod = mModuleMap.lowerBound(parentId); itMod != mModuleMap.upperBound(parentId); ++itMod) + { + ModuleItem* parentItem = itMod.value(); + if (parentsHandled.contains(parentItem)) continue; + if (moduleItemToBeMoved && !moduleItemReassigned) + { + QModelIndex index = getIndexFromItem(parentItem); + int row = parentItem->getChildCount(); + mIsModifying = true; + beginInsertRows(index, row, row); + parentItem->appendChild(moduleItemToBeMoved); + endInsertRows(); + mIsModifying = false; + moduleItemReassigned = true; + } + else + { + addRecursively(module, parentItem); + } + } + + if (moduleItemToBeMoved && !moduleItemReassigned) + { + // stored item could not be reassigned, delete it + auto it = mModuleMap.lowerBound(id); + while (it != mModuleMap.upperBound(id)) + { + if (it.value() == moduleItemToBeMoved) + it = mModuleMap.erase(it); + else + ++it; + } + delete moduleItemToBeMoved; + } - mIsModifying = true; - beginMoveRows(oldIndex, row, row, newIndex, newParent->getChildCount()); - oldParent->removeChild(item); - newParent->appendChild(item); - mIsModifying = false; - endMoveRows(); } void ModuleModel::updateModuleName(u32 id) { - assert(gNetlist->get_module_by_id(id)); - assert(mModuleMap.contains(id)); + Q_ASSERT(gNetlist->get_module_by_id(id)); - ModuleItem* item = mModuleMap.value(id); - assert(item); + for (auto it = mModuleMap.lowerBound(id); it != mModuleMap.upperBound(id); ++it) + { + ModuleItem* item = it.value(); + Q_ASSERT(item); - item->setName(QString::fromStdString(gNetlist->get_module_by_id(id)->get_name())); // REMOVE & ADD AGAIN + item->setName(QString::fromStdString(gNetlist->get_module_by_id(id)->get_name())); // REMOVE & ADD AGAIN - QModelIndex index = getIndex(item); - Q_EMIT dataChanged(index, index); + QModelIndex index = getIndexFromItem(item); + Q_EMIT dataChanged(index, index); + } } void ModuleModel::updateGateName(u32 id) { - assert(gNetlist->get_gate_by_id(id)); - assert(mGateMap.contains(id)); + Q_ASSERT(gNetlist->get_gate_by_id(id)); - ModuleItem* item = mGateMap.value(id); - assert(item); + for (auto it = mGateMap.lowerBound(id); it != mGateMap.upperBound(id); ++it) + { + ModuleItem* item = it.value(); + Q_ASSERT(item); - item->setName(QString::fromStdString(gNetlist->get_gate_by_id(id)->get_name())); // REMOVE & ADD AGAIN + item->setName(QString::fromStdString(gNetlist->get_gate_by_id(id)->get_name())); // REMOVE & ADD AGAIN - QModelIndex index = getIndex(item); - Q_EMIT dataChanged(index, index); + QModelIndex index = getIndexFromItem(item); + Q_EMIT dataChanged(index, index); + } } void ModuleModel::updateNetName(u32 id) { - assert(gNetlist->get_net_by_id(id)); - assert(mNetMap.contains(id)); + Q_ASSERT(gNetlist->get_net_by_id(id)); + Q_ASSERT(mNetMap.contains(id)); - ModuleItem* item = mNetMap.value(id); - assert(item); + for (auto it = mNetMap.lowerBound(id); it != mNetMap.upperBound(id); ++it) + { + ModuleItem* item = it.value(); + Q_ASSERT(item); - item->setName(QString::fromStdString(gNetlist->get_net_by_id(id)->get_name())); // REMOVE & ADD AGAIN + item->setName(QString::fromStdString(gNetlist->get_net_by_id(id)->get_name())); // REMOVE & ADD AGAIN - QModelIndex index = getIndex(item); - Q_EMIT dataChanged(index, index); + QModelIndex index = getIndexFromItem(item); + Q_EMIT dataChanged(index, index); + } } ModuleItem* ModuleModel::getItem(u32 id, ModuleItem::TreeItemType type) const @@ -411,45 +708,27 @@ namespace hal return mModuleItemMaps[(int)type]->value(id); } - bool ModuleModel::isModifying() + ModuleItem* ModuleModel::createChildItem(u32 id, ModuleItem::TreeItemType itemType, BaseTreeItem *parentItem) { - return mIsModifying; - } - - Module* ModuleModel::findNetParent(const Net* net){ - // cannot use Module::get_internal_nets(), because currently that function is implemented so, - // that a net can be "internal" to multiple modules at the same depth. - // => instead manually search for deepest module, that contains all sources and destinations of net. - assert(net); - if(net->get_num_of_sources() == 0 && net->get_num_of_destinations() == 0) - return nullptr; - - std::vector endpoints = net->get_sources(); - - { - std::vector destinations = net->get_destinations(); - endpoints.insert(endpoints.end(), destinations.begin(), destinations.end()); - } + ModuleItem* retval = new ModuleItem(id, itemType); + mModuleItemMaps[(int)itemType]->insertMulti(id,retval); - Module* parent = endpoints[0]->get_gate()->get_module(); - endpoints.erase(endpoints.begin()); + if (!parentItem) parentItem = mRootItem; + QModelIndex index = getIndexFromItem(parentItem); + int row = parentItem->getChildCount(); + mIsModifying = true; + beginInsertRows(index, row, row); + parentItem->appendChild(retval); + endInsertRows(); + mIsModifying = false; - // might want to split up endpoints, if sources and destinations should be handled differently - while(endpoints.size() > 0) - { - std::vector::iterator it = endpoints.begin(); - while(it != endpoints.end()) - { - if(parent->contains_gate((*it)->get_gate(), true)) - it = endpoints.erase(it); - else - ++it; - } + return retval; + } - if(endpoints.size() > 0) - parent = parent->get_parent_module(); - } - return parent; + bool ModuleModel::isModifying() + { + return mIsModifying; } + } diff --git a/plugins/gui/src/module_widget/module_widget.cpp b/plugins/gui/src/module_widget/module_widget.cpp index bde1cf6be42..8013912b997 100644 --- a/plugins/gui/src/module_widget/module_widget.cpp +++ b/plugins/gui/src/module_widget/module_widget.cpp @@ -62,7 +62,8 @@ namespace hal mRenameAction->setToolTip("Rename"); mToggleExpandTreeAction->setToolTip("Toggle expand all / collapse all"); - mModuleProxyModel->setSourceModel(gNetlistRelay->getModuleModel()); + mModuleModel = new ModuleModel(this); + mModuleProxyModel->setSourceModel(mModuleModel); mTreeView->setModel(mModuleProxyModel); mTreeView->setDefaultColumnWidth(); @@ -75,10 +76,9 @@ namespace hal mTreeView->setExpandsOnDoubleClick(false); mTreeView->setSelectionBehavior(QAbstractItemView::SelectRows); mTreeView->setSelectionMode(QAbstractItemView::SingleSelection); - mTreeView->expandAllModules(); mContentLayout->addWidget(mTreeView); - mSearchbar->setColumnNames(gNetlistRelay->getModuleModel()->headerLabels()); + mSearchbar->setColumnNames(mModuleModel->headerLabels()); mContentLayout->addWidget(mSearchbar); mSearchbar->hide(); @@ -91,7 +91,7 @@ namespace hal connect(mTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ModuleWidget::handleTreeSelectionChanged); connect(mTreeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModuleWidget::handleCurrentChanged); connect(mTreeView, &ModuleTreeView::doubleClicked, this, &ModuleWidget::handleItemDoubleClicked); - connect(gSelectionRelay, &SelectionRelay::selectionChanged, this, &ModuleWidget::handleSelectionChanged); + connect(gSelectionRelay, &SelectionRelay::selectionChanged, this, &ModuleWidget::handleSelectionChanged, Qt::QueuedConnection); connect(gNetlistRelay, &NetlistRelay::moduleSubmoduleRemoved, this, &ModuleWidget::handleModuleRemoved); connect(mSearchAction, &QAction::triggered, this, &ModuleWidget::toggleSearchbar); @@ -113,6 +113,9 @@ namespace hal connect(mToggleGatesAction, &QAction::triggered, this, &ModuleWidget::handleToggleGatesClicked); connect(mToggleExpandTreeAction, &QAction::triggered, this, &ModuleWidget::handleToggleExpandTreeClicked); connect(mRenameAction, &QAction::triggered, this, &ModuleWidget::handleRenameClicked); + + mModuleModel->init(); + mTreeView->expandAllModules(); } void ModuleWidget::enableDeleteAction(bool enable) @@ -432,7 +435,7 @@ namespace hal Q_UNUSED(selected) Q_UNUSED(deselected) - if (mIgnoreSelectionChange || gNetlistRelay->getModuleModel()->isModifying()) + if (mIgnoreSelectionChange || mModuleModel->isModifying()) return; gSelectionRelay->clear(); @@ -608,8 +611,12 @@ namespace hal for (auto module_id : gSelectionRelay->selectedModulesList()) { - QModelIndex index = mModuleProxyModel->mapFromSource(gNetlistRelay->getModuleModel()->getIndex(gNetlistRelay->getModuleModel()->getItem(module_id))); - module_selection.select(index, index); + ModuleItem* item = mModuleModel->getItem(module_id); + if(item) + { + QModelIndex index = mModuleProxyModel->mapFromSource(mModuleModel->getIndexFromItem(item)); + module_selection.select(index, index); + } } mTreeView->selectionModel()->select(module_selection, QItemSelectionModel::SelectionFlag::ClearAndSelect); @@ -619,7 +626,7 @@ namespace hal ModuleItem* ModuleWidget::getModuleItemFromIndex(const QModelIndex& index) { - return gNetlistRelay->getModuleModel()->getItem(mModuleProxyModel->mapToSource(index)); + return mModuleModel->getItem(mModuleProxyModel->mapToSource(index)); } void ModuleWidget::updateSearchIcon() @@ -630,6 +637,11 @@ namespace hal mSearchAction->setIcon(gui_utility::getStyledSvgIcon(mSearchIconStyle, mSearchIconPath)); } + ModuleModel* ModuleWidget::getModuleModel() const + { + return mModuleModel; + } + QString ModuleWidget::disabledIconStyle() const { return mDisabledIconStyle; diff --git a/plugins/gui/src/netlist_relay/netlist_relay.cpp b/plugins/gui/src/netlist_relay/netlist_relay.cpp index 1132ffc8db2..51c154a50d7 100644 --- a/plugins/gui/src/netlist_relay/netlist_relay.cpp +++ b/plugins/gui/src/netlist_relay/netlist_relay.cpp @@ -28,7 +28,7 @@ namespace hal { NetlistRelay::NetlistRelay(QObject* parent) - : QObject(parent), mModuleModel(new ModuleModel(this)), mModuleColorManager(new ModuleColorManager(this)) + : QObject(parent), mModuleColorManager(new ModuleColorManager(this)) { connect(FileManager::get_instance(), &FileManager::fileOpened, this, &NetlistRelay::debugHandleFileOpened); // DEBUG LINE connect(this, &NetlistRelay::signalThreadEvent, this, &NetlistRelay::handleThreadEvent, Qt::BlockingQueuedConnection); @@ -85,11 +85,6 @@ namespace hal return mModuleColorManager->moduleColor(id); } - ModuleModel* NetlistRelay::getModuleModel() const - { - return mModuleModel; - } - ModuleColorManager* NetlistRelay::getModuleColorManager() const { return mModuleColorManager; @@ -380,7 +375,6 @@ namespace hal // suppress actions if we receive this for the top module if (mod->get_parent_module() != nullptr) { - mModuleModel->addModule(mod->get_id(), mod->get_parent_module()->get_id()); mModuleColorManager->setRandomColor(mod->get_id()); } @@ -393,7 +387,6 @@ namespace hal //< no associated_data mModuleColorManager->removeColor(mod->get_id()); - mModuleModel->removeModule(mod->get_id()); gGraphContextManager->handleModuleRemoved(mod); gSelectionRelay->handleModuleRemoved(mod->get_id()); @@ -404,8 +397,6 @@ namespace hal case ModuleEvent::event::name_changed: { //< no associated_data - mModuleModel->updateModuleName(mod->get_id()); - gGraphContextManager->handleModuleNameChanged(mod); Q_EMIT moduleNameChanged(mod); @@ -414,8 +405,6 @@ namespace hal case ModuleEvent::event::parent_changed: { //< no associated_data - mModuleModel->handleModuleParentChanged(mod); - Q_EMIT moduleParentChanged(mod); break; } @@ -438,7 +427,6 @@ namespace hal case ModuleEvent::event::gate_assigned: { //< associated_data = id of inserted gate - mModuleModel->handleModuleGateAssinged(associated_data, mod->get_id()); gGraphContextManager->handleModuleGateAssigned(mod, associated_data); Q_EMIT moduleGateAssigned(mod, associated_data); @@ -447,18 +435,18 @@ namespace hal case ModuleEvent::event::gate_removed: { //< associated_data = id of removed gate - mModuleModel->removeGate(associated_data); gGraphContextManager->handleModuleGateRemoved(mod, associated_data); Q_EMIT moduleGateRemoved(mod, associated_data); break; } case ModuleEvent::event::pin_changed: { - //< no associated_data - - gGraphContextManager->handleModulePortsChanged(mod); + //< associated_data = [4LSB: type of action] [28HSB: id of pin group or pin] + PinEvent pev = (PinEvent) (associated_data&0xF); + u32 id = (associated_data >> 4); + gGraphContextManager->handleModulePortsChanged(mod,pev,id); - Q_EMIT modulePortsChanged(mod); + Q_EMIT modulePortsChanged(mod,pev,id); break; } case ModuleEvent::event::type_changed: { @@ -535,7 +523,6 @@ namespace hal case GateEvent::event::name_changed: { //< no associated_data - mModuleModel->updateGateName(gat->get_id()); gGraphContextManager->handleGateNameChanged(gat); Q_EMIT gateNameChanged(gat); @@ -580,7 +567,6 @@ namespace hal case NetEvent::event::created: { //< no associated_data - mModuleModel->addNet(net->get_id(), gNetlist->get_top_module()->get_id()); gGraphContextManager->handleNetCreated(net); Q_EMIT netCreated(net); @@ -589,7 +575,6 @@ namespace hal case NetEvent::event::removed: { //< no associated_data - mModuleModel->removeNet(net->get_id()); gGraphContextManager->handleNetRemoved(net); gSelectionRelay->handleNetRemoved(net->get_id()); @@ -599,7 +584,6 @@ namespace hal case NetEvent::event::name_changed: { //< no associated_data - mModuleModel->updateNetName(net->get_id()); gGraphContextManager->handleNetNameChanged(net); Q_EMIT netNameChanged(net); @@ -618,7 +602,6 @@ namespace hal case NetEvent::event::src_added: { //< associated_data = id of src gate - mModuleModel->updateNet(net); gGraphContextManager->handleNetSourceAdded(net, associated_data); Q_EMIT netSourceAdded(net, associated_data); @@ -627,7 +610,6 @@ namespace hal case NetEvent::event::src_removed: { //< associated_data = id of src gate - mModuleModel->updateNet(net); gGraphContextManager->handleNetSourceRemoved(net, associated_data); Q_EMIT netSourceRemoved(net, associated_data); @@ -636,7 +618,6 @@ namespace hal case NetEvent::event::dst_added: { //< associated_data = id of dst gate - mModuleModel->updateNet(net); gGraphContextManager->handleNetDestinationAdded(net, associated_data); Q_EMIT netDestinationAdded(net, associated_data); @@ -645,7 +626,6 @@ namespace hal case NetEvent::event::dst_removed: { //< associated_data = id of dst gate - mModuleModel->updateNet(net); gGraphContextManager->handleNetDestinationRemoved(net, associated_data); Q_EMIT netDestinationRemoved(net, associated_data); @@ -681,16 +661,23 @@ namespace hal } } + void NetlistRelay::dumpModuleRecursion(Module *m) + { + for (int i=0; iget_submodule_depth(); i++) + std::cerr << " "; + std::cerr << "Mod " << m->get_id() << " <" << m->get_name() << ">\n"; + for (Module* sm : m->get_submodules()) + dumpModuleRecursion(sm); + } + void NetlistRelay::debugHandleFileOpened() { for (Module* m : gNetlist->get_modules()) mModuleColorManager->setRandomColor(m->get_id()); - mModuleModel->init(); mColorSerializer.restore(mModuleColorManager); } void NetlistRelay::debugHandleFileClosed() { - mModuleModel->clear(); } } // namespace hal diff --git a/plugins/gui/src/selection_details_widget/gate_details_widget/gate_pin_tree.cpp b/plugins/gui/src/selection_details_widget/gate_details_widget/gate_pin_tree.cpp index f1ed3a05928..754770955ef 100644 --- a/plugins/gui/src/selection_details_widget/gate_details_widget/gate_pin_tree.cpp +++ b/plugins/gui/src/selection_details_widget/gate_details_widget/gate_pin_tree.cpp @@ -69,11 +69,11 @@ namespace hal if(!idx.isValid()) return; - auto clickedItem = mPinModel->getItemFromIndex(idx); - if(mPinModel->getTypeOfItem(clickedItem) != GatePinsTreeModel::itemType::pin) + PinTreeItem* clickedItem = dynamic_cast(mPinModel->getItemFromIndex(idx)); + if(!clickedItem || clickedItem->type() != PinTreeItem::Pin) return; - auto netId = mPinModel->getNetIDsOfTreeItem(clickedItem).front(); + auto netId = clickedItem->netIds().front(); auto clickedNet = gNetlist->get_net_by_id(netId); if(clickedNet) { @@ -96,9 +96,8 @@ namespace hal if(!idx.isValid()) return; - BaseTreeItem* clickedItem = mPinModel->getItemFromIndex(idx); + PinTreeItem* clickedItem = dynamic_cast(mPinModel->getItemFromIndex(idx)); QMenu menu; - GatePinsTreeModel::itemType type = mPinModel->getTypeOfItem(clickedItem); bool isMiscSectionSet = false;//so that the misc-section is not set multiple times //PLAINTEXT: NAME, DIRECTION, TYPE @@ -118,9 +117,9 @@ namespace hal }); //Check if jump to source or destination is possible - if(type == GatePinsTreeModel::itemType::pin && mPinModel->getNetIDsOfTreeItem(clickedItem).size()==1) + if(clickedItem->type() == PinTreeItem::Pin && clickedItem->netIds().size()==1) { - auto netId = mPinModel->getNetIDsOfTreeItem(clickedItem).front(); + auto netId = clickedItem->netIds().front(); auto clickedNet = gNetlist->get_net_by_id(netId); if(clickedNet) { @@ -156,15 +155,19 @@ namespace hal } //Add nets to selection if possible - QList netIds; - if(type == GatePinsTreeModel::itemType::pin) + QList netIds; + if(clickedItem->type() == PinTreeItem::Pin) { - netIds = mPinModel->getNetIDsOfTreeItem(clickedItem); + netIds = clickedItem->netIds(); } else { for(auto childItem : clickedItem->getChildren()) - netIds.append(mPinModel->getNetIDsOfTreeItem(childItem)); + { + PinTreeItem* pti = dynamic_cast(childItem); + if (pti) + netIds.append(pti->netIds()); + } } if(netIds.size() != 0) { @@ -191,7 +194,7 @@ namespace hal menu.addSection("Python"); - if(type == GatePinsTreeModel::itemType::pin) + if(clickedItem->type() == PinTreeItem::Pin) buildPythonMenuForPin(menu, clickedItem); else buildPythonMenuForPinGroup(menu, clickedItem); @@ -201,10 +204,10 @@ namespace hal } - void GatePinTree::buildPythonMenuForPin(QMenu &menu, BaseTreeItem *clickedPinItem) + void GatePinTree::buildPythonMenuForPin(QMenu &menu, PinTreeItem *clickedPinItem) { // 1.) NET-OBJECT - QList netIdsOfItem = mPinModel->getNetIDsOfTreeItem(clickedPinItem); + QList netIdsOfItem = clickedPinItem->netIds(); QString pythonCommandNetIds, pythonCommandName; if(netIdsOfItem.size() == 1) @@ -243,7 +246,7 @@ namespace hal } - void GatePinTree::buildPythonMenuForPinGroup(QMenu &menu, BaseTreeItem *clickedPinIGrouptem) + void GatePinTree::buildPythonMenuForPinGroup(QMenu &menu, PinTreeItem *clickedPinIGrouptem) { // 1. PYTHON LIST OF PIN GROUPS QString pythonList = "["; diff --git a/plugins/gui/src/selection_details_widget/gate_details_widget/pin_tree_model.cpp b/plugins/gui/src/selection_details_widget/gate_details_widget/pin_tree_model.cpp index c4b62870444..34e85964008 100644 --- a/plugins/gui/src/selection_details_widget/gate_details_widget/pin_tree_model.cpp +++ b/plugins/gui/src/selection_details_widget/gate_details_widget/pin_tree_model.cpp @@ -99,7 +99,7 @@ namespace hal void GatePinsTreeModel::clear() { BaseTreeModel::clear(); - mPinGroupingToTreeItem.clear(); + mPinGroupToTreeItem.clear(); mGateId = -1; } @@ -121,7 +121,7 @@ namespace hal //evaluate netname (in case of inout multiple possible nets), method depends on pindirection (kind of ugly switch) QString netName = ""; - QList netIDs; + QList netIDs; switch (direction) { case PinDirection::input: @@ -159,20 +159,20 @@ namespace hal } pinItem->setData(QList() << QString::fromStdString(pin->get_name()) << pinDirection << pinType << netName); - pinItem->setAdditionalData(keyType, QVariant::fromValue(itemType::pin)); - pinItem->setAdditionalData(keyRepresentedNetsID, QVariant::fromValue(netIDs)); + pinItem->setType(PinTreeItem::Pin); + pinItem->setNetIds(netIDs); if (!grouping.empty()) { - BaseTreeItem* groupingsItem = mPinGroupingToTreeItem.value(grouping, nullptr); //since its a map, its okay - if (!groupingsItem) + PinTreeItem* pingroupItem = dynamic_cast(mPinGroupToTreeItem.value(grouping, nullptr)); //since its a map, its okay + if (!pingroupItem) { //assume all items in the same grouping habe the same direction and type, so the grouping-item has also these types - groupingsItem = new PinTreeItem(grouping, pinDirection, pinType, ""); - groupingsItem->setAdditionalData(keyType, QVariant::fromValue(itemType::grouping)); - mRootItem->appendChild(groupingsItem); - mPinGroupingToTreeItem.insert(grouping, groupingsItem); + pingroupItem = new PinTreeItem(grouping, pinDirection, pinType, ""); + pingroupItem->setType(PinTreeItem::Group); + mRootItem->appendChild(pingroupItem); + mPinGroupToTreeItem.insert(grouping, pingroupItem); } - groupingsItem->appendChild(pinItem); + pingroupItem->appendChild(pinItem); } else mRootItem->appendChild(pinItem); @@ -185,16 +185,6 @@ namespace hal return mGateId; } - QList GatePinsTreeModel::getNetIDsOfTreeItem(BaseTreeItem* item) - { - return item->getAdditionalData(keyRepresentedNetsID).value>(); - } - - GatePinsTreeModel::itemType GatePinsTreeModel::getTypeOfItem(BaseTreeItem* item) - { - return item->getAdditionalData(keyType).value(); - } - int GatePinsTreeModel::getNumberOfDisplayedPins() { Gate* g = gNetlist->get_gate_by_id(mGateId); diff --git a/plugins/gui/src/selection_details_widget/module_details_tab_widget.cpp b/plugins/gui/src/selection_details_widget/module_details_tab_widget.cpp index d97e986f8aa..bf04ac12806 100644 --- a/plugins/gui/src/selection_details_widget/module_details_tab_widget.cpp +++ b/plugins/gui/src/selection_details_widget/module_details_tab_widget.cpp @@ -67,16 +67,20 @@ namespace hal { setIcon(SelectionDetailsIconProvider::ModuleIcon, module->get_id()); mModuleId = module->get_id(); + //pass module or other stuff to widgets + mModuleInfoTable->setModule(module); + mPinsTree->setModule(module); + mElementsTree->setModule(module); + mGroupingsOfItemTable->setModule(module); + mDataTable->setModule(module); + mCommentWidget->nodeChanged(Node(module->get_id(), Node::NodeType::Module)); } else + { mModuleId = 0; - //pass module or other stuff to widgets - mModuleInfoTable->setModule(module); - mPinsTree->setModule(module); - mElementsTree->setModule(module); - mGroupingsOfItemTable->setModule(module); - mDataTable->setModule(module); - mCommentWidget->nodeChanged(Node(module->get_id(), Node::NodeType::Module)); + mElementsTree->removeContent(); + mCommentWidget->nodeChanged(Node()); + } } void ModuleDetailsTabWidget::clear() diff --git a/plugins/gui/src/selection_details_widget/module_details_widget/module_elements_tree.cpp b/plugins/gui/src/selection_details_widget/module_details_widget/module_elements_tree.cpp index 208a6c1d362..30e3cf47006 100644 --- a/plugins/gui/src/selection_details_widget/module_details_widget/module_elements_tree.cpp +++ b/plugins/gui/src/selection_details_widget/module_details_widget/module_elements_tree.cpp @@ -61,9 +61,9 @@ namespace hal if(!clickedIndex.isValid()) return; - BaseTreeItem* clickedItem = mModel->getItemFromIndex(clickedIndex); + ModuleTreeitem* clickedItem = dynamic_cast(mModel->getItemFromIndex(clickedIndex)); int id = clickedItem->getData(ModuleTreeModel::sIdColumn).toInt(); - ModuleTreeModel::itemType type = mModel->getTypeOfItem(clickedItem); + ModuleTreeitem::ItemType type = clickedItem->itemType(); QMenu menu; //menu.addSection("here comes the plaintext"); @@ -97,8 +97,8 @@ namespace hal gSelectionRelay->clear(); switch(type) { - case ModuleTreeModel::itemType::module: gSelectionRelay->addModule(id); break; - case ModuleTreeModel::itemType::gate: gSelectionRelay->addGate(id); break; + case ModuleTreeitem::Module: gSelectionRelay->addModule(id); break; + case ModuleTreeitem::Gate: gSelectionRelay->addGate(id); break; } gSelectionRelay->relaySelectionChanged(this); } @@ -109,8 +109,8 @@ namespace hal { switch(type) { - case ModuleTreeModel::itemType::module: gSelectionRelay->addModule(id); break; - case ModuleTreeModel::itemType::gate: gSelectionRelay->addGate(id); break; + case ModuleTreeitem::Module: gSelectionRelay->addModule(id); break; + case ModuleTreeitem::Gate: gSelectionRelay->addGate(id); break; } gSelectionRelay->relaySelectionChanged(this); } @@ -122,8 +122,8 @@ namespace hal Node nd; switch(type) { - case ModuleTreeModel::itemType::module: nd = Node(id, Node::Module); break; - case ModuleTreeModel::itemType::gate: nd = Node(id, Node::Gate); break; + case ModuleTreeitem::Module: nd = Node(id, Node::Module); break; + case ModuleTreeitem::Gate: nd = Node(id, Node::Gate); break; } SelectionTreeView::isolateInNewViewAction(nd); } @@ -134,16 +134,16 @@ namespace hal { switch(type) { - case ModuleTreeModel::itemType::module: gContentManager->getGraphTabWidget()->handleModuleFocus(id); break; - case ModuleTreeModel::itemType::gate: gContentManager->getGraphTabWidget()->handleGateFocus(id); break; + case ModuleTreeitem::Module: gContentManager->getGraphTabWidget()->handleModuleFocus(id); break; + case ModuleTreeitem::Gate: gContentManager->getGraphTabWidget()->handleGateFocus(id); break; } } ); menu.addSection("Python Code"); - QString pythonGetObject = (type == ModuleTreeModel::itemType::module) ? PyCodeProvider::pyCodeModule(id) : PyCodeProvider::pyCodeGate(id); - QString pythonDescription = (type == ModuleTreeModel::itemType::module) ? "Get module" : "Get gate"; + QString pythonGetObject = (type == ModuleTreeitem::Module) ? PyCodeProvider::pyCodeModule(id) : PyCodeProvider::pyCodeGate(id); + QString pythonDescription = (type == ModuleTreeitem::Module) ? "Get module" : "Get gate"; menu.addAction(QIcon(":/icons/python"), pythonDescription, [pythonGetObject]() { diff --git a/plugins/gui/src/selection_details_widget/module_details_widget/module_ports_tree.cpp b/plugins/gui/src/selection_details_widget/module_details_widget/module_ports_tree.cpp index c4c34d3d2a2..b38eea359f7 100644 --- a/plugins/gui/src/selection_details_widget/module_details_widget/module_ports_tree.cpp +++ b/plugins/gui/src/selection_details_widget/module_details_widget/module_ports_tree.cpp @@ -12,6 +12,7 @@ #include "gui/user_action/action_remove_items_from_object.h" #include "gui/user_action/action_rename_object.h" #include "gui/user_action/action_set_object_type.h" +#include "gui/user_action/action_pingroup.h" #include "gui/user_action/user_action_compound.h" #include "hal_core/netlist/gate_library/enums/pin_direction.h" #include "hal_core/netlist/gate_library/enums/pin_type.h" @@ -87,8 +88,7 @@ namespace hal return; //all relevant information - PortTreeItem* clickedItem = static_cast(mPortModel->getItemFromIndex(clickedIndex)); - ModulePinsTreeModel::itemType type = mPortModel->getTypeOfItem(clickedItem); + PortTreeItem* clickedItem = static_cast(mPortModel->getItemFromIndex(clickedIndex)); Net* n = mPortModel->getNetFromItem(clickedItem); QString name = clickedItem->getData(ModulePinsTreeModel::sNameColumn).toString(); u32 modId = mPortModel->getRepresentedModuleId(); @@ -97,7 +97,7 @@ namespace hal std::pair sameGroup; bool onlyPins; std::tie(selectedPins, sameGroup, onlyPins) = getSelectedPins(); - int itemId = mPortModel->getIdOfItem(clickedItem); + int itemId = clickedItem->id(); QMenu menu; //shared plaintext entries: NAME, DIRECTION, TYPE (shared with pins and groups) @@ -119,30 +119,28 @@ namespace hal // } if (addToExistingActionPossible) { - menu.addAction("Add selection to existing pin group", [this, selectedPins, mod]() { + menu.addAction("Add selection to existing pin group", [selectedPins, mod]() { PingroupSelectorDialog psd("Pingroup selector", "Select pingroup", mod, false); if (psd.exec() == QDialog::Accepted) { - QSet pinSet; + QList pins; auto* pinGroup = mod->get_pin_group_by_id(psd.getSelectedGroupId()); if (pinGroup == nullptr) return; for (auto item : selectedPins) { - auto* pin = mod->get_pin_by_id(mPortModel->getIdOfItem(item)); + auto* pin = mod->get_pin_by_id(static_cast(item)->id()); if (pin == nullptr) return; - pinSet.insert(pin->get_id()); + pins.append(pin->get_id()); } - ActionAddItemsToObject* act = new ActionAddItemsToObject(QSet(), QSet(), QSet(), pinSet); - act->setObject(UserActionObject(pinGroup->get_id(), UserActionObjectType::PinGroup)); - act->setParentObject(UserActionObject(mod->get_id(), UserActionObjectType::Module)); - act->exec(); + ActionPingroup* act = ActionPingroup::addPinsToExistingGroup(mod,pinGroup->get_id(),pins); + if (act) act->exec(); } }); } - if (type == ModulePinsTreeModel::itemType::group) //group specific context, own helper function? (returns at the end) + if (clickedItem->itemType() == PortTreeItem::Group) //group specific context, own helper function? (returns at the end) { menu.addAction("Change name", [name, modId, itemId]() { InputDialog ipd("Change pin group name", "New group name", name); @@ -153,10 +151,9 @@ namespace hal auto* group = gNetlist->get_module_by_id(modId)->get_pin_group_by_id(itemId); if (group != nullptr) { - ActionRenameObject* renameObj = new ActionRenameObject(ipd.textValue()); - renameObj->setObject(UserActionObject(group->get_id(), UserActionObjectType::PinGroup)); - renameObj->setParentObject(UserActionObject(modId, UserActionObjectType::Module)); - renameObj->exec(); + ActionPingroup* act = new ActionPingroup(PinActionType::GroupRename,itemId,ipd.textValue()); + act->setObject(UserActionObject(modId, UserActionObjectType::Module)); + act->exec(); } } }); @@ -164,10 +161,8 @@ namespace hal auto* pinGroup = mod->get_pin_group_by_id(itemId); if (pinGroup != nullptr) { - ActionDeleteObject* delObj = new ActionDeleteObject; - delObj->setObject(UserActionObject(pinGroup->get_id(), UserActionObjectType::PinGroup)); - delObj->setParentObject(UserActionObject(mod->get_id(), UserActionObjectType::Module)); - delObj->exec(); + ActionPingroup* act = ActionPingroup::deletePinGroup(mod,itemId); + if (act) act->exec(); } }); @@ -193,10 +188,9 @@ namespace hal auto* pin = mod->get_pin_by_id(itemId); if (pin != nullptr) { - ActionRenameObject* renameObj = new ActionRenameObject(ipd.textValue()); - renameObj->setObject(UserActionObject(pin->get_id(), UserActionObjectType::Pin)); - renameObj->setParentObject(UserActionObject(mod->get_id(), UserActionObjectType::Module)); - renameObj->exec(); + ActionPingroup* act = new ActionPingroup(PinActionType::PinRename,pin->get_id(),ipd.textValue()); + act->setObject(UserActionObject(mod->get_id(), UserActionObjectType::Module)); + act->exec(); } } }); @@ -214,9 +208,10 @@ namespace hal if (cbd.exec() == QDialog::Accepted) { - ActionSetObjectType* act = new ActionSetObjectType(cbd.textValue()); - act->setObject(UserActionObject(pin->get_id(), UserActionObjectType::Pin)); - act->setParentObject(UserActionObject(mod->get_id(), UserActionObjectType::Module)); + PinType ptype = enum_from_string(cbd.textValue().toStdString(),PinType::none); + + ActionPingroup* act = new ActionPingroup(PinActionType::PinTypeChange,pin->get_id(),"",(int)ptype); + act->setObject(UserActionObject(mod->get_id(), UserActionObjectType::Module)); act->exec(); } }); @@ -233,15 +228,13 @@ namespace hal //can be both single(simple right-click, no real selection) and multi-selection if (sameGroup.first && mod->get_pin_group_by_id(sameGroup.second)->size() > 1) { - menu.addAction("Remove selection from group", [this, selectedPins, mod, sameGroup]() { - QSet pins; + menu.addAction("Remove selection from group", [selectedPins, mod /*, sameGroup*/]() { + QList pins; for (auto item : selectedPins) - pins.insert(mPortModel->getIdOfItem(item)); + pins.append(static_cast(item)->id()); - ActionRemoveItemsFromObject* act = new ActionRemoveItemsFromObject(QSet(), QSet(), QSet(), pins); - act->setObject(UserActionObject(mod->get_pin_group_by_id(sameGroup.second)->get_id(), UserActionObjectType::PinGroup)); - act->setParentObject(UserActionObject(mod->get_id(), UserActionObjectType::Module)); - act->exec(); + ActionPingroup* act = ActionPingroup::removePinsFromGroup(mod, pins); + if (act) act->exec(); }); } @@ -250,7 +243,7 @@ namespace hal appendMultiSelectionEntries(menu, modId); menu.addSection("Python"); - if(type == ModulePinsTreeModel::itemType::pin) + if(clickedItem->itemType()==PortTreeItem::Pin) menu.addAction(QIcon(":/icons/python"), "Get pin", [modId, itemId]() { QApplication::clipboard()->setText(PyCodeProvider::pyCodeModulePinById(modId, itemId)); }); else menu.addAction(QIcon(":/icons/python"), "Get group", [modId, itemId]() { QApplication::clipboard()->setText(PyCodeProvider::pyCodeModulePinGroup(modId, itemId)); }); @@ -272,28 +265,22 @@ namespace hal std::tie(selectedPins, sameGroup, onlyPins) = getSelectedPins(); if (selectedPins.size() > 1) { - menu.addAction("Add objects to new pin group", [this, selectedPins, modId]() { + menu.addAction("Add objects to new pin group", [selectedPins, modId]() { InputDialog ipd("Pingroup name", "New pingroup name", "ExampleName"); if (ipd.exec() == QDialog::Accepted && !ipd.textValue().isEmpty()) { - QSet pins; - auto mod = gNetlist->get_module_by_id(modId); + QList pins; + Module* mod = gNetlist->get_module_by_id(modId); for (auto item : selectedPins) { - auto* pin = mod->get_pin_by_id(mPortModel->getIdOfItem(item)); + auto* pin = mod->get_pin_by_id(static_cast(item)->id()); if (pin == nullptr) return; - pins.insert(pin->get_id()); + pins.append(pin->get_id()); } - UserActionCompound* act = new UserActionCompound; - act->setUseCreatedObject(); - ActionCreateObject* actCreate = new ActionCreateObject(UserActionObjectType::PinGroup, ipd.textValue()); - actCreate->setParentObject(UserActionObject(modId, UserActionObjectType::Module)); - ActionAddItemsToObject* actAdd = new ActionAddItemsToObject(QSet(), QSet(), QSet(), pins); - actAdd->setUsedInCreateContext(); - act->addAction(actCreate); - act->addAction(actAdd); - act->exec(); + + ActionPingroup* act = ActionPingroup::addPinsToNewGroup(mod,ipd.textValue(),pins); + if (act) act->exec(); } }); } @@ -309,8 +296,7 @@ namespace hal for (auto index : selectionModel()->selectedRows()) { PortTreeItem* item = static_cast(mPortModel->getItemFromIndex(index)); - auto itemType = mPortModel->getTypeOfItem(item); - if (itemType == ModulePinsTreeModel::itemType::pin) + if (item->itemType() == PortTreeItem::Pin) { if (!alreadyProcessedPins.contains(item)) { @@ -318,7 +304,7 @@ namespace hal alreadyProcessedPins.insert(item); } } - else if (itemType == ModulePinsTreeModel::itemType::group) + else if (item->itemType() == PortTreeItem::Group) { onlyPins = false; for (auto pinItem : item->getChildren()) @@ -335,11 +321,11 @@ namespace hal if (!selectedPins.isEmpty()) { auto mod = gNetlist->get_module_by_id(mModuleID); - auto* firstPin = mod->get_pin_by_id(mPortModel->getIdOfItem(selectedPins.front())); + auto* firstPin = mod->get_pin_by_id(static_cast(selectedPins.front())->id()); groupId = firstPin->get_group().first->get_id(); for (auto pinTreeItem : selectedPins) { - auto pin = mod->get_pin_by_id(mPortModel->getIdOfItem(pinTreeItem)); + auto pin = mod->get_pin_by_id(static_cast(pinTreeItem)->id()); if (groupId != (int)pin->get_group().first->get_id()) { sameGroup = false; diff --git a/plugins/gui/src/selection_details_widget/module_details_widget/module_tree_model.cpp b/plugins/gui/src/selection_details_widget/module_details_widget/module_tree_model.cpp index 76b19c5a5f8..630bed28d37 100644 --- a/plugins/gui/src/selection_details_widget/module_details_widget/module_tree_model.cpp +++ b/plugins/gui/src/selection_details_widget/module_details_widget/module_tree_model.cpp @@ -9,35 +9,29 @@ namespace hal { - ModuleTreeitem::ModuleTreeitem(const std::string &name, int id, std::string tp) - : mType(tp), mId(id), mName(name) + ModuleTreeitem::ModuleTreeitem(ItemType itp, int id, const QString &name, const QString &ntp) + : mItemType(itp), mId(id), mName(name), mNodeType(ntp) {;} QVariant ModuleTreeitem::getData(int index) const { switch (index) { - case 0: { - QVariant qvName = QVariant(QString::fromStdString(mName)); - return qvName; - break;} - case 1: { - QVariant qvId = QVariant(mId); - return qvId; - break;} - case 2: { - QVariant qvType = QVariant(QString::fromStdString(mType)); - return qvType; - break;} + case 0: + return mName; + case 1: + return mId; + case 2: + return mNodeType; } return QVariant(); } void ModuleTreeitem::setData(QList data) { - mName = data[0].toString().toStdString(); + mName = data[0].toString(); mId = data[1].toInt(); - mType = data[2].toString().toStdString(); + mNodeType = data[2].toString(); } void ModuleTreeitem::setDataAtIndex(int index, QVariant &data) @@ -46,13 +40,13 @@ namespace hal switch (index) { - case 0: mName = data.toString().toStdString(); break; + case 0: mName = data.toString(); break; case 1: mId = data.toInt(); break; case 2: for (int j=0; j<3; j++) if (data.toString() == ctyp[j]) { - mType = data.toString().toStdString(); + mNodeType = data.toString(); break; } } @@ -101,21 +95,21 @@ namespace hal //add modules for(auto mod : m->get_submodules()) { - ModuleTreeitem* modItem = new ModuleTreeitem(mod->get_name(), - mod->get_id(), mod->get_type()); + ModuleTreeitem* modItem = new ModuleTreeitem(ModuleTreeitem::Module, + mod->get_id(), + QString::fromStdString(mod->get_name()), + QString::fromStdString(mod->get_type())); moduleRecursive(mod, modItem); - modItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::module)); - modItem->setAdditionalData(mKeyRepId, mod->get_id()); mRootItem->appendChild(modItem); mModuleToTreeitems.insert(mod, modItem); } //add gates for(auto gate : m->get_gates()) { - ModuleTreeitem* gateItem = new ModuleTreeitem(gate->get_name(), - gate->get_id(), gate->get_type()->get_name()); - gateItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::gate)); - gateItem->setAdditionalData(mKeyRepId, gate->get_id()); + ModuleTreeitem* gateItem = new ModuleTreeitem(ModuleTreeitem::Gate, + gate->get_id(), + QString::fromStdString(gate->get_name()), + QString::fromStdString(gate->get_type()->get_name())); mRootItem->appendChild(gateItem); mGateToTreeitems.insert(gate, gateItem); } @@ -138,42 +132,37 @@ namespace hal if(!index.isValid()) return QVariant(); - BaseTreeItem* item = getItemFromIndex(index); + ModuleTreeitem* item = dynamic_cast(getItemFromIndex(index)); if(!item) return QVariant(); if(role == Qt::DecorationRole && index.column() == 0) - return getIconFromItem(getItemFromIndex(index)); + return getIconFromItem(item); //yes, it performs the same two checks again, should be okay though (in terms of performance) return BaseTreeModel::data(index, role); } - ModuleTreeModel::itemType ModuleTreeModel::getTypeOfItem(BaseTreeItem *item) const - { - return item->getAdditionalData(mKeyItemType).value(); - } - void ModuleTreeModel::moduleRecursive(Module *mod, BaseTreeItem *modItem) { ModuleTreeitem* subModItem = nullptr; for(Module* subMod : mod->get_submodules()) { - subModItem = new ModuleTreeitem(subMod->get_name(), - subMod->get_id(), subMod->get_type()); + subModItem = new ModuleTreeitem(ModuleTreeitem::Module, + subMod->get_id(), + QString::fromStdString(subMod->get_name()), + QString::fromStdString(subMod->get_type())); moduleRecursive(subMod, subModItem); - subModItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::module)); - subModItem->setAdditionalData(mKeyRepId, subMod->get_id()); modItem->appendChild(subModItem); mModuleToTreeitems.insert(subMod, subModItem); } for(auto gate : mod->get_gates()) { - ModuleTreeitem* gateItem = new ModuleTreeitem(gate->get_name(), - gate->get_id(), gate->get_type()->get_name()); - gateItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::gate)); - gateItem->setAdditionalData(mKeyRepId, gate->get_id()); + ModuleTreeitem* gateItem = new ModuleTreeitem(ModuleTreeitem::Gate, + gate->get_id(), + QString::fromStdString(gate->get_name()), + QString::fromStdString(gate->get_type()->get_name())); modItem->appendChild(gateItem); mGateToTreeitems.insert(gate, gateItem); } @@ -190,8 +179,10 @@ namespace hal //1. Find index of first gate-type item int startIndex = 0; for(; startIndex < modItem->getChildCount(); startIndex++) - if(getTypeOfItem(modItem->getChild(startIndex)) != itemType::module) + { + if(static_cast(modItem->getChild(startIndex))->itemType() != ModuleTreeitem::Module) break; + } beginResetModel(); @@ -213,10 +204,10 @@ namespace hal beginResetModel(); for(auto gate : mod->get_gates()) { - ModuleTreeitem* gateItem = new ModuleTreeitem(gate->get_name(), - gate->get_id(), gate->get_type()->get_name()); - gateItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::gate)); - gateItem->setAdditionalData(mKeyRepId, gate->get_id()); + ModuleTreeitem* gateItem = new ModuleTreeitem(ModuleTreeitem::Gate, + gate->get_id(), + QString::fromStdString(gate->get_name()), + QString::fromStdString(gate->get_type()->get_name())); modItem->appendChild(gateItem); mGateToTreeitems.insert(gate, gateItem); } @@ -224,17 +215,17 @@ namespace hal endResetModel(); } - QIcon ModuleTreeModel::getIconFromItem(BaseTreeItem *item) const + QIcon ModuleTreeModel::getIconFromItem(ModuleTreeitem *item) const { if(!item) return QIcon(); u32 id = item->getData(1).toInt(); - switch (getTypeOfItem(item)) + switch (item->itemType()) { - case itemType::module: + case ModuleTreeitem::Module: return QIcon(*SelectionDetailsIconProvider::instance()->getIcon(SelectionDetailsIconProvider::ModuleIcon,id)); - case itemType::gate: + case ModuleTreeitem::Gate: return QIcon(*SelectionDetailsIconProvider::instance()->getIcon(SelectionDetailsIconProvider::GateIcon,id)); default: return QIcon(); @@ -298,11 +289,11 @@ namespace hal { beginResetModel(); auto addedMod = gNetlist->get_module_by_id(added_module); - ModuleTreeitem* addedSubmodItem = new ModuleTreeitem(addedMod->get_name(), addedMod->get_id(), - addedMod->get_type()); + ModuleTreeitem* addedSubmodItem = new ModuleTreeitem(ModuleTreeitem::Module, + addedMod->get_id(), + QString::fromStdString(addedMod->get_name()), + QString::fromStdString(addedMod->get_type())); moduleRecursive(addedMod, addedSubmodItem); - addedSubmodItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::module)); - addedSubmodItem->setAdditionalData(mKeyRepId, addedMod->get_id()); parentModItem ? parentModItem->insertChild(0, addedSubmodItem) : mRootItem->insertChild(0, addedSubmodItem); mModuleToTreeitems.insert(addedMod, addedSubmodItem); endResetModel(); @@ -322,11 +313,11 @@ namespace hal treeItemsQueue.enqueue(removedModItem); while(!treeItemsQueue.isEmpty()) { - BaseTreeItem* current = treeItemsQueue.dequeue(); - switch (getTypeOfItem(current)) + ModuleTreeitem* current = static_cast(treeItemsQueue.dequeue()); + switch (current->itemType()) { - case itemType::module: mModuleToTreeitems.remove(gNetlist->get_module_by_id(current->getData(ModuleTreeModel::sIdColumn).toInt())); break; - case itemType::gate: mGateToTreeitems.remove(gNetlist->get_gate_by_id(current->getData(ModuleTreeModel::sIdColumn).toInt()));break; + case ModuleTreeitem::Module: mModuleToTreeitems.remove(gNetlist->get_module_by_id(current->getData(ModuleTreeModel::sIdColumn).toInt())); break; + case ModuleTreeitem::Gate: mGateToTreeitems.remove(gNetlist->get_gate_by_id(current->getData(ModuleTreeModel::sIdColumn).toInt()));break; } for(auto child : current->getChildren()) treeItemsQueue.enqueue(child); @@ -353,12 +344,13 @@ namespace hal auto assignedGate = gNetlist->get_gate_by_id(assigned_gate); int indexToInsert = 0; //first item after the modules for(; indexToInsert < modItem->getChildCount(); indexToInsert++) - if(getTypeOfItem(modItem->getChild(indexToInsert)) != itemType::module) + if(static_cast(modItem->getChild(indexToInsert))->itemType() != ModuleTreeitem::Module) break; - ModuleTreeitem* gateItem = new ModuleTreeitem(assignedGate->get_name(), - assignedGate->get_id(), assignedGate->get_type()->get_name()); - gateItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::gate)); + ModuleTreeitem* gateItem = new ModuleTreeitem(ModuleTreeitem::Gate, + assignedGate->get_id(), + QString::fromStdString(assignedGate->get_name()), + QString::fromStdString(assignedGate->get_type()->get_name())); mGateToTreeitems.insert(assignedGate, gateItem); //beginInsertRows(getIndexFromItem(modItem), indexToInsert, indexToInsert); beginResetModel(); diff --git a/plugins/gui/src/selection_details_widget/module_details_widget/netlist_elements_tree_model.cpp b/plugins/gui/src/selection_details_widget/module_details_widget/netlist_elements_tree_model.cpp index c17b91f3735..bf68a43ff41 100644 --- a/plugins/gui/src/selection_details_widget/module_details_widget/netlist_elements_tree_model.cpp +++ b/plugins/gui/src/selection_details_widget/module_details_widget/netlist_elements_tree_model.cpp @@ -10,26 +10,20 @@ namespace hal { - NetlistElementsTreeitem::NetlistElementsTreeitem(const QString &name, int id, QString tp) - : mType(tp), mId(id), mName(name) + NetlistElementsTreeitem::NetlistElementsTreeitem(ItemType itp, u32 id_, const QString &name, const QString &ntp) + : mItemType(itp), mId(id_), mName(name), mNodeType(ntp) {;} QVariant NetlistElementsTreeitem::getData(int index) const { switch (index) { - case 0: { - QVariant qvName = QVariant(mName); - return qvName; - break;} - case 1: { - QVariant qvId = QVariant(mId); - return qvId; - break;} - case 2: { - QVariant qvType = QVariant(mType); - return qvType; - break;} + case 0: + return mName; + case 1: + return mId; + case 2: + return mNodeType; } return QVariant(); } @@ -38,7 +32,7 @@ namespace hal { mName = data[0].toString(); mId = data[1].toInt(); - mType = data[2].toString(); + mNodeType = data[2].toString(); } @@ -54,7 +48,7 @@ namespace hal for (int j=0; j<3; j++) if (data.toString() == ctyp[j]) { - mType = data.toString(); + mNodeType = data.toString(); break; } } @@ -143,12 +137,12 @@ namespace hal Module* mod = gNetlist->get_module_by_id(id); if(!mod) continue; - NetlistElementsTreeitem* modItem = new NetlistElementsTreeitem(QString::fromStdString(mod->get_name()), - mod->get_id(), QString::fromStdString(mod->get_type())); + NetlistElementsTreeitem* modItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Module, + mod->get_id(), + QString::fromStdString(mod->get_name()), + QString::fromStdString(mod->get_type())); if(displayModulesRecursive) moduleRecursive(mod, modItem, showGatesInSubmods, showNetsInSubmods); - modItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::module)); - modItem->setAdditionalData(keyRepresentedID, mod->get_id()); mRootItem->appendChild(modItem); mModuleToTreeitems.insert(mod, modItem); } @@ -156,20 +150,19 @@ namespace hal for(int id : gateIds) { Gate* gate = gNetlist->get_gate_by_id(id); - NetlistElementsTreeitem* gateItem = new NetlistElementsTreeitem(QString::fromStdString(gate->get_name()), - gate->get_id(), QString::fromStdString(gate->get_type()->get_name())); - gateItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::gate)); - gateItem->setAdditionalData(keyRepresentedID, gate->get_id()); + NetlistElementsTreeitem* gateItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Gate, + gate->get_id(), + QString::fromStdString(gate->get_name()), + QString::fromStdString(gate->get_type()->get_name())); mRootItem->appendChild(gateItem); mGateToTreeitems.insert(gate, gateItem); } for(int id : netIds) { Net* net = gNetlist->get_net_by_id(id); - NetlistElementsTreeitem* netItem = new NetlistElementsTreeitem(QString::fromStdString(net->get_name()), - net->get_id(), ""); - netItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::net)); - netItem->setAdditionalData(keyRepresentedID, net->get_id()); + NetlistElementsTreeitem* netItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Net, + net->get_id(), + QString::fromStdString(net->get_name())); mRootItem->appendChild(netItem); mNetToTreeitems.insert(net, netItem); } @@ -197,16 +190,6 @@ namespace hal Q_EMIT numberOfSubmodulesChanged(mod->get_submodules().size()); } - NetlistElementsTreeModel::itemType NetlistElementsTreeModel::getTypeOfItem(NetlistElementsTreeitem *item) const - { - return item->getAdditionalData(keyItemType).value(); - } - - int NetlistElementsTreeModel::getRepresentedIdOfItem(NetlistElementsTreeitem *item) const - { - return item->getAdditionalData(keyRepresentedID).toInt(); - } - void NetlistElementsTreeModel::gateNameChanged(Gate *g) { for(BaseTreeItem* gateItem : mGateToTreeitems.values(g)) @@ -300,13 +283,13 @@ namespace hal while(!treeItemsQueue.isEmpty()) { NetlistElementsTreeitem* currentItem = treeItemsQueue.dequeue(); - int id = currentItem->getAdditionalData(keyRepresentedID).toUInt(); + int id = currentItem->id(); - switch (getTypeOfItem(currentItem)) + switch (currentItem->itemType()) { - case itemType::module: mModuleToTreeitems.remove(gNetlist->get_module_by_id(id),currentItem); break; - case itemType::gate: mGateToTreeitems.remove(gNetlist->get_gate_by_id(id), currentItem); break; - case itemType::net: mNetToTreeitems.remove(gNetlist->get_net_by_id(id), currentItem); break; + case NetlistElementsTreeitem::Module : mModuleToTreeitems.remove(gNetlist->get_module_by_id(id),currentItem); break; + case NetlistElementsTreeitem::Gate : mGateToTreeitems.remove(gNetlist->get_gate_by_id(id), currentItem); break; + case NetlistElementsTreeitem::Net : mNetToTreeitems.remove(gNetlist->get_net_by_id(id), currentItem); break; } for(BaseTreeItem* child : currentItem->getChildren()){ @@ -347,14 +330,14 @@ namespace hal int indexToInsert = 0; for(; indexToInsert < modItem->getChildCount(); indexToInsert++) { NetlistElementsTreeitem* neti = static_cast(modItem->getChild(indexToInsert)); - if(getTypeOfItem(neti) != itemType::module) + if(neti->itemType() != NetlistElementsTreeitem::Module) break; } - NetlistElementsTreeitem* gateItem = new NetlistElementsTreeitem(QString::fromStdString(assignedGate->get_name()), - assignedGate->get_id(), QString::fromStdString(assignedGate->get_type()->get_name())); - gateItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::gate)); - gateItem->setAdditionalData(keyRepresentedID, assignedGate->get_id()); + NetlistElementsTreeitem* gateItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Gate, + assignedGate->get_id(), + QString::fromStdString(assignedGate->get_name()), + QString::fromStdString(assignedGate->get_type()->get_name())); //beginInsertRows(getIndexFromItem(modItem), indexToInsert, indexToInsert); beginResetModel(); modItem->insertChild(indexToInsert, gateItem); @@ -391,11 +374,11 @@ namespace hal Module* addedModule = gNetlist->get_module_by_id(added_module); auto appendNewSubmodItem = [this, addedModule](BaseTreeItem* parentModItem){ - NetlistElementsTreeitem* addedSubmodItem = new NetlistElementsTreeitem(QString::fromStdString(addedModule->get_name()), - addedModule->get_id(), QString::fromStdString(addedModule->get_type())); + NetlistElementsTreeitem* addedSubmodItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Module, + addedModule->get_id(), + QString::fromStdString(addedModule->get_name()), + QString::fromStdString(addedModule->get_type())); moduleRecursive(addedModule, addedSubmodItem, mGatesDisplayed, mNetsDisplayed); - addedSubmodItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::module)); - addedSubmodItem->setAdditionalData(keyRepresentedID, addedModule->get_id()); parentModItem->insertChild(0, addedSubmodItem); mModuleToTreeitems.insert(addedModule, addedSubmodItem); if(mNetsDisplayed) { @@ -423,11 +406,11 @@ namespace hal NetlistElementsTreeitem* subModItem = nullptr; for(Module* subMod : mod->get_submodules()) { - subModItem = new NetlistElementsTreeitem(QString::fromStdString(subMod->get_name()), - subMod->get_id(), QString::fromStdString(subMod->get_type())); + subModItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Module, + subMod->get_id(), + QString::fromStdString(subMod->get_name()), + QString::fromStdString(subMod->get_type())); moduleRecursive(subMod, subModItem, showGates); - subModItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::module)); - subModItem->setAdditionalData(keyRepresentedID, subMod->get_id()); modItem->appendChild(subModItem); mModuleToTreeitems.insert(subMod, subModItem); } @@ -435,10 +418,10 @@ namespace hal { for(auto gate : mod->get_gates()) { - NetlistElementsTreeitem* gateItem = new NetlistElementsTreeitem(QString::fromStdString(gate->get_name()), - gate->get_id(), QString::fromStdString(gate->get_type()->get_name())); - gateItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::gate)); - gateItem->setAdditionalData(keyRepresentedID, gate->get_id()); + NetlistElementsTreeitem* gateItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Gate, + gate->get_id(), + QString::fromStdString(gate->get_name()), + QString::fromStdString(gate->get_type()->get_name())); modItem->appendChild(gateItem); mGateToTreeitems.insert(gate, gateItem); } @@ -447,10 +430,10 @@ namespace hal { for(auto net : mod->get_internal_nets()) { - NetlistElementsTreeitem* netItem = new NetlistElementsTreeitem(QString::fromStdString(net->get_name()), - net->get_id(), ""); - netItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::net)); - netItem->setAdditionalData(keyRepresentedID, net->get_id()); + NetlistElementsTreeitem* netItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Net, + net->get_id(), + QString::fromStdString(net->get_name()), + ""); modItem->appendChild(netItem); mNetToTreeitems.insert(net, netItem); } @@ -463,11 +446,11 @@ namespace hal return QIcon(); u32 id = item->getData(1).toInt(); - switch (getTypeOfItem(item)) + switch (item->itemType()) { - case itemType::module: + case NetlistElementsTreeitem::Module: return QIcon(*SelectionDetailsIconProvider::instance()->getIcon(SelectionDetailsIconProvider::ModuleIcon,id)); - case itemType::gate: + case NetlistElementsTreeitem::Gate: return QIcon(*SelectionDetailsIconProvider::instance()->getIcon(SelectionDetailsIconProvider::GateIcon,id)); default: return QIcon(); @@ -477,27 +460,26 @@ namespace hal void NetlistElementsTreeModel::updateInternalNetsOfModule(NetlistElementsTreeitem *moduleItem) { BaseTreeItem* moduleItemBase = static_cast(moduleItem); - BaseTreeItem* mRootBase = static_cast(mRootItem); - int moduleId = (moduleItemBase == mRootBase) ? mModId : moduleItem->getAdditionalData(keyRepresentedID).toInt(); + BaseTreeItem* mRootBase = static_cast(mRootItem); + int moduleId = (moduleItemBase == mRootBase) ? mModId : moduleItem->id(); Module* mod = gNetlist->get_module_by_id(moduleId); //remove and delte the last child of the module-item until no net items are left - while(moduleItem->getChildCount() > 0 && getTypeOfItem(static_cast(moduleItem->getChild(moduleItem->getChildCount()-1))) == itemType::net) + while(moduleItem->getChildCount() > 0 && static_cast(moduleItem->getChild(moduleItem->getChildCount()-1))->itemType() == NetlistElementsTreeitem::Net) { NetlistElementsTreeitem* lastNetItem = static_cast(moduleItem->removeChildAtPos(moduleItem->getChildCount()-1)); - mNetToTreeitems.remove(gNetlist->get_net_by_id(lastNetItem->getAdditionalData(keyRepresentedID).toUInt()), lastNetItem); + mNetToTreeitems.remove(gNetlist->get_net_by_id(lastNetItem->id()), lastNetItem); delete lastNetItem; } //append (potentionally) new internal nets for(Net* n : mod->get_internal_nets()) { - NetlistElementsTreeitem* netItem = new NetlistElementsTreeitem(QString::fromStdString(n->get_name()),n->get_id(), ""); + NetlistElementsTreeitem* netItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Net, + n->get_id(), + QString::fromStdString(n->get_name()), + ""); //netItem->setAdditionalData(keyItemType, itemType::net); - netItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::net)); - netItem->setAdditionalData(keyRepresentedID, n->get_id()); mNetToTreeitems.insert(n, netItem); moduleItem->appendChild(netItem); } } - - } diff --git a/plugins/gui/src/selection_details_widget/module_details_widget/port_tree_model.cpp b/plugins/gui/src/selection_details_widget/module_details_widget/port_tree_model.cpp index c93c70820bf..f38d4ad5819 100644 --- a/plugins/gui/src/selection_details_widget/module_details_widget/port_tree_model.cpp +++ b/plugins/gui/src/selection_details_widget/module_details_widget/port_tree_model.cpp @@ -3,7 +3,7 @@ #include "gui/basic_tree_model/base_tree_item.h" #include "gui/gui_globals.h" #include "gui/input_dialog/input_dialog.h" -#include "gui/user_action/action_add_items_to_object.h" +#include "gui/user_action/action_pingroup.h" #include "gui/user_action/action_remove_items_from_object.h" #include "gui/user_action/action_reorder_object.h" #include "gui/user_action/user_action_compound.h" @@ -19,40 +19,32 @@ namespace hal { - PortTreeItem::PortTreeItem(QString pinName, QString pinDirection, QString pinTypee, QString netName) - : mPinName(pinName), mPinDirection(pinDirection), mPinType(pinTypee), mNetName(netName) + PortTreeItem::PortTreeItem(Type itype, u32 id_, QString pinName, PinDirection dir, PinType ptype, QString netName) + : mItemType(itype), mId(id_), mPinName(pinName), mPinDirection(dir), mPinType(ptype), mNetName(netName) {;} QVariant PortTreeItem::getData(int index) const { switch (index) { - case 0: { - QVariant qvPinName = QVariant(mPinName); - return qvPinName; - break;} - case 1: { - QVariant qvPinDirection = QVariant(mPinDirection); - return qvPinDirection; - break;} - case 2: { - QVariant qvPinType = QVariant(mPinType); - return qvPinType; - break;} - case 3: { - QVariant qvNetName = QVariant(mNetName); - return qvNetName; - break;} + case 0: + return mPinName; + case 1: + return QString::fromStdString(enum_to_string(mPinDirection)); + case 2: + return QString::fromStdString(enum_to_string(mPinType)); + case 3: + return mNetName; } return QVariant(); } void PortTreeItem::setData(QList data) { - mPinName = data[0].toString(); - mPinDirection = data[1].toString(); - mPinType = data[2].toString(); - mNetName = data[3].toString(); + mPinName = data[0].toString(); + mPinDirection = enum_from_string(data[1].toString().toStdString()); + mPinType = enum_from_string(data[2].toString().toStdString()); + mNetName = data[3].toString(); } void PortTreeItem::setDataAtIndex(int index, QVariant &data) @@ -63,10 +55,10 @@ namespace hal mPinName = data.toString(); break;} case 1: { - mPinDirection = data.toString(); + mPinDirection = enum_from_string(data.toString().toStdString()); break;} case 2: { - mPinType = data.toString(); + mPinType = enum_from_string(data.toString().toStdString()); break;} case 3: { mNetName = data.toString(); @@ -76,7 +68,7 @@ namespace hal void PortTreeItem::appendData(QVariant data) { - + Q_UNUSED(data) } int PortTreeItem::getColumnCount() const @@ -84,7 +76,7 @@ namespace hal return 4; } - ModulePinsTreeModel::ModulePinsTreeModel(QObject* parent) : BaseTreeModel(parent), mIgnoreEventsFlag(false) + ModulePinsTreeModel::ModulePinsTreeModel(QObject* parent) : BaseTreeModel(parent) { setHeaderLabels(QStringList() << "Name" << "Direction" @@ -144,15 +136,16 @@ namespace hal return new QMimeData(); QMimeData* data = new QMimeData(); - auto item = static_cast(getItemFromIndex(indexes.at(0))); + PortTreeItem* item = static_cast(getItemFromIndex(indexes.at(0))); QByteArray encodedData; QDataStream stream(&encodedData, QIODevice::WriteOnly); - QString type = getTypeOfItem(item) == itemType::pin ? "pin" : "group"; - stream << type << getIdOfItem(item); + QString type = item->itemType() == PortTreeItem::Pin ? "pin" : "group"; + stream << type << item->id(); data->setText(item->getData(sNameColumn).toString()); data->setData("pintreemodel/item", encodedData); return data; } + bool ModulePinsTreeModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) { Q_UNUSED(action) @@ -162,6 +155,7 @@ namespace hal int id; QByteArray encItem = data->data("pintreemodel/item"); QDataStream dataStream(&encItem, QIODevice::ReadOnly); +// debug pingroup qDebug() << "dropMimeData" << encItem << row << column; dataStream >> type >> id; auto droppedItem = (type == "group") ? static_cast(mIdToGroupItem.value(id)) : static_cast(mIdToPinItem.value(id)); @@ -179,23 +173,33 @@ namespace hal if(type == "group") { if(!parentItem) - //qDebug() << "group was dropped between groups... with row: " << row; //check in canDropMine if its not an adjacent row? + { +// debug pingroup qDebug() << "group was dropped between groups... with row: " << row; //check in canDropMine if its not an adjacent row? dndGroupBetweenGroup(droppedItem, row); + } else - //qDebug() << "group was dropped on a group?"; + { +// debug pingroup qDebug() << "group was dropped on a group?"; dndGroupOnGroup(droppedItem, parentItem); + } } else { if(!parentItem) - //qDebug() << "pin was dropped between groups on row " << row; + { +// debug pingroup qDebug() << "pin was dropped between groups on row " << row; dndPinBetweenGroup(droppedItem, row); + } else if(row != -1) - //qDebug() << "pin was dropped between pins"; + { +// debug pingroup qDebug() << "pin was dropped between pins"; dndPinBetweenPin(droppedItem, parentItem, row); + } else - //qDebug() << "pin was dropped on a group..."; + { +// debug pingroup qDebug() << "pin was dropped on a group..."; dndPinOnGroup(droppedItem, parentItem); + } } return true; @@ -240,7 +244,6 @@ namespace hal // return false; // removeItem(droppedItem); -// mIgnoreEventsFlag = true; // if (bottomEdge) // { // insertItem(newItem, droppedParentItem, row - 1); @@ -263,7 +266,6 @@ namespace hal // reorderObj->setParentObject(UserActionObject(mod->get_id(), UserActionObjectType::Module)); // reorderObj->exec(); // } -// mIgnoreEventsFlag = false; // return true; // } @@ -275,7 +277,6 @@ namespace hal // if (pinGroup == nullptr) // return false; -// mIgnoreEventsFlag = true; // UserActionCompound* comp = new UserActionCompound; // if (droppedParentItem != mRootItem && onDroppedParentItem != mRootItem) @@ -295,7 +296,6 @@ namespace hal // comp->addAction(addAct); // comp->addAction(reordAct); // bool ret = comp->exec(); -// mIgnoreEventsFlag = false; // if (ret) // { // removeItem(droppedItem); @@ -315,8 +315,7 @@ namespace hal // //if(droppedParentItem == mRootItem)//item which is dropped // if (droppedParentItem != onDroppedItem) // { -// mIgnoreEventsFlag = true; -// //int ret = mod->assign_pin_to_group(onDroppedGroup, droppedPin).is_ok(); +// //bool ret = mod->assign_pin_to_group(onDroppedGroup, droppedPin); // ActionAddItemsToObject* addAct = new ActionAddItemsToObject(QSet(), QSet(), QSet(), QSet() << droppedPin->get_id()); // addAct->setObject(UserActionObject(onDroppedGroup->get_id(), UserActionObjectType::PinGroup)); // addAct->setParentObject(UserActionObject(mod->get_id(), UserActionObjectType::Module)); @@ -325,10 +324,8 @@ namespace hal // { // removeItem(droppedItem); // insertItem(newItem, onDroppedItem, onDroppedItem->getChildCount()); -// mIgnoreEventsFlag = false; // return true; // } -// mIgnoreEventsFlag = false; // return false; // } // } @@ -337,8 +334,8 @@ namespace hal bool ModulePinsTreeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const { - Q_UNUSED(action); - Q_UNUSED(column); + Q_UNUSED(column) + Q_UNUSED(action) if(!data->formats().contains("pintreemodel/item")) return false; QString type; int id; @@ -346,7 +343,7 @@ namespace hal QDataStream dataStream(&encItem, QIODevice::ReadOnly); dataStream >> type >> id; auto parentItem = static_cast(getItemFromIndex(parent)); - qDebug() << "type: " << type << ", id" << id << ", row: " << row; + // qDebug() << "type: " << type << ", id" << id << ", row: " << row; // construct a "drop-matrix" here, but only 4(5) things are NOT allowed (so check for these): // 1: drop a pin on its OWN parent @@ -355,11 +352,10 @@ namespace hal // 5: drop adjecent index to itself, must be at least 1 item apart if(type == "group") { - auto item = mIdToGroupItem[id]; + auto item = static_cast(mIdToGroupItem[id]); if(parentItem) { - auto type = getTypeOfItem(parentItem); - if(type == itemType::pin || (type == itemType::group && row != -1) || item == parentItem) + if(item->itemType() == PortTreeItem::Pin || (item->itemType() == PortTreeItem::Group && row != -1) || item == parentItem) return false; } else // here, only check for adjacent rows @@ -375,7 +371,7 @@ namespace hal // otherwise it does not make much sense...perhaps change this check auto item = mIdToPinItem[id]; if((!parentItem && item->getParent()->getChildCount() == 1) || (item->getParent() == parentItem && row == -1) || item == parentItem - || (parentItem && (getTypeOfItem(parentItem) == itemType::pin))) + || (parentItem && (parentItem->itemType() == PortTreeItem::Pin))) return false; // case if one wants to drop between pins in same group, check if its not adjacent row (other cases are handled on case above if(item->getParent() == parentItem) @@ -411,21 +407,16 @@ namespace hal continue; auto pinGroupName = QString::fromStdString(pinGroup->get_name()); - auto pinGroupDirection = QString::fromStdString(enum_to_string((pinGroup->get_direction()))); - auto pinGroupType = QString::fromStdString(enum_to_string(pinGroup->get_type())); - - PortTreeItem* pinGroupItem = new PortTreeItem(pinGroupName, pinGroupDirection, pinGroupType, ""); - pinGroupItem->setAdditionalData(keyType, QVariant::fromValue(itemType::group)); // port multi bit - pinGroupItem->setAdditionalData(keyId, pinGroup->get_id()); + PortTreeItem* pinGroupItem = new PortTreeItem(PortTreeItem::Group, pinGroup->get_id(), pinGroupName, pinGroup->get_direction(), pinGroup->get_type()); mIdToGroupItem.insert(pinGroup->get_id(), pinGroupItem); for(ModulePin* pin : pinGroup->get_pins()) { - PortTreeItem* pinItem = new PortTreeItem(QString::fromStdString(pin->get_name()), - QString::fromStdString(enum_to_string(pin->get_direction())), - QString::fromStdString(enum_to_string(pin->get_type())), - QString::fromStdString(pin->get_net()->get_name())); - pinItem->setAdditionalData(keyType, QVariant::fromValue(itemType::pin)); - pinItem->setAdditionalData(keyId, pin->get_id()); + PortTreeItem* pinItem = new PortTreeItem(PortTreeItem::Pin, + pin->get_id(), + QString::fromStdString(pin->get_name()), + pin->get_direction(), + pin->get_type(), + QString::fromStdString(pin->get_net()->get_name())); pinGroupItem->appendChild(pinItem); mNameToTreeItem.insert(QString::fromStdString(pin->get_name()), pinItem); mIdToPinItem.insert(pin->get_id(), pinItem); @@ -493,8 +484,7 @@ namespace hal if (mModuleId == -1) //no current module = no represented net return nullptr; - itemType type = getTypeOfItem(item); - if (type == itemType::portMultiBit) + if (item->itemType() == PortTreeItem::Group && item->getChildCount() > 1) return nullptr; Module* m = gNetlist->get_module_by_id(mModuleId); @@ -502,7 +492,7 @@ namespace hal return nullptr; //std::string name = item->getData(sNameColumn).toString().toStdString(); - if (auto* pin = m->get_pin_by_id(getIdOfItem(item)); pin != nullptr) + if (auto* pin = m->get_pin_by_id(item->id()); pin != nullptr) { return pin->get_net(); } @@ -515,22 +505,175 @@ namespace hal return mModuleId; } - ModulePinsTreeModel::itemType ModulePinsTreeModel::getTypeOfItem(PortTreeItem* item) const + void ModulePinsTreeModel::handleModulePortsChanged(Module* m, PinEvent pev, u32 pgid) { - return item->getAdditionalData(keyType).value(); - } + static const QSet groupEvents = { PinEvent::GroupCreate, + PinEvent::GroupReorder, + PinEvent::GroupRename, + PinEvent::GroupTypeChange, + PinEvent::GroupDirChange, + PinEvent::GroupDelete}; + Q_UNUSED(pev); + Q_UNUSED(pgid); + if ((int)m->get_id() != mModuleId) return; + + // debug pingroups log_info("gui", "Handle pin_changed event {} ID={}", enum_to_string(pev), pgid); + PortTreeItem* ptiPin = nullptr; + PortTreeItem* ptiGroup = nullptr; + const PinGroup* pgroup = nullptr; + const ModulePin* pin = nullptr; + int pinRow = -1; + + + if (groupEvents.contains(pev)) + { + // group event + ptiGroup = mIdToGroupItem.value(pgid); + if (pev != PinEvent::GroupCreate && !ptiGroup) + { + log_warning("gui", "Cannot handle event for pin group ID={}, tree item does not exist.", pgid); + return; + } + if (pev != PinEvent::GroupDelete) + { + pgroup = m->get_pin_group_by_id(pgid); + if (!pgroup) + { + log_warning("gui", "Cannot handle event for pin group ID={}, no such group.", pgid); + return; + } + } + } + else + { + // pin event + ptiPin = mIdToPinItem.value(pgid); + if (pev != PinEvent::PinCreate && !ptiPin) + { + log_warning("gui", "Cannot handle event for pin ID={}, tree item does not exist.", pgid); + return; + } + if (pev != PinEvent::PinDelete) + { + pin = m->get_pin_by_id(pgid); + if (!pin) + { + log_warning("gui", "Cannot handle event for pin ID={}, no such pid.", pgid); + return; + } + auto pgPair = pin->get_group(); + pgroup = pgPair.first; + pinRow = pinIndex2Row(pin,pgPair.second); + if (pgroup) + ptiGroup = mIdToGroupItem.value(pgroup->get_id()); + } + } - int ModulePinsTreeModel::getIdOfItem(BaseTreeItem* item) const - { - return item->getAdditionalData(keyId).toInt(); - } + QModelIndex dataChangedIndex; - void ModulePinsTreeModel::handleModulePortsChanged(Module* m) - { - if ((int)m->get_id() == mModuleId) + switch (pev) + { + case PinEvent::GroupCreate: + { + ptiGroup = new PortTreeItem(PortTreeItem::Group, + pgroup->get_id(), + QString::fromStdString(pgroup->get_name()), + pgroup->get_direction(), + pgroup->get_type()); + mIdToGroupItem.insert(ptiGroup->id(), ptiGroup); + int inx = pinGroupIndex(m,pgroup); + insertItem(ptiGroup, mRootItem, inx); + break; + } + case PinEvent::GroupReorder: + { + int inx = pinGroupIndex(m,pgroup); + removeItem(ptiGroup); + insertItem(ptiGroup, mRootItem, inx); + break; + } + case PinEvent::GroupRename: + ptiGroup->setName(QString::fromStdString(pgroup->get_name())); + dataChangedIndex = getIndexFromItem(ptiGroup); + break; + case PinEvent::GroupTypeChange: + ptiGroup->setPinType(pgroup->get_type()); + dataChangedIndex = getIndexFromItem(ptiGroup); + break; + case PinEvent::GroupDirChange: + ptiGroup->setPinDirection(pgroup->get_direction()); + dataChangedIndex = getIndexFromItem(ptiGroup); + break; + case PinEvent::GroupDelete: + removeItem(ptiGroup); + delete ptiGroup; + break; + case PinEvent::PinCreate: + { + if (!pgroup || !ptiGroup) + { + log_warning("gui", "Cannot handle pin create event for pin ID={}, pin is not assigned to any group.", pgid); + return; + } + QString netName; + if (pin->get_net()) + netName = QString::fromStdString(pin->get_net()->get_name()); + ptiPin = new PortTreeItem(PortTreeItem::Pin, + pin->get_id(), + QString::fromStdString(pin->get_name()), + pin->get_direction(), + pin->get_type(), + netName); + mIdToPinItem.insert(ptiPin->id(), ptiPin); + insertItem(ptiPin, ptiGroup, pinRow); + break; + } + case PinEvent::PinReorder: + { + if (!pgroup || !ptiGroup) + { + log_warning("gui", "Cannot handle pin reorder event for pin ID={}, pin is not assigned to any group.", pgid); + return; + } + removeItem(ptiPin); + insertItem(ptiPin, ptiGroup, pinRow); + break; + } + case PinEvent::PinAssignToGroup: + { + if (!pgroup || !ptiGroup) + { + log_warning("gui", "Cannot handle pin assign event for pin ID={}, pin is not assigned to any group.", pgid); + return; + } + removeItem(ptiPin); + insertItem(ptiPin, ptiGroup, pinRow); + break; + } + case PinEvent::PinRename: + ptiPin->setName(QString::fromStdString(pin->get_name())); + dataChangedIndex = getIndexFromItem(ptiPin); + break; + case PinEvent::PinTypeChange: + ptiPin->setPinType(pin->get_type()); + dataChangedIndex = getIndexFromItem(ptiPin); + break; + case PinEvent::PinDirChange: + ptiPin->setPinDirection(pin->get_direction()); + dataChangedIndex = getIndexFromItem(ptiPin); + break; + case PinEvent::PinDelete: + removeItem(ptiPin); + delete ptiPin; + break; + default: + break; + } + + if (dataChangedIndex.isValid()) { - if (!mIgnoreEventsFlag) - setModule(m); + QModelIndex inxLastCol = createIndex(dataChangedIndex.row(),columnCount()-1,dataChangedIndex.internalPointer()); + Q_EMIT dataChanged(dataChangedIndex,inxLastCol); } } @@ -540,147 +683,73 @@ namespace hal // 2) just add all pins from dropped group to "ondroppedgroup", then rename? // InputDialog ipd("Name of new group", "Name of new group:", onDroppedGroup->getData(sNameColumn).toString()); // if(ipd.exec() == QDialog::Rejected) return false; - mIgnoreEventsFlag = true; - QSet pins, e; - auto group = mModule->get_pin_group_by_id(getIdOfItem(droppedGroup)); - for(const auto &pin : group->get_pins()) - pins.insert(pin->get_id()); - - UserActionCompound* compAct = new UserActionCompound; - ActionReorderObject* reorderActHack = new ActionReorderObject(droppedGroup->getOwnRow()); - reorderActHack->setObject(UserActionObject(group->get_id(), UserActionObjectType::PinGroup)); - reorderActHack->setParentObject(UserActionObject(mModuleId, UserActionObjectType::Module)); - ActionAddItemsToObject* addAct = new ActionAddItemsToObject(e,e,e, pins); - addAct->setObject(UserActionObject(getIdOfItem(onDroppedGroup), UserActionObjectType::PinGroup)); - addAct->setParentObject(UserActionObject(mModuleId, UserActionObjectType::Module)); - compAct->addAction(reorderActHack); - compAct->addAction(addAct); - compAct->exec(); + QList pins; + auto srcgroup = mModule->get_pin_group_by_id(static_cast(droppedGroup)->id()); + for(const auto &pin : srcgroup->get_pins()) + pins.append(pin->get_id()); + if (pins.isEmpty()) return; // no pins to move + + auto tgtgroup = mModule->get_pin_group_by_id(static_cast(onDroppedGroup)->id()); + + ActionPingroup* act = ActionPingroup::addPinsToExistingGroup(mModule,tgtgroup->get_id(),pins); + act->setObject(UserActionObject(mModuleId,UserActionObjectType::Module)); + if (act) act->exec(); + // too keep the order, ActionAddItemsToObject cannot be executed with all pins, but a ComAction must be created // with many ActionAddItemsToObject that contain a single pin each -> set destroys order of pins in source pingroup - setModule(mModule); - mIgnoreEventsFlag = false; - } void ModulePinsTreeModel::dndGroupBetweenGroup(PortTreeItem *droppedGroup, int row) { - mIgnoreEventsFlag = true; int ownRow = droppedGroup->getOwnRow(); bool bottomEdge = row == mRootItem->getChildCount(); auto desiredIdx = bottomEdge ? row-1 : row; if(ownRow < row && !bottomEdge) desiredIdx--; - //mModule->move_pin_group(mModule->get_pin_group_by_id(getIdOfItem(droppedGroup)), desiredIdx); - ActionReorderObject* reordObj = new ActionReorderObject(desiredIdx); - reordObj->setObject(UserActionObject(getIdOfItem(droppedGroup), UserActionObjectType::PinGroup)); - reordObj->setParentObject(UserActionObject(mModule->get_id(), UserActionObjectType::Module)); - auto ret = reordObj->exec(); - if(ret){ - removeItem(droppedGroup); - insertItem(droppedGroup, mRootItem, desiredIdx); - } - mIgnoreEventsFlag = false; + ActionPingroup* act = new ActionPingroup(PinActionType::GroupMoveToRow,droppedGroup->id(),"",desiredIdx); + act->setObject(UserActionObject(mModuleId,UserActionObjectType::Module)); + act->exec(); } void ModulePinsTreeModel::dndPinOnGroup(PortTreeItem *droppedPin, BaseTreeItem *onDroppedGroup) { - mIgnoreEventsFlag = true; - QSet e; - ActionAddItemsToObject* addAct = new ActionAddItemsToObject(e,e,e, QSet() << getIdOfItem(droppedPin)); - addAct->setObject(UserActionObject(getIdOfItem(onDroppedGroup), UserActionObjectType::PinGroup)); - addAct->setParentObject(UserActionObject(mModuleId, UserActionObjectType::Module)); - addAct->exec(); - auto oldParent = droppedPin->getParent(); - removeItem(droppedPin); - insertItem(droppedPin, onDroppedGroup, onDroppedGroup->getChildCount()); - if(!(oldParent->getChildCount())){ - removeItem(static_cast(oldParent)); - delete oldParent; - } - //setModule(mModule); - mIgnoreEventsFlag = false; + ActionPingroup* act = new ActionPingroup(PinActionType::PinAsignToGroup,droppedPin->id(),"",static_cast(onDroppedGroup)->id()); + act->setObject(UserActionObject(mModuleId,UserActionObjectType::Module)); + act->exec(); } void ModulePinsTreeModel::dndPinBetweenPin(PortTreeItem *droppedPin, BaseTreeItem *onDroppedParent, int row) { - mIgnoreEventsFlag = true; int desiredIdx = row; + ActionPingroup* act = nullptr; if(droppedPin->getParent() == onDroppedParent) // same group { int ownRow = droppedPin->getOwnRow(); bool bottomEdge = row == onDroppedParent->getChildCount(); desiredIdx = bottomEdge ? row-1 : row; if(ownRow < row && !bottomEdge) desiredIdx--; // insert item here - ActionReorderObject* reorderObj = new ActionReorderObject(desiredIdx); - reorderObj->setObject(UserActionObject(getIdOfItem(droppedPin), UserActionObjectType::Pin)); - reorderObj->setParentObject(UserActionObject(mModule->get_id(), UserActionObjectType::Module)); - reorderObj->exec(); + act = new ActionPingroup(PinActionType::PinMoveToRow,droppedPin->id(),"",desiredIdx); // TODO : start_index, descending } - else // different groups + else { - // reorder action from source group is still needed (for undo action)! - UserActionCompound* compAct = new UserActionCompound; - ActionReorderObject* reorderActHack = new ActionReorderObject(droppedPin->getOwnRow()); - reorderActHack->setObject(UserActionObject(getIdOfItem(droppedPin), UserActionObjectType::Pin)); - reorderActHack->setParentObject(UserActionObject(mModuleId, UserActionObjectType::Module)); - ActionAddItemsToObject* addAct = new ActionAddItemsToObject(QSet(), QSet(), QSet(), QSet() << getIdOfItem(droppedPin)); - addAct->setObject(UserActionObject(getIdOfItem(onDroppedParent), UserActionObjectType::PinGroup)); - addAct->setParentObject(UserActionObject(mModuleId, UserActionObjectType::Module)); - ActionReorderObject* reorderAct = new ActionReorderObject(row); - reorderAct->setObject(UserActionObject(getIdOfItem(droppedPin), UserActionObjectType::Pin)); - reorderAct->setParentObject(UserActionObject(mModule->get_id(), UserActionObjectType::Module)); - compAct->addAction(reorderActHack); - compAct->addAction(addAct); - compAct->addAction(reorderAct); - compAct->exec(); + act = ActionPingroup::addPinToExistingGroup(mModule,static_cast(onDroppedParent)->id(),droppedPin->id(),desiredIdx); + if (!act) return; } - auto oldParent = droppedPin->getParent(); - removeItem(droppedPin); - insertItem(droppedPin, onDroppedParent, desiredIdx); - if(!(oldParent->getChildCount())){ - removeItem(static_cast(oldParent)); - delete oldParent; - } - //setModule(mModule); - mIgnoreEventsFlag = false; + act->setObject(UserActionObject(mModuleId,UserActionObjectType::Module)); + act->exec(); } void ModulePinsTreeModel::dndPinBetweenGroup(PortTreeItem *droppedPin, int row) { // row is needed for when groups can change its order within the module Q_UNUSED(row) - mIgnoreEventsFlag = true; - auto pinGroup = mModule->get_pin_group_by_id(getIdOfItem(droppedPin->getParent())); - QSet e; - ActionRemoveItemsFromObject* removeAct = new ActionRemoveItemsFromObject(e,e,e, QSet() << getIdOfItem(droppedPin)); - removeAct->setObject(UserActionObject(pinGroup->get_id(), UserActionObjectType::PinGroup)); - removeAct->setParentObject(UserActionObject(mModuleId, UserActionObjectType::Module)); - bool ret = removeAct->exec(); - // must search for the created group (must secure way is to serve for a group that contains the pin id) - // and then move that group (the source group cannot be empty after the pin was removed -> canDropMimeData) - if(ret) // can fail if the pins name that one wants to remove has the same name as another group that already exists - { - auto newGroup = mModule->get_pin_by_id(getIdOfItem(droppedPin))->get_group().first; - auto pinGroupName = QString::fromStdString(newGroup->get_name()); - auto pinGroupDirection = QString::fromStdString(enum_to_string((newGroup->get_direction()))); - auto pinGroupType = QString::fromStdString(enum_to_string(newGroup->get_type())); - - PortTreeItem* pinGroupItem = new PortTreeItem(pinGroupName, pinGroupDirection, pinGroupType, ""); - pinGroupItem->setAdditionalData(keyType, QVariant::fromValue(itemType::group)); - pinGroupItem->setAdditionalData(keyId, newGroup->get_id()); - - int pos = mRootItem->getChildCount(); // or query current index - ActionReorderObject* reordObj = new ActionReorderObject(row); - reordObj->setObject(UserActionObject(newGroup->get_id(), UserActionObjectType::PinGroup)); - reordObj->setParentObject(UserActionObject(mModule->get_id(), UserActionObjectType::Module)); - if(reordObj->exec()) - pos = row; - - insertItem(pinGroupItem, mRootItem, pos); - removeItem(droppedPin); - insertItem(droppedPin, pinGroupItem, 0); - } - mIgnoreEventsFlag = false; + + auto pinToMove = mModule->get_pin_by_id(droppedPin->id()); + if (!pinToMove) return; + + QString groupName = generateGroupName(mModule,pinToMove); + + ActionPingroup* act = ActionPingroup::addPinToNewGroup(mModule, groupName, droppedPin->id(),row); + act->exec(); } void ModulePinsTreeModel::insertItem(PortTreeItem* item, BaseTreeItem* parent, int index) @@ -690,7 +759,7 @@ namespace hal parent->insertChild(index, item); endInsertRows(); //mNameToTreeItem.insert(item->getData(sNameColumn).toString(), item); - getTypeOfItem(item) == itemType::pin ? mIdToPinItem.insert(getIdOfItem(item), item) : mIdToGroupItem.insert(getIdOfItem(item), item); + item->itemType() == PortTreeItem::Pin ? mIdToPinItem.insert(item->id(), item) : mIdToGroupItem.insert(item->id(), item); //mIdToPinItem.insert(getIdOfItem(item), item); } void ModulePinsTreeModel::removeItem(PortTreeItem* item) @@ -700,7 +769,7 @@ namespace hal endRemoveRows(); //mNameToTreeItem.remove(item->getData(sNameColumn).toString()); //for now, only ids of pin-items (since these functions are only relevant for dnd) - getTypeOfItem(item) == itemType::pin ? mIdToPinItem.remove(getIdOfItem(item)) : mIdToGroupItem.remove(getIdOfItem(item)); + item->itemType() == PortTreeItem::Pin ? mIdToPinItem.remove(item->id()) : mIdToGroupItem.remove(item->id()); //mIdToPinItem.remove(getIdOfItem(item)); //delete item; } diff --git a/plugins/gui/src/selection_details_widget/net_details_widget/module_table_model.cpp b/plugins/gui/src/selection_details_widget/net_details_widget/module_table_model.cpp index 1dccb1bdf49..4bdebadb2bf 100644 --- a/plugins/gui/src/selection_details_widget/net_details_widget/module_table_model.cpp +++ b/plugins/gui/src/selection_details_widget/net_details_widget/module_table_model.cpp @@ -178,8 +178,10 @@ namespace hal return mEntries[index.row()].name; } - void ModuleTableModel::handleModulePortsChanged(Module* m) + void ModuleTableModel::handleModulePortsChanged(Module* m, PinEvent pev, u32 pgid) { + Q_UNUSED(pev); + Q_UNUSED(pgid); if (mModIds.find((int)m->get_id()) != mModIds.end()) { Net* net = gNetlist->get_net_by_id(mNetId); diff --git a/plugins/gui/src/selection_details_widget/selection_details_widget.cpp b/plugins/gui/src/selection_details_widget/selection_details_widget.cpp index 136c2636ed2..1a7791ba911 100644 --- a/plugins/gui/src/selection_details_widget/selection_details_widget.cpp +++ b/plugins/gui/src/selection_details_widget/selection_details_widget.cpp @@ -436,6 +436,13 @@ namespace hal Q_EMIT triggerHighlight(highlight); } + void SelectionDetailsWidget::showNoSelection() + { + if(mStackedWidget->currentWidget() == mModuleDetailsTabs) + mModuleDetailsTabs->clear(); + mStackedWidget->setCurrentWidget(mNoSelectionLabel); + } + void SelectionDetailsWidget::singleSelectionInternal(const SelectionTreeItem *sti) { SelectionTreeItem::TreeItemType tp = sti @@ -444,33 +451,37 @@ namespace hal switch (tp) { case SelectionTreeItem::NullItem: - //mModuleDetails->update(0); - if(mStackedWidget->currentWidget() == mModuleDetailsTabs) - mModuleDetailsTabs->clear(); - mStackedWidget->setCurrentWidget(mNoSelectionLabel); -// set_name("Selection Details"); + showNoSelection(); break; case SelectionTreeItem::ModuleItem: if (Module* m = gNetlist->get_module_by_id(sti->id()); m) { - mModuleDetailsTabs->setModule(gNetlist->get_module_by_id(sti->id())); + mModuleDetailsTabs->setModule(m); mStackedWidget->setCurrentWidget(mModuleDetailsTabs); + // if (mNumberSelectedItems==1) set_name("Module Details"); } -// if (mNumberSelectedItems==1) set_name("Module Details"); + else + showNoSelection(); + break; + case SelectionTreeItem::GateItem: - if(mStackedWidget->currentWidget() == mModuleDetailsTabs) - mModuleDetailsTabs->clear(); - mGateDetailsTabs->setGate(gNetlist->get_gate_by_id(sti->id())); - mStackedWidget->setCurrentWidget(mGateDetailsTabs); -// if (mNumberSelectedItems==1) set_name("Gate Details"); + showNoSelection(); + if (Gate* g = gNetlist->get_gate_by_id(sti->id()); g) + { + mGateDetailsTabs->setGate(g); + mStackedWidget->setCurrentWidget(mGateDetailsTabs); + // if (mNumberSelectedItems==1) set_name("Gate Details"); + } break; case SelectionTreeItem::NetItem: - if(mStackedWidget->currentWidget() == mModuleDetailsTabs) - mModuleDetailsTabs->clear(); - mNetDetailsTabs->setNet(gNetlist->get_net_by_id(sti->id())); - mStackedWidget->setCurrentWidget(mNetDetailsTabs); -// if (mNumberSelectedItems==1) set_name("Net Details"); + showNoSelection(); + if (Net* n = gNetlist->get_net_by_id(sti->id()); n) + { + mNetDetailsTabs->setNet(n); + mStackedWidget->setCurrentWidget(mNetDetailsTabs); + // if (mNumberSelectedItems==1) set_name("Net Details"); + } break; default: break; diff --git a/plugins/gui/src/user_action/action_add_items_to_object.cpp b/plugins/gui/src/user_action/action_add_items_to_object.cpp index 44b87bba1fe..4ba1022590b 100644 --- a/plugins/gui/src/user_action/action_add_items_to_object.cpp +++ b/plugins/gui/src/user_action/action_add_items_to_object.cpp @@ -173,6 +173,7 @@ namespace hal else return false; break; + /* TODO PIN case UserActionObjectType::PinGroup: { if (mPins.empty()) return true; @@ -200,7 +201,7 @@ namespace hal for (auto id : mPins) { - if (mod->assign_pin_to_group(pinGrp, mod->get_pin_by_id(id), false).is_error()) + if (!mod->assign_pin_to_group(pinGrp, mod->get_pin_by_id(id), false)) { return false; } @@ -257,6 +258,7 @@ namespace hal } } break; + */ default: return false; } diff --git a/plugins/gui/src/user_action/action_create_object.cpp b/plugins/gui/src/user_action/action_create_object.cpp index 2a73b467ae0..236cf48c73e 100644 --- a/plugins/gui/src/user_action/action_create_object.cpp +++ b/plugins/gui/src/user_action/action_create_object.cpp @@ -63,6 +63,7 @@ namespace hal switch (mObject.type()) { + /* TODO PIN case UserActionObjectType::PinGroup: { Module* parentModule = gNetlist->get_module_by_id(mParentObject.id()); @@ -77,6 +78,7 @@ namespace hal else return false; } + */ break; case UserActionObjectType::Module: @@ -84,8 +86,15 @@ namespace hal Module* parentModule = gNetlist->get_module_by_id(mParentId); if (parentModule) { - Module* m = gNetlist->create_module(gNetlist->get_unique_module_id(), + u32 modId = mObject.id() ? mObject.id() : gNetlist->get_unique_module_id(); + Module* m = gNetlist->create_module(modId, mObjectName.toStdString(), parentModule); + if (!m) + { + log_warning("gui", "Failed to create module '{}' with ID={} under parent ID={}.", + mObjectName.toStdString(), modId, mParentId); + return false; + } setObject(UserActionObject(m->get_id(),UserActionObjectType::Module)); standardUndo = true; } diff --git a/plugins/gui/src/user_action/action_delete_object.cpp b/plugins/gui/src/user_action/action_delete_object.cpp index c1ddee64cb1..ad1a5c5266e 100644 --- a/plugins/gui/src/user_action/action_delete_object.cpp +++ b/plugins/gui/src/user_action/action_delete_object.cpp @@ -42,6 +42,7 @@ namespace hal switch (mObject.type()) { + /* TODO PIN case UserActionObjectType::PinGroup: { mod = gNetlist->get_module_by_id(mParentObject.id()); auto* pinGroup = mod->get_pin_group_by_id(mObject.id()); @@ -65,6 +66,7 @@ namespace hal return false; } break; + */ case UserActionObjectType::Module: mod = gNetlist->get_module_by_id(mObject.id()); if (mod) @@ -72,6 +74,7 @@ namespace hal UserActionCompound* act = new UserActionCompound; act->setUseCreatedObject(); ActionCreateObject* actCreate = new ActionCreateObject(UserActionObjectType::Module, QString::fromStdString(mod->get_name())); + actCreate->setObject(mObject); actCreate->setParentId(mod->get_parent_module()->get_id()); act->addAction(actCreate); act->addAction(new ActionSetObjectType(QString::fromStdString(mod->get_type()))); diff --git a/plugins/gui/src/user_action/action_pingroup.cpp b/plugins/gui/src/user_action/action_pingroup.cpp new file mode 100644 index 00000000000..73de9f426aa --- /dev/null +++ b/plugins/gui/src/user_action/action_pingroup.cpp @@ -0,0 +1,578 @@ +#include "gui/user_action/action_pingroup.h" +#include "gui/gui_globals.h" +#include "hal_core/netlist/grouping.h" +#include "gui/grouping/grouping_manager_widget.h" +#include "gui/graph_widget/contexts/graph_context.h" +#include "gui/graph_widget/layout_locker.h" +#include + +namespace hal +{ + int pinGroupIndex(const Module* mod, const PinGroup* pgrp) + { + if (!mod || !pgrp) return -1; + int inx = 0; + for (const PinGroup* testgrp : mod->get_pin_groups()) + { + if (testgrp == pgrp) return inx; + ++inx; + } + return -1; + } + + void dumpPingroups(Module *m) + { + if (!m) m = gNetlist->get_top_module(); + std::cerr << "module: " << m->get_id() << " <" << m->get_name() << ">\n"; + for (PinGroup* pg : m->get_pin_groups()) + { + std::cerr << " grp: " << pg->get_id() << (pg->is_ascending()?" asc ": " des ") << pg->get_start_index() + << " <" << pg->get_name() << ">\n"; + for (ModulePin* pin : pg->get_pins()) + std::cerr << " pin: " << pin->get_id() << " inx:" << pin->get_group().second << " row:" + << pinIndex2Row(pin,pin->get_group().second) << " <" << pin->get_name() << ">\n"; + } + std::cerr << "-------------" << std::endl; + for (Module* sm : m->get_submodules()) + dumpPingroups(sm); + } + + int pinIndex2Row(const ModulePin* pin, int index) + { + auto pg = pin->get_group(); + if (pg.first->is_ascending()) + return index - pg.first->get_start_index(); + return pg.first->get_start_index() - index; + } + + int pinRow2Index(const ModulePin* pin, int row) + { + auto pg = pin->get_group(); + if (pg.first->is_ascending()) + return pg.first->get_start_index() + row; + return pg.first->get_start_index() - row; + } + + uint qHash(PinEvent pev) + { + return (uint) pev; + } + + QString generateGroupName(const Module* mod, const ModulePin* pin) + { + QString baseName = QString::fromStdString(pin->get_name()); + QSet existingGroups; + for (auto g : mod->get_pin_groups()) + existingGroups.insert(QString::fromStdString(g->get_name())); + QString retval = baseName; + int count = 1; + while (existingGroups.contains(retval)) + retval = QString("%1_%2").arg(baseName).arg(++count); + return retval; + } + + QString PinActionType::toString(PinActionType::Type tp) + { + QMetaEnum me = QMetaEnum::fromType(); + return QString(me.key(tp)); + } + + PinActionType::Type PinActionType::fromString(const QString &s) + { + QMetaEnum me = QMetaEnum::fromType(); + for (int t = None; t < MaxAction; t++) + if (s == me.key(t)) + { + return static_cast(t); + } + return None; + } + + bool PinActionType::useExistingGroup(PinActionType::Type tp) + { + static const QSet types = {GroupDelete, GroupMoveToRow, GroupRename, GroupTypeChange, GroupDirChange}; + return types.contains(tp); + } + + bool PinActionType::useExistingPin(PinActionType::Type tp) + { + static const QSet types = {PinAsignToGroup, PinRename, PinTypeChange, PinDirChange, PinMoveToRow}; + return types.contains(tp); + } + + ActionPingroupFactory::ActionPingroupFactory() + : UserActionFactory("Pingroup") {;} + + ActionPingroupFactory* ActionPingroupFactory::sFactory = new ActionPingroupFactory; + + UserAction* ActionPingroupFactory::newAction() const + { + return new ActionPingroup; + } + + QString ActionPingroup::tagname() const + { + return ActionPingroupFactory::sFactory->tagname(); + } + + ActionPingroup::ActionPingroup(PinActionType::Type tp, int id, const QString &name, int value) + { + mPinActions.append(AtomicAction(tp, id, name, value)); + } + + ActionPingroup::ActionPingroup(const QList& aaList) + : mPinActions(aaList) + {;} + + void ActionPingroup::addToHash(QCryptographicHash &cryptoHash) const + { + for (const AtomicAction& aa : mPinActions) + { + cryptoHash.addData((char*)(&aa.mType),sizeof(aa.mType)); + cryptoHash.addData((char*)(&aa.mId),sizeof(aa.mId)); + cryptoHash.addData(aa.mName.toUtf8()); + cryptoHash.addData((char*)(&aa.mValue),sizeof(aa.mValue)); + } + } + + void ActionPingroup::writeToXml(QXmlStreamWriter& xmlOut) const + { + // TODO xml parent element + for (const AtomicAction& aa : mPinActions) + { + if (aa.mType != PinActionType::None) + xmlOut.writeTextElement("type", PinActionType::toString(aa.mType)); + if (aa.mId) + xmlOut.writeTextElement("id", QString::number(aa.mId)); + if (!aa.mName.isEmpty()) + xmlOut.writeTextElement("name", aa.mName); + if (aa.mValue) + xmlOut.writeTextElement("value", QString::number(aa.mValue)); + } + } + + void ActionPingroup::readFromXml(QXmlStreamReader& xmlIn) + { + // TODO loop xml parent element + while (xmlIn.readNextStartElement()) + { + PinActionType::Type tp = PinActionType::None; + int id = 0; + QString name; + int val = 0; + + if (xmlIn.name() == "type") + tp = PinActionType::fromString(xmlIn.readElementText()); + if (xmlIn.name() == "id") + id = xmlIn.readElementText().toInt(); + if (xmlIn.name() == "name") + name = xmlIn.readElementText(); + if (xmlIn.name() == "value") + val = xmlIn.readElementText().toInt(); + mPinActions.append(AtomicAction(tp,id,name,val)); + } + } + PinGroup* ActionPingroup::getGroup(ModulePin* pin) const + { + return pin->get_group().first; + } + + PinGroup* ActionPingroup::getGroup(int grpId) const + { + PinGroup* pgroup = mPinGroups.value(grpId); + if (pgroup) return pgroup; + if (!mParentModule || grpId<=0) return nullptr; + return mParentModule->get_pin_group_by_id(grpId); + } + + void ActionPingroup::addUndoAction(PinActionType::Type tp, int id, const QString& name, int value) + { + ActionPingroup* undo = nullptr; + if (mUndoAction) + { + undo = static_cast(mUndoAction); + undo->mPinActions.append(AtomicAction(tp,id,name,value)); + } + else + { + undo = new ActionPingroup(tp,id,name,value); + undo->setObject(object()); + } + mUndoAction = undo; + } + + + void ActionPingroup::prepareUndoAction() + { + QHash*,int> remainingPins; + for (const AtomicAction& aa : mPinActions) + { + if (aa.mType != PinActionType::PinAsignToGroup) + continue; + ModulePin* pin = mParentModule->get_pin_by_id(aa.mId); + PinGroup* pgroup = pin->get_group().first; + if (remainingPins.contains(pgroup)) + remainingPins[pgroup]--; + else + remainingPins[pgroup] = pgroup->size()-1; + } + + // for groups that will be deleted after pin assign a create action is needed in undo + for (auto it = remainingPins.begin(); it != remainingPins.end(); ++it) + { + if (it.value() > 0) continue; + GroupRestore gr(mParentModule,it.key()); + mGroupRestore.insert(gr.mRow,gr); + } + } + + void ActionPingroup::finalizeUndoAction() + { + QList restoreActions; + for (auto it = mGroupRestore.begin(); it != mGroupRestore.end(); ++it) + { + const GroupRestore& gr = it.value(); + restoreActions.append(AtomicAction(PinActionType::GroupCreate,gr.mId,gr.mName,gr.mStartIndex)); + restoreActions.append(AtomicAction(PinActionType::GroupMoveToRow,gr.mId,"",gr.mRow)); + if (gr.mType != PinType::none) + restoreActions.append(AtomicAction(PinActionType::GroupTypeChange,gr.mId,"",(int)gr.mType)); + if (gr.mDirection != PinDirection::none) + restoreActions.append(AtomicAction(PinActionType::GroupDirChange,gr.mId,"",(int)gr.mDirection)); + } + if (!restoreActions.isEmpty()) + { + if (mUndoAction) + { + ActionPingroup* act = static_cast(mUndoAction); + restoreActions += act->mPinActions; + act->mPinActions = restoreActions; + } + else + { + mUndoAction = new ActionPingroup(restoreActions); + } + } + + for (u32 grpId : mGroupToRemove) + { + if (mUndoAction) + { + ActionPingroup* act = static_cast(mUndoAction); + act->mPinActions.append(AtomicAction(PinActionType::GroupDelete,grpId)); + } + else + mUndoAction = new ActionPingroup(PinActionType::GroupDelete,grpId); + } + + if (mUndoAction) mUndoAction->setObject(object()); + } + + int ActionPingroup::pinGroupRow(Module *m, PinGroup* pgroup) + { + int inx = 0; + for (PinGroup* testgroup : m->get_pin_groups()) + { + if (testgroup == pgroup) return inx; + ++inx; + } + return -1; + } + + bool ActionPingroup::exec() + { + mPinGroups.clear(); + mGroupRestore.clear(); + mPinsMoved.clear(); + mGroupToRemove.clear(); + if (mObject.type() != UserActionObjectType::Module) + return false; + + mParentModule = gNetlist->get_module_by_id(mObject.id()); + if (!mParentModule) + return false; + + prepareUndoAction(); // create pingroups in case we are going to delete some while assigning + LayoutLocker llock; + + for (const AtomicAction& aa : mPinActions) + { + PinGroup* pgroup = nullptr; + ModulePin* pin = nullptr; + + if (PinActionType::useExistingGroup(aa.mType)) + { + auto it = mPinGroups.find(aa.mId); + if (it == mPinGroups.end()) + { + pgroup = mParentModule->get_pin_group_by_id(aa.mId); + if (!pgroup) return false; + mPinGroups.insert(aa.mId,pgroup); + } + else + pgroup = it.value(); + } + + if (PinActionType::useExistingPin(aa.mType)) + { + pin = mParentModule->get_pin_by_id(aa.mId); + } + + switch (aa.mType) + { + case PinActionType::GroupCreate: + { + int startIndex = aa.mValue; + bool ascending = true; + if (aa.mValue < 0) + { + ascending = false; + startIndex = -aa.mValue-1; + } + if (aa.mId > 0) + { + if (auto res = mParentModule->create_pin_group(aa.mId, aa.mName.toStdString(), {}, PinDirection::none, PinType::none,ascending,startIndex); res.is_ok()) + pgroup = res.get(); + else + return false; + } + else + { + if (auto res = mParentModule->create_pin_group(aa.mName.toStdString(), {}, PinDirection::none, PinType::none,ascending,startIndex); res.is_ok()) + pgroup = res.get(); + else + return false; + } + if (pgroup) + { + mPinGroups[aa.mId] = pgroup; + mGroupToRemove.insert(pgroup->get_id()); + } + break; + } + case PinActionType::GroupDelete: + { + int v = pgroup->get_start_index(); + if (!pgroup->is_ascending()) v = -v-1; + u32 id = pgroup->get_id(); + int ptype = (int) pgroup->get_type(); + int pdir = (int) pgroup->get_direction(); + QString name = QString::fromStdString(pgroup->get_name()); + if (!mParentModule->delete_pin_group(pgroup)) + return false; + addUndoAction(PinActionType::GroupCreate,id,name,v); + addUndoAction(PinActionType::GroupTypeChange,id,"",ptype); + addUndoAction(PinActionType::GroupDirChange,id,"",pdir); + break; + } + case PinActionType::GroupMoveToRow: + { + int inx = pinGroupRow(mParentModule,pgroup); + if (inx < 0) return false; + addUndoAction(PinActionType::GroupMoveToRow,pgroup->get_id(),"",inx); + if (!mParentModule->move_pin_group(pgroup,aa.mValue)) + return false; + break; + } + case PinActionType::GroupRename: + addUndoAction(PinActionType::GroupRename,pgroup->get_id(),QString::fromStdString(pgroup->get_name())); + if (!mParentModule->set_pin_group_name(pgroup,aa.mName.toStdString())) + return false; + break; + case PinActionType::GroupTypeChange: + addUndoAction(PinActionType::GroupTypeChange,pgroup->get_id(),"",(int)pgroup->get_type()); + if (!mParentModule->set_pin_group_type(pgroup, (PinType) aa.mValue)) + return false; + break; + case PinActionType::GroupDirChange: + addUndoAction(PinActionType::GroupDirChange,pgroup->get_id(),"",(int)pgroup->get_direction()); + if (!mParentModule->set_pin_group_direction(pgroup, (PinDirection) aa.mValue)) + return false; + break; + case PinActionType::PinAsignToGroup: + addUndoAction(PinActionType::PinAsignToGroup,aa.mId,"",pin->get_group().first->get_id()); + addUndoAction(PinActionType::PinMoveToRow,aa.mId,"",pinIndex2Row(pin,pin->get_group().second)); + mPinsMoved.insert(aa.mId); + pgroup = getGroup(aa.mValue); + if (!pgroup) return false; + if (!mParentModule->assign_pin_to_group(pgroup,pin)) + { + qDebug() << "assign_pin_to_group failed"; + return false; + } + // dumpPingroups(); + break; + case PinActionType::PinRename: + addUndoAction(PinActionType::PinRename,aa.mId, QString::fromStdString(pin->get_name())); + if (!mParentModule->set_pin_name(pin, aa.mName.toStdString())) + return false; + break; + case PinActionType::PinTypeChange: + addUndoAction(PinActionType::PinTypeChange,aa.mId,"",(int)pin->get_type()); + if (!mParentModule->set_pin_type(pin, (PinType) aa.mValue)) + return false; + break; + case PinActionType::PinMoveToRow: + if (!mPinsMoved.contains(aa.mId)) + addUndoAction(PinActionType::PinMoveToRow,aa.mId,"",pinIndex2Row(pin,pin->get_group().second)); + pgroup = pin->get_group().first; + if (!mParentModule->move_pin_within_group(pgroup,pin,pinRow2Index(pin,aa.mValue))) + { + qDebug() << "move_pin_within_group failed"; + return false; + } + // dumpPingroups(); + break; + default: + break; + } + } + + finalizeUndoAction(); + + return UserAction::exec(); + } + + ActionPingroup* ActionPingroup::addPinsToExistingGroup(const Module *m, u32 grpId, QList pinIds, int pinRow) + { + ActionPingroup* retval = nullptr; + for (u32 pinId : pinIds) + { + if (retval) + retval->mPinActions.append(AtomicAction(PinActionType::PinAsignToGroup,pinId,"",grpId)); + else + retval = new ActionPingroup(PinActionType::PinAsignToGroup,pinId,"",grpId); + if (pinRow >= 0) + retval->mPinActions.append(AtomicAction(PinActionType::PinMoveToRow,pinId,"",pinRow++)); + } + retval->setObject(UserActionObject(m->get_id(),UserActionObjectType::Module)); + return retval; + } + + ActionPingroup* ActionPingroup::addPinToExistingGroup(const Module* m, u32 grpId, u32 pinId, int pinRow) + { + QList pinIds; + pinIds << pinId; + return addPinsToExistingGroup(m,grpId,pinIds,pinRow); + } + + ActionPingroup* ActionPingroup::addPinsToNewGroup(const Module* m, const QString& name, QList pinIds, int grpRow) + { + static int vid = -9; + ActionPingroup* retval = new ActionPingroup(PinActionType::GroupCreate,vid,name); + if (!pinIds.isEmpty()) + { + ModulePin* pin = m->get_pin_by_id(pinIds.first()); + if (pin) + { + retval->mPinActions.append(AtomicAction(PinActionType::GroupDirChange,vid,"",(int)pin->get_direction())); + retval->mPinActions.append(AtomicAction(PinActionType::GroupTypeChange,vid,"",(int)pin->get_type())); + } + } + for (u32 pinId : pinIds) + retval->mPinActions.append(AtomicAction(PinActionType::PinAsignToGroup,pinId,"",vid)); + + if (grpRow >= 0) + retval->mPinActions.append(AtomicAction(PinActionType::GroupMoveToRow,vid,"",grpRow)); + retval->setObject(UserActionObject(m->get_id(),UserActionObjectType::Module)); + return retval; + } + + ActionPingroup* ActionPingroup::addPinToNewGroup(const Module *m, const QString& name, u32 pinId, int grpRow) + { + QList pinIds; + pinIds << pinId; + return addPinsToNewGroup(m,name,pinIds, grpRow); + } + + ActionPingroup* ActionPingroup::deletePinGroup(const Module *m, u32 grpId) + { + ActionPingroup* retval = nullptr; + + PinGroup* groupToDelete = m->get_pin_group_by_id(grpId); + if (!groupToDelete) return retval; + + QMap existingGroups; + for (PinGroup* pgroup : m->get_pin_groups()) + existingGroups.insert(QString::fromStdString(pgroup->get_name()),pgroup->get_id()); + + bool doNotDelete = false; // if there is a pin with the same name as the + int vid = -1; + + for (ModulePin* pin : groupToDelete->get_pins()) + { + if (pin->get_name() == groupToDelete->get_name()) + doNotDelete = true; + else + { + QString pinName = QString::fromStdString(pin->get_name()); + auto it = existingGroups.find(pinName); + if (it == existingGroups.end()) + { + if (retval) + retval->mPinActions.append(AtomicAction(PinActionType::GroupCreate,vid,pinName)); + else + retval = new ActionPingroup(PinActionType::GroupCreate,vid,pinName); + retval->mPinActions.append(AtomicAction(PinActionType::PinAsignToGroup,pin->get_id(),"",vid)); + --vid; + } + else + { + if (retval) + retval->mPinActions.append(AtomicAction(PinActionType::PinAsignToGroup,pin->get_id(),"",it.value())); + else + retval = new ActionPingroup(PinActionType::PinAsignToGroup,pin->get_id(),"",it.value()); + } + } + + } + + if (!doNotDelete) + { + if (retval) + retval->mPinActions.append(AtomicAction(PinActionType::GroupDelete,groupToDelete->get_id())); + else + retval = new ActionPingroup(PinActionType::GroupDelete,groupToDelete->get_id()); + } + + retval->setObject(UserActionObject(m->get_id(),UserActionObjectType::Module)); + return retval; + } + + ActionPingroup* ActionPingroup::removePinsFromGroup(const Module* m, QList pinIds) + { + ActionPingroup* retval = nullptr; + QSet existingGroupNames; + for (PinGroup* pgroup : m->get_pin_groups()) + existingGroupNames.insert(QString::fromStdString(pgroup->get_name())); + int vid = -1; + QString basename; + for (u32 pinId : pinIds) + { + ModulePin* pin = m->get_pin_by_id(pinId); + if (!pin) return nullptr; + int count = 2; + QString name = basename = QString::fromStdString(pin->get_name()); + while (existingGroupNames.contains(name)) + name = QString("%1_%2").arg(basename).arg(count++); + if (retval) + retval->mPinActions.append(AtomicAction(PinActionType::GroupCreate,vid,name)); + else + retval = new ActionPingroup(PinActionType::GroupCreate,vid,name); + retval->mPinActions.append(AtomicAction(PinActionType::PinAsignToGroup,pinId,"",vid)); + --vid; + } + retval->setObject(UserActionObject(m->get_id(),UserActionObjectType::Module)); + return retval; + } + + ActionPingroup::GroupRestore::GroupRestore(Module* m, PinGroup* pgroup) + : mId(pgroup->get_id()), + mName(QString::fromStdString(pgroup->get_name())), + mRow(pinGroupRow(m,pgroup)), + mStartIndex(pgroup->get_start_index()), + mDirection(pgroup->get_direction()), + mType(pgroup->get_type()) + { + if (!pgroup->is_ascending()) mStartIndex = -mStartIndex-1; + } +} diff --git a/plugins/gui/src/user_action/action_remove_items_from_object.cpp b/plugins/gui/src/user_action/action_remove_items_from_object.cpp index 00719d3bdc0..d5a20fc738b 100644 --- a/plugins/gui/src/user_action/action_remove_items_from_object.cpp +++ b/plugins/gui/src/user_action/action_remove_items_from_object.cpp @@ -116,6 +116,7 @@ namespace hal else return false; break; + /* TODO PIN case UserActionObjectType::PinGroup: { auto mod = gNetlist->get_module_by_id(mParentObject.id()); if (mod) @@ -135,7 +136,7 @@ namespace hal } for (u32 id : mPins) { - if (mod->remove_pin_from_group(pinGroup, mod->get_pin_by_id(id), false).is_error()) + if (!mod->remove_pin_from_group(pinGroup, mod->get_pin_by_id(id), false)) { return false; } @@ -162,6 +163,7 @@ namespace hal } } break; + */ default: return false; } diff --git a/plugins/gui/src/user_action/action_rename_object.cpp b/plugins/gui/src/user_action/action_rename_object.cpp index d5f6d3e35cb..2e8a080cd8c 100644 --- a/plugins/gui/src/user_action/action_rename_object.cpp +++ b/plugins/gui/src/user_action/action_rename_object.cpp @@ -104,6 +104,7 @@ namespace hal return false; } break; + /* TODO PIN case UserActionObjectType::Pin: { mod = gNetlist->get_module_by_id(mParentObject.id()); if (!mod) @@ -138,15 +139,18 @@ namespace hal mod->set_pin_group_name(pinGroup, mNewName.toStdString()); } break; + */ default: return false; } ActionRenameObject* undo = new ActionRenameObject(oldName); undo->setObject(mObject); + /* TODO PIN if (mObject.type() == UserActionObjectType::Pin || mObject.type() == UserActionObjectType::PinGroup) { undo->setParentObject(mParentObject); } + */ mUndoAction = undo; return UserAction::exec(); } diff --git a/plugins/gui/src/user_action/action_reorder_object.cpp b/plugins/gui/src/user_action/action_reorder_object.cpp index 6465fdd1f5f..120aedb02d4 100644 --- a/plugins/gui/src/user_action/action_reorder_object.cpp +++ b/plugins/gui/src/user_action/action_reorder_object.cpp @@ -23,6 +23,7 @@ namespace hal bool ActionReorderObject::exec() { + /* TODO PIN int oldIndex = -1; switch (mObject.type()) { @@ -43,8 +44,7 @@ namespace hal if (pinGroup->size() > 1) { oldIndex = pin->get_group().second; - auto result = mod->move_pin_within_group(pinGroup, pin, mNewIndex); - if (result.is_error()) + if (!mod->move_pin_within_group(pinGroup, pin, mNewIndex)) { return false; } @@ -86,6 +86,7 @@ namespace hal undo->setParentObject(mParentObject); mUndoAction = undo; } + */ return UserAction::exec(); } diff --git a/plugins/gui/src/user_action/action_set_object_type.cpp b/plugins/gui/src/user_action/action_set_object_type.cpp index f86cb5d2f41..00c52ebc305 100644 --- a/plugins/gui/src/user_action/action_set_object_type.cpp +++ b/plugins/gui/src/user_action/action_set_object_type.cpp @@ -49,6 +49,7 @@ namespace hal Module* mod; switch (mObject.type()) { + /* TODO PIN case UserActionObjectType::Pin: //only possible to change module pin types { //should also check if its a valid type? (enum_from_string default value doesnt help @@ -74,6 +75,7 @@ namespace hal } } break; + */ case UserActionObjectType::Module: mod = gNetlist->get_module_by_id(mObject.id()); if (mod != nullptr) diff --git a/src/netlist/decorators/netlist_modification_decorator.cpp b/src/netlist/decorators/netlist_modification_decorator.cpp index 4eee34294d3..102ac6087c7 100644 --- a/src/netlist/decorators/netlist_modification_decorator.cpp +++ b/src/netlist/decorators/netlist_modification_decorator.cpp @@ -292,15 +292,14 @@ namespace hal // remove pin from current pin group auto current_pin_group = pin->get_group().first; // This get is safe, since we make sure that the pin is a valid pointer and part of the group - current_pin_group->remove_pin(pin).get(); + current_pin_group->remove_pin(pin); // delete old pin group incase it is now empty if (current_pin_group->get_pins().empty()) { - if (const auto res = m->delete_pin_group(current_pin_group); !res.is_ok()) + if (!m->delete_pin_group(current_pin_group)) { - return ERR_APPEND(res.get_error(), - "could not connect master net '" + master_net->get_name() + "' with ID " + std::to_string(master_net->get_id()) + " with slave net '" + slave_net->get_name() + return ERR("could not connect master net '" + master_net->get_name() + "' with ID " + std::to_string(master_net->get_id()) + " with slave net '" + slave_net->get_name() + "' with ID " + std::to_string(slave_net->get_id()) + ": failed to delete pingroup " + current_pin_group->get_name() + "with ID " + std::to_string(current_pin_group->get_id()) + " that is now empty."); } @@ -327,7 +326,7 @@ namespace hal pin_group = pin_groups.front(); } - pin_group->assign_pin(pin).get(); + pin_group->assign_pin(pin); if (const auto res = pin_group->move_pin(pin, pin_index); res.is_error()) { return ERR_APPEND(res.get_error(), @@ -346,4 +345,4 @@ namespace hal return OK(master_net); } -} // namespace hal \ No newline at end of file +} // namespace hal diff --git a/src/netlist/event_system/event_log.cpp b/src/netlist/event_system/event_log.cpp index 1f1973a2603..3dd2eb41a6b 100644 --- a/src/netlist/event_system/event_log.cpp +++ b/src/netlist/event_system/event_log.cpp @@ -287,7 +287,10 @@ namespace hal } else if (event == ModuleEvent::event::pin_changed) { - log_info("event", "changed port of module '{}' (id {:08x})", module->get_name(), module->get_id()); + PinEvent pev = (PinEvent) (associated_data&0xF); + u32 id = (associated_data >> 4); + + log_info("event", "module '{}' (id {:08x}) port event '{}' id={}", module->get_name(), module->get_id(), enum_to_string(pev), id); } else { diff --git a/src/netlist/gate_library/enums/pin_event.cpp b/src/netlist/gate_library/enums/pin_event.cpp new file mode 100644 index 00000000000..73bf9f001e4 --- /dev/null +++ b/src/netlist/gate_library/enums/pin_event.cpp @@ -0,0 +1,102 @@ +#include "hal_core/netlist/gate_library/enums/pin_event.h" +#include "hal_core/netlist/event_system/event_handler.h" +#include "hal_core/netlist/module.h" +#include +#include + +namespace hal { + + template<> + std::map EnumStrings::data = { + {PinEvent::unknown, "unknown"}, + {PinEvent::GroupCreate, "GroupCreate"}, + {PinEvent::GroupReorder, "GroupReorder"}, + {PinEvent::GroupRename, "GroupRename"}, + {PinEvent::GroupTypeChange, "GroupTypeChange"}, + {PinEvent::GroupDirChange, "GroupDirChange"}, + {PinEvent::GroupDelete, "GroupDelete"}, + {PinEvent::PinCreate, "PinCreate"}, + {PinEvent::PinReorder, "PinReorder"}, + {PinEvent::PinAssignToGroup, "PinAssignToGroup"}, + {PinEvent::PinRename, "PinRename"}, + {PinEvent::PinTypeChange, "PinTypeChange"}, + {PinEvent::PinDirChange, "PinDirChange"}, + {PinEvent::PinDelete, "PinDelete"} + }; + + std::unordered_map PinChangedEvent::s_event_stack; + + PinChangedEvent::PinChangedEvent(Module* m, PinEvent pev, u32 id) + : m_module(m), m_event(pev), m_id(id) + {;} + + void PinChangedEvent::send() + { + auto it = s_event_stack.find(m_module); + if (it == s_event_stack.end()) + { + // not stacked, send event immediately + m_module->get_event_handler()->notify(ModuleEvent::event::pin_changed, m_module, associated_data()); + return; + } + + // put event on stack to emit it later + it->second->push_back(*this); + } + + Module* PinChangedEvent::get_module() const + { + return m_module; + } + + u32 PinChangedEvent::associated_data() + { + return (m_id << 4) | (((u32)m_event)&0xF); + } + + bool pin_event_order(const PinChangedEvent& a, const PinChangedEvent& b) + { + if (a.m_event < b.m_event) return true; + if (a.m_event > b.m_event) return false; + return a.m_idget_event_handler()->notify(ModuleEvent::event::pin_changed, m, it->associated_data()); + } + + PinChangedEventScope::PinChangedEventScope(Module* m) + : m_module(m) + { + auto it = PinChangedEvent::s_event_stack.find(m); + if (it == PinChangedEvent::s_event_stack.end()) + PinChangedEvent::s_event_stack[m] = new PinChangedEvent::EventStack; + else + ++it->second->m_count; + } + + PinChangedEventScope::~PinChangedEventScope() + { + auto it = PinChangedEvent::s_event_stack.find(m_module); + assert(it != PinChangedEvent::s_event_stack.end()); + if (it->second->m_count > 0) + --it->second->m_count; + else + { + delete it->second; + PinChangedEvent::s_event_stack.erase(it); + } + } + + void PinChangedEventScope::send_events() + { + auto it = PinChangedEvent::s_event_stack.find(m_module); + assert(it != PinChangedEvent::s_event_stack.end()); + if (it->second->m_count > 0) // do not send yet + return; + it->second->send_events(m_module); + } +} diff --git a/src/netlist/gate_library/enums/pin_type.cpp b/src/netlist/gate_library/enums/pin_type.cpp index e39bee1b366..091c0f98236 100644 --- a/src/netlist/gate_library/enums/pin_type.cpp +++ b/src/netlist/gate_library/enums/pin_type.cpp @@ -19,4 +19,4 @@ namespace hal {PinType::select, "select"}, {PinType::carry, "carry"}, {PinType::sum, "sum"}}; -} \ No newline at end of file +} diff --git a/src/netlist/gate_library/gate_type.cpp b/src/netlist/gate_library/gate_type.cpp index 2d569e30e8d..7c23a250fd2 100644 --- a/src/netlist/gate_library/gate_type.cpp +++ b/src/netlist/gate_library/gate_type.cpp @@ -370,6 +370,12 @@ namespace hal } PinGroup* pin_group; + if (!ascending && !pins.empty()) + { + // compensate for shifting the start index + start_index -= (pins.size()-1); + } + if (auto res = create_pin_group_internal(id, name, direction, type, ascending, start_index); res.is_error()) { return ERR_APPEND(res.get_error(), "could not create pin group '" + name + "' for gate type '" + m_name + "' with ID " + std::to_string(m_id)); @@ -379,13 +385,23 @@ namespace hal pin_group = res.get(); } - for (auto* pin : pins) + if (ascending) { - if (auto res = assign_pin_to_group(pin_group, pin, delete_empty_groups); res.is_error()) - { - assert(delete_pin_group(pin_group).is_ok()); - return ERR(res.get_error()); - } + for (auto it = pins.begin(); it != pins.end(); ++it) + if (auto res = assign_pin_to_group(pin_group, *it, delete_empty_groups); res.is_error()) + { + assert(delete_pin_group(pin_group)); + return ERR(res.get_error()); + } + } + else + { + for (auto it = pins.rbegin(); it != pins.rend(); ++it) + if (auto res = assign_pin_to_group(pin_group, *it, delete_empty_groups); res.is_error()) + { + assert(delete_pin_group(pin_group)); + return ERR(res.get_error()); + } } return OK(pin_group); @@ -397,17 +413,17 @@ namespace hal return create_pin_group(get_unique_pin_group_id(), name, pins, direction, type, ascending, start_index, delete_empty_groups); } - Result GateType::delete_pin_group_internal(PinGroup* pin_group) + bool GateType::delete_pin_group_internal(PinGroup* pin_group) { // some sanity checks if (pin_group == nullptr) { - return ERR("could not delete pin group of gate type '" + m_name + "' with ID " + std::to_string(m_id) + ": pin group is a 'nullptr'"); + log_warning("gate", "could not delete pin group of gate type '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id); + return false; } if (const auto it = m_pin_groups_map.find(pin_group->get_id()); it == m_pin_groups_map.end() || it->second != pin_group) { - return ERR("could not delete pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id()) + " of gate type '" + m_name + "' with ID " + std::to_string(m_id) - + ": pin group does not belong to gate type"); + log_warning("gate", "could not delete pin group '{}' with ID {} of gate type '{}' with ID {}: pin group does not belong to gate type", pin_group->get_name(), pin_group->get_id(), m_name, m_id); } // erase pin group @@ -422,20 +438,21 @@ namespace hal m_free_pin_group_ids.insert(del_id); m_used_pin_group_ids.erase(del_id); - return OK({}); + return true; } - Result GateType::delete_pin_group(PinGroup* pin_group) + bool GateType::delete_pin_group(PinGroup* pin_group) { if (pin_group == nullptr) { - return ERR("could not delete pin group from gate type '" + m_name + "' with ID " + std::to_string(m_id) + ": pin group is a 'nullptr'"); + log_warning("gate", "could not delete pin group from gate type '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id); + return false; } if (const auto it = m_pin_groups_map.find(pin_group->get_id()); it == m_pin_groups_map.end() || it->second != pin_group) { - return ERR("could not delete pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id()) + " from gate type '" + m_name + "' with ID " + std::to_string(m_id) - + ": pin group does not belong to gate type"); + log_warning("gate", "could not delete pin group '{}' with ID {} from gate type '{}' with ID {}: pin group does not belong to gate type", pin_group->get_name(), pin_group->get_id(), m_name, m_id); + return false; } bool removed_pins = false; @@ -446,16 +463,17 @@ namespace hal removed_pins = true; if (auto res = create_pin_group(pin->get_name(), {pin}, pin->get_direction(), pin->get_type(), true, 0, false); res.is_error()) { - return ERR(res.get_error()); + log_warning("gate", "{}", res.get_error().get()); + return false; } } - if (auto res = delete_pin_group_internal(pin_group); res.is_error()) + if (!delete_pin_group_internal(pin_group)) { - return ERR(res.get_error()); + return false; } - return OK({}); + return true; } Result GateType::assign_pin_to_group(PinGroup* pin_group, GatePin* pin, bool delete_empty_groups) @@ -486,30 +504,27 @@ namespace hal if (PinGroup* pg = pin->get_group().first; pg != nullptr) { // remove from old group and potentially delete old group if empty - if (auto res = pg->remove_pin(pin); res.is_error()) + if (!pg->remove_pin(pin)) { - return ERR_APPEND(res.get_error(), - "could not assign pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " to pin group '" + pin_group->get_name() + "' with ID " + return ERR("could not assign pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " to pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id()) + " of gate type '" + m_name + "' with ID " + std::to_string(m_id) + ": unable to remove pin from pin group '" + pg->get_name() + "' with ID " + std::to_string(pg->get_id())); } if (delete_empty_groups && pg->empty()) { - if (auto res = delete_pin_group_internal(pg); res.is_error()) + if (!delete_pin_group_internal(pg)) { - return ERR_APPEND(res.get_error(), - "could not assign pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " to pin group '" + pin_group->get_name() + "' with ID " + return ERR("could not assign pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " to pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id()) + " of gate type '" + m_name + "' with ID " + std::to_string(m_id) + ": unable to delete pin group '" + pg->get_name() + "' with ID " + std::to_string(pg->get_id())); } } } - if (auto res = pin_group->assign_pin(pin); res.is_error()) + if (!pin_group->assign_pin(pin)) { - return ERR_APPEND(res.get_error(), - "could not assign pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " to pin group '" + pin_group->get_name() + "' with ID " + return ERR("could not assign pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " to pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id()) + " of gate type '" + m_name + "' with ID " + std::to_string(m_id)); } diff --git a/src/netlist/module.cpp b/src/netlist/module.cpp index fcb8d740f8d..612db982c25 100644 --- a/src/netlist/module.cpp +++ b/src/netlist/module.cpp @@ -660,20 +660,20 @@ namespace hal { m_output_nets.insert(net); pin->set_direction(PinDirection::inout); - m_event_handler->notify(ModuleEvent::event::pin_changed, this); + PinChangedEvent(this,PinEvent::PinTypeChange,pin->get_id()).send(); } else if (direction == PinDirection::output) { m_input_nets.insert(net); pin->set_direction(PinDirection::inout); - m_event_handler->notify(ModuleEvent::event::pin_changed, this); + PinChangedEvent(this,PinEvent::PinTypeChange,pin->get_id()).send(); } } else { - if (auto res = assign_pin_net(get_unique_pin_id(), net, PinDirection::inout); res.is_error()) + if (!assign_pin_net(get_unique_pin_id(), net, PinDirection::inout)) { - return ERR(res.get_error()); + return ERR("could not assign inout pin to net ID " + std::to_string(net->get_id())+ ": failed to create pin"); } } } @@ -687,15 +687,15 @@ namespace hal m_input_nets.insert(net); m_output_nets.erase(net); pin->set_direction(PinDirection::input); - m_event_handler->notify(ModuleEvent::event::pin_changed, this); + PinChangedEvent(this,PinEvent::PinTypeChange,pin->get_id()).send(); } } else { m_input_nets.insert(net); - if (auto res = assign_pin_net(get_unique_pin_id(), net, PinDirection::input); res.is_error()) + if (!assign_pin_net(get_unique_pin_id(), net, PinDirection::input)) { - return ERR(res.get_error()); + return ERR("could not assign input pin to net ID " + std::to_string(net->get_id())+ ": failed to create pin"); } } } @@ -709,15 +709,15 @@ namespace hal m_output_nets.insert(net); m_input_nets.erase(net); pin->set_direction(PinDirection::output); - m_event_handler->notify(ModuleEvent::event::pin_changed, this); + PinChangedEvent(this,PinEvent::PinTypeChange,pin->get_id()).send(); } } else { m_output_nets.insert(net); - if (auto res = assign_pin_net(get_unique_pin_id(), net, PinDirection::output); res.is_error()) + if (!assign_pin_net(get_unique_pin_id(), net, PinDirection::output)) { - return ERR(res.get_error()); + return ERR("could not assign output pin to net ID " + std::to_string(net->get_id())+ ": failed to create pin"); } } } @@ -734,9 +734,9 @@ namespace hal { m_output_nets.erase(net); } - if (auto res = remove_pin_net(net); res.is_error()) + if (!remove_pin_net(net)) { - return res; + return ERR("Remove pin net failed"); } } } @@ -831,25 +831,34 @@ namespace hal } else { + // create_pin_internal OK if (create_group) { 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()); + assert(delete_pin_internal(pin_res.get())); 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"); } else { - if (const auto assign_res = group_res.get()->assign_pin(pin_res.get()); assign_res.is_error()) + // create_pin_group_internal OK + if (!group_res.get()->assign_pin(pin_res.get())) { - assert(delete_pin_internal(pin_res.get()).is_ok()); - assert(delete_pin_group_internal(group_res.get()).is_ok()); - return ERR_APPEND(assign_res.get_error(), - "could not create pin '" + name + "' for module '" + m_name + "' with ID " + std::to_string(m_id) + ": failed to assign pin to pin group"); + assert(delete_pin_internal(pin_res.get())); + assert(delete_pin_group_internal(group_res.get())); + 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"); + } + else + { + // pin assigned to new group OK + PinChangedEvent(this,PinEvent::GroupCreate,group_res.get()->get_id()).send(); } } } - m_event_handler->notify(ModuleEvent::event::pin_changed, this); + else + { + PinChangedEvent(this,PinEvent::PinCreate,pin_res.get()->get_id()).send(); + } return pin_res; } } @@ -1104,7 +1113,7 @@ namespace hal m_pin_names_map.erase(old_name); pin->set_name(new_name); m_pin_names_map[new_name] = pin; - m_event_handler->notify(ModuleEvent::event::pin_changed, this); + PinChangedEvent(this,PinEvent::PinRename,pin->get_id()).send(); } return true; @@ -1127,7 +1136,7 @@ namespace hal if (pin->get_type() != new_type) { pin->set_type(new_type); - m_event_handler->notify(ModuleEvent::event::pin_changed, this); + PinChangedEvent(this,PinEvent::PinTypeChange,pin->get_id()).send(); } return true; @@ -1183,7 +1192,7 @@ namespace hal m_pin_group_names_map.erase(old_name); pin_group->set_name(new_name); m_pin_group_names_map[new_name] = pin_group; - m_event_handler->notify(ModuleEvent::event::pin_changed, this); + PinChangedEvent(this,PinEvent::GroupRename,pin_group->get_id()).send(); } return true; @@ -1207,7 +1216,7 @@ namespace hal if (pin_group->get_type() != new_type) { pin_group->set_type(new_type); - m_event_handler->notify(ModuleEvent::event::pin_changed, this); + PinChangedEvent(this,PinEvent::GroupTypeChange,pin_group->get_id()).send(); } return true; } @@ -1234,7 +1243,7 @@ namespace hal if (pin_group->get_direction() != new_direction) { pin_group->set_direction(new_direction); - m_event_handler->notify(ModuleEvent::event::pin_changed, this); + PinChangedEvent(this,PinEvent::GroupTypeChange,pin_group->get_id()).send(); } return true; } @@ -1249,12 +1258,20 @@ namespace hal bool delete_empty_groups, bool force_name) { + PinChangedEventScope scope(this); + if (name.empty()) { return ERR("could not create pin group for module '" + m_name + "' with ID " + std::to_string(m_id) + ": empty string passed as name"); } PinGroup* pin_group; + if (!ascending && !pins.empty()) + { + // compensate for shifting the start index + start_index -= (pins.size()-1); + } + 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)); @@ -1264,16 +1281,27 @@ namespace hal pin_group = res.get(); } - for (auto* pin : pins) + if (ascending) { - if (auto res = assign_pin_to_group(pin_group, pin, delete_empty_groups); res.is_error()) - { - assert(delete_pin_group(pin_group).is_ok()); - return ERR(res.get_error()); - } + for (auto it = pins.begin(); it != pins.end(); ++it) + if (!assign_pin_to_group(pin_group, *it, delete_empty_groups)) + { + assert(delete_pin_group(pin_group)); + return ERR("Assign pin to group failed."); + } + } + else + { + for (auto it = pins.rbegin(); it != pins.rend(); ++it) + if (!assign_pin_to_group(pin_group, *it, delete_empty_groups)) + { + assert(delete_pin_group(pin_group)); + return ERR("Assign pin to group failed."); + } } - m_event_handler->notify(ModuleEvent::event::pin_changed, this); + PinChangedEvent(this,PinEvent::GroupCreate,pin_group->get_id()).send(); + scope.send_events(); return OK(pin_group); } @@ -1289,60 +1317,67 @@ namespace hal 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) + bool Module::delete_pin_group(PinGroup* pin_group) { + PinChangedEventScope scope(this); if (pin_group == nullptr) { - return ERR("could not delete pin group from module '" + m_name + "' with ID " + std::to_string(m_id) + ": pin group is a 'nullptr'"); + log_warning("module", "could not delete pin group from module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id); + return false; } if (const auto it = m_pin_groups_map.find(pin_group->get_id()); it == m_pin_groups_map.end() || it->second != pin_group) { - return ERR("could not delete pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id()) + " from module '" + m_name + "' with ID " + std::to_string(m_id) - + ": pin group does not belong to module"); + log_warning("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); + return false; } - bool removed_pins = false; - std::vector pins_copy = pin_group->get_pins(); for (ModulePin* pin : pins_copy) { - removed_pins = true; - if (auto res = create_pin_group(pin->get_name(), {pin}, pin->get_direction(), pin->get_type(), true, 0, false); res.is_error()) + auto res = create_pin_group(pin->get_name(), {pin}, pin->get_direction(), pin->get_type(), true, 0, false); + if (res.is_error()) { - return ERR(res.get_error()); + return false; } + PinChangedEvent(this,PinEvent::GroupCreate,res.get()->get_id()).send(); + PinChangedEvent(this,PinEvent::PinAssignToGroup,pin->get_id()).send(); } - if (auto res = delete_pin_group_internal(pin_group); res.is_error()) - { - return ERR(res.get_error()); - } + u32 pin_group_id_to_delete = pin_group->get_id(); - if (removed_pins) + if (!delete_pin_group_internal(pin_group)) { - m_event_handler->notify(ModuleEvent::event::pin_changed, this); + return false; } - return OK({}); + + PinChangedEvent(this,PinEvent::GroupDelete,pin_group_id_to_delete).send(); + scope.send_events(); + return true; } - Result Module::move_pin_group(PinGroup* pin_group, u32 new_index) + bool Module::move_pin_group(PinGroup* pin_group, u32 new_index) { if (pin_group == nullptr) { - return ERR("could not move pin group of module '" + m_name + "' with ID " + std::to_string(m_id) + ": pin group is a 'nullptr'"); + log_warning("module", "could not move pin group of module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id); + return false; } if (const auto it = m_pin_groups_map.find(pin_group->get_id()); it == m_pin_groups_map.end() || it->second != pin_group) { - return ERR("could not move pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id()) + " within module '" + m_name + "' with ID " + std::to_string(m_id) - + ": pin group does not belong to module"); + log_warning("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); + return false; } if (new_index >= m_pin_groups_ordered.size()) { - return ERR("could not move pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id) - + ": index " + std::to_string(new_index) + " is out of bounds"); + 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); + return false; } auto src_it = std::find(m_pin_groups_ordered.begin(), m_pin_groups_ordered.end(), pin_group); @@ -1350,7 +1385,7 @@ namespace hal std::advance(dst_it, new_index); if (src_it == dst_it) { - return OK({}); + return true; } else if (std::distance(m_pin_groups_ordered.begin(), src_it) < std::distance(m_pin_groups_ordered.begin(), dst_it)) { @@ -1362,237 +1397,258 @@ namespace hal m_pin_groups_ordered.splice(dst_it, m_pin_groups_ordered, src_it); } - m_event_handler->notify(ModuleEvent::event::pin_changed, this); - return OK({}); + PinChangedEvent(this,PinEvent::GroupReorder,pin_group->get_id()).send(); + return true; } - Result Module::assign_pin_to_group(PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups) + bool Module::assign_pin_to_group(PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups) { + PinChangedEventScope scope(this); + if (pin_group == nullptr) { - return ERR("could not assign pin to pin group of module '" + m_name + "' with ID " + std::to_string(m_id) + ": pin group is a 'nullptr'"); + log_warning("module", "could not assign pin to pin group of module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id); + return false; } if (pin == nullptr) { - return ERR("could not assign pin to pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " - + std::to_string(m_id) + ": pin is a 'nullptr'"); + 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); + return false; } if (const auto it = m_pin_groups_map.find(pin_group->get_id()); it == m_pin_groups_map.end() || it->second != pin_group) { - return ERR("could not assign pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " to pin group '" + pin_group->get_name() + "' with ID " - + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id) + ": pin group does not belong to module"); + log_warning("module", "could not assign pin '{}' with ID {} to pin group '{}' with ID {} of module '{}' with ID {}: pin group does not belong to module", + pin->get_name(), pin->get_id(), pin_group->get_name(), pin_group->get_id(), m_name, m_id); + return false; } if (const auto it = m_pins_map.find(pin->get_id()); it == m_pins_map.end() || it->second != pin) { - return ERR("could not assign pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " to pin group '" + pin_group->get_name() + "' with ID " - + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id) + ": pin does not belong to module"); + log_warning("module", "could not assign pin '{}' with ID {} to pin group '{}' with ID {} of module '{}' with ID {}: pin does not belong to module", + pin->get_name(), pin->get_id(), pin_group->get_name(), pin_group->get_id(), m_name, m_id); + return false; } if (PinGroup* pg = pin->get_group().first; pg != nullptr) { // remove from old group and potentially delete old group if empty - if (auto res = pg->remove_pin(pin); res.is_error()) + if (!pg->remove_pin(pin)) { - return ERR_APPEND(res.get_error(), - "could not assign pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " to pin group '" + pin_group->get_name() + "' with ID " - + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id) + ": unable to remove pin from pin group '" + pg->get_name() - + "' with ID " + std::to_string(pg->get_id())); + log_warning("module", + "could not assign pin '{}' with ID {} to pin group '{}' with ID {} of module '{}' with ID {}: unable to remove pin from pin group '{}' with ID {}", + pin->get_name(), pin->get_id(), pin_group->get_name(), pin_group->get_id(), m_name, m_id, pg->get_name(), pg->get_id()); + return false; } if (delete_empty_groups && pg->empty()) { - if (auto res = delete_pin_group_internal(pg); res.is_error()) + PinChangedEvent(this,PinEvent::GroupDelete,pg->get_id()).send(); + if (!delete_pin_group_internal(pg)) { - return ERR_APPEND(res.get_error(), - "could not assign pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " to pin group '" + pin_group->get_name() + "' with ID " - + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id) + ": unable to delete pin group '" + pg->get_name() - + "' with ID " + std::to_string(pg->get_id())); + log_warning("module", + "could not assign pin '{}' with ID {} to pin group '{}' with ID {} of module '{}' with ID {}: unable to delete pin group '{}' with ID {}", + pin->get_name(), pin->get_id(), pin_group->get_name(), pin_group->get_id(), m_name, m_id, pg->get_name(), pg->get_id()); + return false; } } } - if (auto res = pin_group->assign_pin(pin); res.is_error()) + if (!pin_group->assign_pin(pin)) { - return ERR_APPEND(res.get_error(), - "could not assign pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " to pin group '" + pin_group->get_name() + "' with ID " - + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id)); + log_warning("module", + "could not assign pin '{}' with ID {} to pin group '{}' with ID {} of module '{}' with ID {}", pin->get_name(), pin->get_id(), pin_group->get_name(), pin_group->get_id(), m_name, m_id); + return false; } - m_event_handler->notify(ModuleEvent::event::pin_changed, this); - return OK({}); + PinChangedEvent(this,PinEvent::PinAssignToGroup,pin->get_id()).send(); + scope.send_events(); + return true;; } - Result Module::move_pin_within_group(PinGroup* pin_group, ModulePin* pin, u32 new_index) + bool Module::move_pin_within_group(PinGroup* pin_group, ModulePin* pin, u32 new_index) { if (pin_group == nullptr) { - return ERR("could not move pin within pin group of module '" + m_name + "' with ID " + std::to_string(m_id) + ": pin group is a 'nullptr'"); + log_warning("module", "could not move pin within pin group of module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id); + return false; } if (pin == nullptr) { - return ERR("could not move pin within pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " - + std::to_string(m_id) + ": pin is a 'nullptr'"); + 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); + return false; } if (const auto it = m_pin_groups_map.find(pin_group->get_id()); it == m_pin_groups_map.end() || it->second != pin_group) { - return ERR("could not move pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " within pin group '" + pin_group->get_name() + "' with ID " - + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id) + ": pin group does not belong to module"); + log_warning("module", + "could not move pin '{}' with ID {} within pin group '{}' with ID {} of module '{}' with ID {}: pin group does not belong to module", + pin->get_name(), pin->get_id(), pin_group->get_name(), pin_group->get_id(), m_name, m_id); + return false; } if (const auto it = m_pins_map.find(pin->get_id()); it == m_pins_map.end() || it->second != pin) { - return ERR("could not move pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " within pin group '" + pin_group->get_name() + "' with ID " - + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id) + ": pin does not belong to module"); + log_warning("module", + "could not move pin '{}' with ID {} within pin group '{}' with return ERRID {} of module '{}' with ID {}: pin does not belong to module", + pin->get_name(), pin->get_id(), pin_group->get_name(), pin_group->get_id(), m_name, m_id); + return false; } if (auto res = pin_group->move_pin(pin, new_index); res.is_error()) { - return ERR_APPEND(res.get_error(), - "could not move pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " within pin group '" + pin_group->get_name() + "' with ID " - + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id)); + log_warning("module", + "could not move pin '{}' with ID {} within pin group '{}' with ID {} of module '{}' with ID {}", + pin->get_name(), pin->get_id(), pin_group->get_name(), pin_group->get_id(), m_name, m_id); + return false; } - m_event_handler->notify(ModuleEvent::event::pin_changed, this); - return OK({}); + PinChangedEvent(this,PinEvent::PinReorder,pin->get_id()).send(); + return true; } - Result Module::remove_pin_from_group(PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups) + bool Module::remove_pin_from_group(PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups) { if (pin_group == nullptr) { - return ERR("could not remove pin from pin group of module '" + m_name + "' with ID " + std::to_string(m_id) + ": pin group is a 'nullptr'"); + log_warning("module", "could not remove pin from pin group of module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id); + return false; } if (pin == nullptr) { - return ERR("could not remove pin from pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " - + std::to_string(m_id) + ": pin is a 'nullptr'"); + 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); + return false; } if (const auto it = m_pin_groups_map.find(pin_group->get_id()); it == m_pin_groups_map.end() || it->second != pin_group) { - return ERR("could not remove pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " from pin group '" + pin_group->get_name() + "' with ID " - + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id) + ": pin group does not belong to module"); + log_warning("module", "could not remove pin '{}' with ID {} from pin group '{}' with ID {} of module '{}' with ID {}: pin group does not belong to module", pin->get_name(), pin->get_id(), pin_group->get_name(), pin_group->get_id(), m_name, m_id); + return false; } if (const auto it = m_pins_map.find(pin->get_id()); it == m_pins_map.end() || it->second != pin) { - return ERR("could not remove pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " from pin group '" + pin_group->get_name() + "' with ID " - + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id) + ": pin does not belong to module"); + log_warning("module", "could not remove pin '{}' with ID {} from pin group '{}' with ID {} of module '{}' with ID {}: pin does not belong to module", pin->get_name(), pin->get_id(), pin_group->get_name(), pin_group->get_id(), m_name, m_id); + return false; } if (auto res = create_pin_group(get_unique_pin_group_id(), pin->get_name(), {pin}, pin->get_direction(), pin->get_type(), true, 0, delete_empty_groups); res.is_error()) { - return ERR_APPEND(res.get_error(), - "could not remove pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " from pin group '" + pin_group->get_name() + "' with ID " - + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id) + ": unable to create new pin group for pin"); + log_warning("module", "could not remove pin '{}' with ID {} from pin group '{}' with ID {} of module '{}' with ID : unable to create new pin group for pin", pin->get_name(), pin->get_id(), pin_group->get_name(), pin_group->get_id(), m_name, m_id); + return false; } - return OK({}); + return true; } - Result Module::assign_pin_net(const u32 pin_id, Net* net, PinDirection direction, const std::string& name, PinType type) - { - std::string name_internal; - - if (!name.empty()) - { - name_internal = name; + bool Module::assign_pin_net(const u32 pin_id, Net* net, PinDirection direction) + { + PinChangedEventScope scope(this); + std::string port_prefix; + u32 ctr = 0; + switch (direction) + { + case PinDirection::input: + port_prefix = "I"; + break; + case PinDirection::inout: + port_prefix = "IO"; + break; + case PinDirection::output: + port_prefix = "O"; + break; + default: + log_warning("module", "could not assign pin to net ID {}: invalid pin direction '{}'", net->get_id(), enum_to_string(direction)); + return false; } - else + + std::string name_internal; + do { - std::string port_prefix; - u32 ctr = 0; - switch (direction) - { - case PinDirection::input: - port_prefix = "I"; - break; - case PinDirection::inout: - port_prefix = "IO"; - break; - case PinDirection::output: - port_prefix = "O"; - break; - default: - return ERR("could not assign pin '" + name_internal + "' to net: invalid pin direction '" + enum_to_string(direction) + "'"); - } - do - { - name_internal = port_prefix + "(" + std::to_string(ctr) + ")"; - ctr++; - } 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()); - } + name_internal = port_prefix + "(" + std::to_string(ctr) + ")"; + ctr++; + } 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()); // create pin ModulePin* pin; - if (auto res = create_pin_internal(pin_id, name_internal, net, direction, type, false); res.is_error()) + if (auto res = create_pin_internal(pin_id, name_internal, net, direction, PinType::none, false); res.is_error()) { - return ERR_APPEND(res.get_error(), "could not assign pin '" + name_internal + "' to net: failed to create pin"); + log_warning("module", "could not assign pin '{}' to net: failed to create pin", name_internal); + return false; } else { pin = res.get(); + PinChangedEvent(this,PinEvent::PinCreate,pin->get_id()).send(); } 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"); + log_warning("module", "could not assign pin '{}' to net: failed to create pin group", name_internal); + return false; } else { - if (const auto assign_res = group_res.get()->assign_pin(pin); assign_res.is_error()) + PinChangedEvent(this,PinEvent::GroupCreate,group_res.get()->get_id()).send(); + if (!group_res.get()->assign_pin(pin)) { - return ERR_APPEND(assign_res.get_error(), "could not assign pin '" + name_internal + "' to net: failed to assign pin to pin group"); + log_warning("module", "could not assign pin '{}' to net: failed to assign pin to pin group", name_internal); + return false; } + else + PinChangedEvent(this,PinEvent::PinAssignToGroup,pin->get_id()).send(); } - m_event_handler->notify(ModuleEvent::event::pin_changed, this); - return OK(pin); + scope.send_events(); + return true; } - Result Module::remove_pin_net(Net* net) + bool Module::remove_pin_net(Net* net) { + PinChangedEventScope scope(this); auto pin = get_pin_by_net(net); if (pin == nullptr) { - return ERR("could not remove pin from net: failed to get pin corresponding to net"); + log_warning("module", "could not remove pin from net: failed to get pin corresponding to net"); + return false; } PinGroup* pin_group = pin->get_group().first; assert(pin_group != nullptr); - if (auto res = pin_group->remove_pin(pin); res.is_error()) + if (!pin_group->remove_pin(pin)) { - return ERR_APPEND(res.get_error(), - "could not remove pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " from net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) - + ": failed to remove pin from pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id())); + log_warning("module", "could not remove pin '{}' with ID {} from net '{}' with ID {}: failed to remove pin from pin group '{}' with ID {}", pin->get_name(), pin->get_id(), net->get_name(), net->get_id(), pin_group->get_name(), pin_group->get_id()); + return false; } if (pin_group->empty()) { - if (auto res = delete_pin_group_internal(pin_group); res.is_error()) + PinChangedEvent(this,PinEvent::GroupDelete,pin_group->get_id()).send(); + if (!delete_pin_group_internal(pin_group)) { - return ERR_APPEND(res.get_error(), - "could not remove pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " from net '" + net->get_name() + "' with ID " - + std::to_string(net->get_id()) + ": failed to delete pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id())); + log_warning("module", "could not remove pin '{}' with ID {} from net '{}' with ID {}: failed to delete pin group '{}' with ID {}", pin->get_name(), pin->get_id(), net->get_name(), net->get_id(), pin_group->get_name(), pin_group->get_id()); + return false; } } - if (const auto res = delete_pin_internal(pin); res.is_error()) + u32 pin_id_to_delete = pin->get_id(); + + if (!delete_pin_internal(pin)) { - return ERR_APPEND(res.get_error(), - "could not remove pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " from net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) - + ": failed to delete pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id())); + + log_warning("module", "could not remove pin '{}' with ID {} from net '{}' with ID {}: failed to delete pin '{}' with ID {}", pin->get_name(), pin->get_id(), net->get_name(), net->get_id(), pin->get_name(), pin->get_id()); + return false; } - m_event_handler->notify(ModuleEvent::event::pin_changed, this); - return OK({}); + PinChangedEvent(this,PinEvent::PinDelete,pin_id_to_delete).send(); + scope.send_events(); + return true; } Result Module::create_pin_internal(const u32 id, const std::string& name, Net* net, PinDirection direction, PinType type, bool force_name) @@ -1647,17 +1703,18 @@ namespace hal return OK(pin); } - Result Module::delete_pin_internal(ModulePin* pin) + bool Module::delete_pin_internal(ModulePin* pin) { // some sanity checks if (pin == nullptr) { - return ERR("could not delete pin of gate type '" + m_name + "' with ID " + std::to_string(m_id) + ": pin is a 'nullptr'"); + log_warning("module", "could not delete pin of gate type '{}' with ID {}: pin is a 'nullptr'", m_name, m_id); + return false; } if (const auto it = m_pins_map.find(pin->get_id()); it == m_pins_map.end() || it->second != pin) { - return ERR("could not delete pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id) - + ": pin does not belong to module"); + 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); + return false; } // erase pin @@ -1671,7 +1728,7 @@ namespace hal m_free_pin_ids.insert(del_id); m_used_pin_ids.erase(del_id); - return OK({}); + return true; } 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) @@ -1719,17 +1776,20 @@ namespace hal return OK(pin_group); } - Result Module::delete_pin_group_internal(PinGroup* pin_group) + bool Module::delete_pin_group_internal(PinGroup* pin_group) { // some sanity checks if (pin_group == nullptr) { - return ERR("could not delete pin group of module '" + m_name + "' with ID " + std::to_string(m_id) + ": pin group is a 'nullptr'"); + log_warning("module", "could not delete pin group of module '{}' with ID {}: pin group is a 'nullptr'", m_name, m_id); + return false; } if (const auto it = m_pin_groups_map.find(pin_group->get_id()); it == m_pin_groups_map.end() || it->second != pin_group) { - return ERR("could not delete pin group '" + pin_group->get_name() + "' with ID " + std::to_string(pin_group->get_id()) + " of module '" + m_name + "' with ID " + std::to_string(m_id) - + ": pin group does not belong to module"); + log_warning("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); + return false; } // erase pin group @@ -1744,6 +1804,11 @@ namespace hal m_free_pin_group_ids.insert(del_id); m_used_pin_group_ids.erase(del_id); - return OK({}); + return true; + } + + EventHandler* Module::get_event_handler() const + { + return m_event_handler; } } // namespace hal diff --git a/src/python_bindings/bindings/gate_type.cpp b/src/python_bindings/bindings/gate_type.cpp index 449940d128f..4875ab91245 100644 --- a/src/python_bindings/bindings/gate_type.cpp +++ b/src/python_bindings/bindings/gate_type.cpp @@ -487,14 +487,13 @@ namespace hal py_gate_type.def( "delete_pin_group", [](GateType& self, PinGroup* pin_group) { - auto res = self.delete_pin_group(pin_group); - if (res.is_ok()) + if (self.delete_pin_group(pin_group)) { return true; } else { - log_error("python_context", "error encountered while deleting pin group:\n{}", res.get_error().get()); + log_error("python_context", "error encountered while deleting pin group"); return false; } }, diff --git a/src/python_bindings/bindings/module.cpp b/src/python_bindings/bindings/module.cpp index 730166d4c0d..0caed7cebe4 100644 --- a/src/python_bindings/bindings/module.cpp +++ b/src/python_bindings/bindings/module.cpp @@ -782,14 +782,13 @@ namespace hal py_module.def( "delete_pin_group", [](Module& self, PinGroup* pin_group) { - auto res = self.delete_pin_group(pin_group); - if (res.is_ok()) + if (self.delete_pin_group(pin_group)) { return true; } else { - log_error("python_context", "error encountered while deleting pin group:\n{}", res.get_error().get()); + log_error("python_context", "error encountered while deleting pin group."); return false; } }, @@ -805,14 +804,13 @@ namespace hal py_module.def( "move_pin_group", [](Module& self, PinGroup* pin_group, u32 new_index) { - auto res = self.move_pin_group(pin_group, new_index); - if (res.is_ok()) + if (self.move_pin_group(pin_group, new_index)) { return true; } else { - log_error("python_context", "error encountered while moving pin group:\n{}", res.get_error().get()); + log_error("python_context", "error encountered while moving pin group."); return false; } }, @@ -831,14 +829,13 @@ namespace hal py_module.def( "assign_pin_to_group", [](Module& self, PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups = true) { - auto res = self.assign_pin_to_group(pin_group, pin, delete_empty_groups); - if (res.is_ok()) + if (self.assign_pin_to_group(pin_group, pin, delete_empty_groups)) { return true; } else { - log_error("python_context", "error encountered while assigning pin to pin group:\n{}", res.get_error().get()); + log_error("python_context", "error encountered while assigning pin to pin group."); return false; } }, @@ -858,14 +855,13 @@ namespace hal py_module.def( "move_pin_within_group", [](Module& self, PinGroup* pin_group, ModulePin* pin, u32 new_index) { - auto res = self.move_pin_within_group(pin_group, pin, new_index); - if (res.is_ok()) + if (self.move_pin_within_group(pin_group, pin, new_index)) { return true; } else { - log_error("python_context", "error encountered while moving pin within pin group:\n{}", res.get_error().get()); + log_error("python_context", "error encountered while moving pin within pin group."); return false; } }, @@ -886,14 +882,13 @@ namespace hal py_module.def( "remove_pin_from_group", [](Module& self, PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups = true) { - auto res = self.remove_pin_from_group(pin_group, pin, delete_empty_groups); - if (res.is_ok()) + if (self.remove_pin_from_group(pin_group, pin, delete_empty_groups)) { return true; } else { - log_error("python_context", "error encountered while removing pin from pin group:\n{}", res.get_error().get()); + log_error("python_context", "error encountered while removing pin from pin group."); return false; } }, diff --git a/tests/netlist/module.cpp b/tests/netlist/module.cpp index 20a2d552561..1c85e69f817 100644 --- a/tests/netlist/module.cpp +++ b/tests/netlist/module.cpp @@ -980,7 +980,7 @@ namespace hal { // delete pin group u32 group_id = in_group->get_id(); - EXPECT_TRUE(m_1->delete_pin_group(in_group).is_ok()); + EXPECT_TRUE(m_1->delete_pin_group(in_group)); EXPECT_EQ(m_1->get_pin_group_by_id(group_id), nullptr); EXPECT_EQ(m_1->get_pin_groups().size(), 4); PinGroup* in_group_0 = in_pin_0->get_group().first; @@ -995,7 +995,7 @@ namespace hal { EXPECT_EQ(in_group_0->get_index(in_pin_0).get(), 0); // assign pin to group - EXPECT_TRUE(m_1->assign_pin_to_group(in_group_0, in_pin_1).is_ok()); + EXPECT_TRUE(m_1->assign_pin_to_group(in_group_0, in_pin_1)); EXPECT_EQ(m_1->get_pin_groups().size(), 3); EXPECT_EQ(in_group_0->size(), 2); EXPECT_EQ(in_pin_0->get_group(), std::pair(in_group_0, i32(0))); @@ -1006,7 +1006,7 @@ namespace hal { EXPECT_EQ(in_group_0->get_pin_at_index(1).get(), in_pin_1); // move pins within group - EXPECT_TRUE(m_1->move_pin_within_group(in_group_0, in_pin_1, 0).is_ok()); + EXPECT_TRUE(m_1->move_pin_within_group(in_group_0, in_pin_1, 0)); EXPECT_EQ(in_pin_0->get_group(), std::pair(in_group_0, i32(1))); EXPECT_EQ(in_group_0->get_index(in_pin_0).get(), 1); EXPECT_EQ(in_pin_1->get_group(), std::pair(in_group_0, i32(0))); @@ -1014,7 +1014,7 @@ namespace hal { EXPECT_EQ(in_group_0->get_pin_at_index(1).get(), in_pin_0); EXPECT_EQ(in_group_0->get_pin_at_index(0).get(), in_pin_1); - EXPECT_TRUE(m_1->move_pin_within_group(in_group_0, in_pin_1, 1).is_ok()); + EXPECT_TRUE(m_1->move_pin_within_group(in_group_0, in_pin_1, 1)); EXPECT_EQ(in_pin_0->get_group(), std::pair(in_group_0, i32(0))); EXPECT_EQ(in_group_0->get_index(in_pin_0).get(), 0); EXPECT_EQ(in_pin_1->get_group(), std::pair(in_group_0, i32(1))); @@ -1024,20 +1024,20 @@ namespace hal { // remove pin from group EXPECT_TRUE(m_1->set_pin_group_name(in_group_0, "I_tmp")); - EXPECT_TRUE(m_1->remove_pin_from_group(in_group_0, in_pin_0).is_ok()); + EXPECT_TRUE(m_1->remove_pin_from_group(in_group_0, in_pin_0)); EXPECT_EQ(in_pin_1->get_group(), std::pair(in_group_0, i32(0))); EXPECT_EQ(in_group_0->get_index(in_pin_1).get(), 0); EXPECT_EQ(in_group_0->get_pin_at_index(0).get(), in_pin_1); EXPECT_EQ(in_pin_0->get_group().first->get_name(), in_pin_0->get_name()); EXPECT_EQ(in_pin_0->get_group().second, 0); - EXPECT_TRUE(m_1->assign_pin_to_group(in_group_0, in_pin_0).is_ok()); + EXPECT_TRUE(m_1->assign_pin_to_group(in_group_0, in_pin_0)); EXPECT_EQ(in_group_0->size(), 2); // try mixed directions and types EXPECT_TRUE(m_1->set_pin_type(out_pin_0, PinType::address)); EXPECT_TRUE(m_1->set_pin_type(out_pin_1, PinType::data)); - EXPECT_TRUE(m_1->assign_pin_to_group(in_group_0, out_pin_0).is_ok()); // wrong direction - EXPECT_TRUE(m_1->assign_pin_to_group(in_group_0, out_pin_1).is_ok()); // wrong type + EXPECT_TRUE(m_1->assign_pin_to_group(in_group_0, out_pin_0)); // wrong direction + EXPECT_TRUE(m_1->assign_pin_to_group(in_group_0, out_pin_1)); // wrong type EXPECT_EQ(in_group_0->size(), 4); EXPECT_TRUE(m_1->create_pin_group("O1", {out_pin_0, out_pin_1}).is_ok()); // different types EXPECT_TRUE(m_1->create_pin_group("O2", {out_pin_0, in_pin_0}).is_ok()); // different directions @@ -1110,6 +1110,9 @@ namespace hal { // create input pin group auto res = m_1->create_pin_group("I", {in_pin_0, in_pin_1}, PinDirection::input, PinType::none, false, 2); ASSERT_TRUE(res.is_ok()); + // descending group start index 2 + // in_pin_0 "I0" index 2 + // in_pin_1 "I1" index 1 PinGroup* in_group = res.get(); ASSERT_NE(in_group, nullptr); EXPECT_EQ(m_1->get_pin_groups().size(), 3); @@ -1137,7 +1140,10 @@ namespace hal { EXPECT_EQ(in_pin_1->get_group(), std::pair(in_group, i32(1))); // move pins within group - EXPECT_TRUE(m_1->move_pin_within_group(in_group, in_pin_1, 2).is_ok()); + EXPECT_TRUE(m_1->move_pin_within_group(in_group, in_pin_1, 2)); + // descending group start index 2 + // in_pin_1 "I1" index 2 + // in_pin_0 "I0" index 1 EXPECT_EQ(in_pin_0->get_group(), std::pair(in_group, i32(1))); EXPECT_EQ(in_group->get_index(in_pin_0).get(), 1); EXPECT_EQ(in_pin_1->get_group(), std::pair(in_group, i32(2))); @@ -1145,34 +1151,45 @@ namespace hal { EXPECT_EQ(in_group->get_pin_at_index(1).get(), in_pin_0); EXPECT_EQ(in_group->get_pin_at_index(2).get(), in_pin_1); - EXPECT_TRUE(m_1->move_pin_within_group(in_group, in_pin_1, 1).is_ok()); + EXPECT_TRUE(m_1->move_pin_within_group(in_group, in_pin_1, 1)); + // descending group start index 2 + // in_pin_0 "I0" index 2 + // in_pin_1 "I1" index 1 EXPECT_EQ(in_pin_0->get_group(), std::pair(in_group, i32(2))); EXPECT_EQ(in_group->get_index(in_pin_0).get(), 2); EXPECT_EQ(in_pin_1->get_group(), std::pair(in_group, i32(1))); EXPECT_EQ(in_group->get_index(in_pin_1).get(), 1); EXPECT_EQ(in_group->get_pin_at_index(2).get(), in_pin_0); - EXPECT_EQ(in_group->get_pin_at_index(1).get(), in_pin_1); + EXPECT_EQ(in_group->get_pin_at_index(1).get(), in_pin_1); // remove pin from group - EXPECT_TRUE(m_1->remove_pin_from_group(in_group, in_pin_0).is_ok()); - EXPECT_EQ(in_pin_1->get_group(), std::pair(in_group, i32(2))); - EXPECT_EQ(in_group->get_index(in_pin_1).get(), 2); - EXPECT_EQ(in_group->get_pin_at_index(2).get(), in_pin_1); + EXPECT_TRUE(m_1->remove_pin_from_group(in_group, in_pin_0)); + // descending group start index 1 + // in_pin_1 "I1" index 1 + EXPECT_EQ(in_group->get_start_index(), 1); + EXPECT_EQ(in_pin_1->get_group(), std::pair(in_group, i32(1))); + EXPECT_EQ(in_group->get_index(in_pin_1).get(), 1); + EXPECT_EQ(in_group->get_pin_at_index(1).get(), in_pin_1); EXPECT_EQ(in_pin_0->get_group().first->get_name(), in_pin_0->get_name()); EXPECT_EQ(in_pin_0->get_group().second, 0); - EXPECT_TRUE(m_1->assign_pin_to_group(in_group, in_pin_0).is_ok()); - EXPECT_EQ(in_group->size(), 2); // assign pin to group - EXPECT_TRUE(m_1->assign_pin_to_group(in_group, in_pin_0).is_ok()); + EXPECT_TRUE(m_1->assign_pin_to_group(in_group, in_pin_0)); + // descending group start index 2 + // in_pin_0 "I0" index 2 + // in_pin_1 "I1" index 1 + EXPECT_EQ(in_group->size(), 2); + + // assign same pin twice should not do anything + EXPECT_TRUE(m_1->assign_pin_to_group(in_group, in_pin_0)); EXPECT_EQ(m_1->get_pin_groups().size(), 3); EXPECT_EQ(in_group->size(), 2); - EXPECT_EQ(in_pin_0->get_group(), std::pair(in_group, i32(1))); - EXPECT_EQ(in_group->get_index(in_pin_0).get(), 1); - EXPECT_EQ(in_pin_1->get_group(), std::pair(in_group, i32(2))); - EXPECT_EQ(in_group->get_index(in_pin_1).get(), 2); - EXPECT_EQ(in_group->get_pin_at_index(1).get(), in_pin_0); - EXPECT_EQ(in_group->get_pin_at_index(2).get(), in_pin_1); + EXPECT_EQ(in_pin_0->get_group(), std::pair(in_group, i32(2))); + EXPECT_EQ(in_group->get_index(in_pin_0).get(), 2); + EXPECT_EQ(in_pin_1->get_group(), std::pair(in_group, i32(1))); + EXPECT_EQ(in_group->get_index(in_pin_1).get(), 1); + EXPECT_EQ(in_group->get_pin_at_index(2).get(), in_pin_0); + EXPECT_EQ(in_group->get_pin_at_index(1).get(), in_pin_1); } } TEST_END @@ -1257,8 +1274,8 @@ namespace hal { std::make_tuple(ModuleEvent::event::submodule_added, test_mod, other_mod_sub->get_id()), std::make_tuple(ModuleEvent::event::submodule_removed, test_mod, other_mod_sub->get_id()), std::make_tuple(ModuleEvent::event::gate_assigned, test_mod, test_gate->get_id()), - std::make_tuple(ModuleEvent::event::pin_changed, test_mod, NO_DATA), - std::make_tuple(ModuleEvent::event::pin_changed, test_mod, NO_DATA), + std::make_tuple(ModuleEvent::event::pin_changed, test_mod, PinChangedEvent(test_mod,PinEvent::PinRename,3).associated_data()), + std::make_tuple(ModuleEvent::event::pin_changed, test_mod, PinChangedEvent(test_mod,PinEvent::PinRename,1).associated_data()), std::make_tuple(ModuleEvent::event::gate_removed, test_mod, test_gate->get_id()) }; @@ -1268,7 +1285,7 @@ namespace hal { // Create the listener for the tested event test_utils::EventListener listener; std::function cb = listener.get_conditional_callback( - [=](ModuleEvent::event ev, Module* m, u32 id){return ev == event_type[event_idx] && m == test_mod;} + [=](ModuleEvent::event ev, Module* m, u32 /*id*/){return ev == event_type[event_idx] && m == test_mod;} ); std::string cb_name = "mod_event_callback_" + std::to_string((u32)event_type[event_idx]); // Register a callback of the listener @@ -1288,7 +1305,7 @@ namespace hal { // -- 'created' event test_utils::EventListener listener_created; std::function cb_created = listener_created.get_conditional_callback( - [=](ModuleEvent::event ev, Module* m, u32 id){return ev == ModuleEvent::event::created;} + [=](ModuleEvent::event ev, Module* /*m*/, u32 /*id*/){return ev == ModuleEvent::event::created;} ); std::string cb_name_created = "mod_event_callback_created"; test_nl->get_event_handler()->register_callback(cb_name_created, cb_created); @@ -1303,7 +1320,7 @@ namespace hal { // -- 'removed' event test_utils::EventListener listener_removed; std::function cb_removed = listener_removed.get_conditional_callback( - [=](ModuleEvent::event ev, Module* m, u32 id){return ev == ModuleEvent::event::removed;} + [=](ModuleEvent::event ev, Module* /*m*/, u32 /*id*/){return ev == ModuleEvent::event::removed;} ); std::string cb_name_removed = "mod_event_callback_removed"; test_nl->get_event_handler()->register_callback(cb_name_removed, cb_removed); diff --git a/tests/test_utils/src/gate_library_test_utils.cpp b/tests/test_utils/src/gate_library_test_utils.cpp index 019ee656453..c074221da03 100644 --- a/tests/test_utils/src/gate_library_test_utils.cpp +++ b/tests/test_utils/src/gate_library_test_utils.cpp @@ -12,6 +12,21 @@ namespace hal { namespace test_utils { + + void dumpPingroups(const GateType *gt) + { + std::cerr << "gate type: " << gt->get_id() << " <" << gt->get_name() << ">\n"; + for (PinGroup* pg : gt->get_pin_groups()) + { + std::cerr << " grp: " << pg->get_id() << (pg->is_ascending()?" asc ": " des ") << pg->get_start_index() + << " <" << pg->get_name() << ">\n"; + for (GatePin* pin : pg->get_pins()) + std::cerr << " pin: " << pin->get_id() << " inx:" << pin->get_group().second << " <" << pin->get_name() << ">\n"; + } + std::cerr << "-------------" << std::endl; + } + + std::unique_ptr create_gate_library(const std::filesystem::path& file_path) { std::unique_ptr lib = std::unique_ptr(new GateLibrary(file_path, "TESTING_GATE_LIBRARY")); @@ -416,185 +431,179 @@ namespace hal return nullptr; } - if (auto res_grp = carry4->create_pin_group("DI", {}, PinDirection::input, PinType::none, false, 3); res_grp.is_error()) + std::vector temp_pins; + + //--- pingroup DI --- + if (auto res = carry4->create_pin("DI(3)", PinDirection::input, PinType::none, false); res.is_error()) { return nullptr; } else { - const auto grp = res_grp.get(); + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("DI(3)", PinDirection::input, PinType::none, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res = carry4->create_pin("DI(2)", PinDirection::input, PinType::none, false); res.is_error()) + { + return nullptr; + } + else + { + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("DI(2)", PinDirection::input, PinType::none, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res = carry4->create_pin("DI(1)", PinDirection::input, PinType::none, false); res.is_error()) + { + return nullptr; + } + else + { + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("DI(1)", PinDirection::input, PinType::none, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res = carry4->create_pin("DI(0)", PinDirection::input, PinType::none, false); res.is_error()) + { + return nullptr; + } + else + { + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("DI(0)", PinDirection::input, PinType::none, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res_grp = carry4->create_pin_group("DI", temp_pins, PinDirection::input, PinType::none, false, 3); res_grp.is_error()) + { + return nullptr; } + temp_pins.clear(); - if (auto res_grp = carry4->create_pin_group("S", {}, PinDirection::input, PinType::none, false, 3); res_grp.is_error()) + //--- pingroup S ---- + if (auto res = carry4->create_pin("S(3)", PinDirection::input, PinType::none, false); res.is_error()) { return nullptr; } else { - const auto grp = res_grp.get(); + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("S(3)", PinDirection::input, PinType::none, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res = carry4->create_pin("S(2)", PinDirection::input, PinType::none, false); res.is_error()) + { + return nullptr; + } + else + { + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("S(2)", PinDirection::input, PinType::none, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res = carry4->create_pin("S(1)", PinDirection::input, PinType::none, false); res.is_error()) + { + return nullptr; + } + else + { + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("S(1)", PinDirection::input, PinType::none, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res = carry4->create_pin("S(0)", PinDirection::input, PinType::none, false); res.is_error()) + { + return nullptr; + } + else + { + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("S(0)", PinDirection::input, PinType::none, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res_grp = carry4->create_pin_group("S", temp_pins, PinDirection::input, PinType::none, false, 3); res_grp.is_error()) + { + return nullptr; } + temp_pins.clear(); - if (auto res_grp = carry4->create_pin_group("CO", {}, PinDirection::output, PinType::carry, false, 3); res_grp.is_error()) + //--- pingroup CO --- + if (auto res = carry4->create_pin("CO(3)", PinDirection::output, PinType::carry, false); res.is_error()) { return nullptr; } else { - const auto grp = res_grp.get(); + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("CO(3)", PinDirection::output, PinType::carry, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res = carry4->create_pin("CO(2)", PinDirection::output, PinType::carry, false); res.is_error()) + { + return nullptr; + } + else + { + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("CO(2)", PinDirection::output, PinType::carry, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res = carry4->create_pin("CO(1)", PinDirection::output, PinType::carry, false); res.is_error()) + { + return nullptr; + } + else + { + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("CO(1)", PinDirection::output, PinType::carry, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res = carry4->create_pin("CO(0)", PinDirection::output, PinType::carry, false); res.is_error()) + { + return nullptr; + } + else + { + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("CO(0)", PinDirection::output, PinType::carry, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res_grp = carry4->create_pin_group("CO", temp_pins, PinDirection::output, PinType::carry, false, 3); res_grp.is_error()) + { + return nullptr; } + temp_pins.clear(); - if (auto res_grp = carry4->create_pin_group("O", {}, PinDirection::output, PinType::none, false, 3); res_grp.is_error()) + //--- pingroup O ---- + if (auto res = carry4->create_pin("O(3)", PinDirection::output, PinType::none, false); res.is_error()) { return nullptr; } else { - const auto grp = res_grp.get(); + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("O(3)", PinDirection::output, PinType::none, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res = carry4->create_pin("O(2)", PinDirection::output, PinType::none, false); res.is_error()) + { + return nullptr; + } + else + { + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("O(2)", PinDirection::output, PinType::none, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res = carry4->create_pin("O(1)", PinDirection::output, PinType::none, false); res.is_error()) + { + return nullptr; + } + else + { + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("O(1)", PinDirection::output, PinType::none, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res = carry4->create_pin("O(0)", PinDirection::output, PinType::none, false); res.is_error()) + { + return nullptr; + } + else + { + temp_pins.push_back(res.get()); + } - if (auto res = carry4->create_pin("O(0)", PinDirection::output, PinType::none, false); res.is_error()) - { - return nullptr; - } - else - { - grp->assign_pin(res.get()); - } + if (auto res_grp = carry4->create_pin_group("O", temp_pins, PinDirection::output, PinType::none, false, 3); res_grp.is_error()) + { + return nullptr; } + temp_pins.clear(); carry4->add_boolean_function("CO(0)", BooleanFunction::from_string("((S(0) & (CI | CYINIT)) | ((! S(0)) & DI(0)))").get()); carry4->add_boolean_function("CO(1)", BooleanFunction::from_string("((S(1) & CO(0)) | ((! S(1)) & DI(1)))").get()); @@ -1373,6 +1382,8 @@ namespace hal if (!gate_pin_groups_are_equal(*pg1_it, *pg2_it)) { log_info("test_utils", "unequal pin groups of gate types with names '{}' and '{}'", gt1->get_name(), gt2->get_name()); + test_utils::dumpPingroups(gt1); + test_utils::dumpPingroups(gt2); return false; } } @@ -1510,4 +1521,4 @@ namespace hal return is_equal; } } // namespace test_utils -} // namespace hal \ No newline at end of file +} // namespace hal