11 #include <QHBoxLayout>
12 #include <QVBoxLayout>
13 #include <QGridLayout>
21 #include <QTemporaryFile>
23 #include <QSpacerItem>
24 #include <QScrollArea>
35 :
QDialog(parent), mGates(gates), mSimulationInput(new
SimulationInput), mActionCompile(nullptr), mActionIndicate(nullptr)
42 log_warning(
"logic_evaluator",
"No eligible gates selected for logic evaluator, window will close");
51 calculateEvaluationOrder();
63 std::unordered_set<const Net*> inputNets = mSimulationInput->
get_input_nets();
68 for (
const Net* n : grp.get_nets())
70 auto it = inputNets.find(n);
71 if (it != inputNets.end()) inputNets.erase(it);
80 for (
const Net* n : inputNets)
94 bool isOutputGroup =
true;
96 std::vector<const Net*> temp;
97 for (
const Net* n : grp.get_nets())
99 auto it = outputNets.find(n);
100 if (it == outputNets.end())
102 isOutputGroup =
false;
107 outputNets.erase(it);
113 for (
const Net* n : temp)
114 outputNets.insert(n);
119 mOutputs.append(lep);
124 for (
const Net* n : outputNets)
130 mOutputs.append(lep);
145 mActionCompile = options->
addAction(
"Run compiled logic");
149 mActionIndicate = options->
addAction(
"Show in graphic view");
198 delete mSimulationInput;
201 void LogicEvaluatorDialog::handleRelaunchTriggered()
208 void LogicEvaluatorDialog::handleTruthtableTriggered()
210 if (!mSharedLib.handle)
return;
215 for (
const LogicEvaluatorPingroup* lepg : mInputs)
216 for (
int i=lepg->size()-1; i>=0; i--)
217 inpList.
append(lepg->getValue(i).first);
218 for (
const LogicEvaluatorPingroup* lepg : mOutputs)
219 for (
int i=lepg->size()-1; i>=0; i--)
220 outList.
append(lepg->getValue(i).first);
222 if (inpList.
size() > 10)
224 log_warning(
"logic_evaluator",
"Cannot generate truth table for {} logic inputs.", inpList.
size());
227 mTruthtable =
new LogicEvaluatorTruthtableModel(inpList,outList,
this);
229 int maxInput = 1 << inpList.
size();
231 for (
int inputVal = 0; inputVal < maxInput; inputVal++)
235 for (
const Net* n : inpList)
237 int bitVal = (inputVal&
mask) ? 1 : 0;
239 mSharedLib.set(mExternalArrayIndex[n], bitVal);
243 for (
const Net* n : outList)
245 int bitVal = mSharedLib.get(mExternalArrayIndex[n]);
248 mTruthtable->
addColumn(
new LogicEvaluatorTruthtableColumn(inpList.size()+outList.size(),values));
251 if (!mTruthtable)
return;
253 LogicEvaluatorTruthtable lett(mTruthtable,
this);
259 const Net* n = it.key();
261 for (LogicEvaluatorPingroup* lepg : mInputs)
262 lepg->setValue(n,bv);
267 void LogicEvaluatorDialog::handleCompiledToggled(
bool checked)
269 if (checked && !mSharedLib.handle)
272 if (!mSharedLib.handle)
277 void LogicEvaluatorDialog::handleIndicateToggled(
bool checked)
282 omitNetlistVisualization();
285 void LogicEvaluatorDialog::SharedLibHandle::close()
299 mExternalArrayIndex.clear();
303 for (
int i=0; i<lepg->size(); i++)
306 const Net* n = v.first;
307 int sz = mExternalArrayIndex.size();
309 mExternalArrayIndex[n] = sz;
314 for (
const Gate* g : mEvaluationOrder)
316 struct FunctionReference
321 FunctionReference() : placed(
false) {;}
331 auto it = dependencies.
find(var);
332 if (it == dependencies.
end())
return;
333 theFunction.
replace(var, ccExpression);
334 dependencies.
erase(it);
345 referableOutputPins[gp] = FunctionReference(g->get_boolean_function(gp));
353 const Net* nIn = g->get_fan_in_net(gp);
354 int inxIn = mExternalArrayIndex.value(nIn,-1);
355 if (inxIn < 0)
return false;
357 for (
auto it = referableOutputPins.
begin(); it != referableOutputPins.
end(); ++it)
364 int lastUnresolved = 0;
365 while (unresolved || lastUnresolved == unresolved)
367 lastUnresolved = unresolved;
368 for (
auto it = referableOutputPins.
begin(); it != referableOutputPins.
end(); ++it)
370 if (!it->dependencies.isEmpty() || it->placed)
continue;
372 const Net* nOut = g->get_fan_out_net(gp);
373 int inxOut = mExternalArrayIndex.value(nOut,-1);
376 inxOut = mExternalArrayIndex.size();
377 mExternalArrayIndex[nOut] = inxOut;
381 for (
auto jt = referableOutputPins.
begin(); jt != referableOutputPins.
end(); ++jt)
382 if (it != jt) jt->
replace(pinNameOut, ccVar);
383 gateFunctions +=
QString(
" %1 = %2;\n").
arg(ccVar).
arg(it->theFunction);
389 if (unresolved)
return false;
391 codeEvalFunction += gateFunctions;
396 int k = lepg->
size();
397 for (
int i=0; i<k; i++)
399 const Net* n = lepg->getValue(i).first;
400 int inx = mExternalArrayIndex.value(n,-1);
401 if (inx < 0)
return false;
406 ccode +=
QString(
"int logic_evaluator_signals[%1];\n\n").
arg(mExternalArrayIndex.size());
408 ccode +=
"(int inx, int val) {\n"
409 " logic_evaluator_signals[inx] = val;\n"
412 ccode +=
"(int inx) {\n"
413 " return logic_evaluator_signals[inx];\n"
417 ccode += codeEvalFunction +
"\n}\n";
420 QTemporaryFile ftemp(
QDir().temp().absoluteFilePath(
"logic_evaluator_shared_lib_XXXXXX.c"));
424 mSharedLib.fnSharedLib = ftemp.
fileName();
432 args <<
"-shared" <<
"-Wall" <<
"-Werror" <<
"-fpic" <<
"-o" << mSharedLib.fnSharedLib << ftemp.
fileName();
435 log_warning(
"logic_evaluator",
"Failed to run compiler '{}', cannot compile logic.",
COMPILER);
449 mSharedLib.handle = dlopen(mSharedLib.fnSharedLib.toUtf8().constData(), RTLD_LAZY);
450 if (!mSharedLib.handle)
452 log_warning(
"logic_evaluator",
"Failed to load shared library '{}' dlerror: '{}'.", mSharedLib.fnSharedLib.toStdString(), dlerror());
460 const char* dlsymError = dlerror();
468 dlsymError = dlerror();
476 dlsymError = dlerror();
483 log_info(
"logic_evaluator",
"Temporary shared library '{}' successfully build and loaded.", mSharedLib.fnSharedLib.toStdString());
491 if (mActionCompile->
isChecked() && mSharedLib.handle)
498 int k = lepg->size();
499 for (
int i=0; i<k; i++)
501 const Net* n = lepg->getValue(i).first;
502 lepg->setValue(n, mSignals.value(n, BooleanFunction::Value::X));
507 visualizeResultsInNetlist();
510 void LogicEvaluatorDialog::recalcCompiled()
514 for (
int i=0; i<lepg->size(); i++)
517 const Net* n = v.first;
518 int inx = mExternalArrayIndex.value(n,-1);
524 mSharedLib.set(inx, (
int) v.second);
530 for (
auto it=mExternalArrayIndex.begin(); it!=mExternalArrayIndex.end(); ++it)
532 const Net* n = it.key();
533 int val = mSharedLib.get(it.value());
538 void LogicEvaluatorDialog::recalcInterpreted()
541 for (
const LogicEvaluatorPingroup* lepg : mInputs)
543 for (
int i=0; i<lepg->size(); i++)
546 mSignals[v.first] = v.second;
551 for (
const Gate* g : mEvaluationOrder)
553 std::unordered_map<std::string, BooleanFunction::Value> gateSignals;
554 for (
const GatePin* gp : g->get_type()->get_input_pins())
556 const Net* n = g->get_fan_in_net(gp);
557 gateSignals[gp->get_name()] = mSignals.value(n, BooleanFunction::Value::X);
559 for (
const GatePin* gp : g->get_type()->get_output_pins())
561 const Net* n = g->get_fan_out_net(gp);
562 auto res = g->get_boolean_function(gp).evaluate(gateSignals);
564 mSignals[n] = res.get();
566 log_warning(
"logic_evaluator",
"Failed to evaluate boolean function '{}'.", g->get_boolean_function(gp).to_string());
571 void LogicEvaluatorDialog::calculateEvaluationOrder()
573 mEvaluationOrder.clear();
577 for (
const Gate* g: mSimulationInput->
get_gates())
579 undeterminedInput.
insert(g, g->get_fan_in_nets());
582 std::unordered_set<const Net*> inputSignals = mSimulationInput->
get_input_nets();
585 while (!undeterminedInput.
isEmpty() && resolved)
588 std::unordered_set<const Net*> outputSignals;
589 auto it = undeterminedInput.
begin();
590 while (it != undeterminedInput.
end())
592 auto jt = it.
value().begin();
593 while (jt != it.value().end())
595 if (inputSignals.find(*jt) == inputSignals.end())
598 jt = it.value().erase(jt);
602 if (it.value().empty())
604 mEvaluationOrder.append(it.key());
605 for (
const Net* n : it.key()->get_fan_out_nets())
606 outputSignals.insert(n);
607 it = undeterminedInput.
erase(it);
615 inputSignals = outputSignals;
617 if (!undeterminedInput.
isEmpty())
619 std::string leftover;
620 for (
const Gate* g : undeterminedInput.
keys())
621 leftover +=
" [" + std::to_string(g->get_id()) +
',' + g->get_name() +
']';
622 log_warning(
"logic_evaluator",
"Cannot determine evaluation order, {} gate(s) left with undetermined input: {}.", undeterminedInput.
size(), leftover);
626 void LogicEvaluatorDialog::visualizeResultsInNetlist()
629 const char* color[] = {
"#707071",
"#102080",
"#802010" };
630 static const char* grpNames[3] = {
"x state",
"0 state",
"1 state"};
632 for (
int i=0; i<3; i++)
638 gtm->recolorGrouping(grp[i]->get_id(),
QColor(color[i]));
642 for (
auto it = mSignals.constBegin(); it != mSignals.constEnd(); ++it)
644 int grpIndex = 1 + (int) it.value();
645 Q_ASSERT(grpIndex >= 0 && grpIndex <= 2);
646 grp[grpIndex]->assign_net(
const_cast<Net*
>(it.key()),
true);
650 void LogicEvaluatorDialog::omitNetlistVisualization()
653 static const char* grpNames[3] = {
"x state",
"0 state",
"1 state"};
654 for (
int i=0; i<3; i++)
#define LIBRARY_FILE_EXTENSION
const std::string & get_name() const
std::set< std::string > get_variable_names() const
Value
represents the type of the node
static std::string to_string(Value value)
GroupingManagerWidget * getGroupingManagerWidget()
Grouping * groupingByName(const QString &name) const
LogicEvaluatorDialog(const std::vector< Gate * > &gates, bool skipCompile, QWidget *parent=nullptr)
void addColumn(LogicEvaluatorTruthtableColumn *letc)
A model for displaying multiple netlist elements.
void populateFromGatelist(const std::vector< Gate * > &gates)
const std::string & get_name() const
Grouping * create_grouping(const u32 grouping_id, const std::string &name="")
bool delete_grouping(Grouping *grouping)
#define log_info(channel,...)
#define log_warning(channel,...)
T replace(const T &str, const T &search, const T &replace)
const char * LOGIC_EVALUATOR_CALC
ContentManager * gContentManager
const char * LOGIC_EVALUATOR_SET
const char * LOGIC_EVALUATOR_GET
void toggled(bool checked)
void triggered(bool checked)
void addLayout(QLayout *layout, int stretch)
void addStretch(int stretch)
void setSpacing(int spacing)
const char * constData() const const
virtual void close() override
QHash::iterator erase(QHash::iterator pos)
QHash::iterator insert(const Key &key, const T &value)
bool isEmpty() const const
QList< Key > keys() const const
qint64 write(const char *data, qint64 maxSize)
void setSizeConstraint(QLayout::SizeConstraint)
void append(const T &value)
bool isEmpty() const const
QMap::const_iterator constBegin() const const
QMap::const_iterator constEnd() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
int execute(const QString &program, const QStringList &arguments)
int exitCode() const const
QProcess::ExitStatus exitStatus() const const
QByteArray readAllStandardError()
QByteArray readAllStandardOutput()
bool waitForFinished(int msecs)
bool waitForStarted(int msecs)
QSet::iterator erase(QSet::iterator pos)
QSet::iterator find(const T &value)
QSet::iterator insert(const T &value)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromStdString(const std::string &str)
QString & replace(int position, int n, QChar after)
std::string toStdString() const const
QByteArray toUtf8() const const
virtual void polish(QWidget *widget)
virtual void unpolish(QWidget *widget)
virtual QString fileName() const const override
void setAutoRemove(bool b)
void setColumnWidth(int column, int width)
virtual void setModel(QAbstractItemModel *model) override