SimpleKernel 1.17.0
Loading...
Searching...
No Matches
Plic Class Reference

Plic 驱动 More...

#include <plic.h>

Collaboration diagram for Plic:
Collaboration graph

Public Types

using InterruptDelegate = InterruptBase::InterruptDelegate
 

Public Member Functions

auto Which () const -> uint32_t
 Plic 询问中断
 
auto Done (uint32_t source_id) const -> void
 告知 Plic 已经处理了当前 IRQ
 
auto Set (uint32_t hart_id, uint32_t source_id, uint32_t priority, bool enable) const -> void
 设置指定中断源的使能状态
 
auto Get (uint32_t hart_id, uint32_t source_id) const -> std::tuple< uint32_t, bool, bool >
 获取指定中断源的状态信息
 
auto RegisterInterruptFunc (uint8_t cause, InterruptDelegate func) -> void
 注册外部中断处理函数
 
auto Do (uint64_t cause, cpu_io::TrapContext *context) -> void
 执行外部中断处理
 
构造/析构函数
 Plic (uint64_t dev_addr, size_t ndev, size_t context_count)
 构造函数
 
 Plic ()=default
 
 Plic (const Plic &)=default
 
 Plic (Plic &&)=default
 
auto operator= (const Plic &) -> Plic &=default
 
auto operator= (Plic &&) -> Plic &=default
 
 ~Plic ()=default
 

Static Public Attributes

static constexpr size_t kInterruptMaxCount = 16
 最大外部中断数量
 

Private Member Functions

__always_inline auto GetContextId (uint32_t hart_id, uint32_t mode=1) const -> uint32_t
 计算 context ID
 
auto GetEnableBit (uint32_t context_id, uint32_t source_id) const -> bool
 获取使能位寄存器中指定中断源的状态
 
auto SetEnableBit (uint32_t context_id, uint32_t source_id, bool value) const -> void
 设置使能位寄存器中指定中断源的状态
 
auto SourcePriority (uint32_t source_id) const -> uint32_t &
 获取中断源优先级寄存器
 
auto GetPendingBit (uint32_t source_id) const -> bool
 获取挂起位寄存器中指定中断源的状态
 
auto SetPendingBit (uint32_t source_id, bool value) const -> void
 设置挂起位寄存器中指定中断源的状态
 
auto PriorityThreshold (uint32_t context_id) const -> uint32_t &
 获取优先级阈值寄存器
 
auto ClaimComplete (uint32_t context_id) const -> uint32_t &
 获取声明/完成寄存器
 

Private Attributes

uint64_t base_addr_ {0}
 
size_t ndev_ {0}
 
size_t context_count_ {0}
 

Static Private Attributes

static constexpr uint64_t kSourcePriorityOffset = 0x000000
 
static constexpr uint64_t kPendingBitsOffset = 0x001000
 
static constexpr uint64_t kEnableBitsOffset = 0x002000
 
static constexpr uint64_t kContextOffset = 0x200000
 
static constexpr uint64_t kContextSize = 0x1000
 
static constexpr uint64_t kPriorityThresholdOffset = 0x0
 
static constexpr uint64_t kClaimCompleteOffset = 0x4
 
static constexpr uint64_t kEnableSize = 0x80
 
static std::array< InterruptDelegate, kInterruptMaxCountinterrupt_handlers_
 外部中断处理函数数组
 

Detailed Description

Plic 驱动

See also
https://github.com/riscv/riscv-plic

Definition at line 20 of file plic.h.

Member Typedef Documentation

◆ InterruptDelegate

Constructor & Destructor Documentation

◆ Plic() [1/4]

Plic::Plic ( uint64_t  dev_addr,
size_t  ndev,
size_t  context_count 
)
explicit

构造函数

Parameters
dev_addr设备地址
ndev支持的中断源数量 (riscv,ndev)
context_count上下文数量 (通常为 2 * core_count)

Definition at line 24 of file plic.cpp.

