diff options
Diffstat (limited to 'utils/regtools')
-rw-r--r-- | utils/regtools/qeditor/analyser.cpp | 44 | ||||
-rw-r--r-- | utils/regtools/qeditor/analyser.h | 64 | ||||
-rw-r--r-- | utils/regtools/qeditor/backend.cpp | 156 | ||||
-rw-r--r-- | utils/regtools/qeditor/backend.h | 77 | ||||
-rw-r--r-- | utils/regtools/qeditor/main.cpp | 30 | ||||
-rw-r--r-- | utils/regtools/qeditor/mainwindow.cpp | 108 | ||||
-rw-r--r-- | utils/regtools/qeditor/mainwindow.h | 44 | ||||
-rw-r--r-- | utils/regtools/qeditor/qeditor.pro | 8 | ||||
-rw-r--r-- | utils/regtools/qeditor/regtab.cpp | 392 | ||||
-rw-r--r-- | utils/regtools/qeditor/regtab.h | 85 | ||||
-rw-r--r-- | utils/regtools/qeditor/settings.cpp | 32 | ||||
-rw-r--r-- | utils/regtools/qeditor/settings.h | 21 | ||||
-rw-r--r-- | utils/regtools/qeditor/std_analysers.cpp | 636 | ||||
-rw-r--r-- | utils/regtools/qeditor/std_analysers.h | 95 |
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 | |||
3 | Analyser::Analyser(const soc_t& soc, IoBackend *backend) | ||
4 | :m_soc(soc), m_io_backend(backend) | ||
5 | { | ||
6 | } | ||
7 | |||
8 | Analyser::~Analyser() | ||
9 | { | ||
10 | } | ||
11 | |||
12 | AnalyserFactory::AnalyserFactory(bool _register) | ||
13 | { | ||
14 | if(_register) | ||
15 | RegisterAnalyser(this); | ||
16 | } | ||
17 | |||
18 | AnalyserFactory::~AnalyserFactory() | ||
19 | { | ||
20 | } | ||
21 | |||
22 | QVector< AnalyserFactory * > AnalyserFactory::m_factories; | ||
23 | |||
24 | QStringList 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 | |||
33 | AnalyserFactory *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 | |||
41 | void 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 | |||
9 | class Analyser : public QObject | ||
10 | { | ||
11 | Q_OBJECT | ||
12 | public: | ||
13 | Analyser(const soc_t& soc, IoBackend *backend); | ||
14 | virtual ~Analyser(); | ||
15 | virtual QWidget *GetWidget() = 0; | ||
16 | |||
17 | protected: | ||
18 | soc_t m_soc; | ||
19 | IoBackend *m_io_backend; | ||
20 | }; | ||
21 | |||
22 | class AnalyserFactory | ||
23 | { | ||
24 | public: | ||
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; | ||
32 | private: | ||
33 | QString m_name; | ||
34 | |||
35 | public: | ||
36 | static QStringList GetAnalysersForSoc(const QString& soc_name); | ||
37 | static AnalyserFactory *GetAnalyserByName(const QString& name); | ||
38 | static void RegisterAnalyser(AnalyserFactory *factory); | ||
39 | |||
40 | private: | ||
41 | static QVector< AnalyserFactory * > m_factories; | ||
42 | }; | ||
43 | |||
44 | template< typename T > | ||
45 | class TmplAnalyserFactory : public AnalyserFactory | ||
46 | { | ||
47 | public: | ||
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 | } | ||
60 | private: | ||
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 | |||
6 | Backend::Backend() | ||
7 | { | ||
8 | } | ||
9 | |||
10 | QStringList 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 | |||
18 | bool 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 | |||
29 | bool 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 | |||
36 | IoBackend *Backend::CreateFileIoBackend(const QString& filename) | ||
37 | { | ||
38 | return new FileIoBackend(filename); | ||
39 | } | ||
40 | |||
41 | IoBackend *Backend::CreateDummyIoBackend() | ||
42 | { | ||
43 | return new DummyIoBackend(); | ||
44 | } | ||
45 | |||
46 | IoBackend::IoBackend() | ||
47 | { | ||
48 | } | ||
49 | |||
50 | FileIoBackend::FileIoBackend(const QString& filename) | ||
51 | { | ||
52 | m_filename = filename; | ||
53 | Reload(); | ||
54 | } | ||
55 | |||
56 | QString FileIoBackend::GetSocName() | ||
57 | { | ||
58 | return m_soc; | ||
59 | } | ||
60 | |||
61 | bool 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 | |||
69 | bool 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 | |||
94 | DummyIoBackend::DummyIoBackend() | ||
95 | { | ||
96 | } | ||
97 | |||
98 | QString DummyIoBackend::GetSocName() | ||
99 | { | ||
100 | return ""; | ||
101 | } | ||
102 | |||
103 | bool DummyIoBackend::ReadRegister(const QString& name, soc_word_t& value) | ||
104 | { | ||
105 | (void) name; | ||
106 | (void) value; | ||
107 | return false; | ||
108 | } | ||
109 | |||
110 | bool DummyIoBackend::Reload() | ||
111 | { | ||
112 | return true; | ||
113 | } | ||
114 | |||
115 | BackendHelper::BackendHelper(IoBackend *io_backend, const soc_t& soc) | ||
116 | :m_io_backend(io_backend), m_soc(soc) | ||
117 | { | ||
118 | } | ||
119 | |||
120 | bool 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 | |||
125 | bool 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 | |||
9 | class IoBackend : public QObject | ||
10 | { | ||
11 | Q_OBJECT | ||
12 | public: | ||
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 | |||
20 | class DummyIoBackend : public IoBackend | ||
21 | { | ||
22 | Q_OBJECT | ||
23 | public: | ||
24 | DummyIoBackend(); | ||
25 | |||
26 | virtual QString GetSocName(); | ||
27 | virtual bool ReadRegister(const QString& name, soc_word_t& value); | ||
28 | virtual bool Reload(); | ||
29 | }; | ||
30 | |||
31 | class FileIoBackend : public IoBackend | ||
32 | { | ||
33 | Q_OBJECT | ||
34 | public: | ||
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 | |||
41 | protected: | ||
42 | QString m_filename; | ||
43 | QString m_soc; | ||
44 | QMap< QString, soc_word_t > m_map; | ||
45 | }; | ||
46 | |||
47 | class Backend : public QObject | ||
48 | { | ||
49 | Q_OBJECT | ||
50 | public: | ||
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 | |||
59 | signals: | ||
60 | void OnSocListChanged(); | ||
61 | private: | ||
62 | std::vector< soc_t > m_socs; | ||
63 | }; | ||
64 | |||
65 | class BackendHelper | ||
66 | { | ||
67 | public: | ||
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); | ||
72 | private: | ||
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 | |||
5 | int 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 | |||
16 | MyTabWidget::MyTabWidget() | ||
17 | { | ||
18 | setMovable(true); | ||
19 | setTabsClosable(true); | ||
20 | connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(OnCloseTab(int))); | ||
21 | } | ||
22 | |||
23 | void MyTabWidget::OnCloseTab(int index) | ||
24 | { | ||
25 | removeTab(index); | ||
26 | } | ||
27 | |||
28 | MainWindow::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 | |||
60 | void MainWindow::ReadSettings() | ||
61 | { | ||
62 | restoreGeometry(Settings::Get()->value("mainwindow/geometry").toByteArray()); | ||
63 | } | ||
64 | |||
65 | void MainWindow::WriteSettings() | ||
66 | { | ||
67 | Settings::Get()->setValue("mainwindow/geometry", saveGeometry()); | ||
68 | } | ||
69 | |||
70 | void MainWindow::OnQuit() | ||
71 | { | ||
72 | WriteSettings(); | ||
73 | } | ||
74 | |||
75 | void MainWindow::OnAbout() | ||
76 | { | ||
77 | } | ||
78 | |||
79 | void MainWindow::closeEvent(QCloseEvent *event) | ||
80 | { | ||
81 | WriteSettings(); | ||
82 | event->accept(); | ||
83 | } | ||
84 | |||
85 | void 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 | |||
105 | void 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 | |||
10 | class MyTabWidget : public QTabWidget | ||
11 | { | ||
12 | Q_OBJECT | ||
13 | public: | ||
14 | MyTabWidget(); | ||
15 | |||
16 | private slots: | ||
17 | void OnCloseTab(int index); | ||
18 | }; | ||
19 | |||
20 | class MainWindow : public QMainWindow | ||
21 | { | ||
22 | Q_OBJECT | ||
23 | |||
24 | public: | ||
25 | MainWindow(Backend *backend); | ||
26 | void center(); | ||
27 | void ReadSettings(); | ||
28 | void WriteSettings(); | ||
29 | |||
30 | private: | ||
31 | void closeEvent(QCloseEvent *event); | ||
32 | |||
33 | private slots: | ||
34 | void OnQuit(); | ||
35 | void OnAbout(); | ||
36 | void OnLoadDesc(); | ||
37 | void OnNewRegTab(); | ||
38 | |||
39 | private: | ||
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 @@ | |||
1 | QT += widgets | ||
2 | |||
3 | HEADERS += mainwindow.h backend.h regtab.h analyser.h settings.h std_analysers.h | ||
4 | SOURCES += main.cpp mainwindow.cpp regtab.cpp backend.cpp analyser.cpp std_analysers.cpp settings.cpp | ||
5 | LIBS += -L../lib/ -lsocdesc -lxml2 | ||
6 | INCLUDEPATH += ../lib/ | ||
7 | |||
8 | CONFIG += 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 | |||
19 | RegTreeItem::RegTreeItem(const QString& string, int type) | ||
20 | :QTreeWidgetItem(QStringList(string), type) | ||
21 | { | ||
22 | } | ||
23 | |||
24 | void 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 | |||
32 | RegTab::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 | |||
113 | void 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 | |||
128 | void 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 | |||
135 | void 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 | |||
165 | void RegTab::OnDataChanged() | ||
166 | { | ||
167 | OnRegItemChanged(m_reg_tree->currentItem(), m_reg_tree->currentItem()); | ||
168 | } | ||
169 | |||
170 | void RegTab::OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) | ||
171 | { | ||
172 | (void) previous; | ||
173 | OnRegItemClicked(current, 0); | ||
174 | } | ||
175 | |||
176 | void 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 | |||
192 | void RegTab::OnAnalyserChanged(QListWidgetItem *current, QListWidgetItem *previous) | ||
193 | { | ||
194 | (void) previous; | ||
195 | OnAnalyserClicked(current); | ||
196 | } | ||
197 | |||
198 | void 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 | |||
208 | void 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 | |||
341 | void 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 | |||
349 | void 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 | |||
364 | void 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 | |||
379 | void RegTab::FillAnalyserList() | ||
380 | { | ||
381 | m_analysers_list->clear(); | ||
382 | m_analysers_list->addItems(AnalyserFactory::GetAnalysersForSoc(m_cur_soc.name.c_str())); | ||
383 | } | ||
384 | |||
385 | void 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 | |||
18 | enum | ||
19 | { | ||
20 | RegTreeDevType = QTreeWidgetItem::UserType, | ||
21 | RegTreeRegType | ||
22 | }; | ||
23 | |||
24 | enum | ||
25 | { | ||
26 | DataSelNothing, | ||
27 | DataSelFile, | ||
28 | }; | ||
29 | |||
30 | class RegTreeItem : public QTreeWidgetItem | ||
31 | { | ||
32 | public: | ||
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; } | ||
40 | private: | ||
41 | int m_dev_idx, m_dev_addr_idx, m_reg_idx, m_reg_addr_idx; | ||
42 | }; | ||
43 | |||
44 | class RegTab : public QObject | ||
45 | { | ||
46 | Q_OBJECT | ||
47 | public: | ||
48 | RegTab(Backend *backend, QTabWidget *parent); | ||
49 | |||
50 | protected: | ||
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 | |||
73 | private 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 | |||
5 | Settings::Settings() | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
10 | Settings::~Settings() | ||
11 | { | ||
12 | if(m_settings) | ||
13 | delete m_settings; | ||
14 | } | ||
15 | |||
16 | QSettings *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 | |||
27 | QSettings *Settings::Get() | ||
28 | { | ||
29 | return g_settings.GetSettings(); | ||
30 | } | ||
31 | |||
32 | Settings 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 | |||
8 | class Settings | ||
9 | { | ||
10 | public: | ||
11 | Settings(); | ||
12 | ~Settings(); | ||
13 | |||
14 | QSettings *GetSettings(); | ||
15 | static QSettings *Get(); | ||
16 | private: | ||
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 | |||
7 | ClockAnalyser::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 | |||
24 | ClockAnalyser::~ClockAnalyser() | ||
25 | { | ||
26 | } | ||
27 | |||
28 | QWidget *ClockAnalyser::GetWidget() | ||
29 | { | ||
30 | return m_group; | ||
31 | } | ||
32 | |||
33 | bool ClockAnalyser::SupportSoc(const QString& soc_name) | ||
34 | { | ||
35 | return soc_name == "imx233"; | ||
36 | } | ||
37 | |||
38 | QString 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 | |||
57 | QTreeWidgetItem *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 | |||
76 | int ClockAnalyser::GetClockFreq(QTreeWidgetItem *item) | ||
77 | { | ||
78 | return item->data(1, Qt::UserRole).toInt(); | ||
79 | } | ||
80 | |||
81 | void 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 | |||
298 | static TmplAnalyserFactory< ClockAnalyser > g_clock_factory(true, "Clock Analyser"); | ||
299 | |||
300 | /** | ||
301 | * EMI analyser | ||
302 | */ | ||
303 | EmiAnalyser::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 | |||
334 | EmiAnalyser::~EmiAnalyser() | ||
335 | { | ||
336 | } | ||
337 | |||
338 | QWidget *EmiAnalyser::GetWidget() | ||
339 | { | ||
340 | return m_group; | ||
341 | } | ||
342 | |||
343 | bool EmiAnalyser::SupportSoc(const QString& soc_name) | ||
344 | { | ||
345 | return soc_name == "imx233"; | ||
346 | } | ||
347 | |||
348 | void 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 | |||
356 | void 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 | |||
368 | void 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 | |||
390 | void 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 | |||
423 | void 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 | |||
636 | static 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 | |||
23 | class ClockAnalyser : public Analyser | ||
24 | { | ||
25 | Q_OBJECT | ||
26 | public: | ||
27 | ClockAnalyser(const soc_t& soc, IoBackend *backend); | ||
28 | virtual ~ClockAnalyser(); | ||
29 | virtual QWidget *GetWidget(); | ||
30 | static bool SupportSoc(const QString& soc_name); | ||
31 | |||
32 | private: | ||
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 | |||
46 | private: | ||
47 | QGroupBox *m_group; | ||
48 | QTreeWidget *m_tree_widget; | ||
49 | }; | ||
50 | |||
51 | /** | ||
52 | * EMI analyser | ||
53 | */ | ||
54 | class EmiAnalyser : public Analyser | ||
55 | { | ||
56 | Q_OBJECT | ||
57 | public: | ||
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 | |||
64 | private slots: | ||
65 | void OnChangeDisplayMode(int index); | ||
66 | |||
67 | private: | ||
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 | |||
86 | private: | ||
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_ */ | ||