1use super::{
2 array::{descriptions, names},
3 Access, BuildError, DataType, Description, DimElement, EmptyToNone, Field, MaybeArray,
4 ModifiedWriteValues, Name, ReadAction, RegisterProperties, SvdError, ValidateLevel,
5 WriteConstraint,
6};
7use std::ops::Deref;
8
9pub type Register = MaybeArray<RegisterInfo>;
11
12#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
14pub enum Error {
15 #[error("Register have `fields` tag, but it is empty")]
17 EmptyFields,
18}
19
20#[cfg_attr(
22 feature = "serde",
23 derive(serde::Deserialize, serde::Serialize),
24 serde(rename_all = "camelCase")
25)]
26#[derive(Clone, Debug, PartialEq, Eq)]
27#[non_exhaustive]
28pub struct RegisterInfo {
29 pub name: String,
32
33 #[cfg_attr(
35 feature = "serde",
36 serde(default, skip_serializing_if = "Option::is_none")
37 )]
38 pub display_name: Option<String>,
39
40 #[cfg_attr(
42 feature = "serde",
43 serde(default, skip_serializing_if = "Option::is_none")
44 )]
45 pub description: Option<String>,
46
47 #[cfg_attr(
49 feature = "serde",
50 serde(default, skip_serializing_if = "Option::is_none")
51 )]
52 pub alternate_group: Option<String>,
53
54 #[cfg_attr(
57 feature = "serde",
58 serde(default, skip_serializing_if = "Option::is_none")
59 )]
60 pub alternate_register: Option<String>,
61
62 pub address_offset: u32,
64
65 #[cfg_attr(feature = "serde", serde(flatten))]
67 pub properties: RegisterProperties,
68
69 #[cfg_attr(
71 feature = "serde",
72 serde(default, skip_serializing_if = "Option::is_none")
73 )]
74 pub datatype: Option<DataType>,
75
76 #[cfg_attr(
78 feature = "serde",
79 serde(default, skip_serializing_if = "Option::is_none")
80 )]
81 pub modified_write_values: Option<ModifiedWriteValues>,
82
83 #[cfg_attr(
85 feature = "serde",
86 serde(default, skip_serializing_if = "Option::is_none")
87 )]
88 pub write_constraint: Option<WriteConstraint>,
89
90 #[cfg_attr(
93 feature = "serde",
94 serde(default, skip_serializing_if = "Option::is_none")
95 )]
96 pub read_action: Option<ReadAction>,
97
98 #[cfg_attr(
100 feature = "serde",
101 serde(default, skip_serializing_if = "Option::is_none")
102 )]
103 pub fields: Option<Vec<Field>>,
104
105 #[cfg_attr(
108 feature = "serde",
109 serde(default, skip_serializing_if = "Option::is_none")
110 )]
111 pub derived_from: Option<String>,
112}
113
114pub fn address_offsets<'a>(
116 info: &'a RegisterInfo,
117 dim: &'a DimElement,
118) -> impl Iterator<Item = u32> + 'a {
119 (0..dim.dim).map(move |i| info.address_offset + i * dim.dim_increment)
120}
121
122pub fn expand<'a>(
124 info: &'a RegisterInfo,
125 dim: &'a DimElement,
126) -> impl Iterator<Item = RegisterInfo> + 'a {
127 dim.indexes()
128 .zip(names(info, dim))
129 .zip(descriptions(info, dim))
130 .zip(address_offsets(info, dim))
131 .map(|(((idx, name), description), address_offset)| {
132 let mut info = info.clone();
133 info.name = name;
134 info.description = description;
135 info.address_offset = address_offset;
136 info.display_name = info
137 .display_name
138 .map(|d| d.replace("[%s]", &idx).replace("%s", &idx));
139 info
140 })
141}
142
143#[derive(Clone, Debug, Default, PartialEq, Eq)]
145pub struct RegisterInfoBuilder {
146 name: Option<String>,
147 display_name: Option<String>,
148 description: Option<String>,
149 alternate_group: Option<String>,
150 alternate_register: Option<String>,
151 address_offset: Option<u32>,
152 properties: RegisterProperties,
153 datatype: Option<DataType>,
154 modified_write_values: Option<ModifiedWriteValues>,
155 write_constraint: Option<WriteConstraint>,
156 read_action: Option<ReadAction>,
157 fields: Option<Vec<Field>>,
158 derived_from: Option<String>,
159}
160
161impl From<RegisterInfo> for RegisterInfoBuilder {
162 fn from(r: RegisterInfo) -> Self {
163 Self {
164 name: Some(r.name),
165 display_name: r.display_name,
166 description: r.description,
167 alternate_group: r.alternate_group,
168 alternate_register: r.alternate_register,
169 address_offset: Some(r.address_offset),
170 properties: r.properties,
171 datatype: r.datatype,
172 modified_write_values: r.modified_write_values,
173 write_constraint: r.write_constraint,
174 read_action: r.read_action,
175 fields: r.fields,
176 derived_from: r.derived_from,
177 }
178 }
179}
180
181impl RegisterInfoBuilder {
182 pub fn name(mut self, value: String) -> Self {
184 self.name = Some(value);
185 self
186 }
187 pub fn display_name(mut self, value: Option<String>) -> Self {
189 self.display_name = value;
190 self
191 }
192 pub fn description(mut self, value: Option<String>) -> Self {
194 self.description = value;
195 self
196 }
197 pub fn alternate_group(mut self, value: Option<String>) -> Self {
199 self.alternate_group = value;
200 self
201 }
202 pub fn alternate_register(mut self, value: Option<String>) -> Self {
204 self.alternate_register = value;
205 self
206 }
207 pub fn address_offset(mut self, value: u32) -> Self {
209 self.address_offset = Some(value);
210 self
211 }
212 pub fn properties(mut self, value: RegisterProperties) -> Self {
214 self.properties = value;
215 self
216 }
217 pub fn datatype(mut self, value: Option<DataType>) -> Self {
219 self.datatype = value;
220 self
221 }
222 pub fn size(mut self, value: Option<u32>) -> Self {
224 self.properties.size = value;
225 self
226 }
227 pub fn access(mut self, value: Option<Access>) -> Self {
229 self.properties.access = value;
230 self
231 }
232 pub fn reset_value(mut self, value: Option<u64>) -> Self {
234 self.properties.reset_value = value;
235 self
236 }
237 pub fn reset_mask(mut self, value: Option<u64>) -> Self {
239 self.properties.reset_mask = value;
240 self
241 }
242 pub fn modified_write_values(mut self, value: Option<ModifiedWriteValues>) -> Self {
244 self.modified_write_values = value;
245 self
246 }
247 pub fn write_constraint(mut self, value: Option<WriteConstraint>) -> Self {
249 self.write_constraint = value;
250 self
251 }
252 pub fn read_action(mut self, value: Option<ReadAction>) -> Self {
254 self.read_action = value;
255 self
256 }
257 pub fn fields(mut self, value: Option<Vec<Field>>) -> Self {
259 self.fields = value;
260 self
261 }
262 pub fn derived_from(mut self, value: Option<String>) -> Self {
264 self.derived_from = value;
265 self
266 }
267 pub fn build(self, lvl: ValidateLevel) -> Result<RegisterInfo, SvdError> {
269 let reg = RegisterInfo {
270 name: self
271 .name
272 .ok_or_else(|| BuildError::Uninitialized("name".to_string()))?,
273 display_name: self.display_name,
274 description: self.description,
275 alternate_group: self.alternate_group,
276 alternate_register: self.alternate_register,
277 address_offset: self
278 .address_offset
279 .ok_or_else(|| BuildError::Uninitialized("address_offset".to_string()))?,
280 properties: self.properties.build(lvl)?,
281 datatype: self.datatype,
282 modified_write_values: self.modified_write_values,
283 write_constraint: self.write_constraint,
284 read_action: self.read_action,
285 fields: self.fields,
286 derived_from: self.derived_from,
287 };
288 reg.validate(lvl)?;
289 Ok(reg)
290 }
291}
292
293impl RegisterInfo {
294 pub fn builder() -> RegisterInfoBuilder {
296 RegisterInfoBuilder::default()
297 }
298 pub const fn single(self) -> Register {
300 Register::Single(self)
301 }
302 pub const fn array(self, dim: DimElement) -> Register {
304 Register::Array(self, dim)
305 }
306 pub fn maybe_array(self, dim: Option<DimElement>) -> Register {
308 if let Some(dim) = dim {
309 self.array(dim)
310 } else {
311 self.single()
312 }
313 }
314 pub fn modify_from(
316 &mut self,
317 builder: RegisterInfoBuilder,
318 lvl: ValidateLevel,
319 ) -> Result<(), SvdError> {
320 if let Some(name) = builder.name {
321 self.name = name;
322 }
323 if builder.display_name.is_some() {
324 self.display_name = builder.display_name.empty_to_none();
325 }
326 if builder.description.is_some() {
327 self.description = builder.description.empty_to_none();
328 }
329 if builder.alternate_group.is_some() {
330 self.alternate_group = builder.alternate_group.empty_to_none();
331 }
332 if builder.alternate_register.is_some() {
333 self.alternate_register = builder.alternate_register.empty_to_none();
334 }
335 if let Some(address_offset) = builder.address_offset {
336 self.address_offset = address_offset;
337 }
338 if builder.derived_from.is_some() {
339 self.derived_from = builder.derived_from;
340 self.fields = None;
341 self.properties = RegisterProperties::default();
342 self.datatype = None;
343 self.modified_write_values = None;
344 self.write_constraint = None;
345 } else {
346 self.properties.modify_from(builder.properties, lvl)?;
347 if builder.datatype.is_some() {
348 self.datatype = builder.datatype;
349 }
350 if builder.modified_write_values.is_some() {
351 self.modified_write_values = builder.modified_write_values;
352 }
353 if builder.write_constraint.is_some() {
354 self.write_constraint = builder.write_constraint;
355 }
356 if builder.read_action.is_some() {
357 self.read_action = builder.read_action;
358 }
359 if builder.fields.is_some() {
360 self.fields = builder.fields.empty_to_none();
361 }
362 }
363 self.validate(lvl)
364 }
365 pub fn validate(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
367 if !lvl.is_disabled() {
368 if lvl.is_strict() {
369 super::check_dimable_name(&self.name, "name")?;
370 if let Some(name) = self.alternate_group.as_ref() {
371 super::check_name(name, "alternateGroup")?;
372 }
373 if let Some(name) = self.alternate_register.as_ref() {
374 super::check_dimable_name(name, "alternateRegister")?;
375 }
376 }
377 if let Some(name) = self.derived_from.as_ref() {
378 if lvl.is_strict() {
379 super::check_derived_name(name, "derivedFrom")?;
380 }
381 } else if let Some(fields) = self.fields.as_ref() {
382 if fields.is_empty() && lvl.is_strict() {
383 return Err(Error::EmptyFields.into());
384 }
385 }
386 }
387 Ok(())
388 }
389 pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
391 self.properties.validate(lvl)?;
392 for f in self.fields() {
393 f.validate_all(lvl)?;
394 }
395 self.validate(lvl)
396 }
397
398 pub fn fields(&self) -> std::slice::Iter<Field> {
400 match &self.fields {
401 Some(fields) => fields.iter(),
402 None => [].iter(),
403 }
404 }
405
406 pub fn fields_mut(&mut self) -> std::slice::IterMut<Field> {
408 match &mut self.fields {
409 Some(fields) => fields.iter_mut(),
410 None => [].iter_mut(),
411 }
412 }
413
414 pub fn get_field(&self, name: &str) -> Option<&Field> {
416 self.fields().find(|f| f.name == name)
417 }
418
419 pub fn get_mut_field(&mut self, name: &str) -> Option<&mut Field> {
421 self.fields_mut().find(|f| f.name == name)
422 }
423
424 pub fn bitmask(&self) -> u64 {
426 self.fields().fold(0, |mask, f| mask | f.bitmask())
427 }
428}
429
430impl Register {
431 pub fn validate_all(&self, lvl: ValidateLevel) -> Result<(), SvdError> {
433 if let Self::Array(_, dim) = self {
434 dim.validate(lvl)?;
435 }
436 self.deref().validate_all(lvl)
437 }
438}
439
440impl Name for RegisterInfo {
441 fn name(&self) -> &str {
442 &self.name
443 }
444}
445
446impl Description for RegisterInfo {
447 fn description(&self) -> Option<&str> {
448 self.description.as_deref()
449 }
450}