From ead7e6bf8ac0dcbd10068f73c1781d449fbda478 Mon Sep 17 00:00:00 2001 From: joern274 Date: Tue, 22 Oct 2024 14:53:05 +0200 Subject: [PATCH 1/3] Attempt to fix logic evaluator input/output groups --- .../src/logic_evaluator_dialog.cpp | 11 +++- .../simulation_input.h | 8 ++- .../src/netlist_simulator_controller.cpp | 6 +- .../src/simulation_input.cpp | 56 ++++++++++++------- 4 files changed, 53 insertions(+), 28 deletions(-) diff --git a/plugins/logic_evaluator/src/logic_evaluator_dialog.cpp b/plugins/logic_evaluator/src/logic_evaluator_dialog.cpp index bc4082d683e..117a48117bd 100644 --- a/plugins/logic_evaluator/src/logic_evaluator_dialog.cpp +++ b/plugins/logic_evaluator/src/logic_evaluator_dialog.cpp @@ -55,12 +55,18 @@ namespace hal { std::unordered_set inputNets = mSimulationInput->get_input_nets(); for (SimulationInput::NetGroup grp : mSimulationInput->get_net_groups()) { - if (!grp.is_input) continue; + std::cerr << "INPUT " << (grp.is_input() ? "+++ " : "--- ") << grp.get_name() << " " << (int) grp.direction << std::endl; + if (!grp.is_input()) + { + std::cerr << "continue" << std::endl; + continue; + } for (const Net* n : grp.get_nets()) { auto it = inputNets.find(n); if (it != inputNets.end()) inputNets.erase(it); } + std::cerr << "LogicEvaluatorPingroup" << std::endl; LogicEvaluatorPingroup* lep = new LogicEvaluatorPingroup(grp.get_nets(), false, QString::fromStdString(grp.get_name()), this); connect(lep, &LogicEvaluatorPingroup::triggerRecalc, this, &LogicEvaluatorDialog::recalc); mInputs.append(lep); @@ -80,7 +86,8 @@ namespace hal { std::unordered_set outputNets(mSimulationInput->get_output_nets().begin(),mSimulationInput->get_output_nets().end()); for (SimulationInput::NetGroup grp : mSimulationInput->get_net_groups()) { - if (grp.is_input) continue; + std::cerr << "OUTPUT " << (grp.is_output() ? "+++ " : "--- ") << grp.get_name() << std::endl; + if (!grp.is_output()) continue; bool isOutputGroup = true; std::vector temp; diff --git a/plugins/simulator/netlist_simulator_controller/include/netlist_simulator_controller/simulation_input.h b/plugins/simulator/netlist_simulator_controller/include/netlist_simulator_controller/simulation_input.h index 9eb73642102..f612f9a38c3 100644 --- a/plugins/simulator/netlist_simulator_controller/include/netlist_simulator_controller/simulation_input.h +++ b/plugins/simulator/netlist_simulator_controller/include/netlist_simulator_controller/simulation_input.h @@ -49,6 +49,8 @@ namespace hal { class SimulationInput { public: + enum DirectionType { Undefined, InputOnly, OutputOnly, Mixed}; + struct Clock { const Net* clock_net; @@ -59,13 +61,15 @@ namespace hal { struct NetGroup { - bool is_input; + DirectionType direction; const Gate* gate; PinGroup* module_pin_group; PinGroup* gate_pin_group; - NetGroup() : is_input(true), gate(nullptr), module_pin_group(nullptr), gate_pin_group(nullptr) {;} + NetGroup() : direction(Undefined), gate(nullptr), module_pin_group(nullptr), gate_pin_group(nullptr) {;} std::vector get_nets() const; std::string get_name() const; + bool is_input() const { direction == InputOnly; } + bool is_output() const { direction == OutputOnly; } }; private: 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 1f611bb4c1d..6bfff13b51d 100644 --- a/plugins/simulator/netlist_simulator_controller/src/netlist_simulator_controller.cpp +++ b/plugins/simulator/netlist_simulator_controller/src/netlist_simulator_controller.cpp @@ -951,11 +951,11 @@ namespace hal { if (inputs) { - if (!ng.is_input) continue; + if (!ng.is_input()) continue; } else { - if (ng.is_input) continue; + if (ng.is_input()) continue; } if (ng.gate) add_waveform_group(ng.gate, ng.gate_pin_group); @@ -1023,7 +1023,7 @@ namespace hal for (SimulationInput::NetGroup ng : mSimulationInput->get_net_groups()) { - if (!ng.is_input) continue; + if (!ng.is_input()) continue; InputColumnHeader ipc; ipc.name = ng.get_name(); ipc.is_clock = false; diff --git a/plugins/simulator/netlist_simulator_controller/src/simulation_input.cpp b/plugins/simulator/netlist_simulator_controller/src/simulation_input.cpp index b3e48f4d31f..fd6b7b11b39 100644 --- a/plugins/simulator/netlist_simulator_controller/src/simulation_input.cpp +++ b/plugins/simulator/netlist_simulator_controller/src/simulation_input.cpp @@ -250,7 +250,11 @@ namespace hal { std::unordered_set simulated_modules; // all nets that are part of the simulation - std::unordered_set single_nets(m_partial_nets.begin(), m_partial_nets.end()); + std::unordered_map ungrouped_nets; + + for (const Net* n : m_partial_nets) ungrouped_nets[n] = Undefined; + for (const Net* n : m_input_nets) ungrouped_nets[n] = InputOnly; + for (const Net* n : m_output_nets) ungrouped_nets[n] = OutputOnly; // all modules that contain at least one simulated gate for (const Gate* g : mSimulationSet) @@ -281,32 +285,40 @@ namespace hal { { if (pg->size() < 2) continue; bool pin_group_simulated = true; + DirectionType groupType = Undefined; for (ModulePin* mp : pg->get_pins()) { Net* n = mp->get_net(); if (n) { - if (single_nets.find(n) == single_nets.end()) + auto itNet = ungrouped_nets.find(n); + if (itNet == ungrouped_nets.end()) { // pin : net exists and is not part of the simulation, ignore pin group pin_group_simulated = false; break; } + else + { + if (groupType == Undefined) + groupType = itNet->second; + else if (groupType != Mixed && groupType != itNet->second) + groupType = Mixed; + } } } if (pin_group_simulated) { NetGroup group; group.module_pin_group = pg; + group.direction = groupType; for (ModulePin* mp : pg->get_pins()) { Net* n = mp->get_net(); if (n) { - single_nets.erase(n); - if (!is_input_net(n)) - group.is_input = false; + ungrouped_nets.erase(n); } } m_netgroups.push_back(group); @@ -325,6 +337,8 @@ namespace hal { { if (pg->size() < 2) continue; bool pin_group_simulated = true; + DirectionType groupType = Undefined; + std::unordered_set connectedNets; for (GatePin* gp : pg->get_pins()) { @@ -342,13 +356,24 @@ namespace hal { } if (n) { - if (single_nets.find(n) == single_nets.end()) + auto itNet = ungrouped_nets.find(n); + if (itNet == ungrouped_nets.end()) { - // pin : net alreade assigned to module pin group, ignore gate pin group + // pin : net already assigned to module pin group, ignore gate pin group pin_group_simulated = false; break; } + else + { + connectedNets.insert(n); + if (groupType == Undefined) + groupType = itNet->second; + else if (groupType != Mixed && groupType != itNet->second) + groupType = Mixed; + } } + else + pin_group_simulated = false; } if (pin_group_simulated) @@ -356,20 +381,9 @@ namespace hal { NetGroup group; group.gate = g; group.gate_pin_group = pg; - if (pg->get_direction() == PinDirection::input) - { - for (GatePin* gp : pg->get_pins()) - { - Net* n = g->get_fan_in_net(gp); - if (n && !is_input_net(n)) - { - group.is_input = false; - break; - } - } - } - else - group.is_input = false; + group.direction = groupType; + for (const Net* n : connectedNets) + ungrouped_nets.erase(n); m_netgroups.push_back(group); } } From 6a42d4006fe8a6d5e04e547581707ccc0c79e5c9 Mon Sep 17 00:00:00 2001 From: joern274 Date: Wed, 23 Oct 2024 13:21:29 +0200 Subject: [PATCH 2/3] Fix boolean functions: Resolve output dependencies - WiP --- .../src/logic_evaluator_dialog.cpp | 52 ++++++++++++++++--- .../simulation_input.h | 4 +- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/plugins/logic_evaluator/src/logic_evaluator_dialog.cpp b/plugins/logic_evaluator/src/logic_evaluator_dialog.cpp index 117a48117bd..932a3420b5d 100644 --- a/plugins/logic_evaluator/src/logic_evaluator_dialog.cpp +++ b/plugins/logic_evaluator/src/logic_evaluator_dialog.cpp @@ -55,18 +55,13 @@ namespace hal { std::unordered_set inputNets = mSimulationInput->get_input_nets(); for (SimulationInput::NetGroup grp : mSimulationInput->get_net_groups()) { - std::cerr << "INPUT " << (grp.is_input() ? "+++ " : "--- ") << grp.get_name() << " " << (int) grp.direction << std::endl; if (!grp.is_input()) - { - std::cerr << "continue" << std::endl; continue; - } for (const Net* n : grp.get_nets()) { auto it = inputNets.find(n); if (it != inputNets.end()) inputNets.erase(it); } - std::cerr << "LogicEvaluatorPingroup" << std::endl; LogicEvaluatorPingroup* lep = new LogicEvaluatorPingroup(grp.get_nets(), false, QString::fromStdString(grp.get_name()), this); connect(lep, &LogicEvaluatorPingroup::triggerRecalc, this, &LogicEvaluatorDialog::recalc); mInputs.append(lep); @@ -86,8 +81,8 @@ namespace hal { std::unordered_set outputNets(mSimulationInput->get_output_nets().begin(),mSimulationInput->get_output_nets().end()); for (SimulationInput::NetGroup grp : mSimulationInput->get_net_groups()) { - std::cerr << "OUTPUT " << (grp.is_output() ? "+++ " : "--- ") << grp.get_name() << std::endl; - if (!grp.is_output()) continue; + if (!grp.is_output()) + continue; bool isOutputGroup = true; std::vector temp; @@ -294,7 +289,44 @@ namespace hal { // propagate by gates for (const Gate* g : mEvaluationOrder) { - QMap referableOutputPins; + struct FunctionReference + { + const GatePin* gatePin; + QString theFunction; + QString ccVariable; + QStringList dependencies; + bool resolved; + FunctionReference(const GatePin* gp, const QString& func) : gatePin(gp), theFunction(func), resolved(false) {;} + }; + + QMap referableOutputPins; + int unresolved = 0; + + // collect all functions + for (const GatePin* gp : g->get_type()->get_output_pins()) + { + QString pinNameOut = QString::fromStdString(gp->get_name()); + referableOutputPins[pinNameOut] = FunctionReference(gp, QString::fromStdString(g->get_boolean_function(gp).to_string())); + ++unresolved; + } + + // find dependencies + for (auto it = referableOutputPins.begin(); it != referableOutputPins.end(); ++it) + { + for (auto jt = referableOutputPins.begin(); jt != referableOutputPins.end(); ++jt) + { + if (it == jt) continue; // cannot reference to itself + if (it->theFunction.contains(jt.key())) + it->dependencies.append(jt.key()); + } + } + + // resolve + while (unresolved) + { + for (auto it = referableOutputPins.begin(); it != referableOutputPins.end(); ++it) + { + } for (const GatePin* gp : g->get_type()->get_output_pins()) { @@ -316,16 +348,20 @@ namespace hal { QString ccVar = QString("logic_evaluator_signals[%1]").arg(inxIn); theFunction.replace(pinNameIn, ccVar); } + std::cerr << "replace: "; for (auto it = referableOutputPins.constBegin(); it != referableOutputPins.constEnd(); ++it) { theFunction.replace(it.key(),it.value()); + std::cerr << "{" << it.key().toStdString() << "} "; } + std::cerr << "\t<" << theFunction.toStdString() << ">" << std::endl; int inxOut = mExternalArrayIndex.value(nOut,-1); if (inxOut < 0) return false; codeEvalFunction += QString(" logic_evaluator_signals[%1] = %2;\n").arg(inxOut).arg(theFunction); referableOutputPins[pinNameOut] = QString("logic_evaluator_signals[%1]").arg(inxOut); + std::cerr << "referable: <" << pinNameOut.toStdString() << ">" << std::endl; } } diff --git a/plugins/simulator/netlist_simulator_controller/include/netlist_simulator_controller/simulation_input.h b/plugins/simulator/netlist_simulator_controller/include/netlist_simulator_controller/simulation_input.h index f612f9a38c3..4cfb1c12799 100644 --- a/plugins/simulator/netlist_simulator_controller/include/netlist_simulator_controller/simulation_input.h +++ b/plugins/simulator/netlist_simulator_controller/include/netlist_simulator_controller/simulation_input.h @@ -68,8 +68,8 @@ namespace hal { NetGroup() : direction(Undefined), gate(nullptr), module_pin_group(nullptr), gate_pin_group(nullptr) {;} std::vector get_nets() const; std::string get_name() const; - bool is_input() const { direction == InputOnly; } - bool is_output() const { direction == OutputOnly; } + bool is_input() const { return direction == InputOnly; } + bool is_output() const { return direction == OutputOnly; } }; private: From d9227ffd2ecc6f7f51fe8a36515f3485e00476b5 Mon Sep 17 00:00:00 2001 From: joern274 Date: Wed, 23 Oct 2024 21:50:24 +0200 Subject: [PATCH 3/3] Fix logic evaluation computation order if gate output depends on other outputs --- .../src/logic_evaluator_dialog.cpp | 104 +++++++++--------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/plugins/logic_evaluator/src/logic_evaluator_dialog.cpp b/plugins/logic_evaluator/src/logic_evaluator_dialog.cpp index 932a3420b5d..8c046cbf27b 100644 --- a/plugins/logic_evaluator/src/logic_evaluator_dialog.cpp +++ b/plugins/logic_evaluator/src/logic_evaluator_dialog.cpp @@ -291,78 +291,80 @@ namespace hal { { struct FunctionReference { - const GatePin* gatePin; QString theFunction; - QString ccVariable; - QStringList dependencies; - bool resolved; - FunctionReference(const GatePin* gp, const QString& func) : gatePin(gp), theFunction(func), resolved(false) {;} + QSet dependencies; + bool placed; + FunctionReference() : placed(false) {;} + FunctionReference(const BooleanFunction& func) + : placed(false) + { + theFunction = QString::fromStdString(func.to_string()); + for (std::string dep : func.get_variable_names()) + dependencies.insert(QString::fromStdString(dep)); + } + void replace(const QString& var, const QString& ccExpression) + { + auto it = dependencies.find(var); + if (it == dependencies.end()) return; + theFunction.replace(var, ccExpression); + dependencies.erase(it); + } }; - QMap referableOutputPins; + QMap referableOutputPins; int unresolved = 0; // collect all functions for (const GatePin* gp : g->get_type()->get_output_pins()) { QString pinNameOut = QString::fromStdString(gp->get_name()); - referableOutputPins[pinNameOut] = FunctionReference(gp, QString::fromStdString(g->get_boolean_function(gp).to_string())); + referableOutputPins[gp] = FunctionReference(g->get_boolean_function(gp)); ++unresolved; } - // find dependencies - for (auto it = referableOutputPins.begin(); it != referableOutputPins.end(); ++it) - { - for (auto jt = referableOutputPins.begin(); jt != referableOutputPins.end(); ++jt) - { - if (it == jt) continue; // cannot reference to itself - if (it->theFunction.contains(jt.key())) - it->dependencies.append(jt.key()); - } - } - - // resolve - while (unresolved) + // replace input pins by C-Variable + for (const GatePin* gp : g->get_type()->get_input_pins()) { + QString pinNameIn = QString::fromStdString(gp->get_name()); + const Net* nIn = g->get_fan_in_net(gp); + int inxIn = mExternalArrayIndex.value(nIn,-1); + if (inxIn < 0) return false; + QString ccVar = QString("logic_evaluator_signals[%1]").arg(inxIn); for (auto it = referableOutputPins.begin(); it != referableOutputPins.end(); ++it) - { + it->replace(pinNameIn, ccVar); } - for (const GatePin* gp : g->get_type()->get_output_pins()) - { - QString pinNameOut = QString::fromStdString(gp->get_name()); - const Net* nOut = g->get_fan_out_net(gp); - if (!mExternalArrayIndex.contains(nOut)) - { - int sz = mExternalArrayIndex.size(); - mExternalArrayIndex[nOut] = sz; - } + QString gateFunctions; - QString theFunction = QString::fromStdString(g->get_boolean_function(gp).to_string()); - for (const GatePin* gp : g->get_type()->get_input_pins()) - { - QString pinNameIn = QString::fromStdString(gp->get_name()); - const Net* nIn = g->get_fan_in_net(gp); - int inxIn = mExternalArrayIndex.value(nIn,-1); - if (inxIn < 0) return false; - QString ccVar = QString("logic_evaluator_signals[%1]").arg(inxIn); - theFunction.replace(pinNameIn, ccVar); - } - std::cerr << "replace: "; - for (auto it = referableOutputPins.constBegin(); it != referableOutputPins.constEnd(); ++it) + // place and resolve outputs + int lastUnresolved = 0; + while (unresolved || lastUnresolved == unresolved) + { + lastUnresolved = unresolved; + for (auto it = referableOutputPins.begin(); it != referableOutputPins.end(); ++it) { - theFunction.replace(it.key(),it.value()); - std::cerr << "{" << it.key().toStdString() << "} "; + if (!it->dependencies.isEmpty() || it->placed) continue; + const GatePin* gp = it.key(); + const Net* nOut = g->get_fan_out_net(gp); + int inxOut = mExternalArrayIndex.value(nOut,-1); + if (inxOut < 0) + { + inxOut = mExternalArrayIndex.size(); + mExternalArrayIndex[nOut] = inxOut; + } + QString pinNameOut = QString::fromStdString(gp->get_name()); + QString ccVar = QString("logic_evaluator_signals[%1]").arg(inxOut); + for (auto jt = referableOutputPins.begin(); jt != referableOutputPins.end(); ++jt) + if (it != jt) jt->replace(pinNameOut, ccVar); + gateFunctions += QString(" %1 = %2;\n").arg(ccVar).arg(it->theFunction); + it->placed=true; + --unresolved; } - std::cerr << "\t<" << theFunction.toStdString() << ">" << std::endl; + } - int inxOut = mExternalArrayIndex.value(nOut,-1); - if (inxOut < 0) return false; - codeEvalFunction += QString(" logic_evaluator_signals[%1] = %2;\n").arg(inxOut).arg(theFunction); + if (unresolved) return false; - referableOutputPins[pinNameOut] = QString("logic_evaluator_signals[%1]").arg(inxOut); - std::cerr << "referable: <" << pinNameOut.toStdString() << ">" << std::endl; - } + codeEvalFunction += gateFunctions; } for (LogicEvaluatorPingroup* lepg : mOutputs)