#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct CacheId(u32);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct PipelineId(u32);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct MemCtrlId(u32);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct DeviceId(u32);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct ChannelId(u8);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct SubchannelId(u8);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct RankId(u8);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct BankGroupId(u8);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct RowId(u32);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct ReqId(u64);
macro_rules! impl_id_new {
($id:ident, $raw:ty) => {
impl $id {
#[inline(always)]
pub const fn new(val: $raw) -> Self {
Self(val)
}
}
};
}
macro_rules! impl_id_val {
($id:ident, $raw:ty) => {
impl $id {
#[inline(always)]
pub const fn val(self) -> $raw {
self.0
}
}
};
}
macro_rules! impl_id_index {
($id:ident) => {
impl $id {
#[inline(always)]
pub const fn as_index(self) -> usize {
self.0 as usize
}
}
};
}
impl ReqId {
#[must_use]
pub const fn for_cache(cache: CacheId, seq: u64) -> Self {
Self((1 << 63) | ((cache.0 as u64) << 48) | (seq & ((1 << 48) - 1)))
}
}
impl ReqId {
#[must_use]
pub const fn for_fabric(seq: u64) -> Self {
Self((1 << 62) | (seq & ((1 << 48) - 1)))
}
#[must_use]
pub const fn for_device(device: DeviceId, seq: u64) -> Self {
Self((1 << 61) | ((device.0 as u64) << 48) | (seq & ((1 << 48) - 1)))
}
}
impl_id_new!(CacheId, u32);
impl_id_val!(CacheId, u32);
impl_id_new!(PipelineId, u32);
impl_id_val!(PipelineId, u32);
impl_id_index!(PipelineId);
impl_id_new!(MemCtrlId, u32);
impl_id_val!(MemCtrlId, u32);
impl_id_new!(DeviceId, u32);
impl_id_index!(DeviceId);
impl_id_new!(ReqId, u64);
impl_id_new!(ChannelId, u8);
impl_id_val!(ChannelId, u8);
impl_id_index!(ChannelId);
impl_id_new!(SubchannelId, u8);
impl_id_index!(SubchannelId);
impl_id_new!(RankId, u8);
impl_id_val!(RankId, u8);
impl_id_index!(RankId);
impl_id_new!(BankGroupId, u8);
impl_id_val!(BankGroupId, u8);
impl_id_index!(BankGroupId);
impl_id_new!(RowId, u32);
impl_id_val!(RowId, u32);
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum ComponentId {
Pipeline(PipelineId),
Cache(CacheId),
Bus,
MemCtrl(MemCtrlId),
Device(DeviceId),
Fabric,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ids_round_trip() {
let c = CacheId::new(7);
assert_eq!(c.val(), 7);
let p = PipelineId::new(2);
let m = MemCtrlId::new(0);
let d = DeviceId::new(3);
assert_eq!(p.val(), 2);
assert_eq!(p.as_index(), 2);
assert_eq!(m.val(), 0);
assert_eq!(d.as_index(), 3);
}
#[test]
fn component_id_variants_are_distinct() {
let a = ComponentId::Cache(CacheId::new(0));
let b = ComponentId::MemCtrl(MemCtrlId::new(0));
assert_ne!(a, b);
}
}