25 : base_addr_(dev_addr), ndev_(ndev), context_count_(context_count) {
26 // 设置所有中断源的优先级为 0 (禁用)
27 klog::Info("Setting all interrupt priorities to 0");
28 for (size_t source_id = 0; source_id <= ndev_; source_id++) {
29 SourcePriority(source_id) = 0;
30 }
31
32 klog::Info("Disabling all interrupts for all contexts");
33
34 for (size_t context_id = 0; context_id < context_count_; context_id++) {
35 // 设置优先级阈值为 0 (允许所有优先级的中断)
36 PriorityThreshold(context_id) = 0;
37 // 禁用所有中断
38 for (size_t source_id = 0; source_id <= ndev_; source_id++) {
39 SetEnableBit(context_id, source_id, false);
40 }
41 }
42
44 "PLIC initialization: all interrupts disabled, priorities set to 0");
45
46 for (auto& h : interrupt_handlers_) {
47 h = InterruptDelegate::create<DefaultPlicHandler>();
48 }
49}
size_t ndev_
Definition plic.h:109
uint64_t base_addr_
Definition plic.h:108
size_t context_count_
Definition plic.h:110
auto PriorityThreshold(uint32_t context_id) const -> uint32_t &
获取优先级阈值寄存器
Definition plic.cpp:143
auto SourcePriority(uint32_t source_id) const -> uint32_t &
获取中断源优先级寄存器
Definition plic.cpp:118
auto SetEnableBit(uint32_t context_id, uint32_t source_id, bool value) const -> void
设置使能位寄存器中指定中断源的状态
Definition plic.cpp:104
static std::array< InterruptDelegate, kInterruptMaxCount > interrupt_handlers_
外部中断处理函数数组
Definition plic.h:106
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
Here is the call graph for this function:

◆ Plic() [2/4]

Plic::Plic ( )
default

◆ Plic() [3/4]

Plic::Plic ( const Plic )
default

◆ Plic() [4/4]

Plic::Plic ( Plic &&  )
default

◆ ~Plic()

Plic::~Plic ( )
default

Member Function Documentation

◆ ClaimComplete()

auto Plic::ClaimComplete ( uint32_t  context_id) const -> uint32_t&
private

获取声明/完成寄存器

Parameters
context_idcontext ID
Returns
uint32_t& 寄存器引用

Definition at line 149 of file plic.cpp.

