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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [socsim_plugin/] [irqctrl.cpp] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 sergeykhbr
/**
2
 * @file
3
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
5
 * @brief      Interrupt controller functional model.
6
 */
7
 
8
#include "api_core.h"
9
#include "irqctrl.h"
10
#include <riscv-isa.h>
11
#include "coreservices/icpuriscv.h"
12
 
13
namespace debugger {
14
 
15
IrqPort::IrqPort(IService *parent, const char *portname, int idx) {
16
    parent_ = parent;
17
    parent->registerPortInterface(portname, static_cast<IWire *>(this));
18
    idx_ = idx;
19
    level_ = false;
20
};
21
 
22
void IrqPort::raiseLine() {
23
    level_ = true;
24
    static_cast<IrqController *>(parent_)->requestInterrupt(idx_);
25
}
26
 
27
void IrqPort::setLevel(bool level) {
28
    if (!level_ && level) {
29
        raiseLine();
30
    } else if (level_ && !level) {
31
        lowerLine();
32
    }
33
}
34
 
35
IrqController::IrqController(const char *name)  : IService(name) {
36
    registerInterface(static_cast<IMemoryOperation *>(this));
37
    registerInterface(static_cast<IClockListener *>(this));
38
    registerAttribute("CPU", &cpu_);
39
    registerAttribute("CSR_MIPI", &mipi_);
40
    registerAttribute("IrqTotal", &irqTotal_);
41
 
42
    char portname[256];
43
    for (int i = 1; i < IRQ_MAX; i++) {
44
        RISCV_sprintf(portname, sizeof(portname), "irq%d", i);
45
        irqlines_[i] = new IrqPort(this, portname, i);
46
    }
47
 
48
    mipi_.make_uint64(0x783);
49
    cpu_.make_string("");
50
    irqTotal_.make_uint64(4);
51
 
52
    memset(&regs_, 0, sizeof(regs_));
53
    regs_.irq_mask = ~0;
54
    regs_.irq_lock = 1;
55
}
56
 
57
IrqController::~IrqController() {
58
}
59
 
60
void IrqController::postinitService() {
61
    iclk_ = static_cast<IClock *>(
62
        RISCV_get_service_iface(cpu_.to_string(), IFACE_CLOCK));
63
    if (!iclk_) {
64
        RISCV_error("Can't find IClock interface %s", cpu_.to_string());
65
        return;
66
    }
67
 
68
    icpu_ = static_cast<ICpuGeneric *>(
69
        RISCV_get_service_iface(cpu_.to_string(), IFACE_CPU_GENERIC));
70
    if (!icpu_) {
71
        RISCV_error("Can't find ICpuRiscV interface %s", cpu_.to_string());
72
        return;
73
    }
74
    uint64_t t = iclk_->getStepCounter();
75
    iclk_->registerStepCallback(static_cast<IClockListener *>(this), t + 1);
76
}
77
 
78
ETransStatus IrqController::b_transport(Axi4TransactionType *trans) {
79
    uint64_t mask = (length_.to_uint64() - 1);
80
    uint64_t off = ((trans->addr - getBaseAddress()) & mask) / 4;
81
    uint32_t t1;
82
    trans->response = MemResp_Valid;
83
    if (trans->action == MemAction_Write) {
84
        for (uint64_t i = 0; i < trans->xsize/4; i++) {
85
            if (((trans->wstrb >> 4*i) & 0xFF) == 0) {
86
                continue;
87
            }
88
 
89
            switch (off + i) {
90
            case 0:
91
                regs_.irq_mask = trans->wpayload.b32[i];
92
                RISCV_info("Set irq_mask = %08x", trans->wpayload.b32[i]);
93
                break;
94
            case 1:
95
                regs_.irq_pending = trans->wpayload.b32[i];
96
                RISCV_info("Set irq_pending = %08x", trans->wpayload.b32[i]);
97
                break;
98
            case 2:
99
                t1 = regs_.irq_pending;
100
                regs_.irq_pending &= ~trans->wpayload.b32[i];
101
                if (t1 && !regs_.irq_pending) {
102
                    icpu_->lowerSignal(INTERRUPT_MExternal);
103
                }
104
                RISCV_info("Set irq_clear = %08x", trans->wpayload.b32[i]);
105
                break;
106
            case 3:
107
                regs_.irq_pending |= trans->wpayload.b32[i];
108
                RISCV_info("Set irq_rise = %08x", trans->wpayload.b32[i]);
109
                break;
110
            case 4:
111
                regs_.isr_table &= ~0xFFFFFFFFLL;
112
                regs_.isr_table |= trans->wpayload.b32[i];
113
                RISCV_info("Set irq_handler[31:0] = %08x",
114
                            trans->wpayload.b32[i]);
115
                break;
116
            case 5:
117
                regs_.isr_table &= ~0xFFFFFFFF00000000LL;
118
                regs_.isr_table |=
119
                    (static_cast<uint64_t>(trans->wpayload.b32[i]) << 32);
120
                RISCV_info("Set irq_handler[63:32] = %08x",
121
                            trans->wpayload.b32[i]);
122
                break;
123
            case 6:
124
                regs_.dbg_cause &= ~0xFFFFFFFFLL;
125
                regs_.dbg_cause |= trans->wpayload.b32[i];
126
                RISCV_info("Set dbg_cause[31:0] = %08x",
127
                            trans->wpayload.b32[i]);
128
                break;
129
            case 7:
130
                regs_.dbg_cause &= ~0xFFFFFFFF00000000LL;
131
                regs_.dbg_cause |=
132
                    (static_cast<uint64_t>(trans->wpayload.b32[i]) << 32);
133
                RISCV_info("Set dbg_cause[63:32] = %08x",
134
                            trans->wpayload.b32[i]);
135
                break;
136
            case 8:
137
                regs_.dbg_epc &= ~0xFFFFFFFFLL;
138
                regs_.dbg_epc |= trans->wpayload.b32[i];
139
                RISCV_info("Set dbg_epc[31:0] = %08x", trans->wpayload.b32[i]);
140
                break;
141
            case 9:
142
                regs_.dbg_epc &= ~0xFFFFFFFF00000000LL;
143
                regs_.dbg_epc |=
144
                    (static_cast<uint64_t>(trans->wpayload.b32[i]) << 32);
145
                RISCV_info("Set dbg_epc[63:32] = %08x",
146
                            trans->wpayload.b32[i]);
147
                break;
148
            case 10:
149
                regs_.irq_lock = trans->wpayload.b32[i];
150
                RISCV_info("Set irq_ena = %08x", trans->wpayload.b32[i]);
151
                if (regs_.irq_lock == 0 && regs_.irq_pending) {
152
                    icpu_->lowerSignal(INTERRUPT_MExternal);
153
                }
154
                break;
155
            case 11:
156
                regs_.irq_cause_idx = trans->wpayload.b32[i];
157
                RISCV_info("Set irq_cause_idx = %08x", trans->wpayload.b32[i]);
158
                break;
159
            default:;
160
            }
161
        }
162
    } else {
163
        for (uint64_t i = 0; i < trans->xsize/4; i++) {
164
            switch (off + i) {
165
            case 0:
166
                trans->rpayload.b32[i] = regs_.irq_mask;
167
                RISCV_info("Get irq_mask = %08x", trans->rpayload.b32[i]);
168
                break;
169
            case 1:
170
                trans->rpayload.b32[i] = regs_.irq_pending;
171
                RISCV_info("Get irq_pending = %08x", trans->rpayload.b32[i]);
172
                break;
173
            case 2:
174
                trans->rpayload.b32[i] = 0;
175
                RISCV_info("Get irq_clear = %08x", trans->rpayload.b32[i]);
176
                break;
177
            case 3:
178
                trans->rpayload.b32[i] = 0;
179
                RISCV_info("Get irq_rise = %08x", trans->rpayload.b32[i]);
180
                break;
181
            case 4:
182
                trans->rpayload.b32[i] =
183
                    static_cast<uint32_t>(regs_.isr_table);
184
                RISCV_info("Get irq_handler[31:0] = %08x",
185
                            trans->rpayload.b32[i]);
186
                break;
187
            case 5:
188
                trans->rpayload.b32[i]
189
                    = static_cast<uint32_t>(regs_.isr_table >> 32);
190
                RISCV_info("Get irq_handler[63:32] = %08x",
191
                            trans->rpayload.b32[i]);
192
                break;
193
            case 6:
194
                trans->rpayload.b32[i] =
195
                    static_cast<uint32_t>(regs_.dbg_cause);
196
                RISCV_info("Get dbg_cause[31:0] = %08x",
197
                            trans->rpayload.b32[i]);
198
                break;
199
            case 7:
200
                trans->rpayload.b32[i] =
201
                    static_cast<uint32_t>(regs_.dbg_cause >> 32);
202
                RISCV_info("Get dbg_cause[63:32] = %08x",
203
                            trans->rpayload.b32[i]);
204
                break;
205
            case 8:
206
                trans->rpayload.b32[i] = static_cast<uint32_t>(regs_.dbg_epc);
207
                RISCV_info("Get dbg_epc[31:0] = %08x",
208
                            trans->rpayload.b32[i]);
209
                break;
210
            case 9:
211
                trans->rpayload.b32[i] =
212
                    static_cast<uint32_t>(regs_.dbg_epc >> 32);
213
                RISCV_info("Get dbg_epc[63:32] = %08x",
214
                            trans->rpayload.b32[i]);
215
                break;
216
            case 10:
217
                trans->rpayload.b32[i] = regs_.irq_lock;
218
                RISCV_info("Get irq_ena = %08x",
219
                            trans->rpayload.b32[i]);
220
                break;
221
            case 11:
222
                trans->rpayload.b32[i] = regs_.irq_cause_idx;
223
                RISCV_info("Get irq_cause_idx = %08x",
224
                            trans->rpayload.b32[i]);
225
                break;
226
            default:
227
                trans->rpayload.b32[i] = ~0;
228
            }
229
        }
230
    }
231
    return TRANS_OK;
232
}
233
 
234
void IrqController::stepCallback(uint64_t t) {
235
    iclk_->registerStepCallback(static_cast<IClockListener *>(this), t + 1);
236
    if (regs_.irq_lock == 1) {
237
        return;
238
    }
239
    if (~regs_.irq_mask & regs_.irq_pending) {
240
        icpu_->raiseSignal(INTERRUPT_MExternal);   // PLIC interrupt (external)
241
        RISCV_debug("Raise interrupt", NULL);
242
    }
243
}
244
 
245
void IrqController::requestInterrupt(int idx) {
246
    regs_.irq_pending |= (0x1 << idx);
247
    RISCV_info("request Interrupt %d", idx);
248
}
249
 
250
}  // namespace debugger
251
 

powered by: WebSVN 2.1.0

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