diff --git a/include/hal_core/plugin_system/plugin_parameter.h b/include/hal_core/plugin_system/plugin_parameter.h index 60d54da14cd..ce964955d9a 100644 --- a/include/hal_core/plugin_system/plugin_parameter.h +++ b/include/hal_core/plugin_system/plugin_parameter.h @@ -32,7 +32,7 @@ namespace hal class PluginParameter { public: - enum ParameterType { Absent, Boolean, Color, ComboBox, Dictionary, ExistingDir, Float, Gate, Integer, Module, NewFile, PushButton, String, TabName }; + enum ParameterType { Absent, Boolean, Color, ComboBox, Dictionary, ExistingDir, ExistingFile, Float, Gate, Integer, Module, NewFile, PushButton, String, TabName }; private: ParameterType m_type; std::string m_tagname; diff --git a/plugins/.gitignore b/plugins/.gitignore index e23df09f1a3..de84bd5d4e4 100644 --- a/plugins/.gitignore +++ b/plugins/.gitignore @@ -40,5 +40,7 @@ !z3_utils/**/* !netlist_modifier* !netlist_modifier/**/* +!netlist_simulator_study* +!netlist_simulator_study/**/* !CMakeLists.txt !.gitignore diff --git a/plugins/gui/src/main_window/plugin_parameter_dialog.cpp b/plugins/gui/src/main_window/plugin_parameter_dialog.cpp index b5c9c05544d..60526b68305 100644 --- a/plugins/gui/src/main_window/plugin_parameter_dialog.cpp +++ b/plugins/gui/src/main_window/plugin_parameter_dialog.cpp @@ -140,6 +140,7 @@ namespace hal { break; } case PluginParameter::ExistingDir: + case PluginParameter::ExistingFile: case PluginParameter::NewFile: mWidgetMap[parTagname] = new PluginParameterFileDialog(par,this); break; @@ -253,6 +254,7 @@ namespace hal { break; } case PluginParameter::ExistingDir: + case PluginParameter::ExistingFile: case PluginParameter::NewFile: { const PluginParameterFileDialog* fileDlg = static_cast(w); @@ -314,9 +316,9 @@ namespace hal { mEditor->setText(parDefault); layout->addWidget(mEditor,0,0); - QString iconPath = (mParameter.get_type() == PluginParameter::ExistingDir) - ? ":/icons/folder" - : ":/icons/folder-down"; + QString iconPath = (mParameter.get_type() == PluginParameter::NewFile) + ? ":/icons/folder-down" + : ":/icons/folder"; mButton = new QPushButton(gui_utility::getStyledSvgIcon("all->#3192C5",iconPath),"",this); mButton->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Preferred); connect(mButton,&QPushButton::clicked,this,&PluginParameterFileDialog::handleActivateFileDialog); @@ -328,9 +330,20 @@ namespace hal { QString parLabel = QString::fromStdString(mParameter.get_label()); QString parDefault = QString::fromStdString(mParameter.get_value()); QString dir = QFileInfo(parDefault).isDir() ? parDefault : QFileInfo(parDefault).path(); - QString filename = (mParameter.get_type() == PluginParameter::ExistingDir) - ? QFileDialog::getExistingDirectory(this,parLabel,dir) - : QFileDialog::getSaveFileName(this,parLabel,dir); + QString filename; + switch (mParameter.get_type()) { + case PluginParameter::ExistingDir: + filename = QFileDialog::getExistingDirectory(this,parLabel,dir); + break; + case PluginParameter::ExistingFile: + filename = QFileDialog::getOpenFileName(this,parLabel,dir); + break; + case PluginParameter::NewFile: + filename = QFileDialog::getSaveFileName(this,parLabel,dir); + break; + default: + Q_ASSERT (1==0); // should never happen + } if (!filename.isEmpty()) mEditor->setText(filename); } diff --git a/plugins/netlist_modifier/include/netlist_modifier/netlist_modifier.h b/plugins/netlist_modifier/include/netlist_modifier/netlist_modifier.h index f5ee934a7d2..5bb0f0d7003 100644 --- a/plugins/netlist_modifier/include/netlist_modifier/netlist_modifier.h +++ b/plugins/netlist_modifier/include/netlist_modifier/netlist_modifier.h @@ -1,25 +1,52 @@ #pragma once #include "hal_core/defines.h" #include "hal_core/plugin_system/plugin_interface_base.h" +#include "hal_core/plugin_system/gui_extension_interface.h" #include "hal_core/utilities/result.h" #include "hal_core/netlist/netlist.h" namespace hal { + class GuiExtensionNetlistModifier; + class PLUGIN_API NetlistModifierPlugin : public BasePluginInterface { + GuiExtensionNetlistModifier* m_gui_extension; + public: std::string get_name() const override; std::string get_version() const override; void initialize() override; - NetlistModifierPlugin(){}; + void on_load() override; + void on_unload() override; + + std::set get_dependencies() const override; + + NetlistModifierPlugin(); bool create_modified_netlist(); - Netlist* modified_netlist_pointer = nullptr; + static Netlist* modified_netlist_pointer; private: bool replace_gates(); }; + + + + class GuiExtensionNetlistModifier : public GuiExtensionInterface + { + std::vector m_parameter; + + public: + NetlistModifierPlugin* m_parent; + + GuiExtensionNetlistModifier(); + + std::vector get_parameter() const override; + + void set_parameter(const std::vector& params) override; + + }; } // namespace hal \ No newline at end of file diff --git a/plugins/netlist_modifier/src/netlist_modifier.cpp b/plugins/netlist_modifier/src/netlist_modifier.cpp index f9cdcd7210a..955f7367b1f 100644 --- a/plugins/netlist_modifier/src/netlist_modifier.cpp +++ b/plugins/netlist_modifier/src/netlist_modifier.cpp @@ -14,11 +14,17 @@ namespace hal extern Netlist* gNetlist; + Netlist* NetlistModifierPlugin::modified_netlist_pointer = nullptr; + extern std::unique_ptr create_plugin_instance() { return std::make_unique(); } + NetlistModifierPlugin::NetlistModifierPlugin(){ + m_gui_extension = nullptr; + } + std::string NetlistModifierPlugin::get_name() const { return std::string("netlist-modifier"); @@ -29,18 +35,38 @@ namespace hal return std::string("0.1"); } + void NetlistModifierPlugin::on_load() + { + m_gui_extension = new GuiExtensionNetlistModifier; + m_gui_extension->m_parent = this; + m_extensions.push_back(m_gui_extension); + } + + void NetlistModifierPlugin::on_unload() + { + delete_extension(m_gui_extension); + } + + std::set NetlistModifierPlugin::get_dependencies() const + { + std::set retval; + retval.insert("hal_gui"); + retval.insert("verilog_writer"); + return retval; + } + void NetlistModifierPlugin::initialize() { } bool NetlistModifierPlugin::replace_gates(){ - auto gates = modified_netlist_pointer->get_gates(); + auto gates = NetlistModifierPlugin::modified_netlist_pointer->get_gates(); for(Gate* gate: gates){ // std::cout << gate->get_type()->to_string() << std::endl; if(gate->get_type()->to_string() == "AND"){ - GateType* new_gate_type = modified_netlist_pointer->get_gate_library()->get_gate_type_by_name("OR"); + GateType* new_gate_type = NetlistModifierPlugin::modified_netlist_pointer->get_gate_library()->get_gate_type_by_name("UNKNOWN_2IN"); std::string gate_name = gate->get_name(); u32 gate_id = gate->get_id(); @@ -56,9 +82,9 @@ namespace hal successors[endpoint->get_pin()->get_name()] = endpoint->get_net(); } - modified_netlist_pointer->delete_gate(gate); + NetlistModifierPlugin::modified_netlist_pointer->delete_gate(gate); - Gate* new_gate = modified_netlist_pointer->create_gate(gate_id, new_gate_type, gate_name); + Gate* new_gate = NetlistModifierPlugin::modified_netlist_pointer->create_gate(gate_id, new_gate_type, gate_name); for(auto entry: predecessors){ entry.second->add_destination(new_gate, entry.first); @@ -74,8 +100,10 @@ namespace hal } bool NetlistModifierPlugin::create_modified_netlist(){ + std::cout << gNetlist->get_gates().size() << std::endl; + auto tmp = gNetlist->copy(); - modified_netlist_pointer = tmp.get().get(); + NetlistModifierPlugin::modified_netlist_pointer = std::move(tmp.get().get()); replace_gates(); @@ -83,11 +111,52 @@ namespace hal replace_gates(); // no writer for .v ???? - // netlist_writer_manager::write(modified_netlist_pointer, "~/Documents/MPI/hal_project_for_testing/modified_netlist_pointer.v"); + netlist_writer_manager::write(modified_netlist_pointer, "/home/ole/Documents/MPI/hal_project_for_testing/modified_netlist_pointer.v"); - // gNetlist = modified_netlist_pointer; + // crashes when executed + // gNetlist = (NetlistModifierPlugin::modified_netlist_pointer->copy()).get().get(); + + // std::cout << gNetlist->get_gates().size() << std::endl; return true; } + + + + + + + + + + + + + GuiExtensionNetlistModifier::GuiExtensionNetlistModifier() + { + m_parameter.push_back(PluginParameter(PluginParameter::PushButton,"modify","Modify and save")); + } + + std::vector GuiExtensionNetlistModifier::get_parameter() const + { + return m_parameter; + } + + void GuiExtensionNetlistModifier::set_parameter(const std::vector& params) + { + m_parameter = params; + bool modify_save = false; + for (PluginParameter par : m_parameter) + { + if(par.get_tagname()=="modify" && par.get_value() == "clicked") + modify_save = true; + } + if (modify_save && m_parent ) + { + m_parent->create_modified_netlist(); + } + } + + } // namespace hal \ No newline at end of file diff --git a/plugins/netlist_simulator_study/CMakeLists.txt b/plugins/netlist_simulator_study/CMakeLists.txt new file mode 100644 index 00000000000..e55b6c4d40e --- /dev/null +++ b/plugins/netlist_simulator_study/CMakeLists.txt @@ -0,0 +1,15 @@ +option(PL_NETLIST_SIMULATOR_STUDY "PL_NETLIST_SIMULATOR_STUDY" OFF) + +if(PL_NETLIST_SIMULATOR_STUDY OR BUILD_ALL_PLUGINS) + file(GLOB_RECURSE NETLIST_SIMULATOR_STUDY_INC ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h) + file(GLOB_RECURSE NETLIST_SIMULATOR_STUDY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) + file(GLOB_RECURSE NETLIST_SIMULATOR_STUDY_PYTHON_SRC ${CMAKE_CURRENT_SOURCE_DIR}/python/*.cpp) + + hal_add_plugin(netlist_simulator_study + SHARED + HEADER ${NETLIST_SIMULATOR_STUDY_INC} + SOURCES ${NETLIST_SIMULATOR_STUDY_SRC} ${NETLIST_SIMULATOR_STUDY_PYTHON_SRC} + LINK_LIBRARIES PUBLIC gui netlist_simulator_controller + PYDOC SPHINX_DOC_INDEX_FILE ${CMAKE_CURRENT_SOURCE_DIR}/documentation/netlist_simulator_study.rst + ) +endif() \ No newline at end of file diff --git a/plugins/netlist_simulator_study/documentation/netlist_simulator_study.rst b/plugins/netlist_simulator_study/documentation/netlist_simulator_study.rst new file mode 100644 index 00000000000..e69de29bb2d diff --git a/plugins/netlist_simulator_study/include/netlist_simulator_study/netlist_simulator_study.h b/plugins/netlist_simulator_study/include/netlist_simulator_study/netlist_simulator_study.h new file mode 100644 index 00000000000..e43d52e4bc7 --- /dev/null +++ b/plugins/netlist_simulator_study/include/netlist_simulator_study/netlist_simulator_study.h @@ -0,0 +1,49 @@ +#pragma once + +#include "hal_core/plugin_system/plugin_interface_base.h" +#include "hal_core/plugin_system/gui_extension_interface.h" + + +namespace hal +{ + class NetlistSimulatorController; + class GuiExtensionNetlistSimulatorStudy; + + class PLUGIN_API NetlistSimulatorStudyPlugin : public BasePluginInterface + { + GuiExtensionNetlistSimulatorStudy* m_gui_extension; + std::unique_ptr m_simul_controller; + public: + std::unique_ptr m_original_netlist; + NetlistSimulatorStudyPlugin(); + + std::string get_name() const override; + std::string get_version() const override; + + void on_load() override; + void on_unload() override; + + /** + * Returns plugin dependencies (GUI, simulation controller, verilator, waveform viewer) + */ + std::set get_dependencies() const override; + + bool simulate(std::filesystem::path sim_input); + + }; + + class GuiExtensionNetlistSimulatorStudy : public GuiExtensionInterface + { + std::vector m_parameter; + + public: + NetlistSimulatorStudyPlugin* m_parent; + + GuiExtensionNetlistSimulatorStudy(); + + std::vector get_parameter() const override; + + void set_parameter(const std::vector& params) override; + + }; +} // namespace hal \ No newline at end of file diff --git a/plugins/netlist_simulator_study/src/netlist_simulator_study.cpp b/plugins/netlist_simulator_study/src/netlist_simulator_study.cpp new file mode 100644 index 00000000000..600d7e85754 --- /dev/null +++ b/plugins/netlist_simulator_study/src/netlist_simulator_study.cpp @@ -0,0 +1,138 @@ +#include "netlist_simulator_study/netlist_simulator_study.h" +#include "hal_core/netlist/netlist_parser/netlist_parser_manager.h" +#include "netlist_simulator_controller/plugin_netlist_simulator_controller.h" +#include "netlist_simulator_controller/netlist_simulator_controller.h" +#include "hal_core/plugin_system/plugin_manager.h" +#include "hal_core/netlist/netlist_factory.h" + +namespace hal +{ + extern std::unique_ptr create_plugin_instance() + { + return std::make_unique(); + } + + NetlistSimulatorStudyPlugin::NetlistSimulatorStudyPlugin(){ + m_gui_extension = nullptr; + } + + std::string NetlistSimulatorStudyPlugin::get_name() const + { + return std::string("netlist_simulator_study"); + } + + std::string NetlistSimulatorStudyPlugin::get_version() const + { + return std::string("0.1"); + } + + void NetlistSimulatorStudyPlugin::on_load() + { + m_original_netlist = netlist_factory::load_netlist("/home/ole/Documents/MPI/hal_project_for_testing/simple.v", "/home/ole/Documents/MPI/hal_project_for_testing/unknown_design.lib"); + std::cout << m_original_netlist.get() << std::endl; + + + m_gui_extension = new GuiExtensionNetlistSimulatorStudy; + m_gui_extension->m_parent = this; + m_extensions.push_back(m_gui_extension); + } + + void NetlistSimulatorStudyPlugin::on_unload() + { + delete_extension(m_gui_extension); + } + + /** + * Returns plugin dependencies. Depends on GUI, simulation controller, verilator, waveform viewer + * @return + */ + std::set NetlistSimulatorStudyPlugin::get_dependencies() const + { + std::set retval; + retval.insert("netlist_simulator_controller"); + retval.insert("hal_gui"); + retval.insert("waveform_viewer"); + retval.insert("verilator"); + retval.insert("liberty_parser"); + retval.insert("verilog_parser"); + return retval; + } + + bool NetlistSimulatorStudyPlugin::simulate(std::filesystem::path sim_input) + { + enum {VCD, CSV, SAL} input_file_format; + if (sim_input.extension() == ".vcd") + input_file_format = VCD; + else if (sim_input.extension() == ".csv") + input_file_format = CSV; + else if (sim_input.extension() == ".json") + input_file_format = SAL; + else + { + log_warning("netlist_simulator_study", "Simulation input file '{}’ has unknown extension.", sim_input.string()); + return false; + } + NetlistSimulatorControllerPlugin* ctrlPlug = static_cast(plugin_manager::get_plugin_instance("netlist_simulator_controller")); + if (!ctrlPlug) + { + log_warning("netlist_simulator_study", "Plugin 'netlist_simulator_controller' not found"); + return false; + } + m_simul_controller = ctrlPlug->create_simulator_controller(); + m_simul_controller.get()->add_gates(m_original_netlist.get()->get_gates()); + m_simul_controller.get()->set_no_clock_used(); + m_simul_controller.get()->create_simulation_engine("verilator"); + + switch (input_file_format) + { + case VCD: + if (!m_simul_controller.get()->import_vcd(sim_input.string(),NetlistSimulatorController::FilterInputFlag::CompleteNetlist)) + { + log_warning("netlist_simulator_study", "Cannot parse simulation input file '{}'.", sim_input.string()); + return false; + } + break; + case CSV: + m_simul_controller.get()->import_csv(sim_input.string(),NetlistSimulatorController::FilterInputFlag::CompleteNetlist); + break; + case SAL: + m_simul_controller.get()->import_simulation(sim_input.parent_path().string(),NetlistSimulatorController::FilterInputFlag::CompleteNetlist); + break; + } + + m_simul_controller.get()->emit_run_simulation(); + } + + //---------------------- + + GuiExtensionNetlistSimulatorStudy::GuiExtensionNetlistSimulatorStudy() + { + m_parameter.push_back(PluginParameter(PluginParameter::ExistingFile,"sim_input","Simulation input file")); + m_parameter.push_back(PluginParameter(PluginParameter::PushButton,"simulate","Start Simulation")); + } + + std::vector GuiExtensionNetlistSimulatorStudy::get_parameter() const + { + return m_parameter; + } + + void GuiExtensionNetlistSimulatorStudy::set_parameter(const std::vector& params) + { + m_parameter = params; + bool simulate = false; + std::filesystem::path sim_input; + for (PluginParameter par : m_parameter) + { + if(par.get_tagname()=="simulate" && par.get_value() == "clicked") + simulate = true; + else if (par.get_tagname()=="sim_input") + sim_input = par.get_value(); + } + if (simulate && m_parent ) + { + m_parent->simulate(sim_input); + } + } + + +} // namespace hal \ No newline at end of file diff --git a/plugins/simulator/netlist_simulator_controller/include/netlist_simulator_controller/netlist_simulator_controller.h b/plugins/simulator/netlist_simulator_controller/include/netlist_simulator_controller/netlist_simulator_controller.h index 65c3cc91b7a..cea2cf534fe 100644 --- a/plugins/simulator/netlist_simulator_controller/include/netlist_simulator_controller/netlist_simulator_controller.h +++ b/plugins/simulator/netlist_simulator_controller/include/netlist_simulator_controller/netlist_simulator_controller.h @@ -316,6 +316,11 @@ class NETLIST_API NetlistSimulatorController : public QObject { */ bool run_simulation(); + /** + * Send signal to viewer to start simulation. + */ + void emit_run_simulation(); + /** * Import VCD file and convert content into SALEAE format * @param[in] filename the filename to read @@ -466,6 +471,7 @@ public Q_SLOTS: void engineFinished(bool success); void parseComplete(); void loadProgress(int percent); + void triggerRunSimulation(); private: std::vector getFilterNets(FilterInputFlag filter) const; diff --git a/plugins/simulator/netlist_simulator_controller/src/netlist_simulator_controller.cpp b/plugins/simulator/netlist_simulator_controller/src/netlist_simulator_controller.cpp index 879e801b643..73442906913 100644 --- a/plugins/simulator/netlist_simulator_controller/src/netlist_simulator_controller.cpp +++ b/plugins/simulator/netlist_simulator_controller/src/netlist_simulator_controller.cpp @@ -407,6 +407,11 @@ namespace hal return jwd.serialize(QDir(mWorkDir).absoluteFilePath(sPersistFile).toStdString()); } + void NetlistSimulatorController::emit_run_simulation() + { + Q_EMIT triggerRunSimulation(); + } + bool NetlistSimulatorController::run_simulation() { if (!mSimulationEngine) diff --git a/plugins/simulator/waveform_viewer/include/waveform_viewer/waveform_viewer.h b/plugins/simulator/waveform_viewer/include/waveform_viewer/waveform_viewer.h index 58d012c0f37..0e8c334031d 100644 --- a/plugins/simulator/waveform_viewer/include/waveform_viewer/waveform_viewer.h +++ b/plugins/simulator/waveform_viewer/include/waveform_viewer/waveform_viewer.h @@ -94,7 +94,6 @@ namespace hal void handleSimulSettings(); void handleOpenInputFile(); void handleSaveWaveforms(); - void handleRunSimulation(); void handleAddResultWave(); void handleToggleMaxZoom(); void handleUndoZoomShift(); @@ -114,6 +113,7 @@ namespace hal void handleControllerAdded(u32 controllerId); void handleControllerRemoved(u32 controllerId); void handleParseComplete(); + void handleRunSimulation(); void displayStatusMessage(const QString& msg = QString()); void closeEvent(QCloseEvent *event) override; void currentTabChanged(int inx); diff --git a/plugins/simulator/waveform_viewer/src/wave_widget.cpp b/plugins/simulator/waveform_viewer/src/wave_widget.cpp index 34564856e00..76a5a89fdfa 100644 --- a/plugins/simulator/waveform_viewer/src/wave_widget.cpp +++ b/plugins/simulator/waveform_viewer/src/wave_widget.cpp @@ -79,6 +79,8 @@ namespace hal { { connect(mController,&NetlistSimulatorController::parseComplete,vv,&WaveformViewer::handleParseComplete,Qt::QueuedConnection); connect(mController,&NetlistSimulatorController::loadProgress,vv,&WaveformViewer::showProgress,Qt::QueuedConnection); + connect(mController,&NetlistSimulatorController::triggerRunSimulation,vv,&WaveformViewer::handleRunSimulation); + connect(mGraphicsCanvas,&WaveGraphicsCanvas::undoStateChanged,vv,&WaveformViewer::testUndoEnable,Qt::QueuedConnection); } }