From 2e450c594c5f7b7a7efff3dab01947b4a5ccdf71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rom=C3=A1n=20C=C3=A1rdenas=20Rodr=C3=ADguez?= Date: Wed, 28 Aug 2024 00:25:29 +0200 Subject: [PATCH] Add configuration for PLIC external interrupt handler --- Cargo.toml | 2 +- src/config.rs | 12 +++++++++++- src/generate/riscv.rs | 25 +++++++++++++++++++++++-- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6b985200..6e3239a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ default = ["bin", "json", "yaml"] bin = ["dep:clap", "dep:env_logger", "serde", "dep:irx-config"] json = ["dep:serde_json"] yaml = ["dep:serde_yaml"] -unstable-riscv = ["svd-rs/unstable-riscv", "svd-parser/unstable-riscv"] +unstable-riscv = [] [dependencies] clap = { version = "4.0", optional = true } diff --git a/src/config.rs b/src/config.rs index 2c066626..2a92b0e2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -325,7 +325,7 @@ pub struct RiscvConfig { pub priorities: Option>, pub harts: Option>, pub clint: Option, - pub plic: Option, + pub plic: Option, } #[cfg(feature = "unstable-riscv")] @@ -358,3 +358,13 @@ pub struct RiscvClintConfig { pub freq: Option, pub async_delay: bool, } + +#[cfg(feature = "unstable-riscv")] +#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))] +#[derive(Clone, PartialEq, Eq, Debug, Default)] +#[non_exhaustive] +pub struct RiscvPlicConfig { + pub name: String, + pub core_interrupt: Option, + pub hart_id: Option, +} diff --git a/src/generate/riscv.rs b/src/generate/riscv.rs index b211c676..e4f333df 100644 --- a/src/generate/riscv.rs +++ b/src/generate/riscv.rs @@ -10,7 +10,7 @@ pub fn is_riscv_peripheral(p: &Peripheral, c: &Config) -> bool { match &c.riscv_config { Some(c) => { c.clint.as_ref().is_some_and(|clint| clint.name == p.name) - || c.plic.as_ref().is_some_and(|plic| plic == &p.name) + || c.plic.as_ref().is_some_and(|plic| plic.name == p.name) } _ => false, } @@ -253,7 +253,7 @@ pub fn render( }); } if let Some(plic) = &c.plic { - let p = peripherals.iter().find(|&p| &p.name == plic).unwrap(); + let p = peripherals.iter().find(|&p| p.name == plic.name).unwrap(); let base = TokenStream::from_str(&format!("base 0x{:X},", p.base_address)).unwrap(); let ctxs = harts .iter() @@ -271,6 +271,27 @@ pub fn render( riscv_peripherals.extend(quote! { riscv_peripheral::plic_codegen!(#base #ctxs); }); + + if let Some(core_interrupt) = &plic.core_interrupt { + let core_interrupt = TokenStream::from_str(core_interrupt).unwrap(); + let ctx = match &plic.hart_id { + Some(hart_id) => { + TokenStream::from_str(&format!("ctx(Hart::{hart_id})")).unwrap() + } + None => quote! { ctx_mhartid() }, + }; + mod_items.extend(quote! { + #[cfg(feature = "rt")] + #[riscv_rt::core_interrupt(CoreInterrupt::#core_interrupt)] + fn plic_handler() { + let claim = crate::PLIC::#ctx.claim(); + if let Some(s) = claim.claim::() { + unsafe { _dispatch_core_interrupt(s.number()) } + claim.complete(s); + } + } + }); + } } }