Skip to content

Commit

Permalink
Implement parsing of value groups
Browse files Browse the repository at this point in the history
This commit fixes issue avr-rust#1
  • Loading branch information
Daan Sprenkels committed Jun 11, 2019
1 parent fe2250e commit f4ab7c6
Showing 1 changed file with 100 additions and 7 deletions.
107 changes: 100 additions & 7 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ mod gen {
writeln!(w, "//!")?;

writeln!(w, "//! # Variants")?;
writeln!(w, "//! | | Pinout | Mcuage | Operating temperature | Operating voltage | Max speed |")?;
writeln!(w, "//! | | Pinout | Mcu age | Operating temperature | Operating voltage | Max speed |")?;
writeln!(w, "//! |--------|--------|---------|-----------------------|-------------------|-----------|")?;
for variant in mcu.variants.iter() {
let pinout_label = variant.pinout.as_ref().map(|p| p.replace('_', "-").to_owned()).unwrap_or_else(|| String::new());
Expand Down Expand Up @@ -145,12 +145,9 @@ mod gen {
let ty = integer_type(register.size);

if !register.caption.is_empty() {
let mut caption = register.caption.trim().to_owned();
if !caption.ends_with('.') { caption.push('.') }

writeln!(w, "/// {}", caption)?;
writeln!(w, "/// {}", format_caption(&register.caption))?;
} else {
writeln!(w, "/// {} register", register.name)?;
writeln!(w, "/// `{}` register", register.name)?;
}

let mut bitfields = register_bitfields.iter().filter_map(|&(reg,bitfield)| {
Expand All @@ -176,16 +173,55 @@ mod gen {
for (register, bitfield) in register_bitfields {
let ty = integer_type(bitfield.size);

writeln!(w, "/// Bitfield on register {}", register.name)?;
writeln!(w, "/// Bitfield on register `{}`", register.name)?;
writeln!(w, "pub const {}: *mut {} = {:#X} as *mut {};",
bitfield.name, ty, bitfield.mask, ty)?;
writeln!(w)?;

}

for value_group in ordered_value_groups(&mcu) {
if !value_group.caption.is_empty() {
writeln!(w, "/// {}", value_group.caption)?;
} else {
writeln!(w, "/// `{}` value group", value_group.name)?;
}
writeln!(w, "#[allow(non_upper_case_globals)]")? ;
writeln!(w, "pub mod {} {{", value_group.name.to_lowercase())?;
for val in unique_value_group_values(&value_group).iter() {
let first_char = val.name.chars().next().expect("empty value name");
let name = if !first_char.is_alphabetic() && first_char != '_' {
format!("_{}", val.name)
} else {
val.name.to_owned()
};

if !val.caption.is_empty() {
let ty = "u32";
writeln!(w, " /// {}", format_caption(&val.caption))?;
writeln!(w, " pub const {}: {} = {:#X};", name, ty, val.value)?;
}
}
writeln!(w, "}}")?;
writeln!(w)?;
}

Ok(())
}

fn format_caption(caption: &str) -> String {
let mut result = caption.to_owned();
// Escape special characters in markdown
result = result.replace("[", "\\[").replace("]", "\\]");

// Trim and make a sentence
result = result.trim().to_owned();
if !result.ends_with('.') {
result.push('.')
}
result
}

fn ordered_registers(mcu: &Mcu) -> Vec<Register> {
let mut unique_registers = self::unique_registers(mcu);
insert_high_low_variants(&mut unique_registers);
Expand All @@ -196,6 +232,19 @@ mod gen {
registers
}

fn ordered_value_groups(mcu: &Mcu) -> Vec<ValueGroup> {
let mut value_groups = Vec::new();
for module in mcu.modules.iter() {
for value_group in module.value_groups.iter() {
value_groups.push(value_group.clone());
}
}
value_groups = unique_value_groups(&value_groups);
value_groups.sort_by(|vg1, vg2| vg1.partial_cmp(vg2).unwrap());

value_groups
}

fn insert_high_low_variants(registers: &mut HashMap<String, Register>) {
let wide_registers: Vec<_> = registers.values()
.filter(|r| r.size == 2)
Expand Down Expand Up @@ -257,6 +306,50 @@ mod gen {
result
}

fn unique_value_groups(value_groups: &[ValueGroup]) -> Vec<ValueGroup> {
let mut value_groups = value_groups.to_owned();
loop {
let mut remove_idx = None;
for (idx, value_group) in value_groups.iter().enumerate() {
if value_groups.iter().filter(|vg| {
if vg.name == value_group.name {
assert_eq!(*vg, value_group);
true
} else {
false
}
}).count() > 1 {
remove_idx = Some(idx);
}
}
match remove_idx {
Some(idx) => value_groups.remove(idx),
None => break,
};
}
value_groups
}

/// Collect al the values in a ValueGroup and deduplicate the,/
///
/// As in the bitfield descriptions, the value-group decriptions contain
/// values with duplicate names. We will skip every value which is
/// ambiguous. See `documentable_bitfields` for more context on this
/// issue.
fn unique_value_group_values(value_group: &ValueGroup) -> Vec<Value> {
let mut values = value_group.values.clone();
let mut remove_names = HashSet::new();
for value in values.iter() {
if values.iter().filter(|v| v.name == value.name).count() > 1 {
remove_names.insert(value.name.to_owned());
}
}
for name in remove_names {
values.retain(|v| v.name != name);
}
values
}

/// Gets the integer type of a specified width.
fn integer_type(byte_count: u32) -> &'static str {
match byte_count {
Expand Down

0 comments on commit f4ab7c6

Please sign in to comment.