gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
clint.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 Huawei International
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include "dev/riscv/clint.hh"
39
40#include "cpu/base.hh"
41#include "debug/Clint.hh"
42#include "mem/packet.hh"
43#include "mem/packet_access.hh"
44#include "params/Clint.hh"
45#include "sim/system.hh"
46
47namespace gem5
48{
49
50using namespace RiscvISA;
51
53 BasicPioDevice(params, params.pio_size),
55 nThread(params.num_threads),
56 signal(params.name + ".signal", 0, this, INT_RTC),
57 reset(params.name + ".reset"),
58 resetMtimecmp(params.reset_mtimecmp),
59 registers(params.name + ".registers", params.pio_addr, this,
60 params.mtimecmp_reset_value)
61{
62 reset.onChange([this](const bool& new_val){
63 if (new_val) {
64 doReset();
65 }
66 });
67}
68
69void
71{
72 // Increment mtime when received RTC signal
73 uint64_t& mtime = registers.mtime.get();
74 if (id == INT_RTC) {
75 mtime++;
76 }
77
78 for (int context_id = 0; context_id < nThread; context_id++) {
79
80 auto tc = system->threads[context_id];
81
82 // Update misc reg file
83 ISA* isa = dynamic_cast<ISA*>(tc->getIsaPtr());
84 if (isa->rvType() == RV32) {
85 isa->setMiscRegNoEffect(MISCREG_TIME, bits(mtime, 31, 0));
86 isa->setMiscRegNoEffect(MISCREG_TIMEH, bits(mtime, 63, 32));
87 } else {
89 }
90
91 // Post timer interrupt
92 uint64_t mtimecmp = registers.mtimecmp[context_id].get();
93 if (mtime >= mtimecmp) {
94 if (mtime == mtimecmp) {
96 "MTIP posted - thread: %d, mtime: %d, mtimecmp: %d\n",
97 context_id, mtime, mtimecmp);
98 }
99 tc->getCpuPtr()->postInterrupt(tc->threadId(),
100 ExceptionCode::INT_TIMER_MACHINE, 0);
101 } else {
102 tc->getCpuPtr()->clearInterrupt(tc->threadId(),
103 ExceptionCode::INT_TIMER_MACHINE, 0);
104 }
105 }
106}
107
108void
110{
111 using namespace std::placeholders;
112
113 // Sanity check
114 assert(clint->pioSize >= minBankSize);
115
116 // Calculate reserved space size
117 const size_t reserved0_size = mtimecmpStart - clint->nThread * 4;
118 reserved.emplace_back("reserved0", reserved0_size);
119 const size_t reserved1_size = mtimeStart
120 - mtimecmpStart - clint->nThread * 8;
121 reserved.emplace_back("reserved1", reserved1_size);
122 const size_t reserved2_size = clint->pioSize - minBankSize;
123 if (reserved2_size > 0) {
124 reserved.emplace_back("reserved2", reserved2_size);
125 }
126
127 // Initialize registers
128 for (int i = 0; i < clint->nThread; i++) {
129 msip.emplace_back(std::string("msip") + std::to_string(i), 0);
130 mtimecmp.emplace_back(
131 std::string("mtimecmp") + std::to_string(i), mtimecmpResetValue);
132 }
133
134 // Add registers to bank
135 for (int i = 0; i < clint->nThread; i++) {
136 auto write_cb = std::bind(&Clint::writeMSIP, clint, _1, _2, i);
137 msip[i].writeable(0x1);
138 msip[i].writer(write_cb);
140 }
142 for (int i = 0; i < clint->nThread; i++) {
144 }
146 mtime.readonly();
148 if (reserved2_size > 0) {
150 }
151}
152
153void
154Clint::writeMSIP(Register32& reg, const uint32_t& data, const int thread_id)
155{
156 reg.update(data);
157 updateMSIP(thread_id);
158};
159
160Tick
162{
163 // Check for atomic operation
164 bool is_atomic = pkt->isAtomicOp() && pkt->cmd == MemCmd::SwapReq;
166 "Read request - addr: %#x, size: %#x, atomic:%d\n",
167 pkt->getAddr(), pkt->getSize(), is_atomic);
168
169 // Perform register read
170 registers.read(pkt->getAddr(), pkt->getPtr<void>(), pkt->getSize());
171
172 if (is_atomic) {
173 // Perform atomic operation
174 (*(pkt->getAtomicOp()))(pkt->getPtr<uint8_t>());
175 return write(pkt);
176 } else {
177 pkt->makeResponse();
178 return pioDelay;
179 }
180}
181
182Tick
184{
186 "Write request - addr: %#x, size: %#x\n",
187 pkt->getAddr(), pkt->getSize());
188
189 // Perform register write
190 registers.write(pkt->getAddr(), pkt->getPtr<void>(), pkt->getSize());
191
192 pkt->makeResponse();
193 return pioDelay;
194}
195
196void
198{
199 registers.init();
201}
202
203Port &
204Clint::getPort(const std::string &if_name, PortID idx)
205{
206 if (if_name == "int_pin")
207 return signal;
208 else if (if_name == "reset")
209 return reset;
210 else
211 return BasicPioDevice::getPort(if_name, idx);
212}
213
214void
216{
217 for (auto const &reg: registers.msip) {
218 paramOut(cp, reg.name(), reg);
219 }
220 for (auto const &reg: registers.mtimecmp) {
221 paramOut(cp, reg.name(), reg);
222 }
223 paramOut(cp, "mtime", registers.mtime);
224}
225
226void
228{
229 for (auto &reg: registers.msip) {
230 paramIn(cp, reg.name(), reg);
231 }
232 for (auto &reg: registers.mtimecmp) {
233 paramIn(cp, reg.name(), reg);
234 }
235 paramIn(cp, "mtime", registers.mtime);
236}
237
238void
239Clint::updateMSIP(const int thread_id)
240{
241 auto tc = system->threads[thread_id];
242 if (registers.msip[thread_id].get()) {
243 DPRINTF(Clint, "MSIP posted - thread: %d\n", thread_id);
244 tc->getCpuPtr()->postInterrupt(tc->threadId(),
245 ExceptionCode::INT_SOFTWARE_MACHINE, 0);
246 } else {
247 DPRINTF(Clint, "MSIP cleared - thread: %d\n", thread_id);
248 tc->getCpuPtr()->clearInterrupt(tc->threadId(),
249 ExceptionCode::INT_SOFTWARE_MACHINE, 0);
250 }
251}
252
253void
255 registers.mtime.reset();
256 for (int i = 0; i < nThread; i++) {
257 // According to the spec, the mtimecmp is in unknown state
258 // Assume we will change the mtimecmp registers to specify value
259 // if the mtimecmp registers accept the reset signal.
260 if (resetMtimecmp) {
261 registers.mtimecmp[i].reset();
262 }
263 registers.msip[i].reset();
264 updateMSIP(i);
265 }
266 // We need to update the mtip interrupt bits when reset
268}
269
270} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
const char data[]
void setMiscRegNoEffect(RegIndex idx, RegVal val) override
Definition isa.cc:674
BasicPioDevice(const Params &p, Addr size)
Definition io_device.cc:75
Tick pioDelay
Delay that the device experinces on an access.
Definition io_device.hh:157
std::vector< Register64 > mtimecmp
Definition clint.hh:121
std::vector< RegisterRaz > reserved
Definition clint.hh:123
std::vector< Register32 > msip
Definition clint.hh:120
void updateMSIP(const int thread_id)
Software Interrupt.
Definition clint.cc:239
void raiseInterruptPin(int id)
Timer tick callback.
Definition clint.cc:70
Clint(const Params &params)
Definition clint.cc:52
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition clint.cc:204
System * system
Definition clint.hh:74
void init() override
SimObject functions.
Definition clint.cc:197
int nThread
Definition clint.hh:75
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition clint.cc:183
SignalSinkPort< bool > reset
Definition clint.hh:77
ClintRegisters::Register32 Register32
Definition clint.hh:138
IntSinkPin< Clint > signal
Definition clint.hh:76
void writeMSIP(Register32 &reg, const uint32_t &data, const int thread_id)
Definition clint.cc:154
gem5::Clint::ClintRegisters registers
@ INT_RESET
Definition clint.hh:98
void doReset()
Definition clint.cc:254
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition clint.cc:227
bool resetMtimecmp
Definition clint.hh:78
ClintParams Params
Definition clint.hh:81
Tick read(PacketPtr pkt) override
PioDevice interface functions.
Definition clint.cc:161
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition clint.cc:215
Addr getAddr() const
Definition packet.hh:807
bool isAtomicOp() const
Definition packet.hh:846
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
Definition packet.hh:1062
T * getPtr()
get a pointer to the data ptr.
Definition packet.hh:1225
unsigned getSize() const
Definition packet.hh:817
AtomicOpFunctor * getAtomicOp() const
Accessor function to atomic op.
Definition packet.hh:845
MemCmd cmd
The command field of the packet.
Definition packet.hh:372
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition io_device.cc:67
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition io_device.cc:59
Ports are used to interface objects to each other.
Definition port.hh:62
void addRegister(RegisterAdder reg)
Definition reg_bank.hh:1024
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
const Params & params() const
Bitfield< 7 > i
Definition misc_types.hh:67
constexpr enums::RiscvType RV32
Definition pcstate.hh:56
Bitfield< 5, 3 > reg
Definition types.hh:92
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
std::ostream CheckpointOut
Definition serialize.hh:66
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition types.cc:40
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition types.cc:72
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition types.hh:245
uint64_t Tick
Tick count type.
Definition types.hh:58
Packet * PacketPtr
Declaration of the Packet class.
const std::string & name()
Definition trace.cc:48

Generated on Mon May 26 2025 09:19:10 for gem5 by doxygen 1.13.2