mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-14 08:03:34 +00:00
create-image: support generating an image from an svd
Now that we can parse svd files, support creating an image using an svd instead of a csv file. Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
e9d9315418
commit
96df91f53b
2 changed files with 111 additions and 49 deletions
|
|
@ -15,6 +15,7 @@ csv = "1.1"
|
|||
env_logger = "0.7"
|
||||
log = "0"
|
||||
xmas-elf = "0.7.0"
|
||||
svd2utra = { path = "../svd2utra" }
|
||||
|
||||
[[bin]]
|
||||
name = "copy-object"
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ extern crate clap;
|
|||
|
||||
extern crate crc;
|
||||
|
||||
use std::convert::TryInto;
|
||||
use std::fs::File;
|
||||
|
||||
use tools::elf::{read_minielf, read_program};
|
||||
|
|
@ -15,6 +16,52 @@ use tools::xous_arguments::XousArguments;
|
|||
|
||||
use clap::{App, Arg};
|
||||
|
||||
struct RamConfig {
|
||||
offset: u32,
|
||||
size: u32,
|
||||
name: u32,
|
||||
regions: MemoryRegions,
|
||||
memory_required: u32,
|
||||
}
|
||||
|
||||
fn csr_to_config(hv: tools::utils::CsrConfig, ram_config: &mut RamConfig) {
|
||||
let mut found_ram_name = None;
|
||||
fn round_mem(src: u32) -> u32 {
|
||||
(src + 4095) & !4095
|
||||
}
|
||||
// Look for the largest "ram" block, which we'll treat as main memory
|
||||
for (k, v) in &hv.regions {
|
||||
if k.find("ram").is_some() && v.length > ram_config.size {
|
||||
ram_config.size = round_mem(v.length);
|
||||
ram_config.offset = v.start;
|
||||
found_ram_name = Some(k.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if found_ram_name.is_none() {
|
||||
eprintln!("Error: Couldn't find a memory region named \"ram\" in config file");
|
||||
return;
|
||||
}
|
||||
|
||||
// Now that we know which block is ram, add the other regions.
|
||||
let found_ram_name = MemoryRegion::make_name(&found_ram_name.unwrap());
|
||||
for (k, v) in &hv.regions {
|
||||
ram_config.memory_required += round_mem(v.length) / 4096;
|
||||
let region_name = MemoryRegion::make_name(k);
|
||||
// Don't add the RAM section to the extra regions block.
|
||||
if region_name == found_ram_name {
|
||||
ram_config.name = region_name;
|
||||
continue;
|
||||
}
|
||||
// Don't add empty sections.
|
||||
if round_mem(v.length) == 0 {
|
||||
continue;
|
||||
}
|
||||
ram_config
|
||||
.regions
|
||||
.add(MemoryRegion::new(v.start, round_mem(v.length), region_name));
|
||||
}
|
||||
}
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
let matches = App::new("Xous Image Creator")
|
||||
|
|
@ -48,7 +95,16 @@ fn main() {
|
|||
.value_name("CSR_CSV")
|
||||
.help("csr.csv file from litex")
|
||||
.takes_value(true)
|
||||
.required_unless("ram"),
|
||||
.required_unless_one(&["ram", "svd", "csv"]),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("svd")
|
||||
.short("s")
|
||||
.long("svd")
|
||||
.value_name("SOC_SVD")
|
||||
.help("soc.csv file from litex")
|
||||
.takes_value(true)
|
||||
.required_unless_one(&["ram", "svd", "csv"]),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("ram")
|
||||
|
|
@ -56,8 +112,8 @@ fn main() {
|
|||
.long("ram")
|
||||
.takes_value(true)
|
||||
.value_name("OFFSET:SIZE")
|
||||
.required_unless("csv")
|
||||
.help("RAM offset and size, in the form of [offset]:[size]"),
|
||||
.help("RAM offset and size, in the form of [offset]:[size]")
|
||||
.required_unless_one(&["ram", "svd", "csv"]),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("debug")
|
||||
|
|
@ -74,11 +130,13 @@ fn main() {
|
|||
)
|
||||
.get_matches();
|
||||
|
||||
let mut ram_offset = Default::default();
|
||||
let mut ram_size = Default::default();
|
||||
let mut ram_name = MemoryRegion::make_name("sram");
|
||||
let mut regions = MemoryRegions::new();
|
||||
let mut memory_required = 0;
|
||||
let mut ram_config = RamConfig {
|
||||
offset: Default::default(),
|
||||
size: Default::default(),
|
||||
name: MemoryRegion::make_name("sram"),
|
||||
regions: MemoryRegions::new(),
|
||||
memory_required: 0,
|
||||
};
|
||||
|
||||
if let Some(val) = matches.value_of("ram") {
|
||||
let ram_parts: Vec<&str> = val.split(':').collect();
|
||||
|
|
@ -87,7 +145,7 @@ fn main() {
|
|||
return;
|
||||
}
|
||||
|
||||
ram_offset = match parse_u32(ram_parts[0]) {
|
||||
ram_config.offset = match parse_u32(ram_parts[0]) {
|
||||
Ok(o) => o,
|
||||
Err(e) => {
|
||||
eprintln!("Error: Unable to parse {}: {:?}", ram_parts[0], e);
|
||||
|
|
@ -95,7 +153,7 @@ fn main() {
|
|||
}
|
||||
};
|
||||
|
||||
ram_size = match parse_u32(ram_parts[1]) {
|
||||
ram_config.size = match parse_u32(ram_parts[1]) {
|
||||
Ok(o) => o,
|
||||
Err(e) => {
|
||||
eprintln!("Error: Unable to parse {}: {:?}", ram_parts[1], e);
|
||||
|
|
@ -103,51 +161,54 @@ fn main() {
|
|||
}
|
||||
};
|
||||
|
||||
memory_required += ram_size / 4096;
|
||||
ram_config.memory_required += ram_config.size / 4096;
|
||||
}
|
||||
|
||||
if let Some(csr_csv) = matches.value_of("csv") {
|
||||
let hv = parse_csr_csv(csr_csv).expect("couldn't find csr.csv file");
|
||||
let mut found_ram_name = None;
|
||||
fn round_mem(src: u32) -> u32 {
|
||||
(src + 4095) & !4095
|
||||
}
|
||||
// Look for the largest "ram" block, which we'll treat as main memory
|
||||
for (k, v) in &hv.regions {
|
||||
if k.find("ram").is_some() && v.length > ram_size {
|
||||
ram_size = round_mem(v.length);
|
||||
ram_offset = v.start;
|
||||
found_ram_name = Some(k.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if found_ram_name.is_none() {
|
||||
eprintln!("Error: Couldn't find a memory region named \"ram\" in csv file");
|
||||
return;
|
||||
}
|
||||
|
||||
// Now that we know which block is ram, add the other regions.
|
||||
let found_ram_name = MemoryRegion::make_name(&found_ram_name.unwrap());
|
||||
for (k, v) in &hv.regions {
|
||||
memory_required += round_mem(v.length) / 4096;
|
||||
let region_name = MemoryRegion::make_name(k);
|
||||
// Don't add the RAM section to the extra regions block.
|
||||
if region_name == found_ram_name {
|
||||
ram_name = region_name;
|
||||
continue;
|
||||
}
|
||||
// Don't add empty sections.
|
||||
if round_mem(v.length) == 0 {
|
||||
continue;
|
||||
}
|
||||
regions.add(MemoryRegion::new(v.start, round_mem(v.length), region_name));
|
||||
}
|
||||
csr_to_config(hv, &mut ram_config);
|
||||
}
|
||||
|
||||
let mut args = XousArguments::new(ram_offset, ram_size, ram_name);
|
||||
if let Some(soc_svd) = matches.value_of("svd") {
|
||||
let soc_svd_file = std::fs::File::open(soc_svd).unwrap();
|
||||
let desc = svd2utra::parse_svd(soc_svd_file).unwrap();
|
||||
let mut map = std::collections::BTreeMap::new();
|
||||
|
||||
if !regions.is_empty() {
|
||||
args.add(regions);
|
||||
let mut csr_top = 0;
|
||||
for peripheral in desc.peripherals {
|
||||
if peripheral.base > csr_top {
|
||||
csr_top = peripheral.base;
|
||||
}
|
||||
}
|
||||
for region in desc.memory_regions {
|
||||
// Ignore the "CSR" region and manually reconstruct it, because this
|
||||
// region is largely empty and we want to avoid allocating too much space.
|
||||
if region.name == "CSR" {
|
||||
const PAGE_SIZE: usize = 4096;
|
||||
map.insert(
|
||||
region.name.to_lowercase(),
|
||||
tools::utils::CsrMemoryRegion {
|
||||
start: region.base.try_into().unwrap(),
|
||||
length: (((csr_top - region.base) + PAGE_SIZE) & !(PAGE_SIZE - 1)).try_into().unwrap(),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
map.insert(
|
||||
region.name.to_lowercase(),
|
||||
tools::utils::CsrMemoryRegion {
|
||||
start: region.base.try_into().unwrap(),
|
||||
length: region.size.try_into().unwrap(),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
csr_to_config(tools::utils::CsrConfig { regions: map }, &mut ram_config);
|
||||
}
|
||||
|
||||
let mut args = XousArguments::new(ram_config.offset, ram_config.size, ram_config.name);
|
||||
|
||||
if !ram_config.regions.is_empty() {
|
||||
args.add(ram_config.regions);
|
||||
}
|
||||
|
||||
if matches.is_present("debug") {
|
||||
|
|
@ -194,7 +255,7 @@ fn main() {
|
|||
|
||||
println!(
|
||||
"Runtime will require {} bytes to track memory allocations",
|
||||
memory_required
|
||||
ram_config.memory_required
|
||||
);
|
||||
println!("Image created in file {}", output_filename);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue