Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion fpga_arch_parser/src/arch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,36 @@ pub struct DeviceInfo {
// TODO: default_fc
}

pub struct Switch {
pub enum SwitchType {
Mux,
Tristate,
PassGate,
Short,
Buffer,
}

pub enum SwitchBufSize {
Auto,
Val(f32),
}

pub struct SwitchTDel {
pub num_inputs: i32,
pub delay: f32,
}

pub struct Switch {
pub sw_type: SwitchType,
pub name: String,
pub resistance: f32,
pub c_in: f32,
pub c_out: f32,
pub c_internal: Option<f32>,
pub t_del: Option<f32>,
pub buf_size: SwitchBufSize,
pub mux_trans_size: Option<f32>,
pub power_buf_size: Option<i32>,
pub t_del_tags: Vec<SwitchTDel>,
}

pub enum SegmentAxis {
Expand Down
15 changes: 12 additions & 3 deletions fpga_arch_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mod parse_port;
mod parse_tiles;
mod parse_layouts;
mod parse_device;
mod parse_switch_list;
mod parse_segment_list;
mod parse_complex_block_list;

Expand All @@ -23,6 +24,7 @@ use crate::parse_port::parse_port;
use crate::parse_tiles::parse_tiles;
use crate::parse_layouts::parse_layouts;
use crate::parse_device::parse_device;
use crate::parse_switch_list::parse_switch_list;
use crate::parse_segment_list::parse_segment_list;
use crate::parse_complex_block_list::parse_complex_block_list;

Expand All @@ -37,6 +39,7 @@ fn parse_architecture(name: &OwnedName,
let mut tiles: Option<Vec<Tile>> = None;
let mut layouts: Option<Vec<Layout>> = None;
let mut device: Option<DeviceInfo> = None;
let mut switch_list: Option<Vec<Switch>> = None;
let mut segment_list: Option<Vec<Segment>> = None;
let mut complex_block_list: Option<Vec<PBType>> = None;

Expand Down Expand Up @@ -67,8 +70,10 @@ fn parse_architecture(name: &OwnedName,
}
},
"switchlist" => {
// TODO: Implement.
let _ = parser.skip();
switch_list = match switch_list {
None => Some(parse_switch_list(&name, &attributes, parser)?),
Some(_) => return Err(FPGAArchParseError::DuplicateTag(format!("<{name}>"), parser.position())),
}
},
"segmentlist" => {
segment_list = match segment_list {
Expand Down Expand Up @@ -134,6 +139,10 @@ fn parse_architecture(name: &OwnedName,
Some(d) => d,
None => return Err(FPGAArchParseError::MissingRequiredTag("<device>".to_string())),
};
let switch_list = match switch_list {
Some(s) => s,
None => return Err(FPGAArchParseError::MissingRequiredTag("<switchlist>".to_string())),
};
let segment_list = match segment_list {
Some(s) => s,
None => return Err(FPGAArchParseError::MissingRequiredTag("<segmentlist>".to_string())),
Expand All @@ -148,7 +157,7 @@ fn parse_architecture(name: &OwnedName,
tiles,
layouts,
device,
switch_list: Vec::new(),
switch_list,
segment_list,
complex_block_list,
})
Expand Down
298 changes: 298 additions & 0 deletions fpga_arch_parser/src/parse_switch_list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
use std::fs::File;
use std::io::BufReader;

use xml::common::Position;
use xml::reader::{EventReader, XmlEvent};
use xml::name::OwnedName;
use xml::attribute::OwnedAttribute;

use crate::parse_error::*;
use crate::arch::*;

fn parse_switch_t_del(name: &OwnedName,
attributes: &[OwnedAttribute],
parser: &mut EventReader<BufReader<File>>) -> Result<SwitchTDel, FPGAArchParseError> {
assert!(name.to_string() == "Tdel");

let mut num_inputs: Option<i32> = None;
let mut delay: Option<f32> = None;

for a in attributes {
match a.name.to_string().as_ref() {
"num_inputs" => {
num_inputs = match num_inputs {
None => match a.value.parse() {
Ok(v) => Some(v),
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
},
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
}
},
"delay" => {
delay = match delay {
None => match a.value.parse() {
Ok(v) => Some(v),
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
},
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
}
},
_ => return Err(FPGAArchParseError::UnknownAttribute(a.to_string(), parser.position())),
}
}
let num_inputs = match num_inputs {
Some(p) => p,
None => return Err(FPGAArchParseError::MissingRequiredAttribute("num_inputs".to_string(), parser.position())),
};
let delay = match delay {
Some(p) => p,
None => return Err(FPGAArchParseError::MissingRequiredAttribute("delay".to_string(), parser.position())),
};

loop {
match parser.next() {
Ok(XmlEvent::StartElement { name, .. }) => {
return Err(FPGAArchParseError::InvalidTag(name.to_string(), parser.position()));
},
Ok(XmlEvent::EndElement { name }) => {
match name.to_string().as_str() {
"Tdel" => break,
_ => return Err(FPGAArchParseError::UnexpectedEndTag(name.to_string(), parser.position())),
}
},
Ok(XmlEvent::EndDocument) => {
return Err(FPGAArchParseError::UnexpectedEndOfDocument(name.to_string()));
},
Err(e) => {
return Err(FPGAArchParseError::XMLParseError(format!("{e:?}"), parser.position()));
},
_ => {},
};
}

Ok(SwitchTDel {
num_inputs,
delay,
})
}

fn parse_switch(name: &OwnedName,
attributes: &[OwnedAttribute],
parser: &mut EventReader<BufReader<File>>) -> Result<Switch, FPGAArchParseError> {
assert!(name.to_string() == "switch");

let mut sw_type: Option<SwitchType> = None;
let mut sw_name: Option<String> = None;
let mut resistance: Option<f32> = None;
let mut c_in: Option<f32> = None;
let mut c_out: Option<f32> = None;
let mut c_internal: Option<f32> = None;
let mut t_del: Option<f32> = None;
let mut buf_size: Option<SwitchBufSize> = None;
let mut mux_trans_size: Option<f32> = None;
let mut power_buf_size: Option<i32> = None;

for a in attributes {
match a.name.to_string().as_ref() {
"type" => {
sw_type = match sw_type {
None => match a.value.to_string().as_ref() {
"mux" => Some(SwitchType::Mux),
"tristate" => Some(SwitchType::Tristate),
"pass_gate" => Some(SwitchType::PassGate),
"short" => Some(SwitchType::Short),
"buffer" => Some(SwitchType::Buffer),
_ => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: Unknown switch type."), parser.position())),
},
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
}
},
"name" => {
sw_name = match sw_name {
None => Some(a.value.clone()),
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
}
},
"R" => {
resistance = match resistance {
None => match a.value.parse() {
Ok(v) => Some(v),
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
},
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
}
},
"Cin" => {
c_in = match c_in {
None => match a.value.parse() {
Ok(v) => Some(v),
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
},
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
}
},
"Cout" => {
c_out = match c_out {
None => match a.value.parse() {
Ok(v) => Some(v),
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
},
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
}
},
"Cinternal" => {
c_internal = match c_internal {
None => match a.value.parse() {
Ok(v) => Some(v),
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
},
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
}
},
"Tdel" => {
t_del = match t_del {
None => match a.value.parse() {
Ok(v) => Some(v),
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
},
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
}
},
"buf_size" => {
buf_size = match buf_size {
None => match a.value.as_ref() {
"auto" => Some(SwitchBufSize::Auto),
_ => match a.value.parse() {
Ok(v) => Some(SwitchBufSize::Val(v)),
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
},
},
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
}
},
"mux_trans_size" => {
mux_trans_size = match mux_trans_size {
None => match a.value.parse() {
Ok(v) => Some(v),
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
},
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
}
},
"power_buf_size" => {
power_buf_size = match power_buf_size {
None => match a.value.parse() {
Ok(v) => Some(v),
Err(e) => return Err(FPGAArchParseError::AttributeParseError(format!("{a}: {e}"), parser.position())),
},
Some(_) => return Err(FPGAArchParseError::DuplicateAttribute(a.to_string(), parser.position())),
}
},
_ => return Err(FPGAArchParseError::UnknownAttribute(a.to_string(), parser.position())),
};
}

let sw_type = match sw_type {
Some(p) => p,
None => return Err(FPGAArchParseError::MissingRequiredAttribute("type".to_string(), parser.position())),
};
let sw_name = match sw_name {
Some(p) => p,
None => return Err(FPGAArchParseError::MissingRequiredAttribute("name".to_string(), parser.position())),
};
let resistance = match resistance {
Some(p) => p,
None => return Err(FPGAArchParseError::MissingRequiredAttribute("R".to_string(), parser.position())),
};
let c_in = match c_in {
Some(p) => p,
None => return Err(FPGAArchParseError::MissingRequiredAttribute("Cin".to_string(), parser.position())),
};
let c_out = match c_out {
Some(p) => p,
None => return Err(FPGAArchParseError::MissingRequiredAttribute("Cout".to_string(), parser.position())),
};
let buf_size = buf_size.unwrap_or(SwitchBufSize::Auto);

let mut t_del_tags: Vec<SwitchTDel> = Vec::new();
loop {
match parser.next() {
Ok(XmlEvent::StartElement { name, .. }) => {
match name.to_string().as_str() {
"Tdel" => {
t_del_tags.push(parse_switch_t_del(&name, &attributes, parser)?);
},
_ => return Err(FPGAArchParseError::InvalidTag(name.to_string(), parser.position())),
};
},
Ok(XmlEvent::EndElement { name }) => {
match name.to_string().as_str() {
"switch" => break,
_ => return Err(FPGAArchParseError::UnexpectedEndTag(name.to_string(), parser.position())),
}
},
Ok(XmlEvent::EndDocument) => {
return Err(FPGAArchParseError::UnexpectedEndOfDocument(name.to_string()));
},
Err(e) => {
return Err(FPGAArchParseError::XMLParseError(format!("{e:?}"), parser.position()));
},
_ => {},
};
}

Ok(Switch {
sw_type,
name: sw_name,
resistance,
c_in,
c_out,
c_internal,
t_del,
buf_size,
mux_trans_size,
power_buf_size,
t_del_tags,
})
}

pub fn parse_switch_list(name: &OwnedName,
attributes: &[OwnedAttribute],
parser: &mut EventReader<BufReader<File>>) -> Result<Vec<Switch>, FPGAArchParseError> {
assert!(name.to_string() == "switchlist");
if !attributes.is_empty() {
return Err(FPGAArchParseError::UnknownAttribute(String::from("Expected to be empty"), parser.position()));
}

let mut switch_list: Vec<Switch> = Vec::new();
loop {
match parser.next() {
Ok(XmlEvent::StartElement { name, attributes, .. }) => {
match name.to_string().as_str() {
"switch" => {
switch_list.push(parse_switch(&name, &attributes, parser)?);
},
_ => return Err(FPGAArchParseError::InvalidTag(name.to_string(), parser.position())),
};
},
Ok(XmlEvent::EndElement { name }) => {
match name.to_string().as_str() {
"switchlist" => break,
_ => return Err(FPGAArchParseError::UnexpectedEndTag(name.to_string(), parser.position())),
}
},
Ok(XmlEvent::EndDocument) => {
return Err(FPGAArchParseError::UnexpectedEndOfDocument(name.to_string()));
},
Err(e) => {
return Err(FPGAArchParseError::XMLParseError(format!("{e:?}"), parser.position()));
},
_ => {},
}
};

// TODO: It is not clear what should happen if the switch list is empty.
// Should confirm with the documentation.

Ok(switch_list)
}
Loading