1use std::io::{BufRead, BufReader, Read, Write};
6
7use quick_xml::events::{Event, attributes::Attribute};
8use quick_xml::name::QName;
9use quick_xml::reader::Reader;
10
11#[derive(Debug)]
12pub enum ParseError {
13 UnexpectedTag,
14 MissingValue,
15 ParseIntError,
16 NonUTF8,
17 WriteError,
18 UnexpectedValue,
19 MissingBasePeripheral(String),
20}
21
22#[derive(Default, Debug, Clone)]
23pub struct Field {
24 name: String,
25 lsb: u32,
26 msb: u32,
27}
28
29#[derive(Default, Debug, Clone)]
30pub struct Register {
31 name: String,
32 offset: u64,
33 description: Option<String>,
34 fields: Vec<Field>,
35}
36
37#[derive(Default, Debug, Clone)]
38pub struct Interrupt {
39 name: String,
40 value: u64,
41}
42
43#[derive(Default, Debug)]
44pub struct Peripheral {
45 name: String,
46 pub base: u64,
47 _size: u64,
48 interrupt: Vec<Interrupt>,
49 registers: Vec<Register>,
50}
51
52#[derive(Default, Debug)]
53pub struct MemoryRegion {
54 pub name: String,
55 pub base: u64,
56 pub size: u64,
57}
58
59#[derive(Default, Debug)]
60pub struct Constant {
61 pub name: String,
62 pub value: String,
63}
64
65#[derive(Default, Debug)]
66pub struct Description {
67 pub peripherals: Vec<Peripheral>,
68 pub memory_regions: Vec<MemoryRegion>,
69 pub constants: Vec<Constant>,
70}
71
72impl core::fmt::Display for ParseError {
73 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
74 use ParseError::*;
75 match *self {
76 UnexpectedTag => write!(f, "unexpected XML tag encountered"),
77 UnexpectedValue => write!(f, "unexpected XML tag value encountered"),
78 MissingValue => write!(f, "XML tag should have contained a value"),
79 ParseIntError => write!(f, "unable to parse number"),
80 NonUTF8 => write!(f, "file is not UTF-8"),
81 WriteError => write!(f, "unable to write destination file"),
82 MissingBasePeripheral(ref name) => write!(f, "undeclared base peripheral: {}", name),
83 }
84 }
85}
86
87impl std::error::Error for ParseError {}
88
89pub fn get_base(value: &str) -> (&str, u32) {
90 if value.starts_with("0x") {
91 (value.trim_start_matches("0x"), 16)
92 } else if value.starts_with("0X") {
93 (value.trim_start_matches("0X"), 16)
94 } else if value.starts_with("0b") {
95 (value.trim_start_matches("0b"), 2)
96 } else if value.starts_with("0B") {
97 (value.trim_start_matches("0B"), 2)
98 } else if value.starts_with('0') && value != "0" {
99 (value.trim_start_matches('0'), 8)
100 } else {
101 (value, 10)
102 }
103}
104
105fn parse_u64(value: &[u8]) -> Result<u64, ParseError> {
106 let value_as_str = String::from_utf8(value.to_vec()).or(Err(ParseError::NonUTF8))?;
107 let (value, base) = get_base(&value_as_str);
108 u64::from_str_radix(value, base).or(Err(ParseError::ParseIntError))
109}
110
111fn parse_u32(value: &[u8]) -> Result<u32, ParseError> {
112 let value_as_str = String::from_utf8(value.to_vec()).or(Err(ParseError::NonUTF8))?;
113 let (value, base) = get_base(&value_as_str);
114 u32::from_str_radix(value, base).or(Err(ParseError::ParseIntError))
115}
116
117fn extract_contents<T: BufRead>(reader: &mut Reader<T>) -> Result<String, ParseError> {
118 let mut buf = Vec::new();
119 let contents = reader.read_event_into(&mut buf).map_err(|_| ParseError::UnexpectedTag)?;
120 match contents {
121 Event::Text(t) => t.unescape().map(|s| s.to_string()).map_err(|_| ParseError::NonUTF8),
122 _ => Err(ParseError::UnexpectedTag),
123 }
124}
125
126fn generate_field<T: BufRead>(reader: &mut Reader<T>) -> Result<Field, ParseError> {
127 let mut buf = Vec::new();
128 let mut name = None;
129 let mut lsb = None;
130 let mut msb = None;
131 let mut bit_offset = None;
132 let mut bit_width = None;
133
134 loop {
135 match reader.read_event_into(&mut buf) {
136 Ok(Event::Start(ref e)) => {
137 let tag_binding = e.name().as_ref().to_vec();
138 let tag_name = std::str::from_utf8(&tag_binding).unwrap();
139 match tag_name {
140 "name" if name.is_none() => name = Some(extract_contents(reader)?),
141 "lsb" => lsb = Some(parse_u32(extract_contents(reader)?.as_bytes())?),
142 "msb" => msb = Some(parse_u32(extract_contents(reader)?.as_bytes())?),
143 "bitRange" => {
144 let range = extract_contents(reader)?;
145 if !range.starts_with('[') || !range.ends_with(']') {
146 return Err(ParseError::UnexpectedValue);
147 }
148
149 let mut parts = range[1..range.len() - 1].split(':');
150 msb = Some(
151 parts
152 .next()
153 .ok_or(ParseError::UnexpectedValue)?
154 .parse::<u32>()
155 .map_err(|_| ParseError::ParseIntError)?,
156 );
157 lsb = Some(
158 parts
159 .next()
160 .ok_or(ParseError::UnexpectedValue)?
161 .parse::<u32>()
162 .map_err(|_| ParseError::ParseIntError)?,
163 );
164 }
165 "bitWidth" => bit_width = Some(parse_u32(extract_contents(reader)?.as_bytes())?),
166 "bitOffset" => bit_offset = Some(parse_u32(extract_contents(reader)?.as_bytes())?),
167 _ => (),
168 }
169 }
170 Ok(Event::End(ref e)) => {
171 if let b"field" = e.local_name().as_ref() {
172 break;
173 }
174 }
175 Ok(_) => (),
176 Err(e) => panic!("error parsing: {:?}", e),
177 }
178 }
179
180 if lsb.is_none() && msb.is_none() {
184 if let (Some(bit_width), Some(bit_offset)) = (bit_width, bit_offset) {
185 lsb = Some(bit_offset);
186 msb = Some(bit_offset + bit_width - 1);
187 }
188 }
189
190 Ok(Field {
191 name: name.ok_or(ParseError::MissingValue)?,
192 lsb: lsb.ok_or(ParseError::MissingValue)?,
193 msb: msb.ok_or(ParseError::MissingValue)?,
194 })
195}
196
197fn generate_fields<T: BufRead>(reader: &mut Reader<T>, fields: &mut Vec<Field>) -> Result<(), ParseError> {
198 let mut buf = Vec::new();
199 loop {
200 match reader.read_event_into(&mut buf) {
201 Ok(Event::Start(ref e)) => match e.local_name().as_ref() {
202 b"field" => fields.push(generate_field(reader)?),
203 _ => panic!("unexpected tag in <field>: {:?}", e),
204 },
205 Ok(Event::End(ref e)) => match e.local_name().as_ref() {
206 b"fields" => {
207 break;
209 }
210 e => panic!("unhandled value: {:?}", e),
211 },
212 Ok(Event::Text(_)) => (),
213 e => panic!("unhandled value: {:?}", e),
214 }
215 }
216 Ok(())
217}
218
219fn generate_register<T: BufRead>(reader: &mut Reader<T>) -> Result<Register, ParseError> {
220 let mut buf = Vec::new();
221 let mut name = None;
222 let mut offset = None;
223 let description = None;
224 let mut fields = vec![];
225 loop {
226 match reader.read_event_into(&mut buf) {
227 Ok(Event::Start(ref e)) => {
228 let tag_binding = e.local_name().as_ref().to_vec();
229 let tag_name = std::str::from_utf8(&tag_binding).map_err(|_| ParseError::NonUTF8)?;
230 match tag_name {
231 "name" => name = Some(extract_contents(reader)?),
232 "addressOffset" => offset = Some(parse_u64(extract_contents(reader)?.as_bytes())?),
233 "fields" => generate_fields(reader, &mut fields)?,
234 _ => (),
235 }
236 }
237 Ok(Event::End(ref e)) => {
238 if let b"register" = e.local_name().as_ref() {
239 break;
240 }
241 }
242 Ok(_) => (),
243 Err(e) => panic!("error parsing: {:?}", e),
244 }
245 }
246
247 Ok(Register {
248 name: name.ok_or(ParseError::MissingValue)?,
249 offset: offset.ok_or(ParseError::MissingValue)?,
250 description,
251 fields,
252 })
253}
254
255fn generate_interrupts<T: BufRead>(
256 reader: &mut Reader<T>,
257 interrupts: &mut Vec<Interrupt>,
258) -> Result<(), ParseError> {
259 let mut buf = Vec::new();
260 let mut name = None;
261 let mut value = None;
262 loop {
263 match reader.read_event_into(&mut buf) {
264 Ok(Event::Start(ref e)) => {
265 let tag_binding = e.local_name().as_ref().to_vec();
266 let tag_name = std::str::from_utf8(&tag_binding).map_err(|_| ParseError::NonUTF8)?;
267 match tag_name {
268 "name" => name = Some(extract_contents(reader)?),
269 "value" => value = Some(parse_u64(extract_contents(reader)?.as_bytes())?),
270 _ => (),
271 }
272 }
273 Ok(Event::End(ref e)) => {
274 if let b"interrupt" = e.local_name().as_ref() {
275 break;
276 }
277 }
278 Ok(_) => (),
279 Err(e) => panic!("error parsing: {:?}", e),
280 }
281 }
282
283 interrupts.push(Interrupt {
284 name: name.ok_or(ParseError::MissingValue)?,
285 value: value.ok_or(ParseError::MissingValue)?,
286 });
287
288 Ok(())
289}
290
291fn generate_registers<T: BufRead>(
292 reader: &mut Reader<T>,
293 registers: &mut Vec<Register>,
294) -> Result<(), ParseError> {
295 let mut buf = Vec::new();
296 loop {
297 match reader.read_event_into(&mut buf) {
298 Ok(Event::Start(ref e)) => match e.local_name().as_ref() {
299 b"register" => registers.push(generate_register(reader)?),
300 _ => panic!("unexpected tag in <registers>: {:?}", e),
301 },
302 Ok(Event::End(ref e)) => match e.local_name().as_ref() {
303 b"registers" => {
304 break;
305 }
306 e => panic!("unhandled value: {:?}", e),
307 },
308 Ok(Event::Text(_)) => (),
309 e => panic!("unhandled value: {:?}", e),
310 }
311 }
312 Ok(())
313}
314
315fn derive_peripheral(base: &Peripheral, child_name: &str, child_base: u64) -> Peripheral {
316 Peripheral {
317 name: child_name.to_owned(),
318 base: child_base,
319 _size: base._size,
320 interrupt: base.interrupt.clone(),
321 registers: base.registers.clone(),
322 }
323}
324
325fn generate_peripheral<T: BufRead>(
326 base_peripheral: Option<&Peripheral>,
327 reader: &mut Reader<T>,
328) -> Result<Peripheral, ParseError> {
329 let mut buf = Vec::new();
330 let mut name = None;
331 let mut base = None;
332 let mut size = None;
333 let mut registers = vec![];
334 let mut interrupts = vec![];
335
336 loop {
337 match reader.read_event_into(&mut buf) {
338 Ok(Event::Start(ref e)) => {
339 let tag_binding = e.local_name().as_ref().to_vec();
340 let tag_name = std::str::from_utf8(&tag_binding).map_err(|_| ParseError::NonUTF8)?;
341 match tag_name {
342 "name" => name = Some(extract_contents(reader)?),
343 "baseAddress" => base = Some(parse_u64(extract_contents(reader)?.as_bytes())?),
344 "size" => size = Some(parse_u64(extract_contents(reader)?.as_bytes())?),
345 "registers" => generate_registers(reader, &mut registers)?,
346 "interrupt" => generate_interrupts(reader, &mut interrupts)?,
347 _ => (),
348 }
349 }
350 Ok(Event::End(ref e)) => {
351 if let b"peripheral" = e.local_name().as_ref() {
352 break;
353 }
354 }
355 Ok(_) => (),
356 Err(e) => panic!("error parsing: {:?}", e),
357 }
358 }
359
360 let name = name.ok_or(ParseError::MissingValue)?;
361 let base = base.ok_or(ParseError::MissingValue)?;
362
363 if let Some(base_peripheral) = base_peripheral {
365 Ok(derive_peripheral(base_peripheral, &name, base))
366 } else {
367 Ok(Peripheral {
368 name,
369 base,
370 _size: size.ok_or(ParseError::MissingValue)?,
371 interrupt: interrupts,
372 registers,
373 })
374 }
375}
376
377fn generate_peripherals<T: BufRead>(reader: &mut Reader<T>) -> Result<Vec<Peripheral>, ParseError> {
378 let mut buf = Vec::new();
379 let mut peripherals: Vec<Peripheral> = vec![];
380
381 loop {
382 match reader.read_event_into(&mut buf) {
383 Ok(Event::Start(ref e)) => match e.local_name().as_ref() {
384 b"peripheral" => {
385 let base_peripheral = match e.attributes().next() {
386 Some(Ok(Attribute { key, value })) if key == QName(b"derivedFrom") => {
387 let base_peripheral_name =
388 String::from_utf8(value.to_vec()).map_err(|_| ParseError::NonUTF8)?;
389
390 let base = peripherals
391 .iter()
392 .find(|p| p.name == base_peripheral_name)
393 .ok_or(ParseError::MissingBasePeripheral(base_peripheral_name))?;
394
395 Some(base)
396 }
397 _ => None,
398 };
399
400 peripherals.push(generate_peripheral(base_peripheral, reader)?);
401 }
402 _ => panic!("unexpected tag in <peripherals>: {:?}", e),
403 },
404 Ok(Event::End(ref e)) => match e.local_name().as_ref() {
405 b"peripherals" => {
406 break;
407 }
408 e => panic!("unhandled value: {:?}", e),
409 },
410 Ok(Event::Text(_)) => (),
411 e => panic!("unhandled value: {:?}", e),
412 }
413 }
414 Ok(peripherals)
415}
416
417fn generate_memory_region<T: BufRead>(reader: &mut Reader<T>) -> Result<MemoryRegion, ParseError> {
418 let mut buf = Vec::new();
419 let mut name = None;
420 let mut base = None;
421 let mut size = None;
422
423 loop {
424 match reader.read_event_into(&mut buf) {
425 Ok(Event::Start(ref e)) => {
426 let tag_binding = e.local_name().as_ref().to_vec();
427 let tag_name = std::str::from_utf8(&tag_binding).map_err(|_| ParseError::NonUTF8)?;
428 match tag_name {
429 "name" => name = Some(extract_contents(reader)?),
430 "baseAddress" => base = Some(parse_u64(extract_contents(reader)?.as_bytes())?),
431 "size" => size = Some(parse_u64(extract_contents(reader)?.as_bytes())?),
432 _ => (),
433 }
434 }
435 Ok(Event::End(ref e)) => {
436 if let b"memoryRegion" = e.local_name().as_ref() {
437 break;
438 }
439 }
440 Ok(_) => (),
441 Err(e) => panic!("error parsing: {:?}", e),
442 }
443 }
444
445 Ok(MemoryRegion {
446 name: name.ok_or(ParseError::MissingValue)?,
447 base: base.ok_or(ParseError::MissingValue)?,
448 size: size.ok_or(ParseError::MissingValue)?,
449 })
450}
451
452fn parse_memory_regions<T: BufRead>(
453 reader: &mut Reader<T>,
454 description: &mut Description,
455) -> Result<(), ParseError> {
456 let mut buf = Vec::new();
457 loop {
458 match reader.read_event_into(&mut buf) {
459 Ok(Event::Start(ref e)) => match e.name() {
460 QName(b"memoryRegion") => {
461 let mut mr = generate_memory_region(reader)?;
462 loop {
464 if description.memory_regions.iter().find(|&m| m.name == mr.name).is_some() {
465 mr.name.push_str("_X");
466 continue;
467 }
468 break;
469 }
470 description.memory_regions.push(mr)
471 }
472 _ => panic!("unexpected tag in <memoryRegions>: {:?}", e),
473 },
474 Ok(Event::End(ref e)) => match e.name() {
475 QName(b"memoryRegions") => {
476 break;
477 }
478 e => panic!("unhandled value: {:?}", e),
479 },
480 Ok(Event::Text(_)) => (),
481 e => panic!("unhandled value: {:?}", e),
482 }
483 }
484 Ok(())
485}
486
487fn generate_constants<T: BufRead>(
488 reader: &mut Reader<T>,
489 description: &mut Description,
490) -> Result<(), ParseError> {
491 let mut buf = Vec::new();
492 loop {
493 match reader.read_event_into(&mut buf) {
494 Ok(Event::Empty(ref e)) => match e.name() {
495 QName(b"constant") => {
496 let mut constant_descriptor = Constant::default();
497 for maybe_att in e.attributes() {
498 match maybe_att {
499 Ok(att) => {
500 let att_name = String::from_utf8(att.key.local_name().as_ref().into())
501 .expect("constant: error parsing attribute name");
502 let att_value = String::from_utf8(att.value.to_vec())
503 .expect("constant: error parsing attribute value");
504 match att_name {
505 _ if att_name == "name" => constant_descriptor.name = att_value,
506 _ if att_name == "value" => constant_descriptor.value = att_value,
507 _ => panic!("unexpected attribute name"),
508 }
509 }
510 _ => panic!("unexpected value in constant: {:?}", maybe_att),
511 }
512 }
513 loop {
515 if description
516 .constants
517 .iter()
518 .find(|&c| c.name == constant_descriptor.name)
519 .is_some()
520 {
521 constant_descriptor.name.push_str("_X");
522 continue;
523 }
524 break;
525 }
526 description.constants.push(constant_descriptor)
527 }
528 _ => panic!("unexpected tag in <constants>: {:?}", e),
529 },
530 Ok(Event::End(ref e)) => match e.name() {
538 QName(b"constants") => break,
539 e => panic!("unhandled value: {:?}", e),
540 },
541 Ok(Event::Text(_)) => (),
542 e => panic!("unhandled value: {:?}", e),
543 }
544 }
545 Ok(())
546}
547
548fn parse_vendor_extensions<T: BufRead>(
549 reader: &mut Reader<T>,
550 description: &mut Description,
551) -> Result<(), ParseError> {
552 let mut buf = Vec::new();
553 loop {
554 match reader.read_event_into(&mut buf) {
555 Ok(Event::Start(ref e)) => match e.name() {
556 QName(b"memoryRegions") => parse_memory_regions(reader, description)?,
557 QName(b"constants") => generate_constants(reader, description)?,
558 _ => panic!("unexpected tag in <vendorExtensions>: {:?}", e),
559 },
560 Ok(Event::End(ref e)) => match e.name() {
561 QName(b"vendorExtensions") => {
562 break;
563 }
564 e => panic!("unhandled value: {:?}", e),
565 },
566 Ok(Event::Text(_)) => (),
567 e => panic!("unhandled value: {:?}", e),
568 }
569 }
570 Ok(())
571}
572
573fn print_header<U: Write>(out: &mut U) -> std::io::Result<()> {
574 let s = r####"
575#![cfg_attr(rustfmt, rustfmt_skip)] // don't format generated files
576#![allow(dead_code)]
577use core::convert::TryInto;
578#[cfg(feature="std")]
579use core::sync::atomic::AtomicPtr;
580#[cfg(feature="std")]
581use std::sync::Arc;
582
583#[derive(Debug, Copy, Clone)]
584pub struct Register {
585 /// Offset of this register within this CSR
586 offset: usize,
587 /// Mask of SVD-specified bits for the register
588 mask: usize,
589}
590impl Register {
591 pub const fn new(offset: usize, mask: usize) -> Register {
592 Register { offset, mask }
593 }
594 pub const fn offset(&self) -> usize { self.offset }
595 pub const fn mask(&self) -> usize { self.mask }
596}
597#[derive(Debug, Copy, Clone)]
598pub struct Field {
599 /// A bitmask we use to AND to the value, unshifted.
600 /// E.g. for a width of `3` bits, this mask would be 0b111.
601 mask: usize,
602 /// Offset of the first bit in this field
603 offset: usize,
604 /// A copy of the register address that this field
605 /// is a member of. Ideally this is optimized out by the
606 /// compiler.
607 register: Register,
608}
609impl Field {
610 /// Define a new CSR field with the given width at a specified
611 /// offset from the start of the register.
612 pub const fn new(width: usize, offset: usize, register: Register) -> Field {
613 let mask = if width < 32 { (1 << width) - 1 } else {0xFFFF_FFFF};
614 Field {
615 mask,
616 offset,
617 register,
618 }
619 }
620 pub const fn offset(&self) -> usize { self.offset }
621 pub const fn mask(&self) -> usize { self.mask }
622 pub const fn register(&self) -> Register { self.register }
623}
624#[derive(Debug, Copy, Clone)]
625pub struct CSR<T> {
626 base: *mut T,
627}
628impl<T> CSR<T>
629where
630 T: core::convert::TryFrom<usize> + core::convert::TryInto<usize> + core::default::Default,
631{
632 pub fn new(base: *mut T) -> Self {
633 CSR { base }
634 }
635 /// Retrieve the raw pointer used as the base of the CSR. This is unsafe because the copied
636 /// value can be used to do all kinds of awful shared mutable operations (like creating
637 /// another CSR accessor owned by another thread). However, sometimes this is unavoidable
638 /// because hardware is in fact shared mutable state.
639 pub unsafe fn base(&self) -> *mut T {
640 self.base
641 }
642 /// Read the contents of this register
643 pub fn r(&self, reg: Register) -> T {
644 // prevent re-ordering
645 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
646
647 let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) };
648 unsafe { usize_base.add(reg.offset).read_volatile() }
649 .try_into()
650 .unwrap_or_default()
651 }
652 /// Read a field from this CSR
653 pub fn rf(&self, field: Field) -> T {
654 // prevent re-ordering
655 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
656
657 let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) };
658 ((unsafe { usize_base.add(field.register.offset).read_volatile() } >> field.offset)
659 & field.mask)
660 .try_into()
661 .unwrap_or_default()
662 }
663 /// Read-modify-write a given field in this CSR
664 pub fn rmwf(&mut self, field: Field, value: T) {
665 let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) };
666 let value_as_usize: usize = value.try_into().unwrap_or_default() << field.offset;
667 let previous =
668 unsafe { usize_base.add(field.register.offset).read_volatile() } & !(field.mask << field.offset);
669 unsafe {
670 usize_base
671 .add(field.register.offset)
672 .write_volatile(previous | value_as_usize)
673 };
674 // prevent re-ordering
675 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
676 }
677 /// Write a given field without reading it first
678 pub fn wfo(&mut self, field: Field, value: T) {
679 let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) };
680 let value_as_usize: usize = (value.try_into().unwrap_or_default() & field.mask) << field.offset;
681 unsafe {
682 usize_base
683 .add(field.register.offset)
684 .write_volatile(value_as_usize)
685 };
686 // Ensure the compiler doesn't re-order the write.
687 // We use `SeqCst`, because `Acquire` only prevents later accesses from being reordered before
688 // *reads*, but this method only *writes* to the locations.
689 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
690 }
691 /// Write the entire contents of a register without reading it first
692 pub fn wo(&mut self, reg: Register, value: T) {
693 let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) };
694 let value_as_usize: usize = value.try_into().unwrap_or_default();
695 unsafe { usize_base.add(reg.offset).write_volatile(value_as_usize) };
696 // Ensure the compiler doesn't re-order the write.
697 // We use `SeqCst`, because `Acquire` only prevents later accesses from being reordered before
698 // *reads*, but this method only *writes* to the locations.
699 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
700 }
701 /// Zero a field from a provided value
702 pub fn zf(&self, field: Field, value: T) -> T {
703 let value_as_usize: usize = value.try_into().unwrap_or_default();
704 (value_as_usize & !(field.mask << field.offset))
705 .try_into()
706 .unwrap_or_default()
707 }
708 /// Shift & mask a value to its final field position
709 pub fn ms(&self, field: Field, value: T) -> T {
710 let value_as_usize: usize = value.try_into().unwrap_or_default();
711 ((value_as_usize & field.mask) << field.offset)
712 .try_into()
713 .unwrap_or_default()
714 }
715}
716
717#[derive(Debug)]
718#[cfg(feature="std")]
719pub struct AtomicCsr<T> {
720 base: Arc::<AtomicPtr<T>>,
721}
722#[cfg(feature="std")]
723impl<T> AtomicCsr<T>
724where
725 T: core::convert::TryFrom<usize> + core::convert::TryInto<usize> + core::default::Default,
726{
727 /// AtomicCsr wraps the CSR in an Arc + AtomicPtr, so that write operations don't require
728 /// a mutable reference. This allows us to stick CSR accesses into APIs that require
729 /// non-mutable references to hardware state (such as certain "standardized" USB APIs).
730 /// Hiding the fact that you're tweaking hardware registers behind Arc/AtomicPtr seems a little
731 /// scary, but, it does make for nicer Rust semantics.
732 pub fn new(base: *mut T) -> Self {
733 AtomicCsr {
734 base: Arc::new(AtomicPtr::new(base))
735 }
736 }
737 pub unsafe fn base(&self) -> *mut T {
738 self.base.load(core::sync::atomic::Ordering::SeqCst) as *mut T
739 }
740 pub fn clone(&self) -> Self {
741 AtomicCsr {
742 base: self.base.clone()
743 }
744 }
745 /// Read the contents of this register
746 pub fn r(&self, reg: Register) -> T {
747 // prevent re-ordering
748 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
749
750 let usize_base: *mut usize = unsafe { core::mem::transmute(self.base.load(core::sync::atomic::Ordering::SeqCst)) };
751 unsafe { usize_base.add(reg.offset).read_volatile() }
752 .try_into()
753 .unwrap_or_default()
754 }
755 /// Read a field from this CSR
756 pub fn rf(&self, field: Field) -> T {
757 // prevent re-ordering
758 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
759
760 let usize_base: *mut usize = unsafe { core::mem::transmute(self.base.load(core::sync::atomic::Ordering::SeqCst)) };
761 ((unsafe { usize_base.add(field.register.offset).read_volatile() } >> field.offset)
762 & field.mask)
763 .try_into()
764 .unwrap_or_default()
765 }
766 /// Read-modify-write a given field in this CSR
767 pub fn rmwf(&self, field: Field, value: T) {
768 let usize_base: *mut usize = unsafe { core::mem::transmute(self.base.load(core::sync::atomic::Ordering::SeqCst)) };
769 let value_as_usize: usize = value.try_into().unwrap_or_default() << field.offset;
770 let previous =
771 unsafe { usize_base.add(field.register.offset).read_volatile() } & !(field.mask << field.offset);
772 unsafe {
773 usize_base
774 .add(field.register.offset)
775 .write_volatile(previous | value_as_usize)
776 };
777 // prevent re-ordering
778 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
779 }
780 /// Write a given field without reading it first
781 pub fn wfo(&self, field: Field, value: T) {
782 let usize_base: *mut usize = unsafe { core::mem::transmute(self.base.load(core::sync::atomic::Ordering::SeqCst)) };
783 let value_as_usize: usize = (value.try_into().unwrap_or_default() & field.mask) << field.offset;
784 unsafe {
785 usize_base
786 .add(field.register.offset)
787 .write_volatile(value_as_usize)
788 };
789 // Ensure the compiler doesn't re-order the write.
790 // We use `SeqCst`, because `Acquire` only prevents later accesses from being reordered before
791 // *reads*, but this method only *writes* to the locations.
792 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
793 }
794 /// Write the entire contents of a register without reading it first
795 pub fn wo(&self, reg: Register, value: T) {
796 let usize_base: *mut usize = unsafe { core::mem::transmute(self.base.load(core::sync::atomic::Ordering::SeqCst)) };
797 let value_as_usize: usize = value.try_into().unwrap_or_default();
798 unsafe { usize_base.add(reg.offset).write_volatile(value_as_usize) };
799 // Ensure the compiler doesn't re-order the write.
800 // We use `SeqCst`, because `Acquire` only prevents later accesses from being reordered before
801 // *reads*, but this method only *writes* to the locations.
802 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
803 }
804 /// Zero a field from a provided value
805 pub fn zf(&self, field: Field, value: T) -> T {
806 let value_as_usize: usize = value.try_into().unwrap_or_default();
807 (value_as_usize & !(field.mask << field.offset))
808 .try_into()
809 .unwrap_or_default()
810 }
811 /// Shift & mask a value to its final field position
812 pub fn ms(&self, field: Field, value: T) -> T {
813 let value_as_usize: usize = value.try_into().unwrap_or_default();
814 ((value_as_usize & field.mask) << field.offset)
815 .try_into()
816 .unwrap_or_default()
817 }
818}
819"####;
820 out.write_all(s.as_bytes())
821}
822
823fn print_memory_regions<U: Write>(regions: &[MemoryRegion], out: &mut U) -> std::io::Result<()> {
824 writeln!(out, "// Physical base addresses of memory regions")?;
825 for region in regions {
826 writeln!(out, "pub const HW_{}_MEM: usize = 0x{:08x};", region.name, region.base)?;
827 writeln!(out, "pub const HW_{}_MEM_LEN: usize = {};", region.name, region.size)?;
828 }
829 writeln!(out)?;
830 Ok(())
831}
832
833fn print_constants<U: Write>(constants: &[Constant], out: &mut U) -> std::io::Result<()> {
834 writeln!(out, "\n// Litex auto-generated constants")?;
835 for constant in constants {
836 let maybe_intval = constant.value.parse::<u32>();
837 match maybe_intval {
838 Ok(intval) => {
839 writeln!(out, "pub const LITEX_{}: usize = {};", constant.name, intval)?;
840 }
841 Err(_) => {
842 writeln!(out, "pub const LITEX_{}: &str = \"{}\";", constant.name, constant.value)?;
843 }
844 }
845 }
846 writeln!(out)?;
847 Ok(())
848}
849
850fn print_peripherals<U: Write>(peripherals: &[Peripheral], out: &mut U) -> std::io::Result<()> {
851 writeln!(out, "// Physical base addresses of registers")?;
852 for peripheral in peripherals {
853 writeln!(
854 out,
855 "pub const HW_{}_BASE : usize = 0x{:08x};",
856 peripheral.name.to_uppercase(),
857 peripheral.base
858 )?;
859 }
860 writeln!(out)?;
861
862 let s = r####"
863pub mod utra {
864"####;
865 out.write_all(s.as_bytes())?;
866
867 for peripheral in peripherals {
868 writeln!(out)?;
869 writeln!(out, " pub mod {} {{", peripheral.name.to_lowercase())?;
870 writeln!(
871 out,
872 " pub const {}_NUMREGS: usize = {};",
873 peripheral.name.to_uppercase(),
874 peripheral.registers.len()
875 )?;
876 for register in &peripheral.registers {
877 writeln!(out)?;
878 if let Some(description) = ®ister.description {
879 writeln!(out, " /// {}", description)?;
880 }
881 let mut mask: usize = 0;
882 for field in ®ister.fields {
883 mask |= ((1 << (field.msb + 1 - field.lsb)) - 1) << field.lsb;
884 }
885 writeln!(
886 out,
887 " pub const {}: crate::Register = crate::Register::new({}, 0x{:x});",
888 register.name.to_uppercase(),
889 register.offset / 4,
890 mask,
891 )?;
892 for field in ®ister.fields {
893 writeln!(
894 out,
895 " pub const {}_{}: crate::Field = crate::Field::new({}, {}, {});",
896 register.name,
897 field.name.to_uppercase(),
898 field.msb + 1 - field.lsb,
899 field.lsb,
900 register.name
901 )?;
902 }
903 }
904 writeln!(out)?;
905 for interrupt in &peripheral.interrupt {
906 writeln!(
907 out,
908 " pub const {}_IRQ: usize = {};",
909 interrupt.name.to_uppercase(),
910 interrupt.value
911 )?;
912 }
913 writeln!(
914 out,
915 " pub const HW_{}_BASE: usize = 0x{:08x};",
916 peripheral.name.to_uppercase(),
917 peripheral.base
918 )?;
919 writeln!(out, " }}")?;
920 }
921 writeln!(out, "}}")?;
922 Ok(())
923}
924
925fn print_tests<U: Write>(peripherals: &[Peripheral], out: &mut U) -> std::io::Result<()> {
926 let test_header = r####"
927#[cfg(test)]
928mod tests {
929"####
930 .as_bytes();
931 out.write_all(test_header)?;
932
933 for peripheral in peripherals {
934 let mod_name = peripheral.name.to_lowercase();
935 let per_name = peripheral.name.to_lowercase() + "_csr";
936
937 write!(
938 out,
939 r####"
940 #[test]
941 #[ignore]
942 fn compile_check_{}() {{
943 use super::*;
944"####,
945 per_name
946 )?;
947
948 writeln!(
949 out,
950 " let mut {} = CSR::new(HW_{}_BASE as *mut u32);",
951 per_name,
952 peripheral.name.to_uppercase()
953 )?;
954 for register in &peripheral.registers {
955 writeln!(out)?;
956 let reg_name = register.name.to_uppercase();
957 writeln!(out, " let foo = {}.r(utra::{}::{});", per_name, mod_name, reg_name)?;
958 writeln!(out, " {}.wo(utra::{}::{}, foo);", per_name, mod_name, reg_name)?;
959 for field in ®ister.fields {
960 let field_name = format!("{}_{}", reg_name, field.name.to_uppercase());
961 writeln!(out, " let bar = {}.rf(utra::{}::{});", per_name, mod_name, field_name)?;
962 writeln!(out, " {}.rmwf(utra::{}::{}, bar);", per_name, mod_name, field_name)?;
963 writeln!(
964 out,
965 " let mut baz = {}.zf(utra::{}::{}, bar);",
966 per_name, mod_name, field_name
967 )?;
968 writeln!(out, " baz |= {}.ms(utra::{}::{}, 1);", per_name, mod_name, field_name)?;
969 writeln!(out, " {}.wfo(utra::{}::{}, baz);", per_name, mod_name, field_name)?;
970 }
971 }
972
973 writeln!(out, " }}")?;
974 }
975 writeln!(out, "}}")?;
976
977 Ok(())
978}
979
980pub fn parse_svd<T: Read>(sources: Vec<T>) -> Result<Description, ParseError> {
981 let mut description = Description::default();
982 for src in sources {
983 let mut buf = Vec::new();
984 let buf_reader = BufReader::new(src);
985 let mut reader = Reader::from_reader(buf_reader);
986 loop {
987 match reader.read_event_into(&mut buf) {
988 Ok(Event::Start(ref e)) => match e.name() {
989 QName(b"peripherals") => {
990 description.peripherals.append(&mut generate_peripherals(&mut reader)?);
991 }
992 QName(b"vendorExtensions") => {
993 parse_vendor_extensions(&mut reader, &mut description)?;
994 }
995 _ => (),
996 },
997 Ok(Event::Eof) => break,
998 Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e),
999 _ => (),
1000 }
1001 buf.clear();
1002 }
1003 }
1004 Ok(description)
1005}
1006
1007pub fn generate<T: Read, U: Write>(src: Vec<T>, dest: &mut U) -> Result<(), ParseError> {
1008 let description = parse_svd(src)?;
1009
1010 print_header(dest).or(Err(ParseError::WriteError))?;
1011 print_memory_regions(&description.memory_regions, dest).or(Err(ParseError::WriteError))?;
1012 print_peripherals(&description.peripherals, dest).or(Err(ParseError::WriteError))?;
1013 print_constants(&description.constants, dest).or(Err(ParseError::WriteError))?;
1014 print_tests(&description.peripherals, dest).or(Err(ParseError::WriteError))?;
1015
1016 Ok(())
1017}