/ioreg/src/node.rs

https://gitlab.com/nwagg14/zinc · Rust · 168 lines · 116 code · 16 blank · 36 comment · 5 complexity · 2debd45a222734a7fd676b9e5e626e03 MD5 · raw file

  1. // Zinc, the bare metal stack for rust.
  2. // Copyright 2014 Ben Gamari <bgamari@gmail.com>
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. use std::ops::Deref;
  16. use std::rc::Rc;
  17. use syntax::codemap::{Spanned, Span};
  18. use syntax::ast;
  19. /// A variant of an enum field type
  20. #[derive(Clone, Debug)]
  21. pub struct Variant {
  22. pub name: Spanned<String>,
  23. pub value: Spanned<u64>,
  24. pub docstring: Option<Spanned<ast::Ident>>,
  25. }
  26. /// A bit field type
  27. #[derive(Clone, Debug)]
  28. pub enum FieldType {
  29. /// A unsigned integer
  30. UIntField,
  31. /// A boolean flag
  32. BoolField,
  33. /// A enum
  34. EnumField {
  35. opt_name: Option<String>,
  36. variants: Vec<Variant>,
  37. },
  38. }
  39. #[derive(Copy, PartialEq, Eq, Clone, Debug)]
  40. pub enum Access {
  41. ReadWrite,
  42. ReadOnly,
  43. WriteOnly,
  44. /// A flag which can be set to clear
  45. SetToClear,
  46. }
  47. #[derive(Clone, Debug)]
  48. pub struct Field {
  49. pub name: Spanned<String>,
  50. /// The index of the first (lowest order) bit of the field
  51. pub low_bit: u8,
  52. /// The width in bits of a single array element
  53. pub width: u8,
  54. /// The number of array elements
  55. pub count: Spanned<u8>,
  56. pub bit_range_span: Span,
  57. pub access: Access,
  58. pub ty: Spanned<FieldType>,
  59. pub docstring: Option<Spanned<ast::Ident>>,
  60. }
  61. impl Field {
  62. /// The index of the highest order bit owned by this field
  63. pub fn high_bit(&self) -> u8 {
  64. self.low_bit + self.width * self.count.node - 1
  65. }
  66. }
  67. #[derive(Copy, Clone, Debug)]
  68. pub enum RegWidth {
  69. /// A 32-bit wide register
  70. Reg32,
  71. /// A 16-bit wide register
  72. Reg16,
  73. /// An 8-bit wide register
  74. Reg8,
  75. }
  76. impl RegWidth {
  77. /// Size of register type in bytes
  78. pub fn size(&self) -> u64 {
  79. match *self {
  80. RegWidth::Reg32 => 4,
  81. RegWidth::Reg16 => 2,
  82. RegWidth::Reg8 => 1,
  83. }
  84. }
  85. }
  86. #[derive(Clone, Debug)]
  87. pub enum RegType {
  88. /// A primitive bitfield
  89. RegPrim(Spanned<RegWidth>, Vec<Field>),
  90. /// A group
  91. RegUnion(Rc<Vec<Reg>>),
  92. }
  93. impl RegType {
  94. /// Size of register type in bytes
  95. pub fn size(&self) -> u64 {
  96. match self {
  97. &RegType::RegPrim(ref width, _) => width.node.size() as u64,
  98. &RegType::RegUnion(ref regs) => regs_size(regs.deref()),
  99. }
  100. }
  101. }
  102. /// A single register, either a union or primitive
  103. #[derive(Clone, Debug)]
  104. pub struct Reg {
  105. pub offset: u64,
  106. pub name: Spanned<String>,
  107. pub ty: RegType,
  108. pub count: Spanned<u32>,
  109. pub docstring: Option<Spanned<ast::Ident>>,
  110. pub address: usize,
  111. }
  112. impl Reg {
  113. /// Size of a register in bytes
  114. pub fn size(&self) -> u64 {
  115. self.count.node as u64 * self.ty.size()
  116. }
  117. /// The offset of the last byte owned by this register
  118. pub fn last_byte(&self) -> u64 {
  119. self.offset + self.size() - 1
  120. }
  121. }
  122. /// Size of registers of register group in bytes
  123. pub fn regs_size(regs: &Vec<Reg>) -> u64 {
  124. match regs.iter().map(|r| r.offset + r.ty.size()).max() {
  125. Some(last) => last,
  126. None => 0,
  127. }
  128. }
  129. pub trait RegVisitor {
  130. /// Path includes name of `Reg` being visited
  131. fn visit_prim_reg<'a>(&'a mut self, _path: &Vec<String>, _reg: &'a Reg,
  132. _fields: &Vec<Field>) {}
  133. fn visit_union_reg<'a>(&'a mut self, _path: &Vec<String>, _reg: &'a Reg,
  134. _subregs: Rc<Vec<Reg>>) {}
  135. }
  136. pub fn visit_reg<T: RegVisitor>(reg: &Reg, visitor: &mut T) {
  137. visit_reg_(reg, visitor, vec!(reg.name.node.clone()))
  138. }
  139. fn visit_reg_<T: RegVisitor>(reg: &Reg, visitor: &mut T, path: Vec<String>) {
  140. match reg.ty {
  141. RegType::RegUnion(ref regs) => {
  142. visitor.visit_union_reg(&path, reg, regs.clone());
  143. for r in regs.iter() {
  144. let mut new_path = path.clone();
  145. new_path.push(r.name.node.clone()); // TODO(bgamari) fix clone
  146. visit_reg_(r, visitor, new_path);
  147. }
  148. },
  149. RegType::RegPrim(_, ref fields) =>
  150. visitor.visit_prim_reg(&path, reg, fields)
  151. }
  152. }