sim_interrupt.h Source File

yasimavr: sim_interrupt.h Source File
yasimavr
Loading...
Searching...
No Matches
sim_interrupt.h
Go to the documentation of this file.
1/*
2 * sim_interrupt.h
3 *
4 * Copyright 2021-2026 Clement Savergne <csavergne@yahoo.com>
5
6 This file is part of yasim-avr.
7
8 yasim-avr is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 yasim-avr is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with yasim-avr. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22//=======================================================================================
23
24#ifndef __YASIMAVR_INTERRUPT_H__
25#define __YASIMAVR_INTERRUPT_H__
26
27#include "sim_peripheral.h"
28#include "sim_types.h"
29#include "sim_signal.h"
30
32
34
35
36//=======================================================================================
37/*
38 * CTLREQ definitions
39*/
40
41//AVR_CTLREQ_GET_SIGNAL :
42// The signal returned is raised when an interrupt is raised
43// the index is set to the vector index
44// the value 'u' is set to the interrupt state (IntrState_Raised)
45
46//Request sent to by any peripheral to register an interrupt vector
47//The index shall be the interrupt vector index
48//The value 'p' shall be the corresponding InterruptHandler object
49//Notes:
50// . a vector can only be registered once
51// . the vector 0 cannot be registered
52#define AVR_CTLREQ_INTR_REGISTER (AVR_CTLREQ_BASE + 1)
53
54//Request sent to raise or clear artificially any interrupt
55//The index shall be the interrupt vector index
56//The value 'u' shall be 1 for raising the interrupt, 0 for clearing it.
57#define AVR_CTLREQ_INTR_RAISE (AVR_CTLREQ_BASE + 2)
58
59#define AVR_INTERRUPT_NONE -1
60
61
62//=======================================================================================
76
77 friend class InterruptHandler;
78
79public:
80
81 enum SignalId {
83 Signal_StateChange
84 };
85
86 enum State {
88 State_Raised = 0x01,
90 State_Cancelled = 0x10,
92 State_Acknowledged = 0x20,
94 State_Returned = 0x30,
96 State_RaisedFromSleep = 0x41,
98 State_Reset = 0x50
99 };
100
113
114 static constexpr IRQ_t NO_INTERRUPT = { AVR_INTERRUPT_NONE, 0, false };
115
116 //===== Constructor/destructor =====
117 explicit InterruptController(unsigned int vector_count);
118
119 //===== Override of IO_CTL virtual methods =====
120 virtual void reset(int flags) override;
121 virtual bool ctlreq(ctlreq_id_t req, ctlreq_data_t* data) override;
122 virtual void sleep(bool on, SleepMode mode) override;
123
124 //===== Interface API for the CPU =====
125 bool cpu_has_irq() const;
126 IRQ_t cpu_get_irq() const;
127 void cpu_ack_irq();
128 virtual void cpu_reti();
129
130protected:
131
132 //Helper methods to access the vector table, for concrete implementing sub-classes
133 bool interrupt_raised(int_vect_t vector) const;
134 int_vect_t intr_count() const;
135 void set_interrupt_raised(int_vect_t vector, bool raised);
136
137 virtual void cpu_ack_irq(int_vect_t vector);
138
148 virtual IRQ_t get_next_irq() const = 0;
149
150 void update_irq();
151
152private:
153
154 //===== Structure holding data on the vector table =====
155 struct interrupt_t {
156 bool used = false;
157 bool raised = false;
158 InterruptHandler* handler = nullptr;
159 };
160
161 //Interrupt vector table
162 std::vector<interrupt_t> m_interrupts;
163 //Variable holding the vector to be executed next
164 IRQ_t m_irq;
165 //Signal raised with changes of interrupt state
166 Signal m_signal;
167
168 //private API used by the interrupt handlers
169 void raise_interrupt(int_vect_t vector);
170 void cancel_interrupt(int_vect_t vector);
171 void disconnect_handler(InterruptHandler* handler);
172
173};
174
181{
182 return m_irq.vector > AVR_INTERRUPT_NONE;
183}
184
193{
194 if (m_irq.vector > AVR_INTERRUPT_NONE)
195 return m_irq;
196 else
197 return NO_INTERRUPT;
198}
199
202{
203 return m_interrupts.size();
204}
205
208{
209 return m_interrupts[vector].raised;
210}
211
212
213//=======================================================================================
222
224
225public:
226
228 virtual ~InterruptHandler();
229
230 //Controlling method for raising (or cancelling) interrupts
231 //It can actually raise any interrupt so long as it has been
232 //registered with the controller
233 void raise_interrupt(int_vect_t vector) const;
234 void cancel_interrupt(int_vect_t vector) const;
235 bool interrupt_raised(int_vect_t vector) const;
236
243 virtual bool interrupt_ack_handler(int_vect_t vector) = 0;
244
245 //Disable copy semantics
248
249private:
250
251 InterruptController* m_intctl;
252
253};
254
255
256//=======================================================================================
265
266public:
267
268 explicit AbstractInterruptFlag(bool clear_on_ack = false);
269
270 bool init(Device& device, int_vect_t vector);
271
272 int update();
273
274 bool raised() const;
275
276 //Override, returns the value of clear_on_ack
277 virtual bool interrupt_ack_handler(int_vect_t vector) override;
278
279protected:
280
281 bool clear_on_ack() const;
282
287 virtual bool flag_raised() const = 0;
288
289private:
290
291 bool m_clr_on_ack;
292 int_vect_t m_vector;
293
294};
295
298{
299 return interrupt_raised(m_vector);
300}
301
304{
305 return m_clr_on_ack;
306}
307
308
309//=======================================================================================
325
326public:
327
328 explicit InterruptFlag(bool clear_on_ack = false);
329
330 bool init(Device& device, const regmask_t& rm_enable, const regmask_t& rm_flag, int_vect_t vector);
331
332 bool set_flag(bitmask_t mask = 0xFF);
333 bool clear_flag(bitmask_t mask = 0xFF);
334
335private:
336
337 regmask_t m_rm_enable;
338 regmask_t m_rm_flag;
339
340 IORegister* m_flag_reg;
341 IORegister* m_enable_reg;
342
343 virtual bool flag_raised() const override final;
344 //Override to clear the flag on ACK if clear_on_ack is true
345 virtual bool interrupt_ack_handler(int_vect_t vector) override final;
346
347 virtual uint8_t ioreg_read_handler(reg_addr_t addr, uint8_t value) override final;
348 virtual uint8_t ioreg_peek_handler(reg_addr_t addr, uint8_t value) override final;
349 virtual void ioreg_write_handler(reg_addr_t addr, const ioreg_write_t& data) override final;
350
351};
352
353
355
356#endif //__YASIMAVR_INTERRUPT_H__
Abstract interrupt flag.
Definition sim_interrupt.h:264
bool clear_on_ack() const
Returns the raised state of the interrupt flag.
Definition sim_interrupt.h:303
virtual bool flag_raised() const =0
bool raised() const
Returns the raised state of the interrupt flag.
Definition sim_interrupt.h:297
Basic AVR device model.
Definition sim_device.h:61
Definition sim_ioreg.h:69
Definition sim_ioreg.h:116
Generic interrupt controller.
Definition sim_interrupt.h:75
State
Definition sim_interrupt.h:86
IRQ_t cpu_get_irq() const
Definition sim_interrupt.h:192
static constexpr IRQ_t NO_INTERRUPT
Definition sim_interrupt.h:114
int_vect_t intr_count() const
Interrupt table size getter.
Definition sim_interrupt.h:201
virtual IRQ_t get_next_irq() const =0
SignalId
Definition sim_interrupt.h:81
bool cpu_has_irq() const
Definition sim_interrupt.h:180
bool interrupt_raised(int_vect_t vector) const
Interrupt state getter.
Definition sim_interrupt.h:207
Generic helper to manage a typical Interrupt Flag/Enable in a I/O register.
Definition sim_interrupt.h:324
Abstract interface to a interrupt controller.
Definition sim_interrupt.h:221
InterruptHandler(const InterruptHandler &)=delete
virtual bool interrupt_ack_handler(int_vect_t vector)=0
InterruptHandler & operator=(const InterruptHandler &)=delete
bool interrupt_raised(int_vect_t vector) const
Definition sim_interrupt.cpp:231
Abstract class defining a framework for MCU peripherals.
Definition sim_peripheral.h:286
virtual bool init(Device &device)
Definition sim_peripheral.cpp:60
virtual bool ctlreq(ctlreq_id_t req, ctlreq_data_t *data)
Definition sim_peripheral.cpp:79
virtual void sleep(bool on, SleepMode mode)
Definition sim_peripheral.cpp:125
virtual void ioreg_write_handler(reg_addr_t addr, const ioreg_write_t &data) override
Definition sim_peripheral.cpp:117
virtual uint8_t ioreg_read_handler(reg_addr_t addr, uint8_t value) override
Definition sim_peripheral.cpp:91
virtual uint8_t ioreg_peek_handler(reg_addr_t addr, uint8_t value) override
Definition sim_peripheral.cpp:106
virtual void reset(int flags)
Definition sim_peripheral.cpp:72
Signalling framework class.
Definition sim_signal.h:97
Representation of a I/O register address, with validity state.
Definition sim_types.h:60
int ctlreq_id_t
Definition sim_peripheral.h:111
#define YASIMAVR_BEGIN_NAMESPACE
Definition sim_globals.h:58
#define AVR_CORE_PUBLIC_API
Definition sim_globals.h:46
#define YASIMAVR_END_NAMESPACE
Definition sim_globals.h:59
#define AVR_INTERRUPT_NONE
Definition sim_interrupt.h:59
SleepMode
Definition sim_sleep.h:49
unsigned long flash_addr_t
Definition sim_types.h:42
short int_vect_t
Definition sim_types.h:43
Definition sim_interrupt.h:105
int_vect_t vector
Vector index.
Definition sim_interrupt.h:107
flash_addr_t address
Address (in bytes) of the interrupt vector.
Definition sim_interrupt.h:109
bool nmi
Non-maskable (by GIE) indicator flag.
Definition sim_interrupt.h:111
Bit mask structure for bitwise operations on 8-bits registers.
Definition sim_types.h:86
Definition sim_peripheral.h:237
Definition sim_ioreg.h:39
Address + bit mask structure.
Definition sim_types.h:156