gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
interrupts.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 Google
3 * Copyright (c) 2024 University of Rostock
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30
32
33namespace gem5
34{
35
36namespace RiscvISA
37{
38
40 ip(0),
41 ie(0),
43{
44 for (uint8_t i = 0;
45 i < p.port_local_interrupt_pins_connection_count;
46 ++i) {
47 uint8_t interruptID = p.local_interrupt_ids[i];
48 assert(interruptID <= 47);
49 std::string pinName =
50 csprintf("%s.local_interrupt_pins[%d]", p.name, i);
52 new IntSinkPin<Interrupts>(pinName,i, this, interruptID);
53 localInterruptPins.push_back(pin);
54 }
55}
56
57
58std::bitset<NumInterruptTypes>
60{
61 INTERRUPT mask = 0;
62 STATUS status = tc->readMiscReg(MISCREG_STATUS);
63 MISA misa = tc->readMiscRegNoEffect(MISCREG_ISA);
64 INTERRUPT mideleg = 0;
65 if (misa.rvs || misa.rvn) {
66 mideleg = tc->readMiscReg(MISCREG_MIDELEG);
67 }
68 INTERRUPT sideleg = 0;
69 if (misa.rvs && misa.rvn) {
70 sideleg = tc->readMiscReg(MISCREG_SIDELEG);
71 }
72 PrivilegeMode prv = (PrivilegeMode)tc->readMiscReg(MISCREG_PRV);
73 switch (prv) {
74 case PRV_U:
75 // status.uie is always 0 if misa.rvn is disabled
76 if (misa.rvs) {
77 mask = ~mideleg | (mideleg & ~sideleg);
78 if (status.uie) {
79 mask |= sideleg;
80 }
81 } else {
82 // According to the RISC-V privilege spec v1.10, if the
83 // S privilege mode is not implemented and user-trap
84 // support, setting mideleg/medeleg bits will delegate the
85 // trap to U-mode trap handler
86 mask = ~mideleg;
87 if (status.uie) {
88 mask |= mideleg;
89 }
90 }
91 break;
92 case PRV_S:
93 mask = ~mideleg;
94 if (status.sie) {
95 mask |= (mideleg & ~sideleg);
96 }
97 break;
98 case PRV_M:
99 if (status.mie) {
100 mask = ~mideleg;
101 }
102 break;
103 default:
104 panic("Unknown privilege mode %d.", prv);
105 break;
106 }
107
108 return std::bitset<NumInterruptTypes>(mask);
109}
110
111Fault
113{
114 assert(checkInterrupts());
116 return std::make_shared<NonMaskableInterruptFault>(nmi_cause);
117 std::bitset<NumInterruptTypes> mask = globalMask();
118 if (((ISA*) tc->getIsaPtr())->rvType() == RV64) {
119 const std::vector<int> interrupt_order {
135 };
136 for (const int &id : interrupt_order) {
137 if (checkInterrupt(id) && mask[id]) {
138 return std::make_shared<InterruptFault>(id);
139 }
140 }
141 } else if (((ISA*) tc->getIsaPtr())->rvType() == RV32) {
142 const std::vector<int> interrupt_order {
150 };
151 for (const int &id : interrupt_order) {
152 if (checkInterrupt(id) && mask[id]) {
153 return std::make_shared<InterruptFault>(id);
154 }
155 }
156 }
157 return NoFault;
158}
159
160void
161Interrupts::post(int int_num, int index)
162{
163 DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
164 if (int_num != INT_NMI) {
165 ip[int_num] = true;
166 } else {
167 postNMI();
168 }
169}
170
171void
172Interrupts::clear(int int_num, int index)
173{
174 DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
175 if (int_num != INT_NMI) {
176 ip[int_num] = false;
177 } else {
178 clearNMI();
179 }
180}
181
182void
184{
185 DPRINTF(Interrupt, "All interrupts cleared\n");
186 ip = 0;
187 clearNMI();
188}
189
190void
192{
193 tc->getCpuPtr()->postInterrupt(tc->threadId(), num + 16, 0);
194}
195
196void
198{
199 unsigned long ip_ulong = ip.to_ulong();
200 unsigned long ie_ulong = ie.to_ulong();
201 SERIALIZE_SCALAR(ip_ulong);
202 SERIALIZE_SCALAR(ie_ulong);
203}
204
205void
207{
208 unsigned long ip_ulong;
209 unsigned long ie_ulong;
210 UNSERIALIZE_SCALAR(ip_ulong);
211 ip = ip_ulong;
212 UNSERIALIZE_SCALAR(ie_ulong);
213 ie = ie_ulong;
214}
215
216Port &
217Interrupts::getPort(const std::string &if_name, PortID idx)
218{
219
220 if (if_name == "local_interrupt_pins" && idx < localInterruptPins.size()) {
221 return *localInterruptPins[idx];
222 } else {
223 return BaseInterrupts::getPort(if_name, idx);
224 }
225}
226
227} // namespace RiscvISA
228
229} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
ThreadContext * tc
Definition interrupts.hh:44
BaseInterrupts(const Params &p)
Definition interrupts.hh:49
Ports are used to interface objects to each other.
Definition port.hh:62
std::vector< gem5::IntSinkPin< Interrupts > * > localInterruptPins
Definition interrupts.hh:65
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Interrupts(const Params &p)
Definition interrupts.cc:39
void clear(int int_num, int index) override
bool checkInterrupts() const override
Definition interrupts.hh:83
bool checkNonMaskableInterrupt() const
Definition interrupts.hh:77
void post(int int_num, int index) override
void serialize(CheckpointOut &cp) const override
Serialize an object.
void raiseInterruptPin(uint32_t num)
Port & getPort(const std::string &if_name, PortID idx) override
Get a port with a given name and index.
RiscvInterruptsParams Params
Definition interrupts.hh:70
std::bitset< NumInterruptTypes > globalMask() const
Definition interrupts.cc:59
std::bitset< NumInterruptTypes > ip
Definition interrupts.hh:62
bool checkInterrupt(int num) const
Definition interrupts.hh:82
Fault getInterrupt() override
std::bitset< NumInterruptTypes > ie
Definition interrupts.hh:63
STL vector class.
Definition stl.hh:37
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Bitfield< 5, 0 > status
Bitfield< 0 > p
constexpr enums::RiscvType RV32
Definition pcstate.hh:56
Bitfield< 30, 0 > index
Bitfield< 2 > i
constexpr enums::RiscvType RV64
Definition pcstate.hh:57
@ MISCREG_SIDELEG
Definition misc.hh:178
@ MISCREG_STATUS
Definition misc.hh:76
@ MISCREG_MIDELEG
Definition misc.hh:149
@ INT_TIMER_MACHINE
Definition faults.hh:93
@ INT_SOFTWARE_SUPER
Definition faults.hh:89
@ INT_SOFTWARE_MACHINE
Definition faults.hh:90
@ INT_SOFTWARE_USER
Definition faults.hh:88
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
std::shared_ptr< FaultBase > Fault
Definition types.hh:249
std::ostream CheckpointOut
Definition serialize.hh:66
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition types.hh:245
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
IntSinkPinBase IntSinkPin
Definition intpin.hh:77
constexpr decltype(nullptr) NoFault
Definition types.hh:253
#define UNSERIALIZE_SCALAR(scalar)
Definition serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition serialize.hh:568

Generated on Mon May 26 2025 09:18:58 for gem5 by doxygen 1.13.2