44#include "debug/Plic.hh"
47#include "params/Plic.hh"
48#include "params/PlicBase.hh"
63 fatal_if(params.hart_config !=
"" && params.n_contexts != 0,
64 "the hart_config and n_contexts can't be set simultaneously");
66 if (params.n_contexts != 0) {
67 initContextFromNContexts(params.n_contexts);
69 if (params.hart_config !=
"") {
70 initContextFromHartConfig(params.hart_config);
78 assert(src_id < nSrc && src_id >= 0);
81 int src_index = src_id >> 5;
82 int src_offset = src_id & 0x1F;
84 uint32_t& pending =
registers.pending[src_index].get();
85 std::bitset<32> pending_bits(pending);
86 pending_bits[src_offset] = 1;
87 pending = (uint32_t) pending_bits.to_ulong();
96 "Int post request - source: %#x, current priority: %#x\n",
107 assert(src_id <
nSrc);
111 int src_index = src_id >> 5;
112 int src_offset = src_id & 0x1F;
113 uint32_t& pending =
registers.pending[src_index].get();
114 std::bitset<32> pending_bits(pending);
115 pending_bits[src_offset] = 0;
116 pending = (uint32_t) pending_bits.to_ulong();
124 "Int clear request - source: %#x, current priority: %#x\n",
137 "Read request - addr: %#x, size: %#x, atomic:%d\n",
157 "Write request - addr: %#x, size: %#x\n",
197 "Device init - %d contexts, %d sources, %d pending registers\n",
206 using namespace std::placeholders;
210 reserved.emplace_back(
"reserved0", reserve0_size);
213 reserved.emplace_back(
"reserved1", reserve1_size);
216 reserved.emplace_back(
"reserved2", reserve2_size);
219 reserved.emplace_back(
"reserved3", reserve3_size);
231 for (
int i = 0;
i <
plic->nSrc;
i++) {
233 std::string(
"priority") + std::to_string(
i), 0);
235 for (
int i = 0;
i <
plic->nSrc32;
i++) {
237 std::string(
"pending") + std::to_string(
i), 0);
239 for (
int i = 0;
i <
plic->contextConfigs.size();
i++) {
242 for (
int j = 0; j <
plic->nSrc32; j++) {
244 std::string(
"enable") + std::to_string(
i)
245 +
"_" + std::to_string(j), 0);
248 std::string(
"enable_hole") + std::to_string(
i), enable_hole_size);
251 std::string(
"threshold") + std::to_string(
i), 0);
253 std::string(
"claim") + std::to_string(
i), 0);
255 std::string(
"claim_hole") + std::to_string(
i), claim_hole_size);
260 for (
int i = 0;
i <
plic->nSrc;
i++) {
268 for (
int i = 0;
i <
plic->nSrc32;
i++) {
275 for (
int i = 0;
i <
plic->contextConfigs.size();
i++) {
276 for (
int j = 0; j <
plic->nSrc32; j++) {
286 for (
int i = 0;
i <
plic->contextConfigs.size();
i++) {
306 int src_index = src_id >> 5;
307 int src_offset = src_id & 0x1F;
310 bool pending =
bits(
registers.pending[src_index].get(), src_offset);
314 registers.enable[
i][src_index].get(), src_offset);
319 "Priority updated - src: %d, val: %d\n",
325 const int src32_id,
const int context_id)
329 for (
int i = 0;
i < 32;
i ++) {
330 int src_id = (src32_id << 5) +
i;
337 "Enable updated - context: %d, src32: %d, val: %#x\n",
338 context_id, src32_id,
reg.get());
343 const int context_id)
348 "Threshold updated - context: %d, val: %d\n",
349 context_id,
reg.get());
355 if (
lastID[context_id] == 0) {
357 uint32_t max_int_id =
output.maxID[context_id];
358 int src_index = max_int_id >> 5;
359 int src_offset = max_int_id & 0x1F;
363 lastID[context_id] = max_int_id;
365 "Claim success - context: %d, interrupt ID: %d\n",
366 context_id, max_int_id);
368 reg.update(max_int_id);
372 "Claim already cleared - context: %d, interrupt ID: %d\n",
373 context_id, max_int_id);
377 warn(
"PLIC claim repeated (not completed) - context: %d, last: %d",
378 context_id,
lastID[context_id]);
379 return lastID[context_id];
395 "Complete - context: %d, interrupt ID: %d\n",
396 context_id,
reg.get());
408 uint32_t max_priority;
413 new_output.maxID[
i] = max_id;
414 new_output.maxPriority[
i] = max_priority;
426 if (!
update.scheduled()) {
427 DPRINTF(
Plic,
"Update scheduled - tick: %d\n", next_update);
436 for (uint32_t
i = 0;
i < (uint32_t)n_contexts;
i += 2) {
446 uint32_t hart_id = 0;
447 for (
char c: hart_config) {
453 contextConfigs.emplace_back(hart_id, ExceptionCode::INT_EXT_MACHINE);
456 contextConfigs.emplace_back(hart_id, ExceptionCode::INT_EXT_SUPER);
459 fatal(
"hart_config should not contains the value: %c",
c);
490 auto tc =
system->threads[thread_id];
491 uint32_t max_id =
output.maxID[
i];
493 uint32_t threshold =
registers.threshold[
i].get();
495 DPRINTF(
Plic,
"Int posted - thread: %d, int id: %d, ",
498 tc->getCpuPtr()->postInterrupt(tc->threadId(), int_id, 0);
501 DPRINTF(
Plic,
"Int filtered - thread: %d, int id: %d, ",
505 tc->getCpuPtr()->clearInterrupt(tc->threadId(), int_id, 0);
522 for (
auto const ®_inner:
reg) {
534 std::to_string(n_outputs), it.first);
536 std::to_string(n_outputs), it.second.maxID);
538 std::to_string(n_outputs), it.second.maxPriority);
565 for (
auto ®_inner:
reg) {
566 paramIn(
cp, reg_inner.name(), reg_inner);
575 for (
int i = 0;
i < n_outputs;
i++) {
580 std::to_string(
i), output_tick);
582 std::to_string(
i), output_id);
584 std::to_string(
i), output_pri);
Addr pioAddr
Address that the device listens to.
Tick pioDelay
Delay that the device experinces on an access.
Tick cyclesToTicks(Cycles c) const
Cycles is a wrapper class for representing cycle counts, i.e.
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
T * getPtr()
get a pointer to the data ptr.
AtomicOpFunctor * getAtomicOp() const
Accessor function to atomic op.
MemCmd cmd
The command field of the packet.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
PlicBase(const Params ¶ms)
std::vector< Register32 > priority
const Addr thresholdPadding
std::vector< Register32 > pending
std::vector< RegisterRaz > enable_holes
const Addr thresholdStart
std::vector< Register32 > threshold
std::vector< std::vector< Register32 > > enable
std::vector< RegisterRaz > reserved
std::vector< RegisterRaz > claim_holes
std::vector< Register32 > claim
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
std::vector< uint32_t > lastID
std::map< Tick, PlicOutput > outputQueue
void updateOutput()
Trigger:
gem5::Plic::PlicRegisters registers
Plic(const Params ¶ms)
void post(int src_id) override
Interrupt interface.
std::vector< std::pair< uint32_t, ExceptionCode > > contextConfigs
PLIC hart/pmode address configs, stored in the format {hartID, pmode}.
EventFunctionWrapper update
Tick read(PacketPtr pkt) override
PioDevice funcitons.
PlicRegisters::Register32 Register32
void writeEnable(Register32 ®, const uint32_t &data, const int src32_id, const int context_id)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void clear(int src_id) override
void writeThreshold(Register32 ®, const uint32_t &data, const int context_id)
uint32_t readClaim(Register32 ®, const int context_id)
void initContextFromHartConfig(const std::string &hart_config)
std::vector< std::vector< uint32_t > > effPriority
void propagateOutput()
Trigger:
int nSrc32
Number of 32-bit pending registers needed = ceil(nSrc / 32)
void init() override
SimObject functions.
std::vector< uint32_t > pendingPriority
void writeClaim(Register32 ®, const uint32_t &data, const int context_id)
void serialize(CheckpointOut &cp) const override
Serialize an object.
void initContextFromNContexts(int n_contexts)
The function for handling context config from params.
void writePriority(Register32 ®, const uint32_t &data, const int src_id)
Register read / write callbacks.
void addRegister(RegisterAdder reg)
static constexpr T divCeil(const T &a, const U &b)
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
void schedule(Event &event, Tick when)
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
#define fatal(...)
This implements a cprintf based fatal() function.
#define UNSERIALIZE_CONTAINER(member)
#define SERIALIZE_CONTAINER(member)
const Params & params() const
Bitfield< 3, 0 > priority
Copyright (c) 2024 Arm Limited All rights reserved.
Tick curTick()
The universal simulation clock.
std::ostream CheckpointOut
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
void arrayParamOut(CheckpointOut &cp, const std::string &name, const CircleBuf< T > ¶m)
uint64_t Tick
Tick count type.
void arrayParamIn(CheckpointIn &cp, const std::string &name, CircleBuf< T > ¶m)
Declaration of the Packet class.
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
NOTE: This implementation of PLIC is based on he riscv-plic-spec repository: https://github....
const std::string & name()