gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 
47 namespace gem5
48 {
49 
50 using namespace RiscvISA;
51 
52 Clint::Clint(const Params &params) :
53  BasicPioDevice(params, params.pio_size),
54  system(params.system),
55  nThread(params.num_threads),
56  signal(params.name + ".signal", 0, this),
57  registers(params.name + ".registers", params.pio_addr, this)
58 {
59 }
60 
61 void
63 {
64  // Increment mtime
65  uint64_t& mtime = registers.mtime.get();
66  mtime++;
67 
68  for (int context_id = 0; context_id < nThread; context_id++) {
69 
70  auto tc = system->threads[context_id];
71 
72  // Update misc reg file
73  ISA* isa = dynamic_cast<ISA*>(tc->getIsaPtr());
74  if (isa->rvType() == RV32) {
75  isa->setMiscRegNoEffect(MISCREG_TIME, bits(mtime, 31, 0));
76  isa->setMiscRegNoEffect(MISCREG_TIMEH, bits(mtime, 63, 32));
77  } else {
78  isa->setMiscRegNoEffect(MISCREG_TIME, mtime);
79  }
80 
81  // Post timer interrupt
82  uint64_t mtimecmp = registers.mtimecmp[context_id].get();
83  if (mtime >= mtimecmp) {
84  if (mtime == mtimecmp) {
85  DPRINTF(Clint,
86  "MTIP posted - thread: %d, mtime: %d, mtimecmp: %d\n",
87  context_id, mtime, mtimecmp);
88  }
89  tc->getCpuPtr()->postInterrupt(tc->threadId(),
91  } else {
92  tc->getCpuPtr()->clearInterrupt(tc->threadId(),
94  }
95  }
96 }
97 
98 void
100 {
101  using namespace std::placeholders;
102 
103  // Calculate reserved space size
104  const size_t reserved0_size = mtimecmpStart - clint->nThread * 4;
105  reserved.emplace_back("reserved0", reserved0_size);
106  const size_t reserved1_size = mtimeStart
107  - mtimecmpStart - clint->nThread * 8;
108  reserved.emplace_back("reserved1", reserved1_size);
109 
110  // Sanity check
111  assert((int) clint->pioSize <= maxBankSize);
112 
113  // Initialize registers
114  for (int i = 0; i < clint->nThread; i++) {
115  msip.emplace_back(std::string("msip") + std::to_string(i), 0);
116  mtimecmp.emplace_back(std::string("mtimecmp") + std::to_string(i), 0);
117  }
118 
119  // Add registers to bank
120  for (int i = 0; i < clint->nThread; i++) {
121  auto read_cb = std::bind(&Clint::readMSIP, clint, _1, i);
122  msip[i].reader(read_cb);
123  auto write_cb = std::bind(&Clint::writeMSIP, clint, _1, _2, i);
124  msip[i].writer(write_cb);
125  addRegister(msip[i]);
126  }
127  addRegister(reserved[0]);
128  for (int i = 0; i < clint->nThread; i++) {
130  }
131  addRegister(reserved[1]);
132  mtime.readonly();
134 }
135 
136 uint32_t
137 Clint::readMSIP(Register32& reg, const int thread_id)
138 {
139  // To avoid discrepancies if mip is externally set using remote_gdb etc.
140  auto tc = system->threads[thread_id];
141  RegVal mip = tc->readMiscReg(MISCREG_IP);
142  uint32_t msip = bits<uint32_t>(mip, ExceptionCode::INT_SOFTWARE_MACHINE);
143  reg.update(msip);
144  return reg.get();
145 };
146 
147 void
148 Clint::writeMSIP(Register32& reg, const uint32_t& data, const int thread_id)
149 {
150  reg.update(data);
151  assert(data <= 1);
152  auto tc = system->threads[thread_id];
153  if (data > 0) {
154  DPRINTF(Clint, "MSIP posted - thread: %d\n", thread_id);
155  tc->getCpuPtr()->postInterrupt(tc->threadId(),
157  } else {
158  DPRINTF(Clint, "MSIP cleared - thread: %d\n", thread_id);
159  tc->getCpuPtr()->clearInterrupt(tc->threadId(),
161  }
162 };
163 
164 Tick
166 {
167  // Check for atomic operation
168  bool is_atomic = pkt->isAtomicOp() && pkt->cmd == MemCmd::SwapReq;
169  DPRINTF(Clint,
170  "Read request - addr: %#x, size: %#x, atomic:%d\n",
171  pkt->getAddr(), pkt->getSize(), is_atomic);
172 
173  // Perform register read
174  registers.read(pkt->getAddr(), pkt->getPtr<void>(), pkt->getSize());
175 
176  if (is_atomic) {
177  // Perform atomic operation
178  (*(pkt->getAtomicOp()))(pkt->getPtr<uint8_t>());
179  return write(pkt);
180  } else {
181  pkt->makeResponse();
182  return pioDelay;
183  }
184 }
185 
186 Tick
188 {
189  DPRINTF(Clint,
190  "Write request - addr: %#x, size: %#x\n",
191  pkt->getAddr(), pkt->getSize());
192 
193  // Perform register write
194  registers.write(pkt->getAddr(), pkt->getPtr<void>(), pkt->getSize());
195 
196  pkt->makeResponse();
197  return pioDelay;
198 }
199 
200 void
202 {
203  registers.init();
205 }
206 
207 Port &
208 Clint::getPort(const std::string &if_name, PortID idx)
209 {
210  if (if_name == "int_pin")
211  return signal;
212  else
213  return BasicPioDevice::getPort(if_name, idx);
214 }
215 
216 void
218 {
219  for (auto const &reg: registers.msip) {
220  paramOut(cp, reg.name(), reg);
221  }
222  for (auto const &reg: registers.mtimecmp) {
223  paramOut(cp, reg.name(), reg);
224  }
225  paramOut(cp, "mtime", registers.mtime);
226 }
227 
228 void
230 {
231  for (auto &reg: registers.msip) {
232  paramIn(cp, reg.name(), reg);
233  }
234  for (auto &reg: registers.mtimecmp) {
235  paramIn(cp, reg.name(), reg);
236  }
237  paramIn(cp, "mtime", registers.mtime);
238 }
239 
240 } // namespace gem5
gem5::PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:245
gem5::Packet::isAtomicOp
bool isAtomicOp() const
Definition: packet.hh:846
gem5::RegisterBank< ByteOrder::little >::addRegister
void addRegister(RegisterAdder reg)
Definition: reg_bank.hh:938
gem5::Clint::nThread
int nThread
Definition: clint.hh:75
gem5::RegVal
uint64_t RegVal
Definition: types.hh:173
system.hh
gem5::Clint::ClintRegisters::mtime
Register64 mtime
Definition: clint.hh:112
data
const char data[]
Definition: circlebuf.test.cc:48
gem5::MemCmd::SwapReq
@ SwapReq
Definition: packet.hh:120
gem5::Clint::write
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: clint.cc:187
gem5::Clint::writeMSIP
void writeMSIP(Register32 &reg, const uint32_t &data, const int thread_id)
Definition: clint.cc:148
gem5::Clint::ClintRegisters::init
void init()
Definition: clint.cc:99
gem5::Clint::registers
gem5::Clint::ClintRegisters registers
gem5::ArmISA::ISA
Definition: isa.hh:70
gem5::Clint::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: clint.cc:229
gem5::Clint::signal
IntSinkPin< Clint > signal
Definition: clint.hh:76
gem5::CheckpointIn
Definition: serialize.hh:68
sc_dt::to_string
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:91
gem5::RiscvISA::MISCREG_TIMEH
@ MISCREG_TIMEH
Definition: misc.hh:208
gem5::RegisterBank< ByteOrder::little >::write
virtual void write(Addr addr, const void *buf, Addr bytes)
Definition: reg_bank.hh:1002
gem5::X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:1004
gem5::RiscvISA::RV32
constexpr enums::RiscvType RV32
Definition: pcstate.hh:54
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
clint.hh
gem5::Clint::ClintRegisters::reserved
std::vector< RegisterRaz > reserved
Definition: clint.hh:113
gem5::Clint::init
void init() override
SimObject functions.
Definition: clint.cc:201
gem5::Clint::system
System * system
Definition: clint.hh:74
gem5::Clint::ClintRegisters::mtimecmp
std::vector< Register64 > mtimecmp
Definition: clint.hh:111
packet.hh
gem5::PioDevice::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: io_device.cc:59
gem5::PioDevice::Params
PioDeviceParams Params
Definition: io_device.hh:134
gem5::Clint::Clint
Clint(const Params &params)
Definition: clint.cc:52
gem5::Packet::getAtomicOp
AtomicOpFunctor * getAtomicOp() const
Accessor function to atomic op.
Definition: packet.hh:845
gem5::Clint
NOTE: This implementation of CLINT is based on the SiFive U54MC datasheet: https://sifive....
Definition: clint.hh:70
gem5::Clint::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: clint.cc:208
gem5::RiscvISA::INT_TIMER_MACHINE
@ INT_TIMER_MACHINE
Definition: faults.hh:92
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:210
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
gem5::Clint::Register32
ClintRegisters::Register32 Register32
Definition: clint.hh:125
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::Clint::ClintRegisters::maxBankSize
const Addr maxBankSize
Definition: clint.hh:108
gem5::Clint::read
Tick read(PacketPtr pkt) override
PioDevice interface functions.
Definition: clint.cc:165
gem5::BasicPioDevice::pioDelay
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:157
gem5::Clint::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: clint.cc:217
gem5::bits
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:76
gem5::Packet::cmd
MemCmd cmd
The command field of the packet.
Definition: packet.hh:372
gem5::Clint::ClintRegisters::mtimecmpStart
const Addr mtimecmpStart
Definition: clint.hh:106
gem5::RiscvISA::INT_SOFTWARE_MACHINE
@ INT_SOFTWARE_MACHINE
Definition: faults.hh:89
name
const std::string & name()
Definition: trace.cc:48
packet_access.hh
gem5::X86ISA::reg
Bitfield< 5, 3 > reg
Definition: types.hh:92
gem5::RegisterBank::read
virtual void read(Addr addr, void *buf, Addr bytes)
Definition: reg_bank.hh:945
gem5::ArmISA::ISA::setMiscRegNoEffect
void setMiscRegNoEffect(RegIndex idx, RegVal val) override
Definition: isa.cc:633
gem5::paramOut
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition: types.cc:40
base.hh
gem5::Port
Ports are used to interface objects to each other.
Definition: port.hh:61
gem5::System::threads
Threads threads
Definition: system.hh:310
gem5::Clint::ClintRegisters::clint
Clint * clint
Definition: clint.hh:119
gem5::Packet::makeResponse
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
gem5::paramIn
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition: types.cc:72
gem5::RiscvISA::MISCREG_TIME
@ MISCREG_TIME
Definition: misc.hh:79
gem5::BasicPioDevice::pioSize
Addr pioSize
Size that the device's address range.
Definition: io_device.hh:154
gem5::CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:66
gem5::Clint::readMSIP
uint32_t readMSIP(Register32 &reg, const int thread_id)
Definition: clint.cc:137
gem5::Packet::getAddr
Addr getAddr() const
Definition: packet.hh:807
gem5::Clint::raiseInterruptPin
void raiseInterruptPin(int id)
Timer tick callback.
Definition: clint.cc:62
gem5::Clint::ClintRegisters::mtimeStart
const Addr mtimeStart
Definition: clint.hh:107
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::Clint::ClintRegisters::msip
std::vector< Register32 > msip
Definition: clint.hh:110
gem5::BasicPioDevice
Definition: io_device.hh:147
gem5::RiscvISA::MISCREG_IP
@ MISCREG_IP
Definition: misc.hh:76
gem5::Packet::getSize
unsigned getSize() const
Definition: packet.hh:817
gem5::PioDevice::getPort
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
gem5::Packet::getPtr
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:1225

Generated on Sun Jul 30 2023 01:56:56 for gem5 by doxygen 1.8.17