149 {
150 return *reinterpret_cast<uint32_t*>(base_addr_ + kContextOffset +
151 (context_id * kContextSize) +
153}
static constexpr uint64_t kContextSize
Definition plic.h:98
static constexpr uint64_t kContextOffset
Definition plic.h:95
static constexpr uint64_t kClaimCompleteOffset
Definition plic.h:100
Here is the caller graph for this function:

◆ Do()

auto Plic::Do ( uint64_t  cause,
cpu_io::TrapContext context 
) -> void

执行外部中断处理

Parameters
cause外部中断号
context中断上下文

Definition at line 66 of file plic.cpp.

66 {
67 interrupt_handlers_[cause](cause, context);
68}

◆ Done()

auto Plic::Done ( uint32_t  source_id) const -> void

告知 Plic 已经处理了当前 IRQ

Parameters
source_id中断源 ID (1-1023)

Definition at line 56 of file plic.cpp.

56 {
57 auto context_id = GetContextId(cpu_io::GetCurrentCoreId());
58 ClaimComplete(context_id) = source_id;
59}
auto ClaimComplete(uint32_t context_id) const -> uint32_t &
获取声明/完成寄存器
Definition plic.cpp:149
__always_inline auto GetContextId(uint32_t hart_id, uint32_t mode=1) const -> uint32_t
计算 context ID
Definition plic.h:119
auto GetCurrentCoreId() -> size_t
Definition cpu_io.h:26
Here is the call graph for this function:

◆ Get()

auto Plic::Get ( uint32_t  hart_id,
uint32_t  source_id 
) const -> std::tuple<uint32_t, bool, bool>

获取指定中断源的状态信息

Parameters
hart_idhart ID
source_id中断源 ID (1-1023)
Returns
<优先级, 使能状态, 挂起状态>

Definition at line 80 of file plic.cpp.

81 {
82 // 获取中断优先级
83 auto priority = SourcePriority(source_id);
84
85 // 获取中断使能状态
86 uint32_t context_id = GetContextId(hart_id);
87 auto enabled = GetEnableBit(context_id, source_id);
88
89 // 获取中断挂起状态
90 auto pending = GetPendingBit(source_id);
91
92 return {priority, enabled, pending};
93}
auto GetEnableBit(uint32_t context_id, uint32_t source_id) const -> bool
获取使能位寄存器中指定中断源的状态
Definition plic.cpp:95
auto GetPendingBit(uint32_t source_id) const -> bool
获取挂起位寄存器中指定中断源的状态
Definition plic.cpp:123

◆ GetContextId()

__always_inline auto Plic::GetContextId ( uint32_t  hart_id,
uint32_t  mode = 1 
) const -> uint32_t
inlineprivate

计算 context ID

Parameters
hart_idhart ID
mode模式 (0=M-mode, 1=S-mode)
Returns
uint32_t context ID
Note
2 个模式的 context ID 计算方式为: hart_id * 2 + mode

Definition at line 119 of file plic.h.

121 {
122 return hart_id * 2 + mode;
123 }
Here is the caller graph for this function:

◆ GetEnableBit()

auto Plic::GetEnableBit ( uint32_t  context_id,
uint32_t  source_id 
) const -> bool
private

获取使能位寄存器中指定中断源的状态

Parameters
context_idcontext ID
source_id中断源 ID (1-1023,0 保留)
Returns
bool 对应位的状态

Definition at line 95 of file plic.cpp.

95 {
96 uint32_t word_index = source_id / 32;
97 uint32_t bit_index = source_id % 32;
98 uint32_t* word_addr = reinterpret_cast<uint32_t*>(
99 base_addr_ + kEnableBitsOffset + (context_id * kEnableSize) +
100 (word_index * 4));
101 return (*word_addr >> bit_index) & 1;
102}
static constexpr uint64_t kEnableSize
Definition plic.h:103
static constexpr uint64_t kEnableBitsOffset
Definition plic.h:94

◆ GetPendingBit()

auto Plic::GetPendingBit ( uint32_t  source_id) const -> bool
private

获取挂起位寄存器中指定中断源的状态

Parameters
source_id中断源 ID (1-1023,0 保留)
Returns
bool 对应位的状态

Definition at line 123 of file plic.cpp.

123 {
124 uint32_t word_index = source_id / 32;
125 uint32_t bit_index = source_id % 32;
126 uint32_t* word_addr = reinterpret_cast<uint32_t*>(
127 base_addr_ + kPendingBitsOffset + (word_index * 4));
128 return (*word_addr >> bit_index) & 1;
129}
static constexpr uint64_t kPendingBitsOffset
Definition plic.h:93

◆ operator=() [1/2]

auto Plic::operator= ( const Plic ) -> Plic &=default
default

◆ operator=() [2/2]

auto Plic::operator= ( Plic &&  ) -> Plic &=default
default

◆ PriorityThreshold()

auto Plic::PriorityThreshold ( uint32_t  context_id) const -> uint32_t&
private

获取优先级阈值寄存器

Parameters
context_idcontext ID
Returns
uint32_t& 寄存器引用

Definition at line 143 of file plic.cpp.

143 {
144 return *reinterpret_cast<uint32_t*>(base_addr_ + kContextOffset +
145 (context_id * kContextSize) +
147}
static constexpr uint64_t kPriorityThresholdOffset
Definition plic.h:99
Here is the caller graph for this function:

◆ RegisterInterruptFunc()

auto Plic::RegisterInterruptFunc ( uint8_t  cause,
InterruptDelegate  func 
) -> void

注册外部中断处理函数

Parameters
cause外部中断号
func外部中断处理函数

Definition at line 61 of file plic.cpp.

62 {
63 interrupt_handlers_[cause] = func;
64}

◆ Set()

auto Plic::Set ( uint32_t  hart_id,
uint32_t  source_id,
uint32_t  priority,
bool  enable 
) const -> void

设置指定中断源的使能状态

Parameters
hart_idhart ID
source_id中断源 ID (1-1023)
priority中断优先级 (0-7, 0 表示禁用)
enable是否使能该中断

Definition at line 70 of file plic.cpp.

71 {
72 // 设置中断优先级
73 SourcePriority(source_id) = priority;
74
75 // 设置中断使能状态
76 uint32_t context_id = GetContextId(hart_id);
77 SetEnableBit(context_id, source_id, enable);
78}

◆ SetEnableBit()

auto Plic::SetEnableBit ( uint32_t  context_id,
uint32_t  source_id,
bool  value 
) const -> void
private

设置使能位寄存器中指定中断源的状态

Parameters
context_idcontext ID
source_id中断源 ID (1-1023,0 保留)
value要设置的值

Definition at line 104 of file plic.cpp.

105 {
106 uint32_t word_index = source_id / 32;
107 uint32_t bit_index = source_id % 32;
108 uint32_t* word_addr = reinterpret_cast<uint32_t*>(
109 base_addr_ + kEnableBitsOffset + (context_id * kEnableSize) +
110 (word_index * 4));
111 if (value) {
112 *word_addr |= (1U << bit_index);
113 } else {
114 *word_addr &= ~(1U << bit_index);
115 }
116}
Here is the caller graph for this function:

◆ SetPendingBit()

auto Plic::SetPendingBit ( uint32_t  source_id,
bool  value 
) const -> void
private

设置挂起位寄存器中指定中断源的状态

Parameters
source_id中断源 ID (1-1023,0 保留)
value要设置的值

Definition at line 131 of file plic.cpp.

131 {
132 uint32_t word_index = source_id / 32;
133 uint32_t bit_index = source_id % 32;
134 uint32_t* word_addr = reinterpret_cast<uint32_t*>(
135 base_addr_ + kPendingBitsOffset + (word_index * 4));
136 if (value) {
137 *word_addr |= (1U << bit_index);
138 } else {
139 *word_addr &= ~(1U << bit_index);
140 }
141}

◆ SourcePriority()

auto Plic::SourcePriority ( uint32_t  source_id) const -> uint32_t&
private

获取中断源优先级寄存器

Parameters
source_id中断源 ID (1-1023,0 保留)
Returns
uint32_t& 寄存器引用

Definition at line 118 of file plic.cpp.

118 {
119 return *reinterpret_cast<uint32_t*>(base_addr_ + kSourcePriorityOffset +
120 (source_id * sizeof(uint32_t)));
121}
static constexpr uint64_t kSourcePriorityOffset
Definition plic.h:92
Here is the caller graph for this function:

◆ Which()

auto Plic::Which ( ) const -> uint32_t

Plic 询问中断

Returns
uint32_t 中断源 ID (1-1023)

Definition at line 51 of file plic.cpp.

51 {
52 auto context_id = GetContextId(cpu_io::GetCurrentCoreId());
53 return ClaimComplete(context_id);
54}
Here is the call graph for this function:

Member Data Documentation

◆ base_addr_

uint64_t Plic::base_addr_ {0}
private

Definition at line 108 of file plic.h.

108{0};

◆ context_count_

size_t Plic::context_count_ {0}
private

Definition at line 110 of file plic.h.

110{0};

◆ interrupt_handlers_

std::array< Plic::InterruptDelegate, Plic::kInterruptMaxCount > Plic::interrupt_handlers_
staticprivate

外部中断处理函数数组

Definition at line 106 of file plic.h.

◆ kClaimCompleteOffset

constexpr uint64_t Plic::kClaimCompleteOffset = 0x4
staticconstexprprivate

Definition at line 100 of file plic.h.

◆ kContextOffset

constexpr uint64_t Plic::kContextOffset = 0x200000
staticconstexprprivate

Definition at line 95 of file plic.h.

◆ kContextSize

constexpr uint64_t Plic::kContextSize = 0x1000
staticconstexprprivate

Definition at line 98 of file plic.h.

◆ kEnableBitsOffset

constexpr uint64_t Plic::kEnableBitsOffset = 0x002000
staticconstexprprivate

Definition at line 94 of file plic.h.

◆ kEnableSize

constexpr uint64_t Plic::kEnableSize = 0x80
staticconstexprprivate

Definition at line 103 of file plic.h.

◆ kInterruptMaxCount

constexpr size_t Plic::kInterruptMaxCount = 16
staticconstexpr

最大外部中断数量

Definition at line 25 of file plic.h.

◆ kPendingBitsOffset

constexpr uint64_t Plic::kPendingBitsOffset = 0x001000
staticconstexprprivate

Definition at line 93 of file plic.h.

◆ kPriorityThresholdOffset

constexpr uint64_t Plic::kPriorityThresholdOffset = 0x0
staticconstexprprivate

Definition at line 99 of file plic.h.

◆ kSourcePriorityOffset

constexpr uint64_t Plic::kSourcePriorityOffset = 0x000000
staticconstexprprivate

Definition at line 92 of file plic.h.

◆ ndev_

size_t Plic::ndev_ {0}
private

Definition at line 109 of file plic.h.

109{0};

The documentation for this class was generated from the following files: