summaryrefslogtreecommitdiff
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 @@
1#include "regtab.h"
2
3#include <QSplitter>
4#include <QVBoxLayout>
5#include <QGroupBox>
6#include <QAbstractListModel>
7#include <QMessageBox>
8#include <QSizePolicy>
9#include <QHBoxLayout>
10#include <QStringBuilder>
11#include <QLabel>
12#include <QGridLayout>
13#include <QTableWidget>
14#include <QHeaderView>
15#include <QFileDialog>
16#include "backend.h"
17#include "analyser.h"
18
19RegTreeItem::RegTreeItem(const QString& string, int type)
20 :QTreeWidgetItem(QStringList(string), type)
21{
22}
23
24void RegTreeItem::SetPath(int dev_idx, int dev_addr_idx, int reg_idx, int reg_addr_idx)
25{
26 m_dev_idx = dev_idx;
27 m_dev_addr_idx = dev_addr_idx;
28 m_reg_idx = reg_idx;
29 m_reg_addr_idx = reg_addr_idx;
30}
31
32RegTab::RegTab(Backend *backend, QTabWidget *parent)
33 :m_backend(backend)
34{
35 m_splitter = new QSplitter();
36 QWidget *left = new QWidget;
37 m_splitter->addWidget(left);
38 QVBoxLayout *left_layout = new QVBoxLayout;
39 left->setLayout(left_layout);
40
41 QGroupBox *top_group = new QGroupBox("SOC selection");
42 QVBoxLayout *top_group_layout = new QVBoxLayout;
43 m_soc_selector = new QComboBox;
44 top_group_layout->addWidget(m_soc_selector);
45 top_group->setLayout(top_group_layout);
46
47 m_reg_tree = new QTreeWidget();
48 m_reg_tree->setColumnCount(1);
49 m_reg_tree->setHeaderLabel(QString("Name"));
50
51 m_analysers_list = new QListWidget;
52
53 m_type_selector = new QTabWidget;
54 m_type_selector->addTab(m_reg_tree, "Registers");
55 m_type_selector->addTab(m_analysers_list, "Analyzers");
56 m_type_selector->setTabPosition(QTabWidget::West);
57
58 left_layout->addWidget(top_group);
59 left_layout->addWidget(m_type_selector);
60
61 m_right_panel = new QVBoxLayout;
62 QGroupBox *data_sel_group = new QGroupBox("Data selection");
63 QHBoxLayout *data_sel_layout = new QHBoxLayout;
64 m_data_selector = new QComboBox;
65 m_data_selector->addItem(QIcon::fromTheme("face-sad"), "None", QVariant(DataSelNothing));
66 m_data_selector->addItem(QIcon::fromTheme("document-open"), "File...", QVariant(DataSelFile));
67 m_data_sel_edit = new QLineEdit;
68 m_data_sel_edit->setReadOnly(true);
69 m_data_soc_label = new QLabel;
70 QPushButton *data_sel_reload = new QPushButton;
71 data_sel_reload->setIcon(QIcon::fromTheme("view-refresh"));
72 data_sel_layout->addWidget(m_data_selector);
73 data_sel_layout->addWidget(m_data_sel_edit);
74 data_sel_layout->addWidget(m_data_soc_label);
75 data_sel_layout->addWidget(data_sel_reload);
76 data_sel_group->setLayout(data_sel_layout);
77 m_data_soc_label->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
78
79 m_right_panel->addWidget(data_sel_group);
80 m_right_content = new QWidget;
81 QVBoxLayout *l = new QVBoxLayout;
82 l->addStretch();
83 m_right_content->setLayout(l);
84 m_right_panel->addWidget(m_right_content);
85 QWidget *w = new QWidget;
86 w->setLayout(m_right_panel);
87 m_splitter->addWidget(w);
88
89 m_io_backend = m_backend->CreateDummyIoBackend();
90
91 parent->addTab(m_splitter, "Register Tab");
92
93 connect(m_soc_selector, SIGNAL(currentIndexChanged(const QString&)),
94 this, SLOT(OnSocChanged(const QString&)));
95 connect(m_backend, SIGNAL(OnSocListChanged()), this, SLOT(OnSocListChanged()));
96 connect(m_reg_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
97 this, SLOT(OnRegItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
98 connect(m_reg_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
99 SLOT(OnRegItemClicked(QTreeWidgetItem *, int)));
100 connect(m_data_selector, SIGNAL(activated(int)),
101 this, SLOT(OnDataSelChanged(int)));
102 connect(m_data_soc_label, SIGNAL(linkActivated(const QString&)), this,
103 SLOT(OnDataSocActivated(const QString&)));
104 connect(m_analysers_list, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
105 this, SLOT(OnAnalyserChanged(QListWidgetItem *, QListWidgetItem *)));
106 connect(m_analysers_list, SIGNAL(itemClicked(QListWidgetItem *)), this,
107 SLOT(OnAnalyserClicked(QListWidgetItem *)));
108
109 OnSocListChanged();
110 OnDataSelChanged(DataSelNothing);
111}
112
113void RegTab::SetDataSocName(const QString& socname)
114{
115 if(socname.size() != 0)
116 {
117 m_data_soc_label->setText("<a href=\"" + socname + "\">" + socname + "</a>");
118 m_data_soc_label->setTextFormat(Qt::RichText);
119 m_data_soc_label->show();
120 }
121 else
122 {
123 m_data_soc_label->setText("");
124 m_data_soc_label->hide();
125 }
126}
127
128void RegTab::OnDataSocActivated(const QString& str)
129{
130 int index = m_soc_selector->findText(str);
131 if(index != -1)
132 m_soc_selector->setCurrentIndex(index);
133}
134
135void RegTab::OnDataSelChanged(int index)
136{
137 if(index == -1)
138 return;
139 QVariant var = m_data_selector->itemData(index);
140 if(var == DataSelFile)
141 {
142 QFileDialog *fd = new QFileDialog(m_data_selector);
143 fd->setFilter("Textual files (*.txt);;All files (*)");
144 fd->setDirectory(Settings::Get()->value("regtab/loaddatadir", QDir::currentPath()).toString());
145 if(fd->exec())
146 {
147 QStringList filenames = fd->selectedFiles();
148 delete m_io_backend;
149 m_io_backend = m_backend->CreateFileIoBackend(filenames[0]);
150 m_data_sel_edit->setText(filenames[0]);
151 SetDataSocName(m_io_backend->GetSocName());
152 OnDataSocActivated(m_io_backend->GetSocName());
153 }
154 Settings::Get()->setValue("regtab/loaddatadir", fd->directory().absolutePath());
155 }
156 else
157 {
158 delete m_io_backend;
159 m_io_backend = m_backend->CreateDummyIoBackend();
160 SetDataSocName("");
161 }
162 OnDataChanged();
163}
164
165void RegTab::OnDataChanged()
166{
167 OnRegItemChanged(m_reg_tree->currentItem(), m_reg_tree->currentItem());
168}
169
170void RegTab::OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
171{
172 (void) previous;
173 OnRegItemClicked(current, 0);
174}
175
176void RegTab::OnRegItemClicked(QTreeWidgetItem *current, int col)
177{
178 (void) col;
179 if(current == 0)
180 return;
181 RegTreeItem *item = dynamic_cast< RegTreeItem * >(current);
182 if(item->type() != RegTreeRegType)
183 return;
184 soc_dev_t& dev = m_cur_soc.dev[item->GetDevIndex()];
185 soc_dev_addr_t& dev_addr = dev.addr[item->GetDevAddrIndex()];
186 soc_reg_t& reg = dev.reg[item->GetRegIndex()];
187 soc_reg_addr_t& reg_addr = reg.addr[item->GetRegAddrIndex()];
188
189 DisplayRegister(dev, dev_addr, reg, reg_addr);
190}
191
192void RegTab::OnAnalyserChanged(QListWidgetItem *current, QListWidgetItem *previous)
193{
194 (void) previous;
195 OnAnalyserClicked(current);
196}
197
198void RegTab::OnAnalyserClicked(QListWidgetItem *current)
199{
200 if(current == 0)
201 return;
202 delete m_right_content;
203 AnalyserFactory *ana = AnalyserFactory::GetAnalyserByName(current->text());
204 m_right_content = ana->Create(m_cur_soc, m_io_backend)->GetWidget();
205 m_right_panel->addWidget(m_right_content);
206}
207
208void RegTab::DisplayRegister(soc_dev_t& dev, soc_dev_addr_t& dev_addr,
209 soc_reg_t& reg, soc_reg_addr_t& reg_addr)
210{
211 (void) dev;
212 delete m_right_content;
213
214 QVBoxLayout *right_layout = new QVBoxLayout;
215
216 QString reg_name;
217 reg_name.sprintf("HW_%s_%s", dev_addr.name.c_str(), reg_addr.name.c_str());
218 QStringList names;
219 QVector< soc_addr_t > addresses;
220 names.append(reg_name);
221 addresses.append(reg_addr.addr);
222 if(reg.flags & REG_HAS_SCT)
223 {
224 names.append(reg_name + "_SET");
225 names.append(reg_name + "_CLR");
226 names.append(reg_name + "_TOG");
227 addresses.append(reg_addr.addr + 4);
228 addresses.append(reg_addr.addr + 8);
229 addresses.append(reg_addr.addr + 12);
230 }
231
232 QString str;
233 str += "<table align=left>";
234 for(int i = 0; i < names.size(); i++)
235 str += "<tr><td><b>" + names[i] + "</b></td></tr>";
236 str += "</table>";
237 QLabel *label_names = new QLabel;
238 label_names->setTextFormat(Qt::RichText);
239 label_names->setText(str);
240
241 QString str_addr;
242 str_addr += "<table align=left>";
243 for(int i = 0; i < names.size(); i++)
244 str_addr += "<tr><td><b>" + QString().sprintf("0x%03x", addresses[i]) + "</b></td></tr>";
245 str_addr += "</table>";
246 QLabel *label_addr = new QLabel;
247 label_addr->setTextFormat(Qt::RichText);
248 label_addr->setText(str_addr);
249
250 QHBoxLayout *top_layout = new QHBoxLayout;
251 top_layout->addStretch();
252 top_layout->addWidget(label_names);
253 top_layout->addWidget(label_addr);
254 top_layout->addStretch();
255
256 soc_word_t value;
257 bool has_value = m_io_backend->ReadRegister(QString().sprintf("HW.%s.%s",
258 dev_addr.name.c_str(), reg_addr.name.c_str()), value);
259
260 QHBoxLayout *raw_val_layout = 0;
261 if(has_value)
262 {
263 QLabel *raw_val_name = new QLabel;
264 raw_val_name->setText("Raw value:");
265 QLineEdit *raw_val_edit = new QLineEdit;
266 raw_val_edit->setReadOnly(true);
267 raw_val_edit->setText(QString().sprintf("0x%08x", value));
268 raw_val_edit->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
269 raw_val_layout = new QHBoxLayout;
270 raw_val_layout->addStretch();
271 raw_val_layout->addWidget(raw_val_name);
272 raw_val_layout->addWidget(raw_val_edit);
273 raw_val_layout->addStretch();
274 }
275
276 QTableWidget *value_table = new QTableWidget;
277 value_table->setRowCount(reg.field.size());
278 value_table->setColumnCount(4);
279 for(size_t i = 0; i < reg.field.size(); i++)
280 {
281 QString bits_str;
282 if(reg.field[i].first_bit == reg.field[i].last_bit)
283 bits_str.sprintf("%d", reg.field[i].first_bit);
284 else
285 bits_str.sprintf("%d:%d", reg.field[i].last_bit, reg.field[i].first_bit);
286 QTableWidgetItem *item = new QTableWidgetItem(bits_str);
287 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
288 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
289 value_table->setItem(i, 0, item);
290 item = new QTableWidgetItem(QString(reg.field[i].name.c_str()));
291 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
292 value_table->setItem(i, 1, item);
293 item = new QTableWidgetItem();
294 if(has_value)
295 {
296 const soc_reg_field_t& field = reg.field[i];
297 soc_word_t v = (value & field.bitmask()) >> field.first_bit;
298 QString value_name;
299 for(size_t j = 0; j < field.value.size(); j++)
300 if(v == field.value[j].value)
301 value_name = field.value[j].name.c_str();
302 const char *fmt = "%lu";
303 // heuristic
304 if((field.last_bit - field.first_bit + 1) > 16)
305 fmt = "0x%lx";
306 item->setText(QString().sprintf(fmt, (unsigned long)v));
307 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
308
309 if(value_name.size() != 0)
310 {
311 QTableWidgetItem *t = new QTableWidgetItem(value_name);
312 t->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
313 t->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
314 value_table->setItem(i, 3, t);
315 }
316 }
317 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
318 value_table->setItem(i, 2, item);
319 }
320 value_table->setHorizontalHeaderItem(0, new QTableWidgetItem("Bits"));
321 value_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Name"));
322 value_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Value"));
323 value_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Meaning"));
324 value_table->verticalHeader()->setVisible(false);
325 value_table->resizeColumnsToContents();
326 value_table->horizontalHeader()->setStretchLastSection(true);
327 value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
328
329 right_layout->addLayout(top_layout);
330 if(raw_val_layout)
331 right_layout->addLayout(raw_val_layout);
332 //right_layout->addWidget(bits_label);
333 right_layout->addWidget(value_table);
334 //right_layout->addStretch();
335
336 m_right_content = new QGroupBox("Register Description");
337 m_right_content->setLayout(right_layout);
338 m_right_panel->addWidget(m_right_content);
339}
340
341void RegTab::OnSocListChanged()
342{
343 m_soc_selector->clear();
344 QStringList socs = m_backend->GetSocNameList();
345 for(int i = 0; i < socs.size(); i++)
346 m_soc_selector->addItem(socs[i]);
347}
348
349void RegTab::FillDevSubTree(RegTreeItem *item)
350{
351 soc_dev_t& sd = m_cur_soc.dev[item->GetDevIndex()];
352 for(size_t i = 0; i < sd.reg.size(); i++)
353 {
354 soc_reg_t& reg = sd.reg[i];
355 for(size_t j = 0; j < reg.addr.size(); j++)
356 {
357 RegTreeItem *reg_item = new RegTreeItem(reg.addr[j].name.c_str(), RegTreeRegType);
358 reg_item->SetPath(item->GetDevIndex(), item->GetDevAddrIndex(), i, j);
359 item->addChild(reg_item);
360 }
361 }
362}
363
364void RegTab::FillRegTree()
365{
366 for(size_t i = 0; i < m_cur_soc.dev.size(); i++)
367 {
368 soc_dev_t& sd = m_cur_soc.dev[i];
369 for(size_t j = 0; j < sd.addr.size(); j++)
370 {
371 RegTreeItem *dev_item = new RegTreeItem(sd.addr[j].name.c_str(), RegTreeDevType);
372 dev_item->SetPath(i, j);
373 FillDevSubTree(dev_item);
374 m_reg_tree->addTopLevelItem(dev_item);
375 }
376 }
377}
378
379void RegTab::FillAnalyserList()
380{
381 m_analysers_list->clear();
382 m_analysers_list->addItems(AnalyserFactory::GetAnalysersForSoc(m_cur_soc.name.c_str()));
383}
384
385void RegTab::OnSocChanged(const QString& soc)
386{
387 m_reg_tree->clear();
388 if(!m_backend->GetSocByName(soc, m_cur_soc))
389 return;
390 FillRegTree();
391 FillAnalyserList();
392}