44#include "debug/Plic.hh"
47#include "params/Plic.hh"
48#include "params/PlicBase.hh"
64 fatal_if(params.hart_config !=
"" && params.n_contexts != 0,
65 "the hart_config and n_contexts can't be set simultaneously");
67 if (params.n_contexts != 0) {
68 initContextFromNContexts(params.n_contexts);
70 if (params.hart_config !=
"") {
71 initContextFromHartConfig(params.hart_config);
79 assert(src_id < nSrc && src_id >= 0);
82 int src_index = src_id >> 5;
83 int src_offset = src_id & 0x1F;
85 uint32_t& pending =
registers.pending[src_index].get();
86 std::bitset<32> pending_bits(pending);
87 pending_bits[src_offset] = 1;
88 pending = (uint32_t) pending_bits.to_ulong();
97 "Int post request - source: %#x, current priority: %#x\n",
108 assert(src_id <
nSrc);
112 int src_index = src_id >> 5;
113 int src_offset = src_id & 0x1F;
114 uint32_t& pending =
registers.pending[src_index].get();
115 std::bitset<32> pending_bits(pending);
116 pending_bits[src_offset] = 0;
117 pending = (uint32_t) pending_bits.to_ulong();
125 "Int clear request - source: %#x, current priority: %#x\n",
138 "Read request - addr: %#x, size: %#x, atomic:%d\n",
158 "Write request - addr: %#x, size: %#x\n",
198 "Device init - %d contexts, %d sources, %d pending registers\n",
207 using namespace std::placeholders;
211 reserved.emplace_back(
"reserved0", reserve0_size);
214 reserved.emplace_back(
"reserved1", reserve1_size);
217 reserved.emplace_back(
"reserved2", reserve2_size);
220 reserved.emplace_back(
"reserved3", reserve3_size);
232 for (
int i = 0;
i <
plic->nSrc;
i++) {
234 std::string(
"priority") + std::to_string(
i), 0);
236 for (
int i = 0;
i <
plic->nSrc32;
i++) {
238 std::string(
"pending") + std::to_string(
i), 0);
240 for (
int i = 0;
i <
plic->contextConfigs.size();
i++) {
243 for (
int j = 0; j <
plic->nSrc32; j++) {
245 std::string(
"enable") + std::to_string(
i)
246 +
"_" + std::to_string(j), 0);
249 std::string(
"enable_hole") + std::to_string(
i), enable_hole_size);
252 std::string(
"threshold") + std::to_string(
i), 0);
254 std::string(
"claim") + std::to_string(
i), 0);
256 std::string(
"claim_hole") + std::to_string(
i), claim_hole_size);
261 for (
int i = 0;
i <
plic->nSrc;
i++) {
269 for (
int i = 0;
i <
plic->nSrc32;
i++) {
276 for (
int i = 0;
i <
plic->contextConfigs.size();
i++) {
277 for (
int j = 0; j <
plic->nSrc32; j++) {
287 for (
int i = 0;
i <
plic->contextConfigs.size();
i++) {
307 int src_index = src_id >> 5;
308 int src_offset = src_id & 0x1F;
311 bool pending =
bits(
registers.pending[src_index].get(), src_offset);
315 registers.enable[
i][src_index].get(), src_offset);
320 "Priority updated - src: %d, val: %d\n",
326 const int src32_id,
const int context_id)
330 for (
int i = 0;
i < 32;
i ++) {
331 int src_id = (src32_id << 5) +
i;
338 "Enable updated - context: %d, src32: %d, val: %#x\n",
339 context_id, src32_id,
reg.get());
344 const int context_id)
349 "Threshold updated - context: %d, val: %d\n",
350 context_id,
reg.get());
356 if (
lastID[context_id] == 0) {
358 uint32_t max_int_id =
output.maxID[context_id];
359 int src_index = max_int_id >> 5;
360 int src_offset = max_int_id & 0x1F;
364 lastID[context_id] = max_int_id;
366 "Claim success - context: %d, interrupt ID: %d\n",
367 context_id, max_int_id);
369 reg.update(max_int_id);
373 "Claim already cleared - context: %d, interrupt ID: %d\n",
374 context_id, max_int_id);
378 warn(
"PLIC claim repeated (not completed) - context: %d, last: %d",
379 context_id,
lastID[context_id]);
380 return lastID[context_id];
396 "Complete - context: %d, interrupt ID: %d\n",
397 context_id,
reg.get());
409 uint32_t max_priority;
414 new_output.
maxID[
i] = max_id;
427 if (!
update.scheduled()) {
428 DPRINTF(
Plic,
"Update scheduled - tick: %d\n", next_update);
437 for (uint32_t
i = 0;
i < (uint32_t)n_contexts;
i += 2) {
447 uint32_t hart_id = 0;
448 for (
char c: hart_config) {
454 contextConfigs.emplace_back(hart_id, ExceptionCode::INT_EXT_MACHINE);
457 contextConfigs.emplace_back(hart_id, ExceptionCode::INT_EXT_SUPER);
460 fatal(
"hart_config should not contains the value: %c",
c);
491 auto tc =
system->threads[thread_id];
492 uint32_t max_id =
output.maxID[
i];
494 uint32_t threshold =
registers.threshold[
i].get();
496 DPRINTF(
Plic,
"Int posted - thread: %d, int id: %d, ",
499 tc->getCpuPtr()->postInterrupt(tc->threadId(), int_id, 0);
502 DPRINTF(
Plic,
"Int filtered - thread: %d, int id: %d, ",
506 tc->getCpuPtr()->clearInterrupt(tc->threadId(), int_id, 0);
523 for (
auto const ®_inner:
reg) {
535 std::to_string(n_outputs), it.first);
537 std::to_string(n_outputs), it.second.maxID);
539 std::to_string(n_outputs), it.second.maxPriority);
566 for (
auto ®_inner:
reg) {
567 paramIn(
cp, reg_inner.name(), reg_inner);
576 for (
int i = 0;
i < n_outputs;
i++) {
581 std::to_string(
i), output_tick);
583 std::to_string(
i), output_id);
585 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 clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
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
uint64_t outputLatency
Cycle latency from received interrupt signal to output.
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.
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....
std::vector< uint32_t > maxPriority
std::vector< uint32_t > maxID
const std::string & name()