summaryrefslogtreecommitdiffstats
path: root/utils/regtools/qeditor/regtab.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/regtools/qeditor/regtab.cpp')
-rw-r--r--utils/regtools/qeditor/regtab.cpp392
1 files changed, 392 insertions, 0 deletions
diff --git a/utils/regtools/qeditor/regtab.cpp b/utils/regtools/qeditor/regtab.cpp
new file mode 100644
index 0000000000..d535f6cdff
--- /dev/null
+++ b/utils/regtools/qeditor/regtab.cpp
@@ -0,0 +1,392 @@
+#include "regtab.h"
+
+#include <QSplitter>
+#include <QVBoxLayout>
+#include <QGroupBox>
+#include <QAbstractListModel>
+#include <QMessageBox>
+#include <QSizePolicy>
+#include <QHBoxLayout>
+#include <QStringBuilder>
+#include <QLabel>
+#include <QGridLayout>
+#include <QTableWidget>
+#include <QHeaderView>
+#include <QFileDialog>
+#include "backend.h"
+#include "analyser.h"
+
+RegTreeItem::RegTreeItem(const QString& string, int type)
+ :QTreeWidgetItem(QStringList(string), type)
+{
+}
+
+void RegTreeItem::SetPath(int dev_idx, int dev_addr_idx, int reg_idx, int reg_addr_idx)
+{
+ m_dev_idx = dev_idx;
+ m_dev_addr_idx = dev_addr_idx;
+ m_reg_idx = reg_idx;
+ m_reg_addr_idx = reg_addr_idx;
+}
+
+RegTab::RegTab(Backend *backend, QTabWidget *parent)
+ :m_backend(backend)
+{
+ m_splitter = new QSplitter();
+ QWidget *left = new QWidget;
+ m_splitter->addWidget(left);
+ QVBoxLayout *left_layout = new QVBoxLayout;
+ left->setLayout(left_layout);
+
+ QGroupBox *top_group = new QGroupBox("SOC selection");
+ QVBoxLayout *top_group_layout = new QVBoxLayout;
+ m_soc_selector = new QComboBox;
+ top_group_layout->addWidget(m_soc_selector);
+ top_group->setLayout(top_group_layout);
+
+ m_reg_tree = new QTreeWidget();
+ m_reg_tree->setColumnCount(1);
+ m_reg_tree->setHeaderLabel(QString("Name"));
+
+ m_analysers_list = new QListWidget;
+
+ m_type_selector = new QTabWidget;
+ m_type_selector->addTab(m_reg_tree, "Registers");
+ m_type_selector->addTab(m_analysers_list, "Analyzers");
+ m_type_selector->setTabPosition(QTabWidget::West);
+
+ left_layout->addWidget(top_group);
+ left_layout->addWidget(m_type_selector);
+
+ m_right_panel = new QVBoxLayout;
+ QGroupBox *data_sel_group = new QGroupBox("Data selection");
+ QHBoxLayout *data_sel_layout = new QHBoxLayout;
+ m_data_selector = new QComboBox;
+ m_data_selector->addItem(QIcon::fromTheme("face-sad"), "None", QVariant(DataSelNothing));
+ m_data_selector->addItem(QIcon::fromTheme("document-open"), "File...", QVariant(DataSelFile));
+ m_data_sel_edit = new QLineEdit;
+ m_data_sel_edit->setReadOnly(true);
+ m_data_soc_label = new QLabel;
+ QPushButton *data_sel_reload = new QPushButton;
+ data_sel_reload->setIcon(QIcon::fromTheme("view-refresh"));
+ data_sel_layout->addWidget(m_data_selector);
+ data_sel_layout->addWidget(m_data_sel_edit);
+ data_sel_layout->addWidget(m_data_soc_label);
+ data_sel_layout->addWidget(data_sel_reload);
+ data_sel_group->setLayout(data_sel_layout);
+ m_data_soc_label->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
+
+ m_right_panel->addWidget(data_sel_group);
+ m_right_content = new QWidget;
+ QVBoxLayout *l = new QVBoxLayout;
+ l->addStretch();
+ m_right_content->setLayout(l);
+ m_right_panel->addWidget(m_right_content);
+ QWidget *w = new QWidget;
+ w->setLayout(m_right_panel);
+ m_splitter->addWidget(w);
+
+ m_io_backend = m_backend->CreateDummyIoBackend();
+
+ parent->addTab(m_splitter, "Register Tab");
+
+ connect(m_soc_selector, SIGNAL(currentIndexChanged(const QString&)),
+ this, SLOT(OnSocChanged(const QString&)));
+ connect(m_backend, SIGNAL(OnSocListChanged()), this, SLOT(OnSocListChanged()));
+ connect(m_reg_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
+ this, SLOT(OnRegItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
+ connect(m_reg_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
+ SLOT(OnRegItemClicked(QTreeWidgetItem *, int)));
+ connect(m_data_selector, SIGNAL(activated(int)),
+ this, SLOT(OnDataSelChanged(int)));
+ connect(m_data_soc_label, SIGNAL(linkActivated(const QString&)), this,
+ SLOT(OnDataSocActivated(const QString&)));
+ connect(m_analysers_list, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
+ this, SLOT(OnAnalyserChanged(QListWidgetItem *, QListWidgetItem *)));
+ connect(m_analysers_list, SIGNAL(itemClicked(QListWidgetItem *)), this,
+ SLOT(OnAnalyserClicked(QListWidgetItem *)));
+
+ OnSocListChanged();
+ OnDataSelChanged(DataSelNothing);
+}
+
+void RegTab::SetDataSocName(const QString& socname)
+{
+ if(socname.size() != 0)
+ {
+ m_data_soc_label->setText("<a href=\"" + socname + "\">" + socname + "</a>");
+ m_data_soc_label->setTextFormat(Qt::RichText);
+ m_data_soc_label->show();
+ }
+ else
+ {
+ m_data_soc_label->setText("");
+ m_data_soc_label->hide();
+ }
+}
+
+void RegTab::OnDataSocActivated(const QString& str)
+{
+ int index = m_soc_selector->findText(str);
+ if(index != -1)
+ m_soc_selector->setCurrentIndex(index);
+}
+
+void RegTab::OnDataSelChanged(int index)
+{
+ if(index == -1)
+ return;
+ QVariant var = m_data_selector->itemData(index);
+ if(var == DataSelFile)
+ {
+ QFileDialog *fd = new QFileDialog(m_data_selector);
+ fd->setFilter("Textual files (*.txt);;All files (*)");
+ fd->setDirectory(Settings::Get()->value("regtab/loaddatadir", QDir::currentPath()).toString());
+ if(fd->exec())
+ {
+ QStringList filenames = fd->selectedFiles();
+ delete m_io_backend;
+ m_io_backend = m_backend->CreateFileIoBackend(filenames[0]);
+ m_data_sel_edit->setText(filenames[0]);
+ SetDataSocName(m_io_backend->GetSocName());
+ OnDataSocActivated(m_io_backend->GetSocName());
+ }
+ Settings::Get()->setValue("regtab/loaddatadir", fd->directory().absolutePath());
+ }
+ else
+ {
+ delete m_io_backend;
+ m_io_backend = m_backend->CreateDummyIoBackend();
+ SetDataSocName("");
+ }
+ OnDataChanged();
+}
+
+void RegTab::OnDataChanged()
+{
+ OnRegItemChanged(m_reg_tree->currentItem(), m_reg_tree->currentItem());
+}
+
+void RegTab::OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
+{
+ (void) previous;
+ OnRegItemClicked(current, 0);
+}
+
+void RegTab::OnRegItemClicked(QTreeWidgetItem *current, int col)
+{
+ (void) col;
+ if(current == 0)
+ return;
+ RegTreeItem *item = dynamic_cast< RegTreeItem * >(current);
+ if(item->type() != RegTreeRegType)
+ return;
+ soc_dev_t& dev = m_cur_soc.dev[item->GetDevIndex()];
+ soc_dev_addr_t& dev_addr = dev.addr[item->GetDevAddrIndex()];
+ soc_reg_t& reg = dev.reg[item->GetRegIndex()];
+ soc_reg_addr_t& reg_addr = reg.addr[item->GetRegAddrIndex()];
+
+ DisplayRegister(dev, dev_addr, reg, reg_addr);
+}
+
+void RegTab::OnAnalyserChanged(QListWidgetItem *current, QListWidgetItem *previous)
+{
+ (void) previous;
+ OnAnalyserClicked(current);
+}
+
+void RegTab::OnAnalyserClicked(QListWidgetItem *current)
+{
+ if(current == 0)
+ return;
+ delete m_right_content;
+ AnalyserFactory *ana = AnalyserFactory::GetAnalyserByName(current->text());
+ m_right_content = ana->Create(m_cur_soc, m_io_backend)->GetWidget();
+ m_right_panel->addWidget(m_right_content);
+}
+
+void RegTab::DisplayRegister(soc_dev_t& dev, soc_dev_addr_t& dev_addr,
+ soc_reg_t& reg, soc_reg_addr_t& reg_addr)
+{
+ (void) dev;
+ delete m_right_content;
+
+ QVBoxLayout *right_layout = new QVBoxLayout;
+
+ QString reg_name;
+ reg_name.sprintf("HW_%s_%s", dev_addr.name.c_str(), reg_addr.name.c_str());
+ QStringList names;
+ QVector< soc_addr_t > addresses;
+ names.append(reg_name);
+ addresses.append(reg_addr.addr);
+ if(reg.flags & REG_HAS_SCT)
+ {
+ names.append(reg_name + "_SET");
+ names.append(reg_name + "_CLR");
+ names.append(reg_name + "_TOG");
+ addresses.append(reg_addr.addr + 4);
+ addresses.append(reg_addr.addr + 8);
+ addresses.append(reg_addr.addr + 12);
+ }
+
+ QString str;
+ str += "<table align=left>";
+ for(int i = 0; i < names.size(); i++)
+ str += "<tr><td><b>" + names[i] + "</b></td></tr>";
+ str += "</table>";
+ QLabel *label_names = new QLabel;
+ label_names->setTextFormat(Qt::RichText);
+ label_names->setText(str);
+
+ QString str_addr;
+ str_addr += "<table align=left>";
+ for(int i = 0; i < names.size(); i++)
+ str_addr += "<tr><td><b>" + QString().sprintf("0x%03x", addresses[i]) + "</b></td></tr>";
+ str_addr += "</table>";
+ QLabel *label_addr = new QLabel;
+ label_addr->setTextFormat(Qt::RichText);
+ label_addr->setText(str_addr);
+
+ QHBoxLayout *top_layout = new QHBoxLayout;
+ top_layout->addStretch();
+ top_layout->addWidget(label_names);
+ top_layout->addWidget(label_addr);
+ top_layout->addStretch();
+
+ soc_word_t value;
+ bool has_value = m_io_backend->ReadRegister(QString().sprintf("HW.%s.%s",
+ dev_addr.name.c_str(), reg_addr.name.c_str()), value);
+
+ QHBoxLayout *raw_val_layout = 0;
+ if(has_value)
+ {
+ QLabel *raw_val_name = new QLabel;
+ raw_val_name->setText("Raw value:");
+ QLineEdit *raw_val_edit = new QLineEdit;
+ raw_val_edit->setReadOnly(true);
+ raw_val_edit->setText(QString().sprintf("0x%08x", value));
+ raw_val_edit->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ raw_val_layout = new QHBoxLayout;
+ raw_val_layout->addStretch();
+ raw_val_layout->addWidget(raw_val_name);
+ raw_val_layout->addWidget(raw_val_edit);
+ raw_val_layout->addStretch();
+ }
+
+ QTableWidget *value_table = new QTableWidget;
+ value_table->setRowCount(reg.field.size());
+ value_table->setColumnCount(4);
+ for(size_t i = 0; i < reg.field.size(); i++)
+ {
+ QString bits_str;
+ if(reg.field[i].first_bit == reg.field[i].last_bit)
+ bits_str.sprintf("%d", reg.field[i].first_bit);
+ else
+ bits_str.sprintf("%d:%d", reg.field[i].last_bit, reg.field[i].first_bit);
+ QTableWidgetItem *item = new QTableWidgetItem(bits_str);
+ item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
+ item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+ value_table->setItem(i, 0, item);
+ item = new QTableWidgetItem(QString(reg.field[i].name.c_str()));
+ item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+ value_table->setItem(i, 1, item);
+ item = new QTableWidgetItem();
+ if(has_value)
+ {
+ const soc_reg_field_t& field = reg.field[i];
+ soc_word_t v = (value & field.bitmask()) >> field.first_bit;
+ QString value_name;
+ for(size_t j = 0; j < field.value.size(); j++)
+ if(v == field.value[j].value)
+ value_name = field.value[j].name.c_str();
+ const char *fmt = "%lu";
+ // heuristic
+ if((field.last_bit - field.first_bit + 1) > 16)
+ fmt = "0x%lx";
+ item->setText(QString().sprintf(fmt, (unsigned long)v));
+ item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
+
+ if(value_name.size() != 0)
+ {
+ QTableWidgetItem *t = new QTableWidgetItem(value_name);
+ t->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
+ t->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+ value_table->setItem(i, 3, t);
+ }
+ }
+ item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+ value_table->setItem(i, 2, item);
+ }
+ value_table->setHorizontalHeaderItem(0, new QTableWidgetItem("Bits"));
+ value_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Name"));
+ value_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Value"));
+ value_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Meaning"));
+ value_table->verticalHeader()->setVisible(false);
+ value_table->resizeColumnsToContents();
+ value_table->horizontalHeader()->setStretchLastSection(true);
+ value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ right_layout->addLayout(top_layout);
+ if(raw_val_layout)
+ right_layout->addLayout(raw_val_layout);
+ //right_layout->addWidget(bits_label);
+ right_layout->addWidget(value_table);
+ //right_layout->addStretch();
+
+ m_right_content = new QGroupBox("Register Description");
+ m_right_content->setLayout(right_layout);
+ m_right_panel->addWidget(m_right_content);
+}
+
+void RegTab::OnSocListChanged()
+{
+ m_soc_selector->clear();
+ QStringList socs = m_backend->GetSocNameList();
+ for(int i = 0; i < socs.size(); i++)
+ m_soc_selector->addItem(socs[i]);
+}
+
+void RegTab::FillDevSubTree(RegTreeItem *item)
+{
+ soc_dev_t& sd = m_cur_soc.dev[item->GetDevIndex()];
+ for(size_t i = 0; i < sd.reg.size(); i++)
+ {
+ soc_reg_t& reg = sd.reg[i];
+ for(size_t j = 0; j < reg.addr.size(); j++)
+ {
+ RegTreeItem *reg_item = new RegTreeItem(reg.addr[j].name.c_str(), RegTreeRegType);
+ reg_item->SetPath(item->GetDevIndex(), item->GetDevAddrIndex(), i, j);
+ item->addChild(reg_item);
+ }
+ }
+}
+
+void RegTab::FillRegTree()
+{
+ for(size_t i = 0; i < m_cur_soc.dev.size(); i++)
+ {
+ soc_dev_t& sd = m_cur_soc.dev[i];
+ for(size_t j = 0; j < sd.addr.size(); j++)
+ {
+ RegTreeItem *dev_item = new RegTreeItem(sd.addr[j].name.c_str(), RegTreeDevType);
+ dev_item->SetPath(i, j);
+ FillDevSubTree(dev_item);
+ m_reg_tree->addTopLevelItem(dev_item);
+ }
+ }
+}
+
+void RegTab::FillAnalyserList()
+{
+ m_analysers_list->clear();
+ m_analysers_list->addItems(AnalyserFactory::GetAnalysersForSoc(m_cur_soc.name.c_str()));
+}
+
+void RegTab::OnSocChanged(const QString& soc)
+{
+ m_reg_tree->clear();
+ if(!m_backend->GetSocByName(soc, m_cur_soc))
+ return;
+ FillRegTree();
+ FillAnalyserList();
+}