diff --git a/src/assembler/simpleasm.cpp b/src/assembler/simpleasm.cpp index 7f6d38c8..53c9d8a6 100644 --- a/src/assembler/simpleasm.cpp +++ b/src/assembler/simpleasm.cpp @@ -71,11 +71,13 @@ void SimpleAsm::setup( machine::FrontendMemory *mem, SymbolTableDb *symtab, machine::Address address, - machine::Xlen xlen) { + machine::Xlen xlen, + QMap *address_to_blocknum) { this->mem = mem; this->symtab = symtab; this->address = address; this->symtab->setSymbol("XLEN", static_cast(xlen), sizeof(uint64_t)); + this->address_to_blocknum = address_to_blocknum; } static const machine::BitArg wordArg = { { { 32, 0 } }, 0 }; @@ -521,6 +523,7 @@ bool SimpleAsm::process_line( } uint32_t *p = inst; for (size_t l = 0; l < size; l += 4) { + if (address_to_blocknum != nullptr) { address_to_blocknum->insert(address, line_number); } if (!fatal_occured) { mem->write_u32(address, *(p++), ae::INTERNAL); } address += 4; } diff --git a/src/assembler/simpleasm.h b/src/assembler/simpleasm.h index be134cd4..3c5c71ae 100644 --- a/src/assembler/simpleasm.h +++ b/src/assembler/simpleasm.h @@ -55,7 +55,8 @@ class SimpleAsm : public QObject { machine::FrontendMemory *mem, SymbolTableDb *symtab, machine::Address address, - machine::Xlen xlen); + machine::Xlen xlen, + QMap *address_to_blocknum = nullptr); bool process_line( const QString &line, const QString &filename = "", @@ -78,6 +79,7 @@ class SimpleAsm : public QObject { private: QStringList include_stack; + QMap *address_to_blocknum = nullptr; machine::FrontendMemory *mem {}; machine::RelocExpressionList reloc; }; diff --git a/src/gui/mainwindow/MainWindow.ui b/src/gui/mainwindow/MainWindow.ui index 93a83c35..d74b7bd7 100644 --- a/src/gui/mainwindow/MainWindow.ui +++ b/src/gui/mainwindow/MainWindow.ui @@ -17,7 +17,7 @@ :/icons/gui.png - :/icons/gui.png + :/icons/gui.png @@ -54,7 +54,7 @@ 0 0 900 - 32 + 31 @@ -127,9 +127,11 @@ - Options + &Options + + @@ -146,7 +148,7 @@ false - Qt::TopToolBarArea + Qt::ToolBarArea::TopToolBarArea TopToolBarArea @@ -629,6 +631,34 @@ Show line number in the code editor. + + + + true + + + true + + + &Highlight Curent Instruction + + + Highlight currently the currently executed instruction in the internal editor. + + + + + true + + + true + + + &Follow Current Instruction + + + Always focus the currently executed instruction in the internal editor. + diff --git a/src/gui/mainwindow/mainwindow.cpp b/src/gui/mainwindow/mainwindow.cpp index d79b3bc0..87164c70 100644 --- a/src/gui/mainwindow/mainwindow.cpp +++ b/src/gui/mainwindow/mainwindow.cpp @@ -93,6 +93,12 @@ MainWindow::MainWindow(QSettings *settings, QWidget *parent) connect( ui->actionEditorShowLineNumbers, &QAction::triggered, editor_tabs.data(), &EditorDock::set_show_line_numbers); + connect( + ui->actionEditorHighlightPC, &QAction::triggered, editor_tabs.data(), + &EditorDock::set_highlight_pc); + connect( + ui->actionEditorFollowPC, &QAction::triggered, editor_tabs.data(), + &EditorDock::set_follow_pc); bool line_numbers_visible = settings->value("EditorShowLineNumbers", true).toBool(); editor_tabs->set_show_line_numbers(line_numbers_visible); @@ -252,14 +258,13 @@ void MainWindow::create_core( bool keep_memory) { // Create machine auto *new_machine = new machine::Machine(config, true, load_executable); - if (keep_memory && (machine != nullptr)) { new_machine->memory_rw()->reset(*machine->memory()); + *new_machine->address_to_blocknum_rw() = *machine->address_to_blocknum(); } // Remove old machine machine.reset(new_machine); - // Create machine view auto focused_index = central_widget_tabs->currentIndex(); corescene.reset(); @@ -306,6 +311,7 @@ void MainWindow::create_core( connect( machine->core(), &machine::Core::stop_on_exception_reached, machine.data(), &machine::Machine::pause); + connect(machine.data(), &machine::Machine::highlight_by_blocknum, this, &MainWindow::handle_highlight_by_blocknum); // Setup docks registers->connectToMachine(machine.data()); @@ -754,7 +760,10 @@ void MainWindow::compile_source() { connect(&sasm, &SimpleAsm::report_message, this, &MainWindow::report_message); - sasm.setup(mem, &symtab, machine::Address(0x00000200), machine->core()->get_xlen()); + machine->address_to_blocknum_rw()->clear(); + sasm.setup( + mem, &symtab, machine::Address(0x00000200), machine->core()->get_xlen(), + machine->address_to_blocknum_rw()); int ln = 1; for (QTextBlock block = content->begin(); block.isValid(); block = block.next(), ln++) { @@ -763,6 +772,8 @@ void MainWindow::compile_source() { } if (!sasm.finish()) { error_occured = true; } + connect(this, &MainWindow::highlight_by_blocknum, editor, &SrcEditor::highlightBlock); + if (error_occured) { show_messages(); } } diff --git a/src/gui/mainwindow/mainwindow.h b/src/gui/mainwindow/mainwindow.h index deab97b9..7d5aec87 100644 --- a/src/gui/mainwindow/mainwindow.h +++ b/src/gui/mainwindow/mainwindow.h @@ -57,6 +57,7 @@ class MainWindow : public QMainWindow { QString text, QString hint); void clear_messages(); + void highlight_by_blocknum(int blocknum); public slots: // Actions signals @@ -111,6 +112,9 @@ public slots: int column, const QString &text, const QString &hint); + void handle_highlight_by_blocknum(int blocknum) { + emit highlight_by_blocknum(blocknum); + } protected: void closeEvent(QCloseEvent *cancel) override; diff --git a/src/gui/windows/editor/editordock.cpp b/src/gui/windows/editor/editordock.cpp index 4631abfb..5af4a8f0 100644 --- a/src/gui/windows/editor/editordock.cpp +++ b/src/gui/windows/editor/editordock.cpp @@ -161,6 +161,22 @@ void EditorDock::set_show_line_numbers(bool visible) { } } +void EditorDock::set_highlight_pc(bool enable) { + enable_hightlight = enable; + settings->setValue("editorEnableHighlisht", enable); + for (int i = 0; i < this->count(); i++) { + get_tab(i)->set_enable_highlight(enable); + } +} + +void EditorDock::set_follow_pc(bool enable) { + enable_focus_change = enable; + settings->setValue("editorEnableFocusChange", enable); + for (int i = 0; i < this->count(); i++) { + get_tab(i)->set_enable_focus_change(enable); + } +} + void EditorDock::tabCountChanged() { Super::tabCountChanged(); emit editor_available_changed(count() > 0); diff --git a/src/gui/windows/editor/editordock.h b/src/gui/windows/editor/editordock.h index 3c26fd12..6f806702 100644 --- a/src/gui/windows/editor/editordock.h +++ b/src/gui/windows/editor/editordock.h @@ -40,6 +40,8 @@ class EditorDock : public HidingTabWidget { public slots: void set_show_line_numbers(bool visible); + void set_highlight_pc(bool enable); + void set_follow_pc(bool enable); void open_file_dialog(); void save_tab(int index); @@ -59,6 +61,8 @@ public slots: private: QSharedPointer settings; bool line_numbers_visible = true; + bool enable_hightlight = true; + bool enable_focus_change = true; size_t unknown_editor_counter = 1; }; diff --git a/src/gui/windows/editor/editortab.cpp b/src/gui/windows/editor/editortab.cpp index 9a4f0348..0639d275 100644 --- a/src/gui/windows/editor/editortab.cpp +++ b/src/gui/windows/editor/editortab.cpp @@ -39,6 +39,14 @@ void EditorTab::set_show_line_number(bool visible) { editor->setShowLineNumbers(visible); } +void EditorTab::set_enable_highlight(bool enable) { + editor->setEnableHighlight(enable); +} + +void EditorTab::set_enable_focus_change(bool enable) { + editor->setEnableFocusChange(enable); +} + void EditorTab::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); elide_file_name(); diff --git a/src/gui/windows/editor/editortab.h b/src/gui/windows/editor/editortab.h index 6eada4a5..306c713e 100644 --- a/src/gui/windows/editor/editortab.h +++ b/src/gui/windows/editor/editortab.h @@ -19,6 +19,8 @@ class EditorTab : public QWidget { public slots: void set_show_line_number(bool visible); + void set_enable_highlight(bool enable); + void set_enable_focus_change(bool enable); protected: void resizeEvent(QResizeEvent *event) override; diff --git a/src/gui/windows/editor/srceditor.cpp b/src/gui/windows/editor/srceditor.cpp index d132c0a9..178df03e 100644 --- a/src/gui/windows/editor/srceditor.cpp +++ b/src/gui/windows/editor/srceditor.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -282,6 +283,19 @@ void SrcEditor::setShowLineNumbers(bool show) { updateMargins(0); } +void SrcEditor::setEnableHighlight(bool enable) { + if (!enable) { + // clear old styles + QList extra_selections; + setExtraSelections(extra_selections); + } + enable_highlight = enable; +} + +void SrcEditor::setEnableFocusChange(bool enable) { + enable_focus_change = enable; +} + void SrcEditor::insertFromMimeData(const QMimeData *source) { if (source->hasText()) { insertPlainText(source->text()); } } @@ -289,3 +303,36 @@ void SrcEditor::insertFromMimeData(const QMimeData *source) { bool SrcEditor::canInsertFromMimeData(const QMimeData *source) const { return source->hasText(); } + +void SrcEditor::highlightBlock(int block_num) { + QTextBlock block = document()->findBlockByNumber(block_num - 1); + + if (enable_highlight) { + // set hightly style + QList extra_selections; + QTextEdit::ExtraSelection selection; + QColor lineColor = QColor(Qt::yellow).lighter(160); + selection.format.setBackground(lineColor); + selection.format.setProperty(QTextFormat::FullWidthSelection, true); + + // move cursor + selection.cursor = QTextCursor(block); + // select until the end of block + selection.cursor.movePosition( + QTextCursor::EndOfBlock, QTextCursor::KeepAnchor, block.length()); + // select an extra \n + selection.cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 1); + extra_selections.append(selection); + setExtraSelections(extra_selections); + } + + if (enable_focus_change) { + // calculate viewport line count + int viewport_line_count + = viewport()->height() / QFontMetrics(document()->defaultFont()).height(); + // scroll to block and show it in editor middle + QScrollBar *vScrollBar = verticalScrollBar(); + vScrollBar->setValue( + vScrollBar->singleStep() * (block.firstLineNumber() - viewport_line_count / 2)); + } +} diff --git a/src/gui/windows/editor/srceditor.h b/src/gui/windows/editor/srceditor.h index 118c80d3..76cec9c5 100644 --- a/src/gui/windows/editor/srceditor.h +++ b/src/gui/windows/editor/srceditor.h @@ -42,6 +42,9 @@ class SrcEditor : public QPlainTextEdit { public slots: void setShowLineNumbers(bool visible); + void setEnableHighlight(bool enable); + void setEnableFocusChange(bool enable); + void highlightBlock(int block_num); private slots: void updateMargins(int newBlockCount); @@ -51,6 +54,8 @@ private slots: ::Box highlighter {}; LineNumberArea *line_number_area; bool line_numbers_visible = true; + bool enable_highlight = true; + bool enable_focus_change = true; QString fname; QString tname; bool saveAsRequiredFl {}; diff --git a/src/machine/machine.cpp b/src/machine/machine.cpp index ea9a7565..116ad9ef 100644 --- a/src/machine/machine.cpp +++ b/src/machine/machine.cpp @@ -34,6 +34,7 @@ Machine::Machine(MachineConfig config, bool load_symtab, bool load_executable) mem = new Memory(*mem_program_only); } else { mem = new Memory(machine_config.get_simulated_endian()); + addr_to_blocknum = new QMap(); } data_bus = new MemoryDataBus(machine_config.get_simulated_endian()); @@ -184,6 +185,8 @@ Machine::~Machine() { symtab = nullptr; delete predictor; predictor = nullptr; + delete addr_to_blocknum; + addr_to_blocknum = nullptr; } const MachineConfig &Machine::config() { @@ -211,6 +214,14 @@ Memory *Machine::memory_rw() { return mem; } +const QMap *Machine::address_to_blocknum() { + return addr_to_blocknum; +} + +QMap *Machine::address_to_blocknum_rw() { + return addr_to_blocknum; +} + const Cache *Machine::cache_program() { return cch_program; } @@ -331,6 +342,10 @@ void Machine::pause() { void Machine::step_internal(bool skip_break) { CTL_GUARD; + if (addr_to_blocknum != nullptr && addr_to_blocknum->contains(regs->read_pc())) { + emit highlight_by_blocknum(addr_to_blocknum->value(regs->read_pc())); + } + enum Status stat_prev = stat; set_status(ST_BUSY); emit tick(); diff --git a/src/machine/machine.h b/src/machine/machine.h index edec4af1..9743c8be 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -36,6 +36,8 @@ class Machine : public QObject { const CSR::ControlState *control_state(); const Memory *memory(); Memory *memory_rw(); + const QMap *address_to_blocknum(); + QMap *address_to_blocknum_rw(); const Cache *cache_program(); const Cache *cache_data(); const Cache *cache_level2(); @@ -92,6 +94,7 @@ public slots: void restart(); signals: + void highlight_by_blocknum(int block_num); void program_exit(); void program_trap(machine::SimulatorException &e); void status_change(enum machine::Machine::Status st); @@ -114,6 +117,7 @@ private slots: * simulation reset without repeated ELF file loading. */ Memory *mem_program_only = nullptr; + QMap *addr_to_blocknum = nullptr; MemoryDataBus *data_bus = nullptr; SerialPort *ser_port = nullptr; PeripSpiLed *perip_spi_led = nullptr;