OpenCores
URL https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [gui_plugin/] [CpuWidgets/] [AsmArea.cpp] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 sergeykhbr
/**
2
 * @file
3
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
5
 * @brief      Disassembler viewer area.
6
 */
7
 
8
#include "AsmArea.h"
9
#include "moc_AsmArea.h"
10
 
11
#include <memory>
12
#include <string.h>
13
#include <QtWidgets/QBoxLayout>
14
#include <QtWidgets/QLabel>
15
#include <QtWidgets/QHeaderView>
16
#include <QtWidgets/QScrollBar>
17
 
18
namespace debugger {
19
 
20
static const uint64_t MAX_BYTES_VIEW = 1 << 12; // 4096
21
 
22
AsmArea::AsmArea(IGui *gui, QWidget *parent, uint64_t fixaddr)
23
    : QTableWidget(parent) {
24
    igui_ = gui;
25
    cmdRegs_.make_string("reg npc");
26
    cmdReadMem_.make_string("disas 0 0");
27
    hideLineIdx_ = 0;
28
    selRowIdx = -1;
29
    fixaddr_ = fixaddr;
30
    waitRegNpc_ = false;
31
 
32
    clear();
33
    QFont font("Courier");
34
    font.setStyleHint(QFont::Monospace);
35
    font.setPointSize(8);
36
    font.setFixedPitch(true);
37
    setFont(font);
38
    setContentsMargins(QMargins(0, 0, 0, 0));
39
    QFontMetrics fm(font);
40
    setMinimumWidth(50 + fm.width(tr(
41
    "   :0011223344556677  11223344 1: addw    r0,r1,0xaabbccdd  ; commment")));
42
    lineHeight_ = fm.height() + 4;
43
    visibleLinesTotal_ = 0;
44
    if (isNpcTrackEna()) {
45
        startAddr_ = 0;
46
        endAddr_ = 0;
47
    } else {
48
        startAddr_ = fixaddr_;
49
        endAddr_ = fixaddr_;  // will be computed in resize() method
50
    }
51
 
52
    setColumnCount(COL_Total);
53
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
54
    setRowCount(1);
55
    asmLines_.make_list(0);
56
    asmLinesOut_.make_list(0);
57
    npc_ = ~0;
58
 
59
    verticalHeader()->setVisible(false);        // remove row indexes
60
    setShowGrid(false);                         // remove borders
61
    setSelectionMode(QAbstractItemView::SingleSelection);
62
    setSelectionBehavior(QAbstractItemView::SelectRows); //select full row
63
 
64
    // change selected row color
65
    QPalette *palette = new QPalette();
66
    palette->setColor(QPalette::Highlight, Qt::gray);
67
    setPalette(*palette);
68
    Qt::ItemFlags fl;
69
    for (int i = 0; i < rowCount(); i++) {
70
        for (int n = 0; n < COL_Total; n++) {
71
            setItem(i, n, new QTableWidgetItem());
72
            fl = item(i, n)->flags();
73
            fl &= ~Qt::ItemIsEditable;
74
            fl &= ~Qt::ItemIsSelectable;
75
            item(i, n)->setFlags(fl);
76
        }
77
        setRowHeight(i, lineHeight_);
78
        item(i, 0)->setBackgroundColor(Qt::lightGray);
79
        item(i, 0)->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
80
    }
81
 
82
    setHorizontalHeaderLabels(
83
        QString("addr/line;code;label;mnemonic;comment").split(";"));
84
    setColumnWidth(0, 10 + fm.width(tr("   :0011223344556677")));
85
    setColumnWidth(1, 10 + fm.width(tr("00112233")));
86
    setColumnWidth(2, 10 + fm.width(tr("0")));
87
    setColumnWidth(3, 10 + fm.width(tr("addw    r1,r2,0x112233445566")));
88
    setColumnWidth(4, 10 + fm.width(tr("some very long long comment+offset")));
89
 
90
    connect(this, SIGNAL(signalNpcChanged()),
91
            this, SLOT(slotNpcChanged()));
92
    connect(this, SIGNAL(signalAsmListChanged()),
93
            this, SLOT(slotAsmListChanged()));
94
    connect(this, SIGNAL(cellDoubleClicked(int, int)),
95
            this, SLOT(slotCellDoubleClicked(int, int)));
96
 
97
    RISCV_mutex_init(&mutexAsmGaurd_);
98
}
99
 
100
AsmArea::~AsmArea() {
101
    igui_->removeFromQueue(static_cast<IGuiCmdHandler *>(this));
102
    RISCV_mutex_destroy(&mutexAsmGaurd_);
103
}
104
 
105
void AsmArea::resizeEvent(QResizeEvent *ev) {
106
    int h = ev->size().height();
107
    if (h < 4 * lineHeight_) {
108
        h = 4 * lineHeight_;
109
    }
110
    visibleLinesTotal_ = h / lineHeight_ + 2;
111
 
112
    if (isNpcTrackEna() && npc_ == ~0ull) {
113
        return;
114
    }
115
 
116
    int line_cnt = static_cast<int>(asmLinesOut_.size());
117
    if (visibleLinesTotal_ > line_cnt) {
118
        char tstr[256];
119
        RISCV_sprintf(tstr, sizeof(tstr), "disas 0x%" RV_PRI64 "x %d",
120
                    endAddr_,
121
                    4*(visibleLinesTotal_ - line_cnt));
122
        cmdReadMem_.make_string(tstr);
123
        igui_->registerCommand(static_cast<IGuiCmdHandler *>(this),
124
                                &cmdReadMem_, true);
125
    }
126
 
127
    QWidget::resizeEvent(ev);
128
}
129
 
130
void AsmArea::wheelEvent(QWheelEvent * ev) {
131
    int dlt = ev->delta();
132
    int scroll_pos = verticalScrollBar()->value();
133
    int scroll_min = verticalScrollBar()->minimum();
134
    int scroll_max = verticalScrollBar()->maximum();
135
    if (dlt >= 0 && scroll_pos > scroll_min) {
136
        verticalScrollBar()->setValue(--scroll_pos);
137
    } else if (dlt < 0 && scroll_pos < scroll_max) {
138
        verticalScrollBar()->setValue(++scroll_pos);
139
    } else {
140
        char tstr[128];
141
        unsigned sz = 4 * static_cast<unsigned>(visibleLinesTotal_ / 2);
142
        if (dlt >= 0) {
143
            RISCV_sprintf(tstr, sizeof(tstr), "disas 0x%" RV_PRI64 "x %d",
144
                        startAddr_ - sz, sz);
145
        } else {
146
            RISCV_sprintf(tstr, sizeof(tstr), "disas 0x%" RV_PRI64 "x %d",
147
                        endAddr_, sz);
148
        }
149
        cmdReadMem_.make_string(tstr);
150
        igui_->registerCommand(static_cast<IGuiCmdHandler *>(this),
151
                                &cmdReadMem_, true);
152
    }
153
    QWidget::wheelEvent(ev);
154
}
155
 
156
void AsmArea::slotUpdateByTimer() {
157
    if (waitRegNpc_) {
158
        return;
159
    }
160
    waitRegNpc_ = true;
161
    igui_->registerCommand(static_cast<IGuiCmdHandler *>(this),
162
                            &cmdRegs_, true);
163
}
164
 
165
void AsmArea::handleResponse(AttributeType *req, AttributeType *resp) {
166
    if (req->is_equal("reg npc")) {
167
        waitRegNpc_ = false;
168
        if (!resp->is_nil()) {
169
            npc_ = resp->to_uint64();
170
            emit signalNpcChanged();
171
        }
172
    } else if (strstr(req->to_string(), "br ")) {
173
        emit signalBreakpointsChanged();
174
    } else if (strstr(req->to_string(), "disas") && !resp->is_nil()) {
175
        addMemBlock(*resp, asmLines_);
176
        emit signalAsmListChanged();
177
    }
178
}
179
 
180
bool AsmArea::isNpcTrackEna() {
181
    return (fixaddr_ == ~0ull);
182
}
183
 
184
void AsmArea::slotNpcChanged() {
185
    int npc_row = getNpcRowIdx();
186
    if (npc_row != -1) {
187
        selectNpcRow(npc_row);
188
        return;
189
    }
190
    if (!isNpcTrackEna()) {
191
        return;
192
    }
193
 
194
    char tstr[256];
195
    RISCV_sprintf(tstr, sizeof(tstr), "disas 0x%" RV_PRI64 "x %d",
196
                npc_, 4*visibleLinesTotal_);
197
    cmdReadMem_.make_string(tstr);
198
    igui_->registerCommand(static_cast<IGuiCmdHandler *>(this),
199
                            &cmdReadMem_, true);
200
}
201
 
202
void AsmArea::slotAsmListChanged() {
203
    RISCV_mutex_lock(&mutexAsmGaurd_);
204
    asmLinesOut_ = asmLines_;
205
    RISCV_mutex_unlock(&mutexAsmGaurd_);
206
 
207
    adjustRowCount();
208
    clearSpans();
209
 
210
    if (asmLinesOut_.size() == 0) {
211
        return;
212
    }
213
 
214
    bool reinit_start = true;
215
    for (unsigned i = 0; i < asmLinesOut_.size(); i++) {
216
        AttributeType &asmLine = asmLinesOut_[i];
217
        if (!asmLine.is_list()) {
218
            continue;
219
        }
220
        switch (asmLine[ASM_list_type].to_uint32()) {
221
        case AsmList_symbol:
222
            outSymbolLine(static_cast<int>(i), asmLine);
223
            break;
224
        case AsmList_disasm:
225
            endAddr_ = asmLine[ASM_addrline].to_uint64();
226
            if (reinit_start) {
227
                reinit_start = false;
228
                startAddr_ = endAddr_;
229
            }
230
            endAddr_ += asmLine[ASM_codesize].to_uint64();
231
            outAsmLine(static_cast<int>(i), asmLine);
232
            break;
233
        default:;
234
        }
235
    }
236
}
237
 
238
void AsmArea::slotRedrawDisasm() {
239
    char tstr[256];
240
    uint64_t sz = endAddr_ - startAddr_;
241
    if (sz == 0) {
242
        return;
243
    }
244
    if (sz > MAX_BYTES_VIEW) {
245
        sz = MAX_BYTES_VIEW;
246
    }
247
    RISCV_sprintf(tstr, sizeof(tstr), "disas 0x%" RV_PRI64 "x %d",
248
                startAddr_, sz);
249
    cmdReadMem_.make_string(tstr);
250
    igui_->registerCommand(static_cast<IGuiCmdHandler *>(this),
251
                            &cmdReadMem_, true);
252
}
253
 
254
void AsmArea::slotCellDoubleClicked(int row, int column) {
255
    if (row >= static_cast<int>(asmLinesOut_.size())) {
256
        return;
257
    }
258
    AttributeType &asmLine = asmLinesOut_[row];
259
    if (!asmLine.is_list()
260
        || asmLine[ASM_list_type].to_uint32() != AsmList_disasm) {
261
        return;
262
    }
263
    char tstr[128];
264
    bool is_breakpoint = asmLine[ASM_breakpoint].to_bool();
265
    uint64_t addr = asmLine[ASM_addrline].to_uint64();
266
 
267
    if (is_breakpoint) {
268
        RISCV_sprintf(tstr, sizeof(tstr), "br rm 0x%" RV_PRI64 "x", addr);
269
    } else {
270
        RISCV_sprintf(tstr, sizeof(tstr), "br add 0x%" RV_PRI64 "x", addr);
271
    }
272
    AttributeType brcmd(tstr);
273
    igui_->registerCommand(static_cast<IGuiCmdHandler *>(this), &brcmd, true);
274
}
275
 
276
int AsmArea::getNpcRowIdx() {
277
    for (unsigned i = 0; i < asmLinesOut_.size(); i++) {
278
        AttributeType &asmLine = asmLinesOut_[i];
279
        if (!asmLine.is_list()) {
280
            continue;
281
        }
282
        if (asmLine[ASM_list_type].to_uint32() != AsmList_disasm) {
283
            continue;
284
        }
285
        if (npc_ == asmLine[ASM_addrline].to_uint64()) {
286
            return static_cast<int>(i);
287
        }
288
    }
289
    return -1;
290
}
291
 
292
void AsmArea::selectNpcRow(int idx) {
293
    QTableWidgetItem *p;
294
    if (selRowIdx != -1 && selRowIdx != idx) {
295
        p = item(selRowIdx, 0);
296
        p->setFlags(p->flags() & ~Qt::ItemIsSelectable);
297
    }
298
    selRowIdx = idx;
299
    p = item(selRowIdx, 0);
300
    p->setFlags(p->flags() | Qt::ItemIsSelectable);
301
    selectRow(selRowIdx);
302
}
303
 
304
void AsmArea::adjustRowCount() {
305
    int asm_cnt = static_cast<int>(asmLinesOut_.size());
306
    int row_cnt = rowCount();
307
    if (row_cnt < asm_cnt) {
308
        Qt::ItemFlags fl;
309
        setRowCount(asm_cnt);
310
        for (int i = row_cnt; i < asm_cnt; i++) {
311
            for (int n = 0; n < COL_Total; n++) {
312
                setItem(i, n, new QTableWidgetItem());
313
                fl = item(i, n)->flags();
314
                fl &= ~Qt::ItemIsEditable;
315
                fl &= ~Qt::ItemIsSelectable;
316
                item(i, n)->setFlags(fl);
317
            }
318
            setRowHeight(i, lineHeight_);
319
            item(i, 0)->setBackgroundColor(Qt::lightGray);
320
            item(i, 0)->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
321
        }
322
    }
323
    if (hideLineIdx_ < asm_cnt) {
324
        for (int i = hideLineIdx_; i < asm_cnt; i++) {
325
            showRow(i);
326
        }
327
    }
328
    hideLineIdx_ = asm_cnt;
329
    for (int i = hideLineIdx_; i < rowCount(); i++) {
330
        hideRow(i);
331
    }
332
}
333
 
334
void AsmArea::outSymbolLine(int idx, AttributeType &line) {
335
    QTableWidgetItem *pw;
336
    uint64_t addr = line[ASM_addrline].to_uint64();
337
    setSpan(idx, COL_label, 1, 3);
338
 
339
    pw = item(idx, COL_addrline);
340
    pw->setText(QString("<%1>").arg(addr, 16, 16, QChar('0')));
341
    pw->setTextColor(QColor(Qt::darkBlue));
342
 
343
    pw = item(idx, COL_code);
344
    pw->setBackgroundColor(Qt::lightGray);
345
    pw->setText(tr(""));
346
 
347
    pw = item(idx, COL_label);
348
    pw->setText(QString(line[ASM_code].to_string()));
349
    pw->setTextColor(QColor(Qt::darkBlue));
350
 
351
    item(idx, COL_mnemonic)->setText(tr(""));
352
    item(idx, COL_comment)->setText(tr(""));
353
}
354
 
355
void AsmArea::outAsmLine(int idx, AttributeType &line) {
356
    QTableWidgetItem *pw;
357
    uint64_t addr = line[ASM_addrline].to_uint64();
358
    if (addr == npc_) {
359
        selectNpcRow(idx);
360
    }
361
 
362
    pw = item(idx, COL_addrline);
363
    pw->setText(QString("%1").arg(addr, 16, 16, QChar('0')));
364
    pw->setTextColor(QColor(Qt::black));
365
    pw->setBackgroundColor(Qt::lightGray);
366
 
367
    pw = item(idx, COL_code);
368
    uint32_t instr = line[ASM_code].to_uint32();
369
    if (line[ASM_breakpoint].to_bool()) {
370
        pw->setBackgroundColor(Qt::red);
371
        pw->setTextColor(Qt::white);
372
    } else if (pw->backgroundColor() != Qt::lightGray) {
373
        pw->setBackgroundColor(Qt::lightGray);
374
        pw->setTextColor(Qt::black);
375
    }
376 4 sergeykhbr
    int codesz = line[ASM_codesize].to_int();
377
    pw->setText(QString("%1").arg(instr, 2*codesz, 16, QChar('0')));
378 3 sergeykhbr
 
379
    pw = item(idx, COL_label);
380
    pw->setTextColor(Qt::black);
381
    pw->setText(QString(line[ASM_label].to_string()));
382
 
383
    pw = item(idx, COL_mnemonic);
384
    pw->setText(QString(line[ASM_mnemonic].to_string()));
385
 
386
    pw = item(idx, COL_comment);
387
    pw->setText(QString(line[ASM_comment].to_string()));
388
}
389
 
390
void AsmArea::addMemBlock(AttributeType &resp,
391
                          AttributeType &lines) {
392
    uint64_t asm_addr_start = 0;
393
    uint64_t asm_addr_end = 0;
394
    if (!resp.is_list() || !resp.size()) {
395
        return;
396
    }
397
    if (!resp[0u].is_list() || !resp[resp.size() - 1].is_list()) {
398
        return;
399
    }
400
    if (lines.size()) {
401
        asm_addr_start = lines[0u][ASM_addrline].to_uint64();
402
        asm_addr_end = lines[lines.size() - 1][ASM_addrline].to_uint64();
403
    }
404
    uint64_t resp_addr_start = resp[0u][ASM_addrline].to_uint64();
405
    uint64_t resp_addr_next = resp[resp.size() - 1][ASM_addrline].to_uint64();
406
    resp_addr_next += resp[resp.size() - 1][ASM_codesize].to_uint64();
407
 
408
    RISCV_mutex_lock(&mutexAsmGaurd_);
409
    if (resp_addr_next == asm_addr_start) {
410
        // Joint lines at the beginning of current list:
411
        for (unsigned i = 0; i < resp.size(); i++) {
412
            lines.insert_to_list(i, &resp[i]);
413
        }
414
    } else if (resp_addr_start >= asm_addr_start
415
            && resp_addr_start <= asm_addr_end) {
416
        // Modify lines values:
417
        unsigned resp_idx = 0;
418
        for (unsigned i = 0; i < lines.size(); i++) {
419
            AttributeType &ln = lines[i];
420
            if (resp_addr_start == ln[ASM_addrline].to_uint64()) {
421
                ln = resp[resp_idx++];
422
                if (resp_idx < resp.size()) {
423
                    resp_addr_start = resp[resp_idx][ASM_addrline].to_uint64();
424
                } else {
425
                    break;
426
                }
427
            }
428
        }
429
        for (unsigned i = resp_idx; i < resp.size(); i++) {
430
            lines.add_to_list(&resp[i]);
431
        }
432
    } else if (resp_addr_start == asm_addr_end + 4) {  // fixme
433
        // Joint lines to end of the current list:
434
        for (unsigned i = 0; i < resp.size(); i++) {
435
            lines.add_to_list(&resp[i]);
436
        }
437
    } else {
438
        lines = resp;
439
    }
440
    RISCV_mutex_unlock(&mutexAsmGaurd_);
441
}
442
 
443
}  // namespace debugger

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.