aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine/qtmipsmachine.h
blob: 7092ec3e1e21e144a798131429a9e6068ed5de46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// SPDX-License-Identifier: GPL-2.0+
/*******************************************************************************
 * QtMips - MIPS 32-bit Architecture Subset Simulator
 *
 * Implemented to support following courses:
 *
 *   B35APO - Computer Architectures
 *   https://cw.fel.cvut.cz/wiki/courses/b35apo
 *
 *   B4M35PAP - Advanced Computer Architectures
 *   https://cw.fel.cvut.cz/wiki/courses/b4m35pap/start
 *
 * Copyright (c) 2017-2019 Karel Koci<cynerd@email.cz>
 * Copyright (c) 2019      Pavel Pisa <pisa@cmp.felk.cvut.cz>
 *
 * Faculty of Electrical Engineering (http://www.fel.cvut.cz)
 * Czech Technical University        (http://www.cvut.cz/)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 *
 ******************************************************************************/

#ifndef QTMIPSMACHINE_H
#define QTMIPSMACHINE_H

#include <QObject>
#include <QTimer>
#include <cstdint>
#include <qtmipsexception.h>
#include <machineconfig.h>
#include <registers.h>
#include <memory.h>
#include <core.h>
#include <cache.h>
#include <physaddrspace.h>
#include <peripheral.h>
#include <serialport.h>
#include <peripspiled.h>
#include <lcddisplay.h>
#include <symboltable.h>

namespace machine {

class QtMipsMachine : public QObject {
    Q_OBJECT
public:
    QtMipsMachine(const MachineConfig &cc, bool load_symtab = false, bool load_executable = true);
    ~QtMipsMachine();

    const MachineConfig &config();
    void set_speed(unsigned int ips, unsigned int time_chunk = 0);

    const Registers *registers();
    const Cop0State *cop0state();
    const Memory *memory();
    Memory *memory_rw();
    const Cache *cache_program();
    const Cache *cache_data();
    Cache *cache_data_rw();
    void cache_sync();
    const  PhysAddrSpace *physical_address_space();
    PhysAddrSpace *physical_address_space_rw();
    SerialPort *serial_port();
    PeripSpiLed *peripheral_spi_led();
    LcdDisplay *peripheral_lcd_display();
    const SymbolTable *symbol_table(bool create = false);
    SymbolTable *symbol_table_rw(bool create = false);
    void set_symbol(QString name, std::uint32_t value, std::uint32_t size,
                    unsigned char info = 0, unsigned char other = 0);
    const Core *core();
    const CoreSingle *core_singe();
    const CorePipelined *core_pipelined();
    bool executable_loaded() const;

    enum Status {
        ST_READY, // Machine is ready to be started or step to be called
        ST_RUNNING, // Machine is running
        ST_BUSY, // Machine is calculating step
        ST_EXIT, // Machine exited
        ST_TRAPPED // Machine exited with failure
    };
    enum Status status();
    bool exited();

    void register_exception_handler(ExceptionCause excause, ExceptionHandler *exhandler);
    bool addressapce_insert_range(MemoryAccess *mem_acces, std::uint32_t start_addr,
                                  std::uint32_t last_addr, bool move_ownership);

    void insert_hwbreak(std::uint32_t address);
    void remove_hwbreak(std::uint32_t address);
    bool is_hwbreak(std::uint32_t address);
    void set_stop_on_exception(enum ExceptionCause excause, bool value);
    bool get_stop_on_exception(enum ExceptionCause excause) const;
    void set_step_over_exception(enum ExceptionCause excause, bool value);
    bool get_step_over_exception(enum ExceptionCause excause) const;
    enum ExceptionCause get_exception_cause() const;

public slots:
    void play();
    void pause();
    void step();
    void restart();

signals:
    void program_exit();
    void program_trap(machine::QtMipsException &e);
    void status_change(enum machine::QtMipsMachine::Status st);
    void tick(); // Time tick
    void post_tick(); // Emitted after tick to allow updates
    void set_interrupt_signal(uint irq_num, bool active);

private slots:
    void step_timer();

private:
    void step_internal(bool skip_break = false);
    MachineConfig mcnf;

    Registers *regs;
    Memory *mem, *mem_program_only;
    PhysAddrSpace *physaddrspace;
    SerialPort *ser_port;
    PeripSpiLed *perip_spi_led;
    LcdDisplay *perip_lcd_display;
    Cache *cch_program, *cch_data;
    Cop0State *cop0st;
    Core *cr;

    QTimer *run_t;
    unsigned int time_chunk;

    SymbolTable *symtab;
    std::uint32_t program_end;
    enum Status stat;
    void set_status(enum Status st);
};

}

#endif // QTMIPSMACHINE_H