20 #include <QApplication>
21 #include <QButtonGroup>
22 #include <QHBoxLayout>
23 #include <QRadioButton>
24 #include <QVBoxLayout>
41 Result<std::string> getLutInitHex(
const Gate* gate,
const std::string& initKey)
43 Result<Parameter> decl = gate->has_parameter(initKey) ? gate->get_parameter_declaration(initKey) : gate->get_type()->get_parameter(initKey);
46 return ERR_APPEND(decl.get_error(),
"no INIT parameter '" + initKey +
"' declared");
49 std::string
hex = gate->has_parameter(initKey) ? gate->get_parameter_value(initKey).get() : decl.get().get_default_value();
50 if (
hex.size() >= 2 && hex[0] ==
'0' && (hex[1] ==
'x' || hex[1] ==
'X'))
59 const size_t numDigits = (
static_cast<size_t>(decl.get().get_size()) + 3) / 4;
60 if (
hex.size() < numDigits)
62 hex.insert(0, numDigits -
hex.size(),
'0');
74 mGateInformationFrame =
new DetailsFrameWidget(mGateInfoTable,
"Gate Information",
this);
75 addTab(
"General", mGateInformationFrame,
true);
81 addTab(
"Groupings", mGroupingsFrame,
false);
88 addTab(
"Pins", mPinsFrame,
false);
95 mLutRadioWidget =
new QWidget(
this);
100 mLutConfigLabel =
new QLabel(
"default",
this);
109 mLutConfigurationFrame =
new DetailsFrameWidget(mLutConfigLabel,
"Configuration String",
this);
118 mMultiTabIndex =
addTab(
"(FF / Latch / LUT)", framesFfLatchLutTab);
119 mMultiTabContent =
widget(mMultiTabIndex);
125 mBooleanFunctionsFrame =
new DetailsFrameWidget(mFullFunctionTable,
"Boolean Functions",
this);
127 addTab(
"Boolean Functions", mBooleanFunctionsFrame,
false);
134 addTab(
"Data", mDataFrame,
false);
140 addTab(
"Parameters", mParameterFrame,
false);
154 mGroupingsOfItemTable->
setGate(gate);
157 mParameterTable->
setGate(gate);
161 GateDetailsTabWidget::GateTypeCategory gateTypeCategory = getGateTypeCategory(gate);
162 hideOrShorMultiTab(gateTypeCategory);
163 setupBooleanFunctionTables(gate, gateTypeCategory);
166 void GateDetailsTabWidget::handleGateBooleanFunctionChanged(
Gate* g)
168 if (g == mCurrentGate && g !=
nullptr)
170 GateDetailsTabWidget::GateTypeCategory gateTypeCategory = getGateTypeCategory(g);
171 setupBooleanFunctionTables(g, gateTypeCategory);
177 void GateDetailsTabWidget::hideOrShorMultiTab(GateDetailsTabWidget::GateTypeCategory gateTypeCategory)
179 if (gateTypeCategory != GateDetailsTabWidget::GateTypeCategory::none)
181 showMultiTab(gateTypeCategory);
189 void GateDetailsTabWidget::hideMultiTab()
191 if (mMultiTabVisible)
194 mMultiTabVisible =
false;
198 void GateDetailsTabWidget::showMultiTab(GateDetailsTabWidget::GateTypeCategory gateTypeCategory)
202 switch (gateTypeCategory)
204 case GateDetailsTabWidget::GateTypeCategory::lut: {
213 case GateDetailsTabWidget::GateTypeCategory::ff: {
222 case GateDetailsTabWidget::GateTypeCategory::latch: {
235 if (!mMultiTabVisible)
237 insertTab(mMultiTabIndex, mMultiTabContent, label);
238 mMultiTabVisible =
true;
246 GateDetailsTabWidget::GateTypeCategory GateDetailsTabWidget::getGateTypeCategory(Gate* gate)
const
250 return GateDetailsTabWidget::GateTypeCategory::none;
253 GateType*
type = gate->get_type();
255 std::set<hal::GateTypeProperty> gateTypeProperties =
type->get_properties();
258 auto relevantFind = find_first_of(begin(gateTypeProperties), end(gateTypeProperties), begin(relevantProperties), end(relevantProperties));
260 if (relevantFind == end(gateTypeProperties))
262 return GateDetailsTabWidget::GateTypeCategory::none;
265 switch (*relevantFind)
268 return GateDetailsTabWidget::GateTypeCategory::lut;
272 return GateDetailsTabWidget::GateTypeCategory::ff;
276 return GateDetailsTabWidget::GateTypeCategory::latch;
280 return GateDetailsTabWidget::GateTypeCategory::none;
286 void GateDetailsTabWidget::handleLutPinSelectionChanged(
int id)
288 if (mCurrentGate ==
nullptr || id < 0 || id >=
static_cast<int>(mCurrentLutPins.size()))
291 const std::string& pinName = mCurrentLutPins[
id];
292 mSelectedLutPin = pinName;
297 GateType* gt = mCurrentGate->
get_type();
300 if (lut_component ==
nullptr)
302 mLutConfigLabel->
setText(
" Could not load init string.");
305 const LUTComponent::LUTOutputConfig* cfg = lut_component->get_output_pin_config(pinName);
308 mLutConfigLabel->
setText(
" Could not load init string.");
311 auto initHex = getLutInitHex(mCurrentGate, cfg->init_identifier);
312 if (initHex.is_error())
314 mLutConfigLabel->
setText(
" Could not load init string.");
318 const std::string displayHex = sliceRes.is_ok() ? sliceRes.get() : initHex.get();
322 void GateDetailsTabWidget::handleLutConfigContextMenuRequested(
QPoint pos)
326 const LUTComponent::LUTOutputConfig* cfg = (lc !=
nullptr) ? lc->get_output_pin_config(mSelectedLutPin) :
nullptr;
329 log_error(
"gui",
"Could not load LUT configuration of pin '{}' from gate with id {}.", mSelectedLutPin, mCurrentGate->
get_id());
332 const std::string initKey = cfg->init_identifier;
333 const u32 bitOffset = cfg->bit_offset;
334 const u32 bitCount = cfg->bit_count;
339 menu.
addAction(
"Change configuration string", [
this, initKey, bitOffset, bitCount]() {
341 QString currentHex = mLutConfigLabel->
text().trimmed();
344 InputDialog ipd(
"Change configuration string",
"New configuration string", currentHex);
345 HexadecimalValidator hexValidator;
346 ipd.addValidator(&hexValidator);
350 const int numDigits = (bitCount + 3) / 4;
352 if (sliceHex.
size() > numDigits)
354 log_error(
"gui",
"Configuration string '{}' exceeds the {} bits of pin '{}'.", sliceHex.
toStdString(), bitCount, mSelectedLutPin);
359 auto initHex = getLutInitHex(mCurrentGate, initKey);
360 if (initHex.is_error())
362 log_error(
"gui",
"Could not load INIT parameter from gate with id {}: {}", mCurrentGate->
get_id(), initHex.get_error().get());
366 if (spliceRes.is_error())
368 log_error(
"gui",
"Could not change configuration string of gate with id {}: {}", mCurrentGate->
get_id(), spliceRes.get_error().get());
377 menu.
addAction(
QIcon(
":/icons/python"),
"Get configuration string", [
this, initKey]() {
384 void GateDetailsTabWidget::setupBooleanFunctionTables(Gate* gate, GateDetailsTabWidget::GateTypeCategory gateTypeCategory)
398 "power_down_function"
411 if (gateTypeCategory == GateDetailsTabWidget::GateTypeCategory::ff)
413 specialBfNames = &ffBfNames;
415 else if (gateTypeCategory == GateDetailsTabWidget::GateTypeCategory::latch)
417 specialBfNames = &latchBfNames;
420 std::unordered_map<std::string, BooleanFunction> allBfs = gate->get_boolean_functions(
false);
425 for (
auto& it : allBfs)
428 if (specialBfNames->
contains(bfName))
431 specialFunctions.
insert(bfName, it.second);
436 otherFunctions.
insert(bfName, it.second);
446 for (i = specialFunctions.
begin(); i != specialFunctions.
end(); i++)
449 for (i = otherFunctions.
begin(); i != otherFunctions.
end(); i++)
452 GateType* gt = gate->get_type();
453 if (FFComponent* ff_component = gt->get_component_as<FFComponent>([](
const GateTypeComponent* c) { return FFComponent::is_class_of(c); }); ff_component !=
nullptr)
457 if (!ff_component->get_clock_function().is_empty())
459 if (!ff_component->get_next_state_function().is_empty())
462 if (!ff_component->get_async_set_function().is_empty())
465 if (!ff_component->get_async_reset_function().is_empty())
469 else if (LatchComponent* latch_component = gt->get_component_as<LatchComponent>([](
const GateTypeComponent* c) { return LatchComponent::is_class_of(c); }); latch_component !=
nullptr)
473 if (!latch_component->get_enable_function().is_empty())
476 if (!latch_component->get_data_in_function().is_empty())
479 if (!latch_component->get_async_set_function().is_empty())
482 if (!latch_component->get_async_reset_function().is_empty())
487 if (StateComponent* state_component = gt->get_component_as<StateComponent>([](
const GateTypeComponent* c) { return StateComponent::is_class_of(c); }); state_component !=
nullptr)
489 if (state_component->get_state_identifier() !=
"")
491 new StateComponentEntry(gate->get_id(), StateComponentEntry::StateCompType::PosState,
QString::fromStdString(state_component->get_state_identifier()))));
492 if (state_component->get_neg_state_identifier() !=
"")
494 new StateComponentEntry(gate->get_id(), StateComponentEntry::StateCompType::NegState,
QString::fromStdString(state_component->get_neg_state_identifier()))));
498 switch (gateTypeCategory)
500 case GateDetailsTabWidget::GateTypeCategory::lut: {
501 const std::vector<std::string> lutPins = gate->get_type()->get_pin_names([](
const GatePin* p) {
return p->get_type() ==
PinType::lut; });
504 const auto existingButtons = mLutPinButtonGroup->
buttons();
509 if (
QWidget* w = item->widget())
513 mCurrentLutPins.clear();
517 for (
const std::string& pin : lutPins)
519 BooleanFunction bf = gate->get_boolean_function(pin);
534 if (!mCurrentGate)
return;
537 const u32 gateId = mCurrentGate->
get_id();
540 menu.
addAction(
"Boolean function to clipboard", [bfStr]() {
543 menu.
addAction(
"Change Boolean function", [
this, pinQStr]() {
544 InputDialog ipd(
"Change Boolean function",
"New function",
"");
550 ActionAddBooleanFunction* act =
new ActionAddBooleanFunction(pinQStr, funcRes.get(), mCurrentGate->
get_id());
557 menu.
addAction(
QIcon(
":/icons/python"),
"Get boolean function", [pyCode]() {
566 mCurrentLutPins.push_back(pin);
569 if (checked) handleLutPinSelectionChanged(idx);
577 if (!mSelectedLutPin.empty())
579 auto it = std::find(mCurrentLutPins.begin(), mCurrentLutPins.end(), mSelectedLutPin);
580 if (it != mCurrentLutPins.end())
581 pinToSelect =
static_cast<int>(it - mCurrentLutPins.begin());
583 if (!mCurrentLutPins.empty())
585 btn->setChecked(
true);
588 case GateDetailsTabWidget::GateTypeCategory::ff: {
589 mFfFunctionTable->
setEntries(specialFunctionList + setPresetBehavior);
592 case GateDetailsTabWidget::GateTypeCategory::latch: {
593 mLatchFunctionTable->
setEntries(specialFunctionList + setPresetBehavior);
599 mFullFunctionTable->
setEntries(specialFunctionList + otherFunctionList);
static Result< BooleanFunction > from_string(const std::string &expression)
A table view that shows BooleanFunctions and clear-preset behaviors.
void setContextMenuPlainDescr(bool enable)
void setEntries(QVector< QSharedPointer< BooleanFunctionTableEntry >> entries)
void setContextMenuPythonPlainDescr(bool enable)
BooleanFunction get_boolean_function(const std::string &name) const
GateType * get_type() const
A widget to display the pins of a given gate.
void updateText(const QString &newHeadline)
T * get_component_as(const std::function< bool(const GateTypeComponent *)> &filter=nullptr) const
static Result< std::string > extract_init_slice(const std::string &full_hex, u32 bit_offset, u32 bit_count)
static Result< std::string > splice_init_slice(const std::string &full_hex, const std::string &slice_hex, u32 bit_offset, u32 bit_count)
static bool is_class_of(const GateTypeComponent *component)
void gateBooleanFunctionChanged(Gate *g) const
The Node class object represents a module or a gate.
static QString pyCodeGateBooleanFunction(u32 gateId, QString booleanFunctionName)
static QString pyCodeGateParameterValue(u32 gateId, QString name)
static PythonQssAdapter * instance()
#define log_error(channel,...)
#define ERR_APPEND(prev_error, message)
NetlistRelay * gNetlistRelay
void addStretch(int stretch)
void setSpacing(int spacing)
virtual QLayoutItem * takeAt(int index) override
void setText(const QString &text, QClipboard::Mode mode)
void setText(const QString &)
void setWordWrap(bool on)
void setContentsMargins(int left, int top, int right, int bottom)
const Key & key() const const
QMap::iterator insert(const Key &key, const T &value)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
bool contains(const T &value) const const
QString fromStdString(const std::string &str)
bool isEmpty() const const
QString mid(int position, int n) const const
QString rightJustified(int width, QChar fill, bool truncate) const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
std::string toStdString() const const
QString toUpper() const const
QTextStream & hex(QTextStream &stream)
void setTabText(int index, const QString &label)
void append(const T &value)