HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
netlist_simulator_controller.cpp
Go to the documentation of this file.
2 
5 #include "hal_core/netlist/net.h"
18 #include "rapidjson/document.h"
19 #include "rapidjson/filereadstream.h"
20 
21 #include <QCoreApplication>
22 #include <QDate>
23 #include <QDebug>
24 #include <QFile>
25 #include <QTemporaryDir>
26 #include <QVector>
27 
28 namespace hal
29 {
30  const char* NetlistSimulatorController::sPersistFile = "netlist_simulator_controller.json";
31 
32  NetlistSimulatorController::NetlistSimulatorController(u32 id, const std::string nam, const std::string& workdir, QObject* parent)
33  : QObject(parent), mId(id), mName(QString::fromStdString(nam)), mState(NoGatesSelected), mSimulationEngine(nullptr), mTempDir(nullptr), mWaveDataList(nullptr),
34  mSimulationInput(new SimulationInput), mLogReceiver(nullptr)
35  {
36  if (mName.isEmpty())
37  {
38  mName = QString("sim_controller%1").arg(mId);
39  }
40  LogManager::get_instance()->add_channel(mName.toStdString(), {LogManager::create_stdout_sink(), LogManager::create_file_sink(), LogManager::create_gui_sink()}, "info");
41 
42  if (workdir.empty())
43  {
46  if (!templatePath.isEmpty())
47  {
48  templatePath += '/';
49  }
50  templatePath += "hal_simulation_" + mName + "_XXXXXX";
51  mTempDir = new QTemporaryDir(templatePath);
52  mWorkDir = mTempDir->path();
53  }
54  else
55  {
56  mWorkDir = QString::fromStdString(workdir);
57  }
58  QDir saleaeDir(QDir(mWorkDir).absoluteFilePath("saleae"));
59  saleaeDir.mkpath(saleaeDir.absolutePath());
60  QString saleaeDirectoryFilename = saleaeDir.absoluteFilePath("saleae.json");
61  if (!QFileInfo(saleaeDirectoryFilename).exists())
62  {
63  QFile of(saleaeDirectoryFilename);
64  if (of.open(QIODevice::WriteOnly))
65  {
66  of.write(QByteArray("{\"saleae\":{}}"));
67  }
68  }
69  mWaveDataList = new WaveDataList(saleaeDirectoryFilename);
70 
72  }
73 
74  NetlistSimulatorController::NetlistSimulatorController(u32 id, Netlist* nl, const std::string& filename, QObject* parent)
75  : QObject(parent), mId(id), mState(NoGatesSelected), mSimulationEngine(nullptr), mTempDir(nullptr), mWaveDataList(nullptr), mSimulationInput(new SimulationInput), mLogReceiver(nullptr)
76  {
77  FILE* ff = fopen(filename.c_str(), "rb");
78  if (!ff)
79  {
80  log_warning("simulation_plugin", "Error opening file '{}'.", filename);
81  return;
82  }
83 
84  char buffer[65536];
85  rapidjson::FileReadStream frs(ff, buffer, sizeof(buffer));
86  rapidjson::Document document;
87  document.ParseStream<0, rapidjson::UTF8<>, rapidjson::FileReadStream>(frs);
88  fclose(ff);
89 
90  if (document.HasParseError() || !document.HasMember("netlist_simulator_controller"))
91  {
92  log_warning("simulation_plugin", "Cannot restore simulation controller from file '{}'.", filename);
93  return;
94  }
95  auto jnsc = document["netlist_simulator_controller"].GetObject();
96  if (jnsc.HasMember("name"))
97  {
98  mName = QString::fromStdString(jnsc["name"].GetString());
99  }
100 
101  QDir workDir(QFileInfo(QString::fromStdString(filename)).path());
102  std::vector<Gate*> simulatedGates;
103  if (jnsc.HasMember("gates"))
104  {
105  for (auto& jgate : jnsc["gates"].GetArray())
106  {
107  u32 gateId = jgate.HasMember("id") ? jgate["id"].GetUint() : 0;
108  Gate* g = nl->get_gate_by_id(gateId);
109  if (!g)
110  {
111  log_warning("simulation_plugin", "Simulated gate ID={} not found in netlist.", gateId);
112  return;
113  }
114  if (jgate.HasMember("name") && jgate["name"].GetString() != g->get_name() && g->get_name().find("UNKNOWN") != 0)
115  {
116  log_warning("simulation_plugin", "Gate name for ID={} differs in simulation '{}' and netlist '{}'", gateId, jgate["name"].GetString(), g->get_name());
117  return;
118  }
119  simulatedGates.push_back(g);
120  }
121  }
122  LogManager::get_instance()->add_channel(mName.toStdString(), {LogManager::create_stdout_sink(), LogManager::create_file_sink(), LogManager::create_gui_sink()}, "info");
123  QDir saleaeDir(workDir.absoluteFilePath("saleae"));
124  saleaeDir.mkpath(saleaeDir.absolutePath());
125  mWaveDataList = new WaveDataList(saleaeDir.absoluteFilePath("saleae.json"));
126 
128  mWaveDataList->updateFromSaleae();
129  mSimulationInput->add_gates(simulatedGates);
130  mWorkDir = workDir.absolutePath();
131  restoreComposed(mWaveDataList->saleaeDirectory());
133 
134  if (jnsc.HasMember("clocks"))
135  {
136  for (auto& jclock : jnsc["clocks"].GetArray())
137  {
138  u32 clkId = jclock.HasMember("id") ? jclock["id"].GetUint() : 0;
139  Net* clkNet = nl->get_net_by_id(clkId);
140  if (!clkNet)
141  {
142  log_warning(mName.toStdString(), "Clock net ID={} not found in netlist.", clkId);
143  continue;
144  }
145  bool startAtZero = jclock.HasMember("start_value") ? (jclock["start_value"].GetInt() == 0) : true;
146  int period = jclock.HasMember("switch_time") ? jclock["switch_time"].GetInt() * 2 : 1000;
147  add_clock_period(clkNet, period, startAtZero, mWaveDataList->timeFrame().simulateMaxTime());
148  }
149  }
150 
151  if (jnsc.HasMember("engine"))
152  {
153  auto jengine = jnsc["engine"].GetObject();
154  if (jengine.HasMember("name"))
155  {
156  create_simulation_engine(jengine["name"].GetString());
157  if (mSimulationEngine && jengine.HasMember("properties"))
158  {
159  auto jprop = jengine["properties"].GetObject();
160 
161  for (auto it = jprop.MemberBegin(); it != jprop.MemberEnd(); ++it)
162  {
163  mSimulationEngine->set_engine_property(it->name.GetString(), it->value.GetString());
164  }
165  }
166  }
167  }
169  }
170 
172  {
174  if (mWaveDataList)
175  {
176  mWaveDataList->deleteLater();
177  }
178  delete mSimulationInput;
179  // delete mTempDir;
180  }
181 
183  {
184  mLogReceiver = logrec;
185  }
186 
187  void NetlistSimulatorController::setState(SimulationState stat)
188  {
189  if (stat == mState)
190  {
191  return;
192  }
193  mState = stat;
194  switch (mState)
195  {
196  case NoGatesSelected:
197  log_info(get_name(), "Select gates for simulation");
198  break;
199  case ParameterSetup:
200  log_info(get_name(), "Expecting parameter and input");
201  break;
202  case ParameterReady:
203  log_info(get_name(), "Preconditions to start simulation met");
204  break;
205  case SimulationRun:
206  log_info(get_name(), "Running simulation, please wait...");
207  break;
208  case ShowResults:
209  log_info(get_name(), "Simulation engine completed successfully");
210  break;
211  case EngineFailed:
212  log_info(get_name(), "Simulation engine process error");
213  if (mSimulationEngine)
214  {
215  mSimulationEngine->failed();
216  }
217  break;
218  }
219  Q_EMIT stateChanged(mState);
220  }
221 
223  {
224  return mWorkDir.toStdString();
225  }
226 
228  {
229  if (mWorkDir.contains(' '))
230  {
231  return false;
232  }
233  return true;
234  }
235 
237  {
238  if (!mWaveDataList)
239  {
240  return 0;
241  }
242  return mWaveDataList->timeFrame().simulateMaxTime();
243  }
244 
246  {
247  return std::filesystem::path(mWaveDataList->saleaeDirectory().get_filename());
248  }
249 
251  {
253  if (!fac)
254  {
255  return nullptr;
256  }
257  if (mSimulationEngine)
258  {
259  delete mSimulationEngine;
260  }
261  mSimulationEngine = fac->createEngine();
262  mSimulationEngine->set_working_directory(get_working_directory());
263  log_info(get_name(), "Engine '{}' created. Work directory set to '{}'.", mSimulationEngine->name(), get_working_directory());
264  checkReadyState();
265  return mSimulationEngine;
266  }
267 
269  {
270  return mSimulationEngine;
271  }
272 
273  std::vector<std::string> NetlistSimulatorController::get_engine_names() const
274  {
276  }
277 
278  void NetlistSimulatorController::initSimulator()
279  {
280  }
281 
283  {
284  mSimulationInput->set_no_clock_used();
285  checkReadyState();
286  }
287 
289  {
290  return mSimulationInput->is_no_clock_used();
291  }
292 
293  void NetlistSimulatorController::simulate_only_probes(const std::vector<const Net*>& probes)
294  {
295  for (const Net* n : probes)
296  {
297  mSimulateOnlyProbes.insert(n->get_id());
298  }
299  }
300 
302  {
303  mSimulateOnlyProbes = probes;
304  }
305 
306  u32 NetlistSimulatorController::add_trigger_time(const std::vector<WaveData*>& trigger_waves, const std::vector<int>& trigger_on_values)
307  {
308  if (trigger_waves.empty())
309  {
310  return 0;
311  }
312  QList<WaveData*> triglist;
313  QList<int> trigOnVal;
314  for (WaveData* wd : trigger_waves)
315  {
316  triglist.append(wd);
317  }
318  for (int tov : trigger_on_values)
319  {
320  trigOnVal.append(tov);
321  }
322  WaveDataTrigger* wdTrig = new WaveDataTrigger(mWaveDataList, triglist, trigOnVal);
323  if (!wdTrig)
324  {
325  return 0;
326  }
327  return wdTrig->id();
328  }
329 
331  {
332  if (expression.empty())
333  {
334  return 0;
335  }
336  WaveDataBoolean* wdBool = new WaveDataBoolean(mWaveDataList, QString::fromStdString(expression));
337  if (!wdBool)
338  {
339  return 0;
340  }
341  return wdBool->id();
342  }
343 
344  u32 NetlistSimulatorController::add_boolean_accept_list_waveform(const std::vector<WaveData*>& input_waves, const std::vector<int>& accepted_combination)
345  {
346  if (input_waves.empty() || accepted_combination.empty())
347  {
348  return 0;
349  }
350  QList<WaveData*> inpWaves;
351  QList<int> acceptVal;
352  for (WaveData* wd : input_waves)
353  {
354  inpWaves.append(wd);
355  }
356  for (int acc : accepted_combination)
357  {
358  acceptVal.append(acc);
359  }
360  WaveDataBoolean* wdBool = new WaveDataBoolean(mWaveDataList, inpWaves, acceptVal);
361  if (!wdBool)
362  {
363  return 0;
364  }
365  return wdBool->id();
366  }
367 
368  u32 NetlistSimulatorController::add_waveform_group(const std::string& name, const std::vector<Net*>& nets)
369  {
370  if (name.empty())
371  {
372  return 0;
373  }
374  QVector<WaveData*> waveVector;
375  waveVector.reserve(nets.size());
376  for (Net* n : nets)
377  {
378  WaveData* wd = get_waveform_by_net(n);
379  if (!wd)
380  {
381  log_warning(get_name(), "Cannot add unkown waveform for net '{}(id={})' to group '{}'.", n->get_name(), n->get_id(), name);
382  continue;
383  }
384  waveVector.append(wd);
385  }
386 
387  WaveDataGroup* wdGrp = new WaveDataGroup(mWaveDataList, QString::fromStdString(name));
388  if (!waveVector.isEmpty())
389  {
390  mWaveDataList->addWavesToGroup(wdGrp->id(), waveVector);
391  }
392  return wdGrp->id();
393  }
394 
396  {
397  if (!pin_group)
398  {
399  log_warning(get_name(), "Invalid 'add_waveform_group' call with nullptr instead of module pin group");
400  return 0;
401  }
402  std::vector<Net*> nets;
403  for (const auto pin : pin_group->get_pins())
404  {
405  nets.push_back(pin->get_net());
406  }
407 
408  return add_waveform_group(pin_group->get_name(), nets);
409  }
410 
412  {
413  if (!gate || !pin_group)
414  {
415  log_warning(get_name(), "Invalid 'add_waveform_group' call with nullptr instead of {}", (gate ? "gate pin group" : "gate"));
416  return 0;
417  }
418  std::vector<Net*> nets;
419  for (const auto pin : pin_group->get_pins())
420  {
421  Net* n = nullptr;
422  switch (pin->get_direction())
423  {
424  case PinDirection::input:
425  n = gate->get_fan_in_net(pin);
426  break;
428  n = gate->get_fan_out_net(pin);
429  break;
430  default:
431  break;
432  }
433 
434  if (n)
435  {
436  nets.push_back(n);
437  }
438  }
439 
440  return add_waveform_group(pin_group->get_name(), nets);
441  }
442 
444  {
445  if (!pin_group)
446  {
447  log_warning(get_name(), "Invalid 'add_waveform_group' call with name='{}' and nullptr instead of module pin group", name);
448  return 0;
449  }
450  std::vector<Net*> nets;
451  for (const auto pin : pin_group->get_pins())
452  {
453  nets.push_back(pin->get_net());
454  }
455 
456  return add_waveform_group((name.empty() ? pin_group->get_name() : name), nets);
457  }
458 
460  {
461  mWaveDataList->removeGroup(group_id);
462  }
463 
465  {
466  if (filename.isEmpty())
467  {
468  return;
469  }
470  VcdSerializer reader(mWorkDir, false, this);
471  QList<const Net*> onlyNets;
472  for (const Net* n : mSimulationInput->get_input_nets())
473  {
474  onlyNets.append(n);
475  }
476  if (reader.importVcd(filename, mWorkDir, onlyNets))
477  {
478  mWaveDataList->updateFromSaleae();
479  }
480  checkReadyState();
481  }
482 
484  {
485  JsonWriteDocument jwd;
486  JsonWriteObject& jnsc = jwd.add_object("netlist_simulator_controller");
487  jnsc["id"] = (int)get_id();
488  jnsc["name"] = get_name();
489  /* jnsc["workdir"] = get_working_directory();*/
490 
491  JsonWriteArray& jgates = jnsc.add_array("gates");
492  for (const Gate* g : mSimulationInput->get_gates())
493  {
494  JsonWriteObject& jgate = jgates.add_object();
495  jgate["id"] = (int)g->get_id();
496  jgate["name"] = g->get_name();
497  jgate.close();
498  }
499  jgates.close();
500 
501  JsonWriteArray& jclocks = jnsc.add_array("clocks");
502  for (const SimulationInput::Clock& clk : mSimulationInput->get_clocks())
503  {
504  JsonWriteObject& jclock = jclocks.add_object();
505  jclock["id"] = (int)clk.clock_net->get_id();
506  jclock["name"] = clk.clock_net->get_name();
507  jclock["switch_time"] = (int)clk.switch_time;
508  jclock["start_value"] = clk.start_at_zero ? 0 : 1;
509  jclock.close();
510  }
511  jclocks.close();
512 
513  if (mSimulationEngine)
514  {
515  JsonWriteObject& jengine = jnsc.add_object("engine");
516  jengine["name"] = mSimulationEngine->name();
517  JsonWriteObject& jprops = jengine.add_object("properties");
518  for (auto it = mSimulationEngine->get_engine_properties().begin(); it != mSimulationEngine->get_engine_properties().end(); ++it)
519  {
520  jprops[it->first] = it->second;
521  }
522  jprops.close();
523  jengine.close();
524  }
525 
526  jnsc.close();
527  return jwd.serialize(QDir(mWorkDir).absoluteFilePath(sPersistFile).toStdString());
528  }
529 
531  {
532  if (!mSimulationEngine)
533  {
534  log_warning(get_name(), "no simulation engine selected");
535  return false;
536  }
537 
539 
540  if (!engPropMap.isEmpty())
541  {
542  bool engPropMapModified = false;
543  for (auto it = engPropMap.begin(); it != engPropMap.end(); ++it)
544  {
545  std::string prop = it.key().toStdString();
546  std::string valu = it.value().toStdString();
547 
548  std::string userAssignedValue = mSimulationEngine->get_engine_property(prop);
549  if (userAssignedValue.empty())
550  {
551  log_info(get_name(), "Engine property '{}' set to '{}'.", prop, valu);
552  mSimulationEngine->set_engine_property(prop, valu);
553  }
554  else
555  {
556  if (userAssignedValue != valu)
557  {
558  log_info(get_name(), "Default value for engine property '{}' changed from '{}' to '{}'.", prop, valu, userAssignedValue);
559  it.value() = QString::fromStdString(userAssignedValue);
560  engPropMapModified = true;
561  }
562  }
563  }
564  if (engPropMapModified)
565  {
568  }
569  }
570 
571  if (mState != ParameterReady)
572  {
573  log_warning(get_name(), "wrong state {}.", (u32)mState);
574  return false;
575  }
576 
577  mWaveDataList->setValueForEmpty(0);
578  mWaveDataList->emitTimeframeChanged();
579  qApp->processEvents();
580 
581  for (auto it = mBadAssignInputWarnings.constBegin(); it != mBadAssignInputWarnings.constEnd(); ++it)
582  {
583  if (it.value() > 3)
584  {
585  log_warning(get_name(), "Totally {} attempts to set input values for net ID={}, but net is not an input.", it.value(), it.key());
586  }
587  }
588 
589  struct WaveIterator
590  {
591  const Net* n;
592  const WaveData* wd;
594  };
595 
596  // generate clock events if required
597  if (mSimulationEngine->clock_events_required())
598  {
599  for (const Net* n : mSimulationInput->get_input_nets())
600  {
601  if (!mSimulationInput->is_clock(n))
602  {
603  continue;
604  }
606  for (const SimulationInput::Clock& testClk : mSimulationInput->get_clocks())
607  {
608  if (testClk.clock_net == n)
609  {
610  clk = testClk;
611  break;
612  }
613  }
614  WaveDataClock* wdc = new WaveDataClock(n, clk, mWaveDataList->timeFrame().sceneMaxTime());
615  mWaveDataList->addOrReplace(wdc);
616  }
617  }
618 
619  qApp->processEvents();
620  persist();
621 
622  if (!mSimulationEngine->setSimulationInput(mSimulationInput))
623  {
624  log_warning(get_name(), "simulation engine error during setup.");
625  setState(EngineFailed);
626  return false;
627  }
628 
629  // start simulation process (might be external process)
630  if (!mSimulationEngine->run(this, mLogReceiver))
631  {
632  log_warning(get_name(), "simulation engine error during startup.");
633  setState(EngineFailed);
634  return false;
635  }
636  setState(SimulationRun);
637  return true;
638  }
639 
641  {
642  mWaveDataList->triggerAddToView(n->get_id());
643  return mWaveDataList->waveDataByNet(n);
644  }
645 
647  {
648  return mWaveDataList->mDataGroups.value(id);
649  }
650 
652  {
653  return mWaveDataList->mDataBooleans.value(id);
654  }
655 
657  {
658  return mWaveDataList->mDataTrigger.value(id);
659  }
660 
662  {
663  WaveDataGroup* grp = dynamic_cast<WaveDataGroup*>(wd);
664  if (grp)
665  {
667  mWaveDataList->emitGroupUpdated(grp->id());
668  return;
669  }
670  int iwave = mWaveDataList->waveIndexByNetId(wd->id());
671  if (iwave >= 0)
672  {
673  mWaveDataList->updateWaveName(iwave, QString::fromStdString(name));
674  }
675  }
676 
677  std::vector<const Net*> NetlistSimulatorController::getFilterNets(FilterInputFlag filter) const
678  {
679  if (!mSimulationInput->has_gates())
680  {
681  return std::vector<const Net*>();
682  }
683  switch (filter)
684  {
685  case GlobalInputs:
686  return std::vector<const Net*>(get_input_nets().begin(), get_input_nets().end());
687  case PartialNetlist:
688  return get_partial_netlist_nets();
689  case CompleteNetlist: {
690  std::vector<Net*> tmp = (*mSimulationInput->get_gates().begin())->get_netlist()->get_nets();
691  return std::vector<const Net*>(tmp.begin(), tmp.end());
692  }
693  case NoFilter:
694  break;
695  }
696  return std::vector<const Net*>();
697  }
698 
700  {
701  // TODO : check for ongoing import ?
702  if (mState == ParameterReady || mState == ParameterSetup || mState == ShowResults)
703  {
704  return true;
705  }
706  return false;
707  }
708 
710  {
711  Q_EMIT loadProgress(percent);
712  }
713 
714  bool NetlistSimulatorController::import_vcd(const std::string& filename, FilterInputFlag filter)
715  {
716  VcdSerializer reader(mWorkDir, false, this);
717 
718  QList<const Net*> inputNets;
719  if (filter != NoFilter)
720  {
721  for (const Net* n : getFilterNets(filter))
722  {
723  inputNets.append(n);
724  }
725  }
726 
727  if (reader.importVcd(QString::fromStdString(filename), mWorkDir, inputNets))
728  {
729  mWaveDataList->updateFromSaleae();
730  }
731  else
732  {
733  return false;
734  }
735 
736  checkReadyState();
738  return true;
739  }
740 
741  void NetlistSimulatorController::import_csv(const std::string& filename, FilterInputFlag filter, u64 timescale)
742  {
743  VcdSerializer reader(mWorkDir, false, this);
744 
745  QList<const Net*> inputNets;
746  if (filter != NoFilter)
747  {
748  for (const Net* n : getFilterNets(filter))
749  {
750  inputNets.append(n);
751  }
752  }
753 
754  if (reader.importCsv(QString::fromStdString(filename), mWorkDir, inputNets, timescale))
755  {
756  mWaveDataList->updateFromSaleae();
757  }
758  checkReadyState();
760  }
761 
762  void NetlistSimulatorController::import_saleae(const std::string& dirname, std::unordered_map<Net*, int> lookupTable, u64 timescale)
763  {
764  VcdSerializer reader(mWorkDir, false, this);
765  if (reader.importSaleae(QString::fromStdString(dirname), lookupTable, mWorkDir, timescale))
766  {
767  mWaveDataList->updateFromSaleae();
768  }
769  checkReadyState();
771  }
772 
773  void NetlistSimulatorController::import_simulation(const std::string& dirname, FilterInputFlag filter, u64 timescale)
774  {
775  QDir sourceDir(QString::fromStdString(dirname));
776  QString sourceSaleaeLookup = sourceDir.absoluteFilePath("saleae.json");
777  SaleaeDirectory sd(sourceSaleaeLookup.toStdString());
778  if (!QFileInfo(sourceSaleaeLookup).isReadable())
779  {
780  log_warning(get_name(), "cannot import SALEAE data from '{}', cannot read lookup table.", dirname);
781  return;
782  }
783  if (filter == NoFilter)
784  {
785  QDir targetDir(QString::fromStdString(mWaveDataList->saleaeDirectory().get_directory()));
786  QString targetSaleaeLookup = targetDir.absoluteFilePath("saleae.json");
787  QFile::remove(targetSaleaeLookup);
788  QFile::copy(sourceSaleaeLookup, targetSaleaeLookup);
789  QStringList nameFilters;
790  nameFilters << "digital_*.bin";
791  for (QFileInfo sourceFileInfo : sourceDir.entryInfoList(nameFilters))
792  {
793  QString targetFile = targetDir.absoluteFilePath(sourceFileInfo.fileName());
794  QFile::remove(targetFile);
795  QFile::copy(sourceFileInfo.absoluteFilePath(), targetFile);
796  }
797  mWaveDataList->updateFromSaleae();
798  }
799  else
800  {
801  std::unordered_map<Net*, int> lookupTable;
802  for (const Net* n : getFilterNets(filter))
803  {
804  int inx = sd.get_datafile_index(n->get_name(), n->get_id());
805  if (inx < 0)
806  {
807  continue;
808  }
809  lookupTable.insert(std::make_pair((Net*)n, inx));
810  }
811  VcdSerializer reader(mWorkDir, false, this);
812  if (reader.importSaleae(QString::fromStdString(dirname), lookupTable, mWorkDir, timescale))
813  {
814  mWaveDataList->updateFromSaleae();
815  }
816  }
817  checkReadyState();
818  restoreComposed(sd);
820  }
821 
822  void NetlistSimulatorController::restoreComposed(const SaleaeDirectory& sd)
823  {
824  for (const SaleaeDirectoryComposedEntry& sdce : sd.get_composed_list())
825  {
826 // sdce.dump();
827  QVector<WaveData*> wds;
828  for (int childKey : sdce.get_children())
829  {
830  WaveData* wd = nullptr;
831  int mType = childKey / SaleaeDirectoryNetEntry::sComposedBaseKey;
833  switch (mType)
834  {
836  wd = mWaveDataList->mDataGroups.value(index);
837  break;
839  wd = mWaveDataList->mDataBooleans.value(index);
840  break;
842  wd = mWaveDataList->mDataTrigger.value(index);
843  break;
844  default:
845  int iwave = mWaveDataList->waveIndexByNetId(childKey);
846  if (iwave >= 0)
847  {
848  wd = mWaveDataList->at(iwave);
849  }
850  }
851  if (wd)
852  {
853  wds.append(wd);
854  }
855  }
857  for (int dat : sdce.get_data())
858  {
859  data.append(dat);
860  }
861  if (!wds.isEmpty() && wds.size() == (int)sdce.get_children().size())
862  {
863  switch (sdce.type())
864  {
866  WaveDataGroup* wdGrp = new WaveDataGroup(mWaveDataList, QString::fromStdString(sdce.name()));
867  mWaveDataList->addWavesToGroup(wdGrp->id(), wds);
868  break;
869  }
871  new WaveDataBoolean(mWaveDataList, wds.toList(), data);
872  break;
873  }
875  WaveDataTrigger* wdTrig = new WaveDataTrigger(mWaveDataList, wds.toList(), data);
876  if (sdce.get_filter_entry())
877  {
878  int filterKey = sdce.get_filter_entry();
879  if (filterKey > 0)
880  {
881  WaveData* wd = nullptr;
882  int mType = filterKey / SaleaeDirectoryNetEntry::sComposedBaseKey;
884  switch (mType)
885  {
887  wd = mWaveDataList->mDataGroups.value(index);
888  break;
890  wd = mWaveDataList->mDataBooleans.value(index);
891  break;
893  wd = mWaveDataList->mDataTrigger.value(index);
894  break;
895  default:
896  int iwave = mWaveDataList->waveIndexByNetId(filterKey);
897  if (iwave >= 0)
898  {
899  wd = mWaveDataList->at(iwave);
900  }
901  }
902  if (wd)
903  {
904  wdTrig->set_filter_wave(wd);
905  }
906  }
907  }
908  break;
909  }
910  default:
911  break;
912  }
913  }
914  }
915  }
916 
918  {
919  SaleaeParser::sTimeScaleFactor = timescale;
920  }
921 
923  {
924  if (!success)
925  {
926  log_warning(get_name(), "simulation engine error during run.");
927  setState(EngineFailed);
928  }
929 
930  Q_EMIT engineFinished(success);
931 
932  // QObject* simulThread = sender();
933  // if (simulThread) simulThread->deleteLater();
934  /*
935  for (Net* n : gNetlist->get_nets())
936  {
937  WaveData* wd = WaveData::simulationResultFactory(n, mSimulator.get());
938  if (wd) mResultMap.insert(wd->id(),wd);
939  }
940 
941  mSimulator->generate_vcd("result.vcd",0,t);
942  */
943  }
944 
946  {
947  bool success = getResultsInternal();
948  setState(success ? ShowResults : EngineFailed);
949  return success;
950  }
951 
952  bool NetlistSimulatorController::getResultsInternal()
953  {
954  SimulationEngineEventDriven* sevd = static_cast<SimulationEngineEventDriven*>(mSimulationEngine);
955  // mWaveDataList->dump();
956  if (mSimulationEngine->can_share_memory())
957  {
958  for (const Net* n : get_partial_netlist_nets())
959  {
960  WaveData* wd = new WaveData(n);
961  for (WaveEvent evt : sevd->get_simulation_events(n->get_id()))
962  {
963  wd->insertBooleanValueWithoutSync(evt.time, evt.new_value);
964  }
965  mWaveDataList->addOrReplace(wd);
966  }
967  }
968  else
969  {
970  std::filesystem::path resultFile = mSimulationEngine->get_result_filename();
971  if (resultFile.is_relative())
972  {
973  resultFile = get_working_directory() / resultFile;
974  }
975  VcdSerializer reader(mWorkDir, false, this);
976  QFileInfo info(QString::fromStdString(resultFile.string()));
977  if (!info.exists() || !info.isReadable())
978  {
979  return false;
980  }
981 
982  QList<const Net*> partialNets;
983  for (const Net* n : get_partial_netlist_nets())
984  {
985  if (!mSimulateOnlyProbes.empty() && !mSimulateOnlyProbes.contains(n->get_id()))
986  {
987  continue;
988  }
989  partialNets.append(n);
990  }
991 
992  if (reader.importVcd(QString::fromStdString(resultFile), mWorkDir, partialNets))
993  {
994  mWaveDataList->updateFromSaleae();
995  }
996  else
997  {
998  return false;
999  }
1000 
1001  if (!mSimulateOnlyProbes.isEmpty())
1002  {
1003  QFile::remove(QString::fromStdString(resultFile.string()));
1004  }
1005  }
1006  return true;
1007  }
1008 
1009  void NetlistSimulatorController::add_clock_frequency(const Net* clock_net, u64 frequency, bool start_at_zero)
1010  {
1011  u64 period = 1'000'000'000'000ul / frequency;
1012  add_clock_period(clock_net, period, start_at_zero);
1013  }
1014 
1015  void NetlistSimulatorController::checkReadyState()
1016  {
1017  if (mState >= ParameterReady)
1018  {
1019  return; // nothing to do
1020  }
1021 
1022  if (mSimulationInput->is_ready() && mSimulationEngine && mWaveDataList->timeFrame().simulateMaxTime() > 0)
1023  {
1024  setState(ParameterReady);
1025  }
1026  persist();
1027  }
1028 
1029  void NetlistSimulatorController::add_clock_period(const Net* clock_net, u64 period, bool start_at_zero, u64 duration)
1030  {
1031  if (!clock_net)
1032  {
1033  log_warning(get_name(), "Generating clock failed, clock net is a nullptr!");
1034  return;
1035  }
1036 
1037  if (!period)
1038  {
1039  log_warning(get_name(), "Generating clock failed, period must not be zero!");
1040  return;
1041  }
1042 
1044  clk.clock_net = clock_net;
1045  clk.switch_time = period / 2;
1046  clk.start_at_zero = start_at_zero;
1047  mSimulationInput->add_clock(clk);
1048  WaveData* wd = new WaveDataClock(clock_net, clk, duration ? duration : 2000);
1049  mWaveDataList->addOrReplace(wd);
1050  checkReadyState();
1051  }
1052 
1054  {
1055  mSimulationInput->compute_net_groups();
1056  }
1057 
1059  {
1060  for (const SimulationInput::NetGroup& ng : mSimulationInput->get_net_groups())
1061  {
1062  if (inputs)
1063  {
1064  if (!ng.is_input())
1065  {
1066  continue;
1067  }
1068  }
1069  else
1070  {
1071  if (ng.is_input())
1072  {
1073  continue;
1074  }
1075  }
1076  if (ng.gate)
1077  {
1078  add_waveform_group(ng.gate, ng.gate_pin_group);
1079  }
1080  else
1081  {
1082  add_waveform_group(ng.module_pin_group);
1083  }
1084  }
1085  }
1086 
1087  void NetlistSimulatorController::add_gates(const std::vector<Gate*>& gates)
1088  {
1089  if (mState != NoGatesSelected)
1090  {
1091  log_warning(get_name(), "Command failed, gates for simulation already selected in this controller.");
1092  return;
1093  }
1094  mSimulationInput->add_gates(gates);
1095 
1096  QSet<u32> previousInputSet = mWaveDataList->toSet();
1097  QSet<u32> currentInputSet;
1098  for (const Net* n : mSimulationInput->get_input_nets())
1099  {
1100  u32 nid = n->get_id();
1101  if (!previousInputSet.contains(nid))
1102  {
1103  WaveData* wd = new WaveData(n, WaveData::InputNet);
1104  mWaveDataList->addOrReplace(wd);
1105  }
1106  currentInputSet.insert(nid);
1107  }
1108  previousInputSet -= currentInputSet;
1109  for (u32 id : previousInputSet)
1110  {
1111  mWaveDataList->remove(id);
1112  }
1113  if (mState == NoGatesSelected && mSimulationInput->has_gates())
1114  {
1115  setState(ParameterSetup);
1116  }
1117  checkReadyState();
1118  }
1119 
1120  const std::unordered_set<const Gate*>& NetlistSimulatorController::get_gates() const
1121  {
1122  return mSimulationInput->get_gates();
1123  }
1124 
1125  const std::unordered_set<const Net*>& NetlistSimulatorController::get_input_nets() const
1126  {
1127  return mSimulationInput->get_input_nets();
1128  }
1129 
1130  std::vector<NetlistSimulatorController::InputColumnHeader> NetlistSimulatorController::get_input_column_headers() const
1131  {
1132  std::vector<InputColumnHeader> retval;
1133  std::unordered_set<const Net*> clkNets;
1134  for (const SimulationInput::Clock& clk : mSimulationInput->get_clocks())
1135  {
1136  clkNets.insert(clk.clock_net);
1137  }
1138 
1139  for (const Net* n : mSimulationInput->get_input_nets())
1140  {
1141  InputColumnHeader ipc;
1142  ipc.nets.push_back(n);
1143  ipc.name = n->get_name();
1144  ipc.is_clock = (clkNets.find(n) != clkNets.end());
1145  retval.push_back(ipc);
1146  }
1147 
1148  for (SimulationInput::NetGroup ng : mSimulationInput->get_net_groups())
1149  {
1150  if (!ng.is_input())
1151  {
1152  continue;
1153  }
1154  InputColumnHeader ipc;
1155  ipc.name = ng.get_name();
1156  ipc.is_clock = false;
1157 
1158  std::vector<const Net*> temp_nets = ng.get_nets();
1159  ipc.nets = ng.ascending ? temp_nets : std::vector<const Net*>(temp_nets.rbegin(),temp_nets.rend());
1160  for (const Net* n : temp_nets)
1161  {
1162  if (clkNets.find(n) != clkNets.end())
1163  {
1164  ipc.is_clock = true;
1165  }
1166  retval.erase(std::remove_if(retval.begin(), retval.end(), [n](const auto& s) { return s.nets.size() == 1 && s.nets.at(0) == n; }), retval.end());
1167  }
1168  retval.push_back(ipc);
1169  }
1170  return retval;
1171  }
1172 
1173  const std::vector<const Net*>& NetlistSimulatorController::get_output_nets() const
1174  {
1175  return mSimulationInput->get_output_nets();
1176  }
1177 
1178  const std::vector<const Net*>& NetlistSimulatorController::get_partial_netlist_nets() const
1179  {
1180  return mSimulationInput->get_partial_netlist_nets();
1181  }
1182 
1184  {
1185  Q_ASSERT(net);
1186  if (!mSimulationInput->is_input_net(net))
1187  {
1188  if (mBadAssignInputWarnings[net->get_id()]++ < 3)
1189  {
1190  log_warning(get_name(), "net[{}] '{}' is not an input net, value not assigned.", net->get_id(), net->get_name());
1191  }
1192  return;
1193  }
1194  u64 t = mWaveDataList->timeFrame().simulateMaxTime();
1195  WaveData* wd = mWaveDataList->waveDataByNet(net);
1196  if (!wd)
1197  {
1198  wd = new WaveData(net);
1199  wd->insertBooleanValueWithoutSync(t, value);
1200  mWaveDataList->addOrReplace(wd);
1201  }
1202  else
1203  {
1204  mWaveDataList->insertBooleanValue(wd, t, value);
1205  }
1206  }
1207 
1209  {
1210  u64 t = mWaveDataList->timeFrame().simulateMaxTime();
1211  mWaveDataList->insertBooleanValue(wd, t, value);
1212  }
1213 
1214  void NetlistSimulatorController::set_input(const std::vector<Net*>& nets, const std::vector<BooleanFunction::Value>& values)
1215  {
1216  if (nets.size() != values.size())
1217  {
1218  log_error(get_name(), "Cannot set vector of nets to vector of values, because vectors are not of equal size! {} vs. {}", nets.size(), values.size());
1219  return;
1220  }
1221 
1222  for (u32 idx = 0; idx < nets.size(); idx++)
1223  {
1224  set_input(nets.at(idx), values.at(idx));
1225  }
1226  }
1227 
1228  void NetlistSimulatorController::set_input(const WaveDataGroup* wdg, const std::vector<BooleanFunction::Value>& values)
1229  {
1230  const auto wave_forms = wdg->get_waveforms();
1231  if (wave_forms.size() != values.size())
1232  {
1233  log_error(
1234  get_name(), "Cannot set WaveDataGroup to vector of values, because the amount of grouped wave forms is not equal to the vector size! {} vs. {}", wave_forms.size(), values.size());
1235  return;
1236  }
1237 
1238  for (u32 idx = 0; idx < wave_forms.size(); idx++)
1239  {
1240  set_input(wave_forms.at(idx), values.at(idx));
1241  }
1242  }
1243 
1244  void NetlistSimulatorController::set_input(const u32 id, const std::vector<BooleanFunction::Value>& values)
1245  {
1246  const auto wave_data_group = get_waveform_group_by_id(id);
1247  set_input(wave_data_group, values);
1248  }
1249 
1250  void NetlistSimulatorController::set_input(const PinGroup<ModulePin>* pin_group, const std::vector<BooleanFunction::Value>& values)
1251  {
1252  std::vector<Net*> nets;
1253  for (const auto pin : pin_group->get_pins())
1254  {
1255  nets.push_back(pin->get_net());
1256  }
1257 
1258  set_input(nets, values);
1259  }
1260 
1262  {
1263  mWaveDataList->setUserTimeframe(tmin, tmax);
1264  }
1265 
1267  {
1268  }
1269 
1271  {
1272  mSimulationInput->clear();
1273  mWaveDataList->clearAll();
1274  mState = NoGatesSelected;
1275  }
1276 
1278  {
1279  mWaveDataList->incrementSimulTime(picoseconds);
1280  checkReadyState();
1281  }
1282 
1284  {
1285  /*
1286  mSimulateGates = gsd.selectedGates();
1287  initSimulator();
1288  */
1289  }
1290 
1291  bool NetlistSimulatorController::generate_vcd(const std::filesystem::path& path, u32 start_time, u32 end_time, std::set<const Net*> nets) const
1292  {
1293  VcdSerializer writer(mWorkDir);
1294  QList<const WaveData*> partialList;
1295  if (nets.empty())
1296  {
1297  for (const WaveData* wd : *mWaveDataList)
1298  {
1299  partialList.append(wd);
1300  }
1301  }
1302  else
1303  {
1304  for (const Net* n : nets)
1305  {
1306  const WaveData* wd = mWaveDataList->waveDataByNet(n);
1307  if (wd)
1308  {
1309  partialList.append(wd);
1310  }
1311  }
1312  }
1313  if (!start_time && !end_time)
1314  {
1315  start_time = mWaveDataList->timeFrame().sceneMinTime();
1316  end_time = mWaveDataList->timeFrame().sceneMaxTime();
1317  }
1318  bool success = writer.exportVcd(QString::fromStdString(path.string()), partialList, start_time, end_time);
1319  return success;
1320  }
1321 
1322  NetlistSimulatorControllerMap* NetlistSimulatorControllerMap::sInst = nullptr;
1323 
1325  {
1326  if (!sInst)
1327  {
1328  sInst = new NetlistSimulatorControllerMap;
1329  }
1330  return sInst;
1331  }
1332 
1334  {
1335  u32 id = ctrl->get_id();
1336  mMap.insert(id, ctrl);
1337  Q_EMIT controllerAdded(id);
1338  }
1339 
1341  {
1342  auto it = mMap.find(id);
1343  if (it == mMap.end())
1344  {
1345  return;
1346  }
1347  mMap.erase(it);
1349  }
1350 
1352  {
1353  for (auto it = mMap.begin(); it != mMap.end(); ++it)
1354  {
1355  Q_EMIT controllerRemoved(it.key());
1356  }
1357  mMap.clear();
1358  }
1359 
1360 } // namespace hal
Value
represents the type of the node
Definition: gate.h:58
Net * get_fan_in_net(const std::string &pin_name) const
Definition: gate.cpp:617
Net * get_fan_out_net(const std::string &pin_name) const
Definition: gate.cpp:761
const std::string & get_name() const
Definition: gate.cpp:105
JsonWriteObject & add_object()
bool serialize(const std::string &filename)
JsonWriteObject & add_object(const std::string &tag)
JsonWriteArray & add_array(const std::string &tag)
std::shared_ptr< spdlog::logger > add_channel(const std::string &channel_name, const std::vector< std::shared_ptr< log_sink >> &sinks, const std::string &level="info")
Definition: log.cpp:100
static LogManager * get_instance(const std::filesystem::path &file_name="")
Definition: log.cpp:61
Definition: net.h:58
u32 get_id() const
Definition: net.cpp:88
Gate * get_gate_by_id(const u32 gate_id) const
Definition: netlist.cpp:193
Net * get_net_by_id(u32 net_id) const
Definition: netlist.cpp:353
void engineFinished(bool success)
const std::unordered_set< const Gate * > & get_gates() const
bool import_vcd(const std::string &filename, FilterInputFlag filter)
bool generate_vcd(const std::filesystem::path &path, u32 start_time=0, u32 end_time=0, std::set< const Net * > nets={}) const
void add_clock_frequency(const Net *clock_net, u64 frequency, bool start_at_zero=true)
const std::vector< const Net * > & get_output_nets() const
WaveDataGroup * get_waveform_group_by_id(u32 id) const
std::vector< InputColumnHeader > get_input_column_headers() const
void add_gates(const std::vector< Gate * > &gates)
void set_input(const Net *net, BooleanFunction::Value value)
void handleOpenInputFile(const QString &filename)
WaveDataTrigger * get_trigger_time_by_id(u32 id) const
void import_csv(const std::string &filename, FilterInputFlag filter, u64 timescale=1000000000)
const std::vector< const Net * > & get_partial_netlist_nets() const
std::filesystem::path get_saleae_directory_filename() const
void stateChanged(hal::NetlistSimulatorController::SimulationState state)
WaveDataBoolean * get_waveform_boolean_by_id(u32 id) const
void add_clock_period(const Net *clock_net, u64 period, bool start_at_zero=true, u64 duration=0)
u32 add_trigger_time(const std::vector< WaveData * > &trigger_waves, const std::vector< int > &trigger_on_values=std::vector< int >())
void setLogReceiver(SimulationLogReceiver *logrec)
WaveData * get_waveform_by_net(const Net *n) const
u32 add_boolean_accept_list_waveform(const std::vector< WaveData * > &input_waves, const std::vector< int > &accepted_combination)
SimulationEngine * create_simulation_engine(const std::string &name)
void import_simulation(const std::string &dirname, FilterInputFlag filter, u64 timescale=1000000000)
void set_saleae_timescale(u64 timescale=1000000000)
void import_saleae(const std::string &dirname, std::unordered_map< Net *, int > lookupTable, u64 timescale=1000000000)
SimulationEngine * get_simulation_engine() const
u32 add_waveform_group(const std::string &name, const std::vector< Net * > &nets)
void loadProgress(int percent)
u32 add_boolean_expression_waveform(const std::string &expression)
std::vector< std::string > get_engine_names() const
const std::unordered_set< const Net * > & get_input_nets() const
void simulate_only_probes(const std::vector< const Net * > &probes)
void rename_waveform(WaveData *wd, std::string name)
NetlistSimulatorController(u32 id, const std::string nam, const std::string &workdir, QObject *parent=nullptr)
static NetlistSimulatorControllerMap * instance()
void addController(NetlistSimulatorController *ctrl)
std::vector< T * > get_pins(const std::function< bool(T *)> &filter=nullptr) const
Definition: pin_group.h:205
const std::string & get_name() const
Definition: pin_group.h:153
static ProjectManager * instance()
The SaleaeDirectoryComposedEntry class represents a composed waveform. There are currently three type...
The SaleaeDirectory class provides the API for the SALEAE directory file. The SALEAE directory file w...
int get_datafile_index(const std::string &nam, uint32_t id) const
Get waveform datafile index for net identified by name and id.
std::string get_directory() const
Get path to SALEAE directory without filename.
std::vector< SaleaeDirectoryComposedEntry > get_composed_list() const
Getter to list of all composed waveform entries.
std::string get_filename() const
Get full path to saleae directory file including filename (/.../saleae.json)
@ Boolean
@ Trigger
@ Group
static const int sComposedBaseKey
static uint64_t sTimeScaleFactor
conversion factor to be applied when converting double values from original SALEAE file to integer va...
virtual std::vector< WaveEvent > get_simulation_events(u32 netId) const
std::vector< std::string > factoryNames() const
static SimulationEngineFactories * instance()
SimulationEngineFactory * factoryByName(const std::string nam) const
virtual SimulationEngine * createEngine() const =0
virtual bool run(NetlistSimulatorController *controller, SimulationLogReceiver *logReceiver=nullptr)=0
bool clock_events_required() const
std::string name() const
virtual void set_engine_property(const std::string &key, const std::string &value)
virtual std::string get_engine_property(const std::string &key)
virtual bool setSimulationInput(SimulationInput *simInput)=0
std::string get_result_filename() const
void set_working_directory(const std::string &workDir)
virtual const std::unordered_map< std::string, std::string > & get_engine_properties() const
const std::vector< NetGroup > & get_net_groups() const
const std::vector< const Net * > & get_partial_netlist_nets() const
const std::vector< Clock > & get_clocks() const
const std::vector< const Net * > & get_output_nets() const
bool is_input_net(const Net *n) const
bool is_clock(const Net *n) const
const std::unordered_set< const Net * > & get_input_nets() const
void add_gates(const std::vector< Gate * > &gates)
const std::unordered_set< const Gate * > & get_gates() const
void add_clock(const Clock &clk)
QMap< QString, QString > engineProperties() const
void setEngineProperties(const QMap< QString, QString > &engProp)
bool importSaleae(const QString &saleaeDirecotry, const std::unordered_map< Net *, int > &lookupTable, const QString &workdir=QString(), u64 timeScale=1000000000)
bool exportVcd(const QString &filename, const QList< const WaveData * > &waves, u32 startTime, u32 endTime, u32 timeShift=0)
bool importCsv(const QString &csvFilename, const QString &workdir=QString(), const QList< const Net * > &onlyNets=QList< const Net * >(), u64 timeScale=1000000000)
bool importVcd(const QString &vcdFilename, const QString &workdir=QString(), const QList< const Net * > &onlyNets=QList< const Net * >())
std::vector< WaveData * > get_waveforms() const
Definition: wave_data.cpp:1004
bool rename(const QString &nam)
Definition: wave_data.cpp:89
void insertBooleanValueWithoutSync(u64 t, BooleanFunction::Value bval)
Definition: wave_data.cpp:103
u32 id() const
Definition: wave_data.h:103
void updateWaveName(int iwave, const QString &nam)
Definition: wave_data.cpp:1347
QMap< u32, WaveDataGroup * > mDataGroups
Definition: wave_data.h:203
void addWavesToGroup(u32 grpId, const QVector< WaveData * > &wds)
Definition: wave_data.cpp:1529
QMap< u32, WaveDataBoolean * > mDataBooleans
Definition: wave_data.h:204
int waveIndexByNetId(u32 id) const
Definition: wave_data.h:227
SaleaeDirectory & saleaeDirectory()
Definition: wave_data.h:242
void addOrReplace(WaveData *wd)
Definition: wave_data.cpp:1630
void setValueForEmpty(int val)
Definition: wave_data.cpp:1744
void remove(u32 id)
Definition: wave_data.cpp:1732
const WaveDataTimeframe & timeFrame() const
Definition: wave_data.h:233
void emitTimeframeChanged()
Definition: wave_data.cpp:1290
WaveData * waveDataByNet(const Net *n)
Definition: wave_data.cpp:1640
void incrementSimulTime(u64 deltaT)
Definition: wave_data.cpp:1295
void setUserTimeframe(u64 t0=0, u64 t1=0)
Definition: wave_data.cpp:1302
QSet< u32 > toSet() const
Definition: wave_data.cpp:1725
void triggerAddToView(u32 id) const
Definition: wave_data.cpp:1457
void removeGroup(u32 grpId)
Definition: wave_data.cpp:1553
void emitGroupUpdated(int grpId)
Definition: wave_data.cpp:1388
void insertBooleanValue(WaveData *wd, u64 t, BooleanFunction::Value bval)
Definition: wave_data.cpp:1547
QMap< u32, WaveDataTrigger * > mDataTrigger
Definition: wave_data.h:205
u64 sceneMaxTime() const
Definition: wave_data.cpp:1228
u64 sceneMinTime() const
Definition: wave_data.cpp:1242
u64 simulateMaxTime() const
Definition: wave_data.cpp:1223
uint64_t u64
Definition: defines.h:42
uint32_t u32
Definition: defines.h:41
#define log_error(channel,...)
Definition: log.h:78
#define log_info(channel,...)
Definition: log.h:70
#define log_warning(channel,...)
Definition: log.h:76
Definition: defines.h:45
Net * net
std::string name
i32 id
QString absoluteFilePath(const QString &fileName) const const
QString absolutePath() const const
QFileInfoList entryInfoList(QDir::Filters filters, QDir::SortFlags sort) const const
bool mkpath(const QString &dirPath) const const
bool copy(const QString &newName)
virtual bool open(QIODevice::OpenMode mode) override
bool remove()
QHash::const_iterator constBegin() const const
QHash::const_iterator constEnd() const const
qint64 write(const char *data, qint64 maxSize)
void append(const T &value)
const T & at(int i) const const
QMap::iterator begin()
QMap::iterator end()
bool isEmpty() const const
const Key key(const T &value, const Key &defaultKey) const const
Q_EMITQ_EMIT
void deleteLater()
bool contains(const T &value) const const
bool empty() const const
QSet::iterator insert(const T &value)
bool isEmpty() const const
void sync()
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString fromStdString(const std::string &str)
bool isEmpty() const const
std::string toStdString() const const
QString path() const const
void append(const T &value)
bool isEmpty() const const
void reserve(int size)
int size() const const
QList< T > toList() const const