hart_mask.rs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /// Hart mask structure in SBI function calls.
  2. #[derive(Debug, Clone)]
  3. pub struct HartMask {
  4. inner: BitVector,
  5. }
  6. impl HartMask {
  7. /// Construct a hart mask from mask value and base hart id.
  8. #[inline]
  9. pub const fn from_mask_base(hart_mask: usize, hart_mask_base: usize) -> HartMask {
  10. HartMask {
  11. inner: BitVector {
  12. hart_mask,
  13. hart_mask_base,
  14. },
  15. }
  16. }
  17. /// Check if the `hart_id` is included in this hart mask structure.
  18. #[inline]
  19. pub const fn has_bit(&self, hart_id: usize) -> bool {
  20. let BitVector {
  21. hart_mask,
  22. hart_mask_base,
  23. } = self.inner;
  24. if hart_mask_base == usize::MAX {
  25. // If `hart_mask_base` equals `usize::MAX`, that means `hart_mask` is ignored
  26. // and all available harts must be considered.
  27. return true;
  28. }
  29. let Some(idx) = hart_id.checked_sub(hart_mask_base) else {
  30. // hart_id < hart_mask_base, not in current mask range
  31. return false;
  32. };
  33. if idx >= usize::BITS as usize {
  34. // hart_idx >= hart_mask_base + XLEN, not in current mask range
  35. return false;
  36. }
  37. hart_mask & (1 << idx) != 0
  38. }
  39. }
  40. #[derive(Debug, Clone)]
  41. struct BitVector {
  42. hart_mask: usize,
  43. hart_mask_base: usize,
  44. }
  45. #[cfg(test)]
  46. mod tests {
  47. use super::HartMask;
  48. #[test]
  49. fn rustsbi_hart_mask() {
  50. let mask = HartMask::from_mask_base(0b1, 400);
  51. assert!(!mask.has_bit(0));
  52. assert!(mask.has_bit(400));
  53. assert!(!mask.has_bit(401));
  54. let mask = HartMask::from_mask_base(0b110, 500);
  55. assert!(!mask.has_bit(0));
  56. assert!(!mask.has_bit(500));
  57. assert!(mask.has_bit(501));
  58. assert!(mask.has_bit(502));
  59. assert!(!mask.has_bit(500 + (usize::BITS as usize)));
  60. let max_bit = 1 << (usize::BITS - 1);
  61. let mask = HartMask::from_mask_base(max_bit, 600);
  62. assert!(mask.has_bit(600 + (usize::BITS as usize) - 1));
  63. assert!(!mask.has_bit(600 + (usize::BITS as usize)));
  64. let mask = HartMask::from_mask_base(0b11, usize::MAX - 1);
  65. assert!(!mask.has_bit(usize::MAX - 2));
  66. assert!(mask.has_bit(usize::MAX - 1));
  67. assert!(mask.has_bit(usize::MAX));
  68. assert!(!mask.has_bit(0));
  69. // hart_mask_base == usize::MAX is special, it means hart_mask should be ignored
  70. // and this hart mask contains all harts available
  71. let mask = HartMask::from_mask_base(0, usize::MAX);
  72. for i in 0..5 {
  73. assert!(mask.has_bit(i));
  74. }
  75. assert!(mask.has_bit(usize::MAX));
  76. }
  77. }