Skip to main content

xous_tools/
utils.rs

1use std::collections::BTreeMap;
2use std::fs::File;
3use std::io;
4
5pub struct CsrMemoryRegion {
6    pub start: u32,
7    pub length: u32,
8}
9
10pub struct CsrConfig {
11    pub regions: BTreeMap<String, CsrMemoryRegion>,
12}
13
14const PAGE_SIZE: u32 = 4096;
15
16#[derive(Debug)]
17pub enum ConfigError {
18    /// Couldn't parse string as number
19    NumberParseError(String, std::num::ParseIntError),
20
21    /// Generic IO Error
22    IoError(io::Error),
23}
24
25impl std::convert::From<io::Error> for ConfigError {
26    fn from(e: io::Error) -> ConfigError { ConfigError::IoError(e) }
27}
28
29pub fn get_base(value: &str) -> (&str, u32) {
30    if value.starts_with("0x") {
31        (value.trim_start_matches("0x"), 16)
32    } else if value.starts_with("0X") {
33        (value.trim_start_matches("0X"), 16)
34    } else if value.starts_with("0b") {
35        (value.trim_start_matches("0b"), 2)
36    } else if value.starts_with("0B") {
37        (value.trim_start_matches("0B"), 2)
38    } else if value.starts_with('0') && value != "0" {
39        (value.trim_start_matches('0'), 8)
40    } else {
41        (value, 10)
42    }
43}
44
45pub fn parse_u32(value: &str) -> Result<u32, ConfigError> {
46    let (value, base) = get_base(value);
47    u32::from_str_radix(value, base).map_err(|e| ConfigError::NumberParseError(value.to_owned(), e))
48}
49
50pub fn parse_csr_csv(filename: &str) -> Result<CsrConfig, ConfigError> {
51    let mut map = BTreeMap::new();
52    let file = File::open(filename)?;
53
54    let mut csr_base = 0;
55    let mut csr_top = 0;
56
57    let mut rdr = csv::ReaderBuilder::new().flexible(true).from_reader(file);
58    for result in rdr.records() {
59        if let Ok(r) = result {
60            if r.is_empty() {
61                eprintln!("csv: ignoring blank line");
62                continue;
63            }
64            match &r[0] {
65                "csr_base" => {
66                    if r.len() < 3 {
67                        eprintln!("csv: found csr_base entry, but entry was short");
68                        continue;
69                    }
70                    let base_addr = parse_u32(&r[2])?;
71                    if base_addr > csr_top {
72                        // println!("csv: increasing csr top: {:08x} -> {:08x}", csr_top, base_addr);
73                        csr_top = base_addr;
74                    }
75                }
76                "memory_region" => {
77                    if r.len() < 4 {
78                        eprintln!("csv: found memory_region entry, but entry was short");
79                        continue;
80                    }
81                    let region_name = &r[1];
82                    let base_addr = parse_u32(&r[2])?;
83                    let length = parse_u32(&r[3])?;
84
85                    if region_name == "csr" {
86                        csr_base = base_addr;
87                    } else {
88                        map.insert(
89                            region_name.to_string().to_lowercase(),
90                            CsrMemoryRegion { start: base_addr, length },
91                        );
92                    }
93                }
94                _ => (),
95            };
96        }
97    }
98
99    if csr_base != 0 && csr_top != 0 {
100        csr_top += 1;
101        csr_top = (csr_top + PAGE_SIZE - 1) & !(PAGE_SIZE - 1);
102        map.insert("csr".to_string(), CsrMemoryRegion { start: csr_base, length: csr_top - csr_base });
103    }
104    Ok(CsrConfig { regions: map })
105}