consortium-cfg-common 0.2.0

Schema and configuration types for Consortium
Documentation
use super::XcoreName;
use core::fmt;
use core::str::FromStr;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub enum McoreName {
    Cm0p,
    Cm4f,
    Cm7,
    Cm33,
}

impl McoreName {
    pub const fn as_str(self) -> &'static str {
        match self {
            Self::Cm0p => "cm0p",
            Self::Cm4f => "cm4f",
            Self::Cm7 => "cm7",
            Self::Cm33 => "cm33",
        }
    }

    pub const fn as_full_name(self) -> &'static str {
        match self {
            Self::Cm0p => "cortex-m0+",
            Self::Cm4f => "cortex-m4f",
            Self::Cm7 => "cortex-m7",
            Self::Cm33 => "cortex-m33",
        }
    }

    pub const fn as_rust_triple(self) -> &'static str {
        match self {
            Self::Cm0p => "thumbv6m-none-eabi",
            Self::Cm4f | Self::Cm7 => "thumbv7em-none-eabihf",
            Self::Cm33 => "thumbv8m.main-none-eabihf",
        }
    }

    pub const fn has_trustzone(self) -> bool {
        matches!(self, Self::Cm33)
    }

    pub const fn is_64_bit(self) -> bool {
        false
    }
}

impl XcoreName for McoreName {
    fn from_abbr(value: &str) -> Result<Self, String> {
        value.parse()
    }

    fn from_full_name(value: &str) -> Result<Self, String> {
        match value {
            "cortex-m0+" => Ok(Self::Cm0p),
            "cortex-m4f" => Ok(Self::Cm4f),
            "cortex-m7" => Ok(Self::Cm7),
            "cortex-m33" => Ok(Self::Cm33),
            other => Err(format!("unknown M-core name {other:?}")),
        }
    }

    fn abbr(&self) -> String {
        self.as_str().to_string()
    }

    fn full_name(&self) -> String {
        self.as_full_name().to_string()
    }

    fn rust_triple(&self) -> String {
        self.as_rust_triple().to_string()
    }

    fn has_trustzone(&self) -> bool {
        (*self).has_trustzone()
    }

    fn is_64_bit(&self) -> bool {
        (*self).is_64_bit()
    }
}

impl FromStr for McoreName {
    type Err = String;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        match value {
            "cm0p" => Ok(Self::Cm0p),
            "cm4f" => Ok(Self::Cm4f),
            "cm7" => Ok(Self::Cm7),
            "cm33" => Ok(Self::Cm33),
            other => Err(format!("unknown M-core name {other:?}")),
        }
    }
}

impl fmt::Display for McoreName {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.as_str())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::config::{AcoreName, RcoreName, RvCoreName, RvExtensions, RvXlen};

    #[test]
    fn reports_m_core_metadata() {
        assert_eq!(McoreName::from_full_name("cortex-m33"), Ok(McoreName::Cm33));
        assert_eq!(McoreName::Cm33.abbr(), "cm33");
        assert_eq!(McoreName::Cm33.full_name(), "cortex-m33");
        assert_eq!(McoreName::Cm33.rust_triple(), "thumbv8m.main-none-eabihf");
        assert!(McoreName::Cm33.has_trustzone());
        assert!(McoreName::Cm33.is_32_bit());
    }

    #[test]
    fn reports_a_core_metadata() {
        assert_eq!(AcoreName::from_full_name("cortex-a55"), Ok(AcoreName::Ca55));
        assert_eq!(AcoreName::Ca55.abbr(), "ca55");
        assert_eq!(AcoreName::Ca55.full_name(), "cortex-a55");
        assert_eq!(AcoreName::Ca55.rust_triple(), "aarch64-unknown-none");
        assert!(AcoreName::Ca55.has_trustzone());
        assert!(AcoreName::Ca55.is_64_bit());
        assert!(AcoreName::Ca7.is_32_bit());
    }

    #[test]
    fn reports_r_core_metadata() {
        assert_eq!(RcoreName::from_full_name("cortex-r5f"), Ok(RcoreName::Cr5f));
        assert_eq!(RcoreName::Cr5f.abbr(), "cr5f");
        assert_eq!(RcoreName::Cr5f.full_name(), "cortex-r5f");
        assert_eq!(RcoreName::Cr5f.rust_triple(), "armv7r-none-eabihf");
        assert!(!RcoreName::Cr5f.has_trustzone());
        assert!(RcoreName::Cr5f.is_32_bit());
    }

    #[test]
    fn reports_riscv_core_metadata() {
        let core: RvCoreName = "rv32imafc".parse().unwrap();
        assert_eq!(
            core,
            RvCoreName::new(
                RvXlen::X32,
                RvExtensions {
                    i: true,
                    m: true,
                    a: true,
                    f: true,
                    d: false,
                    c: true,
                }
            )
        );
        assert_eq!(core.abbr(), "rv32imafc");
        assert_eq!(core.full_name(), "riscv32imafc");
        assert_eq!(RvCoreName::from_full_name("riscv32imafc"), Ok(core));
        assert_eq!(core.rust_triple(), "rv32imafc-unknown-none-elf");
        assert!(!core.has_trustzone());
        assert!(core.is_32_bit());
    }
}