OXYGENHUB
◆ main openmsx / src / cpu / IRQHelper.hh
2.5 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef IRQHELPER_HH
2
#define IRQHELPER_HH
3
4
#include "MSXMotherBoard.hh"
5
#include "Probe.hh"
6
#include "serialize.hh"
7
8
#include <cstdint>
9
#include <string>
10
11
namespace openmsx {
12
13
class MSXCPU;
14
class DeviceConfig;
15
16
/** Helper class for doing interrupt request (IRQ) administration.
17
  * IRQ is either enabled or disabled; when enabled it contributes
18
  * one to the CPU IRQ count, when disabled zero.
19
  * Calling set() in enabled state does nothing;
20
  * neither does calling reset() in disabled state.
21
  */
22
23
// policy class for IRQ source
24
class IRQSource
25
{
26
protected:
27
	explicit IRQSource(MSXCPU& cpu);
28
	void raise();
29
	void lower();
30
private:
31
	MSXCPU& cpu;
32
};
33
34
// supports <irq_connected> tag in hardware config
35
class OptionalIRQ
36
{
37
protected:
38
	OptionalIRQ(MSXCPU& cpu, const DeviceConfig& config);
39
	void raise();
40
	void lower();
41
private:
42
	MSXCPU& cpu;
43
	enum Type : uint8_t { NotConnected, Maskable, NonMaskable };
44
	const Type type;
45
};
46
47
48
// generic implementation
49
template<typename SOURCE> class IntHelper : public SOURCE
50
{
51
public:
52
	IntHelper(const IntHelper&) = delete;
53
	IntHelper(IntHelper&&) = delete;
54
	IntHelper& operator=(const IntHelper&) = delete;
55
	IntHelper& operator=(IntHelper&&) = delete;
56
57
	/** Create a new IntHelper.
58
	  * Initially there is no interrupt request on the bus.
59
	  */
60
	template<typename ...Args>
61
	IntHelper(MSXMotherBoard& motherboard, const std::string& name,
62
	          Args&& ...args)
63
		: SOURCE(motherboard.getCPU(), std::forward<Args>(args)...)
64
		, request(motherboard.getDebugger(), name,
65
		          "Outgoing IRQ signal.", false)
66
	{
67
	}
68
69
	/** Destroy this IntHelper.
70
	  * Resets interrupt request if it is active.
71
	  */
72
	~IntHelper() {
73
		reset();
74
	}
75
76
	/** Set the interrupt request on the bus.
77
	  */
78
	void set() {
79
		if (!request) {
80
			request = true;
81
			SOURCE::raise();
82
		}
83
	}
84
85
	/** Reset the interrupt request on the bus.
86
	  */
87
	void reset() {
88
		if (request) {
89
			request = false;
90
			SOURCE::lower();
91
		}
92
	}
93
94
	/** Convenience function: calls set() or reset().
95
	  */
96
	void set(bool s) {
97
		if (s) {
98
			set();
99
		} else {
100
			reset();
101
		}
102
	}
103
104
	/** Get the interrupt state.
105
	  * @return true iff interrupt request is active.
106
	  */
107
	[[nodiscard]] bool getState() const {
108
		return request;
109
	}
110
111
	template<typename Archive>
112
	void serialize(Archive& ar, unsigned /*version*/)
113
	{
114
		bool pending = request;
115
		ar.serialize("pending", pending);
116
		if constexpr (Archive::IS_LOADER) {
117
			set(pending);
118
		}
119
	}
120
121
private:
122
	Probe<bool> request;
123
};
124
125
// convenience types
126
using IRQHelper         = IntHelper<IRQSource>;
127
using OptionalIRQHelper = IntHelper<OptionalIRQ>;
128
129
} // namespace openmsx
130
131
#endif