svd2utra/
generate.rs

1// SPDX-FileCopyrightText: 2020 Sean Cross <sean@xobs.io>
2// SPDX-FileCopyrightText: 2020 bunnie <bunnie@kosagi.com>
3// SPDX-License-Identifier: MIT OR Apache-2.0
4
5use 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 no msb/lsb and bitRange tags were encountered then
181    // it's possible that the field is defined via
182    // `bitWidth` and `bitOffset` tags instead. Let's handle this.
183    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                    // println!("End fields");
208                    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    // Derive from the base peripheral if specified
364    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                    // keep adding _ to the end of the name until it's unique
463                    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                    // keep adding _ to the end of the name until it's unique
514                    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            // note to future self: if Litex goe away from attributes to nested elements, you would want
531            // Ok(Event::Start(ref e) => match e.name() ... to descend into the next tag level, and then
532            // use the tag_name match and extract_contents methods from other functions to generate
533            // the structure.
534            // note that the two formats could be mutually exclusively compatible within the same code base:
535            // if there are no attributes, the attribute iterator would do nothing; and if there are no
536            // child elements, the recursive descent would also do nothing.
537            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) = &register.description {
879                writeln!(out, "        /// {}", description)?;
880            }
881            let mut mask: usize = 0;
882            for field in &register.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 &register.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 &register.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}