summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-08-21 20:16:26 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-08-21 20:18:37 +0200
commitc323381f0b3ee68b0093442335e8e7cbb112858a (patch)
treeac27964bd0da6bc56f05ad965ce4de957ef22d59
parent902306378e38ce571f4595ae8dabb2acd2412faa (diff)
downloadrockbox-c323381f0b3ee68b0093442335e8e7cbb112858a.tar.gz
rockbox-c323381f0b3ee68b0093442335e8e7cbb112858a.zip
regtools: add graphical register explorer + analyser
This tool allows one to explore any register map. Register dumps (like produced by hwstub tools) can be loaded and decoded by the tool. Finally some analysers are provided for specific soc analysis like clock tree and emi on imx233 for example. Change-Id: Iaf81bd52d15f3e44ab4fe9bc039153fcf60cf92a
-rw-r--r--utils/regtools/qeditor/analyser.cpp44
-rw-r--r--utils/regtools/qeditor/analyser.h64
-rw-r--r--utils/regtools/qeditor/backend.cpp156
-rw-r--r--utils/regtools/qeditor/backend.h77
-rw-r--r--utils/regtools/qeditor/main.cpp30
-rw-r--r--utils/regtools/qeditor/mainwindow.cpp108
-rw-r--r--utils/regtools/qeditor/mainwindow.h44
-rw-r--r--utils/regtools/qeditor/qeditor.pro8
-rw-r--r--utils/regtools/qeditor/regtab.cpp392
-rw-r--r--utils/regtools/qeditor/regtab.h85
-rw-r--r--utils/regtools/qeditor/settings.cpp32
-rw-r--r--utils/regtools/qeditor/settings.h21
-rw-r--r--utils/regtools/qeditor/std_analysers.cpp636
-rw-r--r--utils/regtools/qeditor/std_analysers.h95
14 files changed, 1792 insertions, 0 deletions
diff --git a/utils/regtools/qeditor/analyser.cpp b/utils/regtools/qeditor/analyser.cpp
new file mode 100644
index 0000000000..1ab213872b
--- /dev/null
+++ b/utils/regtools/qeditor/analyser.cpp
@@ -0,0 +1,44 @@
1#include "analyser.h"
2
3Analyser::Analyser(const soc_t& soc, IoBackend *backend)
4 :m_soc(soc), m_io_backend(backend)
5{
6}
7
8Analyser::~Analyser()
9{
10}
11
12AnalyserFactory::AnalyserFactory(bool _register)
13{
14 if(_register)
15 RegisterAnalyser(this);
16}
17
18AnalyserFactory::~AnalyserFactory()
19{
20}
21
22QVector< AnalyserFactory * > AnalyserFactory::m_factories;
23
24QStringList AnalyserFactory::GetAnalysersForSoc(const QString& soc_name)
25{
26 QStringList list;
27 for(int i = 0; i < m_factories.size(); i++)
28 if(m_factories[i]->SupportSoc(soc_name))
29 list.append(m_factories[i]->GetName());
30 return list;
31}
32
33AnalyserFactory *AnalyserFactory::GetAnalyserByName(const QString& name)
34{
35 for(int i = 0; i < m_factories.size(); i++)
36 if(m_factories[i]->GetName() == name)
37 return m_factories[i];
38 return 0;
39}
40
41void AnalyserFactory::RegisterAnalyser(AnalyserFactory *factory)
42{
43 m_factories.append(factory);
44}
diff --git a/utils/regtools/qeditor/analyser.h b/utils/regtools/qeditor/analyser.h
new file mode 100644
index 0000000000..33094574c1
--- /dev/null
+++ b/utils/regtools/qeditor/analyser.h
@@ -0,0 +1,64 @@
1#ifndef _ANALYSER_H_
2#define _ANALYSER_H_
3
4#include <QObject>
5#include <QVector>
6#include <QString>
7#include "backend.h"
8
9class Analyser : public QObject
10{
11 Q_OBJECT
12public:
13 Analyser(const soc_t& soc, IoBackend *backend);
14 virtual ~Analyser();
15 virtual QWidget *GetWidget() = 0;
16
17protected:
18 soc_t m_soc;
19 IoBackend *m_io_backend;
20};
21
22class AnalyserFactory
23{
24public:
25 AnalyserFactory(bool _register);
26 virtual ~AnalyserFactory();
27
28 virtual QString GetName() = 0;
29 virtual bool SupportSoc(const QString& soc_name) = 0;
30 // return NULL of soc is not handled by the analyser
31 virtual Analyser *Create(const soc_t& soc, IoBackend *backend) = 0;
32private:
33 QString m_name;
34
35public:
36 static QStringList GetAnalysersForSoc(const QString& soc_name);
37 static AnalyserFactory *GetAnalyserByName(const QString& name);
38 static void RegisterAnalyser(AnalyserFactory *factory);
39
40private:
41 static QVector< AnalyserFactory * > m_factories;
42};
43
44template< typename T >
45class TmplAnalyserFactory : public AnalyserFactory
46{
47public:
48 TmplAnalyserFactory(bool _register, const QString& name) :AnalyserFactory(_register) { m_name = name; }
49 virtual ~TmplAnalyserFactory() {}
50
51 virtual QString GetName() { return m_name; }
52 virtual bool SupportSoc(const QString& soc_name) { return T::SupportSoc(soc_name); }
53 // return NULL of soc is not handled by the analyser
54 virtual T *Create(const soc_t& soc, IoBackend *backend)
55 {
56 if(!T::SupportSoc(soc.name.c_str()))
57 return 0;
58 return new T(soc, backend);
59 }
60private:
61 QString m_name;
62};
63
64#endif /* _ANALYSER_H_ */
diff --git a/utils/regtools/qeditor/backend.cpp b/utils/regtools/qeditor/backend.cpp
new file mode 100644
index 0000000000..e011965bd2
--- /dev/null
+++ b/utils/regtools/qeditor/backend.cpp
@@ -0,0 +1,156 @@
1#include <QFile>
2#include <QTextStream>
3#include <QDebug>
4#include "backend.h"
5
6Backend::Backend()
7{
8}
9
10QStringList Backend::GetSocNameList()
11{
12 QStringList sl;
13 for(size_t i = 0; i < m_socs.size(); i++)
14 sl.append(QString(m_socs[i].name.c_str()));
15 return sl;
16}
17
18bool Backend::GetSocByName(const QString& name, soc_t& s)
19{
20 for(size_t i = 0; i < m_socs.size(); i++)
21 if(m_socs[i].name == name.toStdString())
22 {
23 s = m_socs[i];
24 return true;
25 }
26 return false;
27}
28
29bool Backend::LoadSocDesc(const QString& filename)
30{
31 bool ret = soc_desc_parse_xml(filename.toStdString(), m_socs);
32 emit OnSocListChanged();
33 return ret;
34}
35
36IoBackend *Backend::CreateFileIoBackend(const QString& filename)
37{
38 return new FileIoBackend(filename);
39}
40
41IoBackend *Backend::CreateDummyIoBackend()
42{
43 return new DummyIoBackend();
44}
45
46IoBackend::IoBackend()
47{
48}
49
50FileIoBackend::FileIoBackend(const QString& filename)
51{
52 m_filename = filename;
53 Reload();
54}
55
56QString FileIoBackend::GetSocName()
57{
58 return m_soc;
59}
60
61bool FileIoBackend::ReadRegister(const QString& name, soc_word_t& value)
62{
63 if(m_map.find(name) == m_map.end())
64 return false;
65 value = m_map[name];
66 return true;
67}
68
69bool FileIoBackend::Reload()
70{
71 QFile file(m_filename);
72 if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
73 return false;
74 m_map.clear();
75
76 QTextStream in(&file);
77 while(!in.atEnd())
78 {
79 QString line = in.readLine();
80 int idx = line.indexOf('=');
81 if(idx == -1)
82 continue;
83 QString key = line.left(idx).trimmed();
84 bool ok;
85 soc_word_t val = line.mid(idx + 1).trimmed().toULong(&ok, 0);
86 if(key == "HW")
87 m_soc = line.mid(idx + 1).trimmed();
88 else if(ok)
89 m_map[key] = val;
90 }
91 return true;
92}
93
94DummyIoBackend::DummyIoBackend()
95{
96}
97
98QString DummyIoBackend::GetSocName()
99{
100 return "";
101}
102
103bool DummyIoBackend::ReadRegister(const QString& name, soc_word_t& value)
104{
105 (void) name;
106 (void) value;
107 return false;
108}
109
110bool DummyIoBackend::Reload()
111{
112 return true;
113}
114
115BackendHelper::BackendHelper(IoBackend *io_backend, const soc_t& soc)
116 :m_io_backend(io_backend), m_soc(soc)
117{
118}
119
120bool BackendHelper::ReadRegister(const QString& dev, const QString& reg, soc_word_t& v)
121{
122 return m_io_backend->ReadRegister("HW." + dev + "." + reg, v);
123}
124
125bool BackendHelper::ReadRegisterField(const QString& dev, const QString& reg,
126 const QString& field, soc_word_t& v)
127{
128 soc_dev_t *sdev = 0;
129 for(size_t i = 0; i < m_soc.dev.size(); i++)
130 {
131 for(size_t j = 0; j < m_soc.dev[i].addr.size(); j++)
132 if(m_soc.dev[i].addr[j].name.c_str() == dev)
133 sdev = &m_soc.dev[i];
134 }
135 if(sdev == 0)
136 return false;
137 soc_reg_t *sreg = 0;
138 for(size_t i = 0; i < sdev->reg.size(); i++)
139 {
140 for(size_t j = 0; j < sdev->reg[i].addr.size(); j++)
141 if(sdev->reg[i].addr[j].name.c_str() == reg)
142 sreg = &sdev->reg[i];
143 }
144 if(sreg == 0)
145 return false;
146 soc_reg_field_t *sfield = 0;
147 for(size_t i = 0; i < sreg->field.size(); i++)
148 if(sreg->field[i].name.c_str() == field)
149 sfield = &sreg->field[i];
150 if(sfield == 0)
151 return false;
152 if(!ReadRegister(dev, reg, v))
153 return false;
154 v = (v & sfield->bitmask()) >> sfield->first_bit;
155 return true;
156} \ No newline at end of file
diff --git a/utils/regtools/qeditor/backend.h b/utils/regtools/qeditor/backend.h
new file mode 100644
index 0000000000..536eb8cec5
--- /dev/null
+++ b/utils/regtools/qeditor/backend.h
@@ -0,0 +1,77 @@
1#ifndef __BACKEND_H__
2#define __BACKEND_H__
3
4#include <QObject>
5#include <QStringList>
6#include <QMap>
7#include "soc_desc.hpp"
8
9class IoBackend : public QObject
10{
11 Q_OBJECT
12public:
13 IoBackend();
14
15 virtual QString GetSocName() = 0;
16 virtual bool ReadRegister(const QString& name, soc_word_t& value) = 0;
17 virtual bool Reload() = 0;
18};
19
20class DummyIoBackend : public IoBackend
21{
22 Q_OBJECT
23public:
24 DummyIoBackend();
25
26 virtual QString GetSocName();
27 virtual bool ReadRegister(const QString& name, soc_word_t& value);
28 virtual bool Reload();
29};
30
31class FileIoBackend : public IoBackend
32{
33 Q_OBJECT
34public:
35 FileIoBackend(const QString& filename);
36
37 virtual QString GetSocName();
38 virtual bool ReadRegister(const QString& name, soc_word_t& value);
39 virtual bool Reload();
40
41protected:
42 QString m_filename;
43 QString m_soc;
44 QMap< QString, soc_word_t > m_map;
45};
46
47class Backend : public QObject
48{
49 Q_OBJECT
50public:
51 Backend();
52
53 QStringList GetSocNameList();
54 bool LoadSocDesc(const QString& filename);
55 bool GetSocByName(const QString& name, soc_t& s);
56 IoBackend *CreateDummyIoBackend();
57 IoBackend *CreateFileIoBackend(const QString& filename);
58
59signals:
60 void OnSocListChanged();
61private:
62 std::vector< soc_t > m_socs;
63};
64
65class BackendHelper
66{
67public:
68 BackendHelper(IoBackend *io_backend, const soc_t& soc);
69 bool ReadRegister(const QString& dev, const QString& reg, soc_word_t& v);
70 bool ReadRegisterField(const QString& dev, const QString& reg,
71 const QString& field, soc_word_t& v);
72private:
73 IoBackend *m_io_backend;
74 soc_t m_soc;
75};
76
77#endif /* __BACKEND_H__ */
diff --git a/utils/regtools/qeditor/main.cpp b/utils/regtools/qeditor/main.cpp
new file mode 100644
index 0000000000..cc3ea16066
--- /dev/null
+++ b/utils/regtools/qeditor/main.cpp
@@ -0,0 +1,30 @@
1#include <QApplication>
2#include <QDir>
3#include "mainwindow.h"
4
5int main(int argc, char *argv[])
6{
7 QApplication app(argc, argv);
8
9 Backend *backend = new Backend;
10 QDir dir(QCoreApplication::applicationDirPath());
11 dir.cdUp();
12 dir.cd("desc");
13 dir.setFilter(QDir::Files);
14 printf("%s\n", dir.absolutePath().toStdString().c_str());
15 QFileInfoList list = dir.entryInfoList();
16 for(int i = 0; i < list.size(); i++)
17 {
18 QFileInfo fileInfo = list.at(i);
19 if(fileInfo.fileName().right(4) != ".xml" || fileInfo.fileName().left(5) != "regs-")
20 continue;
21 backend->LoadSocDesc(fileInfo.absoluteFilePath());
22 }
23
24 QCoreApplication::setOrganizationName("Rockbox");
25 QCoreApplication::setApplicationName("Register Editor");
26 QCoreApplication::setOrganizationDomain("rockbox.com");
27 MainWindow win(backend);
28 win.show();
29 return app.exec();
30}
diff --git a/utils/regtools/qeditor/mainwindow.cpp b/utils/regtools/qeditor/mainwindow.cpp
new file mode 100644
index 0000000000..1e39dd1a83
--- /dev/null
+++ b/utils/regtools/qeditor/mainwindow.cpp
@@ -0,0 +1,108 @@
1#include <QWidget>
2#include <QApplication>
3#include <QDesktopWidget>
4#include <QFileDialog>
5#include <QAction>
6#include <QMenu>
7#include <QMenuBar>
8#include <QMessageBox>
9#include <QTabBar>
10#include <QCloseEvent>
11#include <QDebug>
12
13#include "mainwindow.h"
14#include "regtab.h"
15
16MyTabWidget::MyTabWidget()
17{
18 setMovable(true);
19 setTabsClosable(true);
20 connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(OnCloseTab(int)));
21}
22
23void MyTabWidget::OnCloseTab(int index)
24{
25 removeTab(index);
26}
27
28MainWindow::MainWindow(Backend *backend)
29 :m_backend(backend)
30{
31 QAction *new_regtab_act = new QAction(QIcon::fromTheme("document-new"), tr("&Register Tab"), this);
32 QAction *load_desc_act = new QAction(QIcon::fromTheme("document-open"), tr("&Soc Description"), this);
33 QAction *quit_act = new QAction(QIcon::fromTheme("application-exit"), tr("&Quit"), this);
34 QAction *about_act = new QAction(QIcon::fromTheme("help-about"), tr("&About"), this);
35
36 connect(new_regtab_act, SIGNAL(triggered()), this, SLOT(OnNewRegTab()));
37 connect(load_desc_act, SIGNAL(triggered()), this, SLOT(OnLoadDesc()));
38 connect(quit_act, SIGNAL(triggered()), this, SLOT(OnQuit()));
39 connect(about_act, SIGNAL(triggered()), this, SLOT(OnAbout()));
40
41 QMenu *file_menu = menuBar()->addMenu(tr("&File"));
42 QMenu *new_submenu = file_menu->addMenu(QIcon::fromTheme("document-new"), "&New");
43 QMenu *load_submenu = file_menu->addMenu(QIcon::fromTheme("document-open"), "&Load");
44 file_menu->addAction(quit_act);
45
46 new_submenu->addAction(new_regtab_act);
47
48 load_submenu->addAction(load_desc_act);
49
50 QMenu *about_menu = menuBar()->addMenu(tr("&About"));
51 about_menu->addAction(about_act);
52
53 m_tab = new MyTabWidget();
54
55 setCentralWidget(m_tab);
56
57 ReadSettings();
58}
59
60void MainWindow::ReadSettings()
61{
62 restoreGeometry(Settings::Get()->value("mainwindow/geometry").toByteArray());
63}
64
65void MainWindow::WriteSettings()
66{
67 Settings::Get()->setValue("mainwindow/geometry", saveGeometry());
68}
69
70void MainWindow::OnQuit()
71{
72 WriteSettings();
73}
74
75void MainWindow::OnAbout()
76{
77}
78
79void MainWindow::closeEvent(QCloseEvent *event)
80{
81 WriteSettings();
82 event->accept();
83}
84
85void MainWindow::OnLoadDesc()
86{
87 QFileDialog *fd = new QFileDialog(this);
88 fd->setFilter("XML files (*.xml);;All files (*)");
89 fd->setFileMode(QFileDialog::ExistingFiles);
90 fd->setDirectory(Settings::Get()->value("mainwindow/loaddescdir", QDir::currentPath()).toString());
91 if(fd->exec())
92 {
93 QStringList filenames = fd->selectedFiles();
94 for(int i = 0; i < filenames.size(); i++)
95 if(!m_backend->LoadSocDesc(filenames[i]))
96 {
97 QMessageBox msg;
98 msg.setText(QString("Cannot load ") + filenames[i]);
99 msg.exec();
100 }
101 Settings::Get()->setValue("mainwindow/loaddescdir", fd->directory().absolutePath());
102 }
103}
104
105void MainWindow::OnNewRegTab()
106{
107 new RegTab(m_backend, m_tab);
108}
diff --git a/utils/regtools/qeditor/mainwindow.h b/utils/regtools/qeditor/mainwindow.h
new file mode 100644
index 0000000000..2897cde1ca
--- /dev/null
+++ b/utils/regtools/qeditor/mainwindow.h
@@ -0,0 +1,44 @@
1#ifndef MAINWINDOW_H
2#define MAINWINDOW_H
3
4#include <QMainWindow>
5#include <QTabWidget>
6#include <QSettings>
7#include "backend.h"
8#include "settings.h"
9
10class MyTabWidget : public QTabWidget
11{
12 Q_OBJECT
13public:
14 MyTabWidget();
15
16private slots:
17 void OnCloseTab(int index);
18};
19
20class MainWindow : public QMainWindow
21{
22 Q_OBJECT
23
24public:
25 MainWindow(Backend *backend);
26 void center();
27 void ReadSettings();
28 void WriteSettings();
29
30private:
31 void closeEvent(QCloseEvent *event);
32
33private slots:
34 void OnQuit();
35 void OnAbout();
36 void OnLoadDesc();
37 void OnNewRegTab();
38
39private:
40 QTabWidget *m_tab;
41 Backend *m_backend;
42};
43
44#endif
diff --git a/utils/regtools/qeditor/qeditor.pro b/utils/regtools/qeditor/qeditor.pro
new file mode 100644
index 0000000000..4e25a48d89
--- /dev/null
+++ b/utils/regtools/qeditor/qeditor.pro
@@ -0,0 +1,8 @@
1QT += widgets
2
3HEADERS += mainwindow.h backend.h regtab.h analyser.h settings.h std_analysers.h
4SOURCES += main.cpp mainwindow.cpp regtab.cpp backend.cpp analyser.cpp std_analysers.cpp settings.cpp
5LIBS += -L../lib/ -lsocdesc -lxml2
6INCLUDEPATH += ../lib/
7
8CONFIG += debug \ No newline at end of file
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}
diff --git a/utils/regtools/qeditor/regtab.h b/utils/regtools/qeditor/regtab.h
new file mode 100644
index 0000000000..7ec8c9009f
--- /dev/null
+++ b/utils/regtools/qeditor/regtab.h
@@ -0,0 +1,85 @@
1#ifndef REGTAB_H
2#define REGTAB_H
3
4#include <QComboBox>
5#include <QEvent>
6#include <QTreeWidget>
7#include <QVBoxLayout>
8#include <QTabWidget>
9#include <QSplitter>
10#include <QLineEdit>
11#include <QPushButton>
12#include <QLabel>
13#include <QListWidget>
14#include <soc_desc.hpp>
15#include "backend.h"
16#include "settings.h"
17
18enum
19{
20 RegTreeDevType = QTreeWidgetItem::UserType,
21 RegTreeRegType
22};
23
24enum
25{
26 DataSelNothing,
27 DataSelFile,
28};
29
30class RegTreeItem : public QTreeWidgetItem
31{
32public:
33 RegTreeItem(const QString& string, int type);
34
35 void SetPath(int dev_idx, int dev_addr_idx, int reg_idx = -1, int reg_addr_idx = -1);
36 int GetDevIndex() const { return m_dev_idx; }
37 int GetDevAddrIndex() const { return m_dev_addr_idx; }
38 int GetRegIndex() const { return m_reg_idx; }
39 int GetRegAddrIndex() const { return m_reg_addr_idx; }
40private:
41 int m_dev_idx, m_dev_addr_idx, m_reg_idx, m_reg_addr_idx;
42};
43
44class RegTab : public QObject
45{
46 Q_OBJECT
47public:
48 RegTab(Backend *backend, QTabWidget *parent);
49
50protected:
51 void FillDevSubTree(RegTreeItem *item);
52 void FillRegTree();
53 void FillAnalyserList();
54 void UpdateSocList();
55 void DisplayRegister(soc_dev_t& dev, soc_dev_addr_t& dev_addr,
56 soc_reg_t& reg, soc_reg_addr_t& reg_addr);
57 void SetDataSocName(const QString& socname);
58 QComboBox *m_soc_selector;
59 Backend *m_backend;
60 QTreeWidget *m_reg_tree;
61 soc_t m_cur_soc;
62 QVBoxLayout *m_right_panel;
63 QWidget *m_right_content;
64 QSplitter *m_splitter;
65 QLineEdit *m_data_sel_edit;
66 QLabel *m_data_soc_label;
67 QPushButton *m_data_sel_reload;
68 QComboBox *m_data_selector;
69 IoBackend *m_io_backend;
70 QTabWidget *m_type_selector;
71 QListWidget *m_analysers_list;
72
73private slots:
74 void OnSocChanged(const QString& text);
75 void OnSocListChanged();
76 void OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
77 void OnRegItemClicked(QTreeWidgetItem *clicked, int col);
78 void OnDataSelChanged(int index);
79 void OnDataChanged();
80 void OnDataSocActivated(const QString&);
81 void OnAnalyserChanged(QListWidgetItem *current, QListWidgetItem *previous);
82 void OnAnalyserClicked(QListWidgetItem *clicked);
83};
84
85#endif /* REGTAB_H */ \ No newline at end of file
diff --git a/utils/regtools/qeditor/settings.cpp b/utils/regtools/qeditor/settings.cpp
new file mode 100644
index 0000000000..d72a15f74f
--- /dev/null
+++ b/utils/regtools/qeditor/settings.cpp
@@ -0,0 +1,32 @@
1#include <QCoreApplication>
2#include <QDebug>
3#include "settings.h"
4
5Settings::Settings()
6{
7
8}
9
10Settings::~Settings()
11{
12 if(m_settings)
13 delete m_settings;
14}
15
16QSettings *Settings::GetSettings()
17{
18 if(!m_settings)
19 {
20 QDir dir(QCoreApplication::applicationDirPath());
21 QString filename = dir.filePath(QCoreApplication::organizationDomain() + ".ini");
22 m_settings = new QSettings(filename, QSettings::IniFormat);
23 }
24 return m_settings;
25}
26
27QSettings *Settings::Get()
28{
29 return g_settings.GetSettings();
30}
31
32Settings Settings::g_settings; \ No newline at end of file
diff --git a/utils/regtools/qeditor/settings.h b/utils/regtools/qeditor/settings.h
new file mode 100644
index 0000000000..0776ec3b89
--- /dev/null
+++ b/utils/regtools/qeditor/settings.h
@@ -0,0 +1,21 @@
1#ifndef _SETTINGS_H_
2#define _SETTINGS_H_
3
4#include <QSettings>
5#include <QString>
6#include <QDir>
7
8class Settings
9{
10public:
11 Settings();
12 ~Settings();
13
14 QSettings *GetSettings();
15 static QSettings *Get();
16private:
17 QSettings *m_settings;
18 static Settings g_settings;
19};
20
21#endif /* _SETTINGS_H_ */ \ No newline at end of file
diff --git a/utils/regtools/qeditor/std_analysers.cpp b/utils/regtools/qeditor/std_analysers.cpp
new file mode 100644
index 0000000000..49df671146
--- /dev/null
+++ b/utils/regtools/qeditor/std_analysers.cpp
@@ -0,0 +1,636 @@
1#include "std_analysers.h"
2
3/**
4 * Clock analyser
5 */
6
7ClockAnalyser::ClockAnalyser(const soc_t& soc, IoBackend *backend)
8 :Analyser(soc, backend)
9{
10 m_group = new QGroupBox("Clock Analyser");
11 QVBoxLayout *layout = new QVBoxLayout;
12 m_group->setLayout(layout);
13 m_tree_widget = new QTreeWidget;
14 layout->addWidget(m_tree_widget);
15
16 m_tree_widget->setColumnCount(2);
17 QStringList list;
18 list << "Name" << "Frequency";
19 m_tree_widget->setHeaderLabels(list);
20
21 FillTree();
22}
23
24ClockAnalyser::~ClockAnalyser()
25{
26}
27
28QWidget *ClockAnalyser::GetWidget()
29{
30 return m_group;
31}
32
33bool ClockAnalyser::SupportSoc(const QString& soc_name)
34{
35 return soc_name == "imx233";
36}
37
38QString ClockAnalyser::GetFreq(unsigned freq)
39{
40 if(freq >= 1000000)
41 {
42 if((freq % 1000000) == 0)
43 return QString().sprintf("%d MHz", freq / 1000000);
44 else
45 return QString().sprintf("%.3f MHz", freq / 1000000.0);
46 }
47 if(freq >= 1000)
48 {
49 if((freq % 1000) == 0)
50 return QString().sprintf("%d KHz", freq / 1000);
51 else
52 return QString().sprintf("%.3f KHz", freq / 1000.0);
53 }
54 return QString().sprintf("%d Hz", freq);
55}
56
57QTreeWidgetItem *ClockAnalyser::AddClock(QTreeWidgetItem *parent, const QString& name, int freq, int mul, int div)
58{
59 if(freq == FROM_PARENT)
60 {
61 int64_t f = GetClockFreq(parent);
62 f *= mul;
63 f /= div;
64 freq = f;
65 }
66 QTreeWidgetItem *item = new QTreeWidgetItem(parent, QStringList() << name
67 << (freq == INVALID ? "<invalid>" : freq == 0 ? "<disabled>" : GetFreq(freq)));
68 item->setData(1, Qt::UserRole, freq);
69 if(freq == DISABLED || freq == INVALID || (parent && parent->isDisabled()))
70 item->setDisabled(true);
71 if(!parent)
72 m_tree_widget->addTopLevelItem(item);
73 return item;
74}
75
76int ClockAnalyser::GetClockFreq(QTreeWidgetItem *item)
77{
78 return item->data(1, Qt::UserRole).toInt();
79}
80
81void ClockAnalyser::FillTree()
82{
83 m_tree_widget->clear();
84 BackendHelper helper(m_io_backend, m_soc);
85 soc_word_t value, value2, value3;
86
87 QTreeWidgetItem *ring_osc = 0;
88 if(helper.ReadRegisterField("POWER", "MINPWR", "ENABLE_OSC", value))
89 ring_osc = AddClock(0, "ring_clk24m", value ? 24000000 : DISABLED);
90 else
91 ring_osc = AddClock(0, "ring_clk24m", INVALID);
92 QTreeWidgetItem *xtal_osc = 0;
93 if(helper.ReadRegisterField("POWER", "MINPWR", "PWD_XTAL24", value))
94 xtal_osc = AddClock(0, "xtal_clk24m", value ? DISABLED : 24000000);
95 else
96 xtal_osc = AddClock(0, "xtal_clk24m", INVALID);
97 QTreeWidgetItem *ref_xtal = 0;
98 if(helper.ReadRegisterField("POWER", "MINPWR", "SELECT_OSC", value))
99 ref_xtal = AddClock(value ? ring_osc : xtal_osc, "ref_xtal", FROM_PARENT);
100 else
101 ref_xtal = AddClock(0, "ref_xtal", INVALID);
102
103 QTreeWidgetItem *ref_pll = 0;
104 if(helper.ReadRegisterField("CLKCTRL", "PLLCTRL0", "POWER", value))
105 ref_pll = AddClock(ref_xtal, "ref_pll", FROM_PARENT, 20);
106 else
107 ref_pll = AddClock(0, "ref_pll", INVALID);
108
109 QTreeWidgetItem *ref_io = 0;
110 if(helper.ReadRegisterField("CLKCTRL", "FRAC", "CLKGATEIO", value) &&
111 helper.ReadRegisterField("CLKCTRL", "FRAC", "IOFRAC", value2))
112 ref_io = AddClock(ref_pll, "ref_io", value ? DISABLED : FROM_PARENT, 18, value2);
113 else
114 ref_io = AddClock(ref_pll, "ref_io", INVALID);
115
116 QTreeWidgetItem *ref_pix = 0;
117 if(helper.ReadRegisterField("CLKCTRL", "FRAC", "CLKGATEPIX", value) &&
118 helper.ReadRegisterField("CLKCTRL", "FRAC", "PIXFRAC", value2))
119 ref_pix = AddClock(ref_pll, "ref_pix", value ? DISABLED : FROM_PARENT, 18, value2);
120 else
121 ref_pix = AddClock(ref_pll, "ref_pix", INVALID);
122
123 QTreeWidgetItem *ref_emi = 0;
124 if(helper.ReadRegisterField("CLKCTRL", "FRAC", "CLKGATEEMI", value) &&
125 helper.ReadRegisterField("CLKCTRL", "FRAC", "EMIFRAC", value2))
126 ref_emi = AddClock(ref_pll, "ref_emi", value ? DISABLED : FROM_PARENT, 18, value2);
127 else
128 ref_emi = AddClock(ref_pll, "ref_emi", INVALID);
129
130 QTreeWidgetItem *ref_cpu = 0;
131 if(helper.ReadRegisterField("CLKCTRL", "FRAC", "CLKGATECPU", value) &&
132 helper.ReadRegisterField("CLKCTRL", "FRAC", "CPUFRAC", value2))
133 ref_cpu = AddClock(ref_pll, "ref_cpu", value ? DISABLED : FROM_PARENT, 18, value2);
134 else
135 ref_cpu = AddClock(ref_pll, "ref_cpu", INVALID);
136
137 QTreeWidgetItem *clk_p = 0;
138 if(helper.ReadRegisterField("CLKCTRL", "CLKSEQ", "BYPASS_CPU", value))
139 {
140 if(!value)
141 {
142 if(helper.ReadRegisterField("CLKCTRL", "CPU", "DIV_CPU", value2))
143 clk_p = AddClock(ref_cpu, "clk_p", FROM_PARENT, 1, value2);
144 else
145 clk_p = AddClock(ref_cpu, "clk_p", INVALID);
146 }
147 else
148 {
149 if(helper.ReadRegisterField("CLKCTRL", "CPU", "DIV_XTAL_FRAC_EN", value) &&
150 helper.ReadRegisterField("CLKCTRL", "CPU", "DIV_XTAL", value2))
151 clk_p = AddClock(ref_xtal, "clk_p", FROM_PARENT, value ? 1024 : 1, value2);
152 else
153 clk_p = AddClock(ref_xtal, "clk_p", INVALID);
154 }
155 }
156 else
157 clk_p = AddClock(ref_xtal, "clk_p", INVALID);
158
159 QTreeWidgetItem *clk_h = 0;
160 if(helper.ReadRegisterField("CLKCTRL", "HBUS", "DIV_FRAC_EN", value) &&
161 helper.ReadRegisterField("CLKCTRL", "HBUS", "DIV", value2))
162 clk_h = AddClock(clk_p, "clk_h", FROM_PARENT, value ? 32 : 1, value2);
163 else
164 clk_h = AddClock(clk_p, "clk_h", INVALID);
165
166 QTreeWidgetItem *clk_x = 0;
167 if(helper.ReadRegisterField("CLKCTRL", "XBUS", "DIV", value))
168 clk_x = AddClock(ref_xtal, "clk_x", FROM_PARENT, 1, value);
169 else
170 clk_x = AddClock(ref_xtal, "clk_x", INVALID);
171
172 if(helper.ReadRegisterField("CLKCTRL", "XTAL", "UART_CLK_GATE", value))
173 AddClock(ref_xtal, "clk_uart", value ? DISABLED : FROM_PARENT);
174 else
175 AddClock(ref_xtal, "clk_uart", INVALID);
176
177 if(helper.ReadRegisterField("CLKCTRL", "XTAL", "FILT_CLK24M_GATE", value))
178 AddClock(ref_xtal, "clk_filt24m", value ? DISABLED : FROM_PARENT);
179 else
180 AddClock(ref_xtal, "clk_filt24m", INVALID);
181
182 if(helper.ReadRegisterField("CLKCTRL", "XTAL", "PWM_CLK24M_GATE", value))
183 AddClock(ref_xtal, "clk_pwm24m", value ? DISABLED : FROM_PARENT);
184 else
185 AddClock(ref_xtal, "clk_pwm24m", INVALID);
186
187 if(helper.ReadRegisterField("CLKCTRL", "XTAL", "DRI_CLK24M_GATE", value))
188 AddClock(ref_xtal, "clk_dri24m", value ? DISABLED : FROM_PARENT);
189 else
190 AddClock(ref_xtal, "clk_dri24m", INVALID);
191
192 if(helper.ReadRegisterField("CLKCTRL", "XTAL", "DIGCTRL_CLK1M_GATE", value))
193 AddClock(ref_xtal, "clk_1m", value ? DISABLED : FROM_PARENT, 1, 24);
194 else
195 AddClock(ref_xtal, "clk_1m", INVALID);
196
197 QTreeWidgetItem *clk_32k = 0;
198 if(helper.ReadRegisterField("CLKCTRL", "XTAL", "TIMROT_CLK32K_GATE", value))
199 clk_32k = AddClock(ref_xtal, "clk_32k", value ? DISABLED : FROM_PARENT, 1, 750);
200 else
201 clk_32k = AddClock(ref_xtal, "clk_32k", INVALID);
202
203 AddClock(clk_32k, "clk_adc", FROM_PARENT, 1, 16);
204
205 if(helper.ReadRegisterField("CLKCTRL", "CLKSEQ", "BYPASS_PIX", value) &&
206 helper.ReadRegisterField("CLKCTRL", "PIX", "DIV", value2))
207 AddClock(value ? ref_xtal : ref_pix, "clk_pix", FROM_PARENT, 1, value2);
208 else
209 AddClock(ref_xtal, "clk_p", INVALID);
210
211 QTreeWidgetItem *clk_ssp = 0;
212 if(helper.ReadRegisterField("CLKCTRL", "CLKSEQ", "BYPASS_SSP", value) &&
213 helper.ReadRegisterField("CLKCTRL", "SSP", "DIV", value2) &&
214 helper.ReadRegisterField("CLKCTRL", "SSP", "CLKGATE", value3))
215 clk_ssp = AddClock(value ? ref_xtal : ref_io, "clk_ssp", value3 ? DISABLED : FROM_PARENT, 1, value2);
216 else
217 clk_ssp = AddClock(ref_xtal, "clk_p", INVALID);
218
219 if(helper.ReadRegisterField("SSP1", "TIMING", "CLOCK_DIVIDE", value) &&
220 helper.ReadRegisterField("SSP1", "TIMING", "CLOCK_RATE", value2) &&
221 helper.ReadRegisterField("SSP1", "CTRL0", "CLKGATE", value3))
222 AddClock(clk_ssp, "clk_ssp1", value3 ? DISABLED : FROM_PARENT, 1, value * (1 + value2));
223 else
224 AddClock(clk_ssp, "clk_ssp1", INVALID);
225
226 if(helper.ReadRegisterField("SSP2", "TIMING", "CLOCK_DIVIDE", value) &&
227 helper.ReadRegisterField("SSP2", "TIMING", "CLOCK_RATE", value2) &&
228 helper.ReadRegisterField("SSP2", "CTRL0", "CLKGATE", value3))
229 AddClock(clk_ssp, "clk_ssp2", value3 ? DISABLED : FROM_PARENT, 1, value * (1 + value2));
230 else
231 AddClock(clk_ssp, "clk_ssp2", INVALID);
232
233 QTreeWidgetItem *clk_gpmi = 0;
234 if(helper.ReadRegisterField("CLKCTRL", "CLKSEQ", "BYPASS_GPMI", value) &&
235 helper.ReadRegisterField("CLKCTRL", "GPMI", "DIV", value2) &&
236 helper.ReadRegisterField("CLKCTRL", "GPMI", "CLKGATE", value3))
237 clk_gpmi = AddClock(value ? ref_xtal : ref_io, "clk_gpmi", value3 ? DISABLED : FROM_PARENT, 1, value2);
238 else
239 clk_gpmi = AddClock(ref_xtal, "clk_p", INVALID);
240
241 if(helper.ReadRegisterField("CLKCTRL", "CLKSEQ", "BYPASS_EMI", value))
242 {
243 if(!value)
244 {
245 if(helper.ReadRegisterField("CLKCTRL", "EMI", "DIV_EMI", value2) &&
246 helper.ReadRegisterField("CLKCTRL", "EMI", "CLKGATE", value3))
247 AddClock(ref_emi, "clk_emi", value3 ? DISABLED : FROM_PARENT, 1, value2);
248 else
249 AddClock(ref_emi, "clk_emi", INVALID);
250 }
251 else
252 {
253 if(helper.ReadRegisterField("CLKCTRL", "EMI", "DIV_XTAL", value2) &&
254 helper.ReadRegisterField("CLKCTRL", "EMI", "CLKGATE", value3))
255 AddClock(ref_xtal, "clk_emi", value3 ? DISABLED : FROM_PARENT, 1, value2);
256 else
257 AddClock(ref_xtal, "clk_emi", INVALID);
258 }
259 }
260 else
261 clk_p = AddClock(ref_xtal, "clk_emi", INVALID);
262
263 QTreeWidgetItem *ref_vid = AddClock(ref_pll, "clk_vid", FROM_PARENT);
264
265 if(helper.ReadRegisterField("CLKCTRL", "TV", "CLK_TV108M_GATE", value) &&
266 helper.ReadRegisterField("CLKCTRL", "TV", "CLK_TV_GATE", value2))
267 {
268 QTreeWidgetItem *clk_tv108m = AddClock(ref_vid, "clk_tv108m", value ? DISABLED : FROM_PARENT, 1, 4);
269 AddClock(clk_tv108m, "clk_tv54m", value2 ? DISABLED : FROM_PARENT, 1, 2);
270 AddClock(clk_tv108m, "clk_tv27m", value2 ? DISABLED : FROM_PARENT, 1, 4);
271 }
272
273 if(helper.ReadRegisterField("CLKCTRL", "PLLCTRL0", "EN_USB_CLKS", value))
274 AddClock(ref_pll, "utmi_clk480m", value ? FROM_PARENT : DISABLED);
275 else
276 AddClock(ref_pll, "utmi_clk480m", INVALID);
277
278 QTreeWidgetItem *xtal_clk32k = 0;
279 if(helper.ReadRegisterField("RTC", "PERSISTENT0", "XTAL32_FREQ", value) &&
280 helper.ReadRegisterField("RTC", "PERSISTENT0", "XTAL32KHZ_PWRUP", value2))
281 xtal_clk32k = AddClock(0, "xtal_clk32k", value2 == 0 ? DISABLED : value ? 32000 : 32768);
282 else
283 xtal_clk32k = AddClock(0, "xtal_clk32k", INVALID);
284
285 if(helper.ReadRegisterField("RTC", "PERSISTENT0", "CLOCKSOURCE", value))
286 AddClock(value ? xtal_clk32k : ref_xtal, "clk_rtc32k", FROM_PARENT, 1, value ? 1 : 768);
287 else
288 AddClock(ref_xtal, "clk_rtc32k", INVALID);
289
290 (void) clk_x;
291 (void) clk_gpmi;
292 (void) clk_h;
293
294 m_tree_widget->expandAll();
295 m_tree_widget->resizeColumnToContents(0);
296}
297
298static TmplAnalyserFactory< ClockAnalyser > g_clock_factory(true, "Clock Analyser");
299
300/**
301 * EMI analyser
302 */
303EmiAnalyser::EmiAnalyser(const soc_t& soc, IoBackend *backend)
304 :Analyser(soc, backend)
305{
306 m_group = new QGroupBox("EMI Analyser");
307 QVBoxLayout *layout = new QVBoxLayout;
308 m_group->setLayout(layout);
309 m_panel = new QToolBox;
310 m_display_selector = new QComboBox;
311 m_display_selector->addItem("Cycles", DisplayCycles);
312 m_display_selector->addItem("Raw Hexadecimal", DisplayRawHex);
313 m_display_selector->addItem("Time", DisplayTime);
314 QHBoxLayout *line_layout = new QHBoxLayout;
315 line_layout->addWidget(new QLabel("Display Mode:"));
316 line_layout->addWidget(m_display_selector);
317 m_emi_freq_label = new QLineEdit;
318 m_emi_freq_label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
319 m_emi_freq_label->setReadOnly(true);
320 line_layout->addStretch();
321 line_layout->addWidget(new QLabel("Frequency:"));
322 line_layout->addWidget(m_emi_freq_label);
323 line_layout->addWidget(new QLabel("MHz"));
324 line_layout->addStretch();
325 layout->addLayout(line_layout);
326 layout->addWidget(m_panel);
327
328 connect(m_display_selector, SIGNAL(currentIndexChanged(int)), this,
329 SLOT(OnChangeDisplayMode(int)));
330
331 FillTable();
332}
333
334EmiAnalyser::~EmiAnalyser()
335{
336}
337
338QWidget *EmiAnalyser::GetWidget()
339{
340 return m_group;
341}
342
343bool EmiAnalyser::SupportSoc(const QString& soc_name)
344{
345 return soc_name == "imx233";
346}
347
348void EmiAnalyser::OnChangeDisplayMode(int index)
349{
350 m_display_mode = (DisplayMode)m_display_selector->itemData(index).toInt();
351 int idx = m_panel->currentIndex();
352 FillTable();
353 m_panel->setCurrentIndex(idx);
354}
355
356void EmiAnalyser::NewGroup(const QString& name)
357{
358 QTableWidget *table = new QTableWidget;
359 table->setColumnCount(3);
360 table->setHorizontalHeaderItem(0, new QTableWidgetItem("Name"));
361 table->setHorizontalHeaderItem(1, new QTableWidgetItem("Value"));
362 table->setHorizontalHeaderItem(2, new QTableWidgetItem("Comment"));
363 table->verticalHeader()->setVisible(false);
364 table->horizontalHeader()->setStretchLastSection(true);
365 m_panel->addItem(table, name);
366}
367
368void EmiAnalyser::AddLine(const QString& name, int value, const QString& unit, const QString& comment)
369{
370 QTableWidget *table = dynamic_cast< QTableWidget* >(m_panel->widget(m_panel->count() - 1));
371 int row = table->rowCount();
372 table->setRowCount(row + 1);
373 table->setItem(row, 0, new QTableWidgetItem(name));
374 QString val;
375 if(value == INVALID)
376 val = "<invalid>";
377 else if(value == NONE)
378 val = unit;
379 else if(m_display_mode == DisplayRawHex && unit.size() == 0)
380 val = QString("0x%1").arg(value, 0, 16);
381 else
382 val = QString("%1%2").arg(value).arg(unit);
383 table->setItem(row, 1, new QTableWidgetItem(val));
384 table->item(row, 1)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
385 table->setItem(row, 2, new QTableWidgetItem(comment));
386 table->resizeColumnToContents(0);
387 table->resizeColumnToContents(1);
388}
389
390void EmiAnalyser::AddCycleLine(const QString& name, unsigned raw_val, float val,
391 int digits, const QString& comment)
392{
393 if(m_display_mode == DisplayCycles)
394 {
395 QString str;
396 if(digits == 0)
397 str = QString("%1").arg((int)val);
398 else
399 str = QString("%1").arg(val, 0, 'f', digits);
400 str += " cycles";
401 AddLine(name, NONE, str, comment);
402 }
403 else if(m_display_mode == DisplayRawHex)
404 {
405 QString str = QString("0x%1").arg(raw_val, 0, 16);
406 AddLine(name, NONE, str, comment);
407 }
408 else if(m_display_mode == DisplayTime && m_emi_freq != 0)
409 {
410 float cycle_time_ns = 1000000000.0 / m_emi_freq;
411 val *= cycle_time_ns;
412 QString str;
413 if(val >= 1000)
414 str = QString::fromWCharArray(L"%1 µs").arg(val / 1000.0, 0, 'f', 2);
415 else
416 str = QString("%1 ns").arg(val, 0, 'f', 2);
417 AddLine(name, NONE, str, comment);
418 }
419 else
420 AddLine(name, raw_val, " cycles", comment);
421}
422
423void EmiAnalyser::FillTable()
424{
425 while(m_panel->count() > 0)
426 m_panel->removeItem(0);
427 BackendHelper helper(m_io_backend, m_soc);
428 soc_word_t value;
429
430 m_emi_freq = 0;
431 if(helper.ReadRegisterField("CLKCTRL", "CLKSEQ", "BYPASS_EMI", value))
432 {
433 bool ret;
434 if(value)
435 {
436 m_emi_freq = 24000000;
437 ret = helper.ReadRegisterField("CLKCTRL", "EMI", "DIV_XTAL", value);
438 }
439 else
440 {
441 m_emi_freq = 480000000;
442 if(helper.ReadRegisterField("CLKCTRL", "FRAC", "EMIFRAC", value))
443 m_emi_freq = 18 * (int64_t)m_emi_freq / value;
444 else
445 m_emi_freq = 0;
446 ret = helper.ReadRegisterField("CLKCTRL", "EMI", "DIV_EMI", value);
447 }
448 if(ret)
449 m_emi_freq /= value;
450 else
451 m_emi_freq = 0;
452 }
453
454 m_emi_freq_label->setText(QString().sprintf("%.3f", m_emi_freq / 1000000.0));
455
456 NewGroup("Control Parameters");
457 if(helper.ReadRegisterField("EMI", "CTRL", "PORT_PRIORITY_ORDER", value))
458 {
459 QStringList ports;
460 ports << "AXI0" << "AHB1" << "AHB2" << "AHB3";
461 QString order;
462 order += ports[value / 6];
463 ports.erase(ports.begin() + value / 6);
464 int ord[6][3] = { {0, 1, 2}, {2, 0, 1}, {1, 2, 0}, {2, 1, 0}, {1, 0, 2}, {0, 2, 1} };
465 for(int i = 0; i < 3; i++)
466 order += ", " + ports[ord[value][i]];
467 AddLine("Port Priority Order", value, "", order);
468 }
469
470 if(helper.ReadRegisterField("EMI", "CTRL", "MEM_WIDTH", value))
471 AddLine("Memory Width", value ? 16 : 8, "-bit");
472
473 if(helper.ReadRegisterField("DRAM", "CTL03", "AP", value))
474 AddLine("Auto Pre-Charge", NONE, value ? "Yes" : "No");
475
476 bool bypass_mode = false;
477 if(helper.ReadRegisterField("DRAM", "CTL04", "DLL_BYPASS_MODE", value))
478 {
479 bypass_mode = value == 1;
480 AddLine("DLL Bypass Mode", NONE, value ? "Yes" : "No");
481 }
482
483 if(helper.ReadRegisterField("DRAM", "CTL05", "EN_LOWPOWER_MODE", value))
484 AddLine("Low Power Mode", NONE, value ? "Enabled" : "Disabled");
485
486 if(helper.ReadRegisterField("DRAM", "CTL08", "SREFRESH", value))
487 AddLine("Self Refresh", NONE, value ? "Yes" : "No");
488
489 if(helper.ReadRegisterField("DRAM", "CTL08", "SDR_MODE", value))
490 AddLine("Mode", NONE, value ? "SDR" : "DDR");
491
492 if(helper.ReadRegisterField("DRAM", "CTL10", "ADDR_PINS", value))
493 AddLine("Address Pins", 13 - value, "");
494
495 if(helper.ReadRegisterField("DRAM", "CTL11", "ADDR_PINS", value))
496 AddLine("Column Size", 12 - value, "-bit");
497
498 if(helper.ReadRegisterField("DRAM", "CTL11", "ADDR_PINS", value))
499 AddLine("Encoded CAS", value, "Memory device dependent");
500
501 if(helper.ReadRegisterField("DRAM", "CTL14", "CS_MAP", value))
502 {
503 QString v;
504 for(int i = 0; i < 4; i++)
505 if(value & (1 << i))
506 {
507 if(v.size() != 0)
508 v += " ";
509 v += QString("%1").arg(i);
510 }
511 AddLine("Chip Select Pins", NONE, v, "");
512 }
513
514 if(helper.ReadRegisterField("DRAM", "CTL37", "TREF_ENABLE", value))
515 AddLine("Refresh Commands", NONE, value ? "Enabled" : "Disabled", "Issue self-refresh every TREF cycles");
516
517 NewGroup("Frequency Parameters");
518
519 if(helper.ReadRegisterField("DRAM", "CTL13", "CASLAT_LIN_GATE", value))
520 {
521 if(value >= 3 && value <= 10 && value != 9)
522 {
523 float v = (value / 2) + 0.5 * (value % 2);
524 AddCycleLine("CAS Gate", value, v, 1, "");
525 }
526 else
527 AddLine("CAS Gate", NONE, "Reserved", "Reserved value");
528 }
529 if(helper.ReadRegisterField("DRAM", "CTL13", "CASLAT_LIN", value))
530 {
531 if(value >= 3 && value <= 10 && value != 9)
532 {
533 float v = (value / 2) + 0.5 * (value % 2);
534 AddCycleLine("CAS Latency", value, v, 1, "");
535 }
536 else
537 AddLine("CAS Latency", NONE, "Reserved", "Reserved value");
538 }
539
540 if(helper.ReadRegisterField("DRAM", "CTL12", "TCKE", value))
541 AddCycleLine("tCKE", value, value, 0, "Minimum CKE pulse width");
542
543 if(helper.ReadRegisterField("DRAM", "CTL15", "TDAL", value))
544 AddCycleLine("tDAL", value, value, 0, "Auto pre-charge write recovery time");
545
546 if(helper.ReadRegisterField("DRAM", "CTL31", "TDLL", value))
547 AddCycleLine("tDLL", value, value, 0, "DLL lock time");
548
549 if(helper.ReadRegisterField("DRAM", "CTL10", "TEMRS", value))
550 AddCycleLine("tEMRS", value, value, 0, "Extended mode parameter set time");
551
552 if(helper.ReadRegisterField("DRAM", "CTL34", "TINIT", value))
553 AddCycleLine("tINIT", value, value, 0, "Initialisation time");
554
555 if(helper.ReadRegisterField("DRAM", "CTL16", "TMRD", value))
556 AddCycleLine("tMRD", value, value, 0, "Mode register set command time");
557
558 if(helper.ReadRegisterField("DRAM", "CTL40", "TPDEX", value))
559 AddCycleLine("tPDEX", value, value, 0, "Power down exit time");
560
561 if(helper.ReadRegisterField("DRAM", "CTL32", "TRAS_MAX", value))
562 AddCycleLine("tRAS Max", value, value, 0, "Maximum row activate time");
563
564 if(helper.ReadRegisterField("DRAM", "CTL20", "TRAS_MIN", value))
565 AddCycleLine("tRAS Min", value, value, 0, "Minimum row activate time");
566
567 if(helper.ReadRegisterField("DRAM", "CTL17", "TRC", value))
568 AddCycleLine("tRC", value, value, 0, "Activate to activate delay (same bank)");
569
570 if(helper.ReadRegisterField("DRAM", "CTL20", "TRCD_INT", value))
571 AddCycleLine("tRCD", value, value, 0, "RAS to CAS");
572
573 if(helper.ReadRegisterField("DRAM", "CTL26", "TREF", value))
574 AddCycleLine("tREF", value, value, 0, "Refresh to refresh time");
575
576 if(helper.ReadRegisterField("DRAM", "CTL21", "TRFC", value))
577 AddCycleLine("tRFC", value, value, 0, "Refresh command time");
578
579 if(helper.ReadRegisterField("DRAM", "CTL15", "TRP", value))
580 AddCycleLine("tRP", value, value, 0, "Pre-charge command time");
581
582 if(helper.ReadRegisterField("DRAM", "CTL12", "TRRD", value))
583 AddCycleLine("tRRD", value, value, 0, "Activate to activate delay (different banks)");
584
585 if(helper.ReadRegisterField("DRAM", "CTL12", "TWR_INT", value))
586 AddCycleLine("tWR", value, value, 0, "Write recovery time");
587
588 if(helper.ReadRegisterField("DRAM", "CTL13", "TWTR", value))
589 AddCycleLine("tWTR", value, value, 0, "Write to read delay");
590
591 if(helper.ReadRegisterField("DRAM", "CTL32", "TXSNR", value))
592 AddCycleLine("tXSNR", value, value, 0, "");
593
594 if(helper.ReadRegisterField("DRAM", "CTL33", "TXSR", value))
595 AddCycleLine("tXSR", value, value, 0, "Self-refresh exit time");
596
597 NewGroup("DLL Parameters");
598
599 if(bypass_mode)
600 {
601 if(helper.ReadRegisterField("DRAM", "CTL19", "DLL_DQS_DELAY_0_BYPASS", value))
602 AddLine("DLL DQS Delay 0", value, "", "In 1/128 fraction of a cycle (bypass mode)");
603
604 if(helper.ReadRegisterField("DRAM", "CTL19", "DLL_DQS_DELAY_1_BYPASS", value))
605 AddLine("DLL DQS Delay 1", value, "", "In 1/128 fraction of a cycle (bypass mode)");
606
607 if(helper.ReadRegisterField("DRAM", "CTL19", "DQS_OUT_SHIFT_BYPASS", value))
608 AddLine("DQS Out Delay", value, "", "(bypass mode)");
609
610 if(helper.ReadRegisterField("DRAM", "CTL20", "WR_DQS_SHIFT_BYPASS", value))
611 AddLine("DQS Write Delay", value, "", "(bypass mode)");
612 }
613 else
614 {
615 if(helper.ReadRegisterField("DRAM", "CTL17", "DLL_START_POINT", value))
616 AddLine("DLL Start Point", value, "", "Initial delay count");
617
618 if(helper.ReadRegisterField("DRAM", "CTL17", "DLL_INCREMENT", value))
619 AddLine("DLL Increment", value, "", "Delay increment");
620
621 if(helper.ReadRegisterField("DRAM", "CTL18", "DLL_DQS_DELAY_0", value))
622 AddLine("DLL DQS Delay 0", value, "", "In 1/128 fraction of a cycle");
623
624 if(helper.ReadRegisterField("DRAM", "CTL18", "DLL_DQS_DELAY_1", value))
625 AddLine("DLL DQS Delay 1", value, "", "In 1/128 fraction of a cycle");
626
627 if(helper.ReadRegisterField("DRAM", "CTL19", "DQS_OUT_SHIFT", value))
628 AddLine("DQS Out Delay", value, "", "");
629
630 if(helper.ReadRegisterField("DRAM", "CTL20", "WR_DQS_SHIFT", value))
631 AddLine("DQS Write Delay", value, "", "");
632 }
633
634}
635
636static TmplAnalyserFactory< EmiAnalyser > g_emi_factory(true, "EMI Analyser"); \ No newline at end of file
diff --git a/utils/regtools/qeditor/std_analysers.h b/utils/regtools/qeditor/std_analysers.h
new file mode 100644
index 0000000000..98c5fa0f98
--- /dev/null
+++ b/utils/regtools/qeditor/std_analysers.h
@@ -0,0 +1,95 @@
1#ifndef _STDANALYSER_H_
2#define _STDANALYSER_H_
3
4#include "analyser.h"
5
6#include <QGroupBox>
7#include <QTreeWidget>
8#include <QVBoxLayout>
9#include <QHBoxLayout>
10#include <QTableWidget>
11#include <QHeaderView>
12#include <QToolBox>
13#include <QComboBox>
14#include <QLabel>
15#include <QLineEdit>
16#include "analyser.h"
17#include "collapsiblepanel.h"
18
19/**
20 * Clock analyser
21 */
22
23class ClockAnalyser : public Analyser
24{
25 Q_OBJECT
26public:
27 ClockAnalyser(const soc_t& soc, IoBackend *backend);
28 virtual ~ClockAnalyser();
29 virtual QWidget *GetWidget();
30 static bool SupportSoc(const QString& soc_name);
31
32private:
33 QString GetFreq(unsigned freq);
34
35 enum
36 {
37 DISABLED = 0,
38 INVALID = -1,
39 FROM_PARENT = -2,
40 };
41
42 QTreeWidgetItem *AddClock(QTreeWidgetItem *parent, const QString& name, int freq, int mul = 1, int div = 1);
43 int GetClockFreq(QTreeWidgetItem *item);
44 void FillTree();
45
46private:
47 QGroupBox *m_group;
48 QTreeWidget *m_tree_widget;
49};
50
51/**
52 * EMI analyser
53 */
54class EmiAnalyser : public Analyser
55{
56 Q_OBJECT
57public:
58 EmiAnalyser(const soc_t& soc, IoBackend *backend);
59 virtual ~EmiAnalyser();
60 virtual QWidget *GetWidget();
61
62 static bool SupportSoc(const QString& soc_name);
63
64private slots:
65 void OnChangeDisplayMode(int index);
66
67private:
68 enum DisplayMode
69 {
70 DisplayCycles,
71 DisplayRawHex,
72 DisplayTime,
73 };
74
75 enum
76 {
77 NONE = -999999,
78 INVALID = -1000000
79 };
80
81 void NewGroup(const QString& name);
82 void AddLine(const QString& name, int value, const QString& unit, const QString& comment = "");
83 void AddCycleLine(const QString& name, unsigned raw_val, float val, int digits, const QString& comment = "");
84 void FillTable();
85
86private:
87 QGroupBox *m_group;
88 QComboBox *m_display_selector;
89 QToolBox *m_panel;
90 DisplayMode m_display_mode;
91 unsigned m_emi_freq;
92 QLineEdit *m_emi_freq_label;
93};
94
95#endif /* _STDANALYSER_H_ */