Improve the parsing of I/O ports
This commit is contained in:
parent
2bb1ff9f45
commit
427b47d602
|
@ -0,0 +1,7 @@
|
|||
pub struct Context {}
|
||||
|
||||
impl Context {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
|
@ -1,20 +1,17 @@
|
|||
use crate::cst::{ModuleDeclaration, Tag};
|
||||
use crate::cst::{ModuleDeclaration, Tag, Tools};
|
||||
use json::JsonValue;
|
||||
use llhd::ir::Module;
|
||||
|
||||
pub struct DescriptionList {}
|
||||
|
||||
impl DescriptionList {
|
||||
pub fn codegen(json: &JsonValue) {
|
||||
assert!(json["tag"] == Tag::DESCRIPTION_LIST);
|
||||
for member in json["children"].members() {
|
||||
if member["tag"] == Tag::MODULE_DECLARATION {
|
||||
ModuleDeclaration::codegen(member);
|
||||
} else {
|
||||
println!(
|
||||
r#"tag "{}" under "{}" not yet supported"#,
|
||||
member["tag"], json["tag"]
|
||||
);
|
||||
}
|
||||
}
|
||||
pub fn codegen(json: &JsonValue) -> Vec<Module> {
|
||||
Tools::extract(
|
||||
vec![json],
|
||||
vec![Tag::DESCRIPTION_LIST, Tag::MODULE_DECLARATION],
|
||||
)
|
||||
.iter()
|
||||
.map(|&x| ModuleDeclaration::codegen(x))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
pub mod context;
|
||||
pub mod description_list;
|
||||
pub mod module_declaration;
|
||||
pub mod tags;
|
||||
pub mod tools;
|
||||
|
||||
pub use context::Context;
|
||||
pub use description_list::DescriptionList;
|
||||
pub use module_declaration::ModuleDeclaration;
|
||||
pub use tags::Tag;
|
||||
pub use tools::Tools;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::cst::Tag;
|
||||
use crate::cst::{Tag, Tools};
|
||||
use json::JsonValue;
|
||||
use llhd::ir::{Arg, InstBuilder, Module, Signature, UnitBuilder, UnitData, UnitKind, UnitName};
|
||||
use llhd::ir::{InstBuilder, Module, Signature, UnitBuilder, UnitData, UnitKind, UnitName};
|
||||
use llhd::ty::{int_ty, signal_ty};
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
@ -8,126 +8,51 @@ pub struct ModuleDeclaration {}
|
|||
|
||||
impl ModuleDeclaration {
|
||||
pub fn codegen(json: &JsonValue) -> Module {
|
||||
assert!(json["tag"] == Tag::MODULE_DECLARATION);
|
||||
let json_module = &json["children"];
|
||||
|
||||
let mut module = Module::new();
|
||||
|
||||
let entity_name = UnitName::global(
|
||||
ModuleDeclaration::extract_node(
|
||||
json_module,
|
||||
vec![Tag::MODULE_HEADER, Tag::SYMBOL_IDENTIFIER],
|
||||
)["text"]
|
||||
.to_string(),
|
||||
);
|
||||
let entity_name = UnitName::global({
|
||||
let json_symbol_identifier = Tools::extract(
|
||||
vec![json],
|
||||
vec![
|
||||
Tag::MODULE_DECLARATION,
|
||||
Tag::MODULE_HEADER,
|
||||
Tag::SYMBOL_IDENTIFIER,
|
||||
],
|
||||
);
|
||||
assert_eq!(json_symbol_identifier.len(), 1);
|
||||
json_symbol_identifier[0]["text"].to_string()
|
||||
});
|
||||
|
||||
let mut entity_signature = Signature::new();
|
||||
|
||||
let json_ports = ModuleDeclaration::extract_children(
|
||||
json_module,
|
||||
vec![Tag::MODULE_ITEM_LIST, Tag::MODULE_PORT_DECLARATION],
|
||||
let json_ports = &Tools::extract(
|
||||
vec![json],
|
||||
vec![
|
||||
Tag::MODULE_DECLARATION,
|
||||
Tag::MODULE_ITEM_LIST,
|
||||
Tag::MODULE_PORT_DECLARATION,
|
||||
],
|
||||
);
|
||||
|
||||
let json_input_ports: Vec<&JsonValue> = json_ports
|
||||
.iter()
|
||||
.filter(|&x| x[0]["tag"] == Tag::INPUT)
|
||||
.cloned()
|
||||
.collect();
|
||||
let input_info = &Self::get_tagged_info(json_ports, Tag::INPUT);
|
||||
let output_info = &Self::get_tagged_info(json_ports, Tag::OUTPUT);
|
||||
|
||||
let input_bits_name: Vec<String> = json_input_ports
|
||||
.iter()
|
||||
.map(|&x| {
|
||||
[
|
||||
ModuleDeclaration::extract(
|
||||
&x,
|
||||
vec![
|
||||
Tag::IDENTIFIER_LIST,
|
||||
Tag::IDENTIFIER_UNPACKED_DIMENSIONS,
|
||||
Tag::UNQUALIFIED_ID,
|
||||
Tag::SYMBOL_IDENTIFIER,
|
||||
],
|
||||
),
|
||||
ModuleDeclaration::extract(
|
||||
&x,
|
||||
vec![
|
||||
Tag::IDENTIFIER_LIST,
|
||||
Tag::IDENTIFIER_UNPACKED_DIMENSIONS,
|
||||
Tag::SYMBOL_IDENTIFIER,
|
||||
],
|
||||
),
|
||||
]
|
||||
.concat()
|
||||
})
|
||||
.reduce(|x, y| [x, y].concat())
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|&x| x["text"].to_string())
|
||||
.collect();
|
||||
|
||||
let input_vec_name: Vec<String> = json_input_ports
|
||||
.iter()
|
||||
.map(|&x| {
|
||||
ModuleDeclaration::extract(
|
||||
&x,
|
||||
vec![
|
||||
Tag::IDENTIFIER_UNPACKED_DIMENSIONS_LIST,
|
||||
Tag::IDENTIFIER_UNPACKED_DIMENSIONS,
|
||||
Tag::SYMBOL_IDENTIFIER,
|
||||
],
|
||||
)
|
||||
})
|
||||
.reduce(|x, y| [x, y].concat())
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|&x| x["text"].to_string())
|
||||
.collect();
|
||||
|
||||
let input_vec_dim: Vec<String> = json_input_ports
|
||||
.iter()
|
||||
.map(|&x| {
|
||||
ModuleDeclaration::extract(
|
||||
&x,
|
||||
vec![
|
||||
Tag::PACKED_DIMENSIONS,
|
||||
Tag::DECLARATION_DIMENSIONS,
|
||||
Tag::DIMENSION_RANGE,
|
||||
Tag::EXPRESSION,
|
||||
Tag::NUMBER,
|
||||
Tag::DEC_NUMBER,
|
||||
],
|
||||
)
|
||||
})
|
||||
.reduce(|x, y| [x, y].concat())
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|&x| x["text"].to_string())
|
||||
.collect();
|
||||
|
||||
assert_eq!(input_vec_name.len() * 2, input_vec_dim.len());
|
||||
let input_vec_info = input_vec_name
|
||||
.iter()
|
||||
.zip(input_vec_dim.iter().zip(input_vec_dim[1..].iter()));
|
||||
|
||||
let mut var_name: HashMap<Arg, String> = HashMap::new();
|
||||
|
||||
for bit_name in input_bits_name {
|
||||
let arg = entity_signature.add_input(signal_ty(int_ty(1)));
|
||||
var_name.insert(arg, bit_name);
|
||||
let mut arg_table = HashMap::new();
|
||||
for (name, width) in input_info {
|
||||
let arg = entity_signature.add_input(signal_ty(int_ty(width.clone())));
|
||||
arg_table.insert(arg, name.to_string());
|
||||
}
|
||||
for (name, (hi, lo)) in input_vec_info {
|
||||
let hi_bit = hi.parse::<usize>().unwrap();
|
||||
let lo_bit = lo.parse::<usize>().unwrap();
|
||||
|
||||
let arg = entity_signature.add_input(signal_ty(int_ty(hi_bit - lo_bit + 1)));
|
||||
var_name.insert(arg, name.to_string());
|
||||
for (name, width) in output_info {
|
||||
let arg = entity_signature.add_output(signal_ty(int_ty(width.clone())));
|
||||
arg_table.insert(arg, name.to_string());
|
||||
}
|
||||
|
||||
let mut entity_data = UnitData::new(UnitKind::Entity, entity_name, entity_signature);
|
||||
let mut entity_builder = UnitBuilder::new_anonymous(&mut entity_data);
|
||||
|
||||
for (arg, name) in var_name.iter() {
|
||||
for (arg, name) in arg_table.iter() {
|
||||
let value = entity_builder.arg_value(*arg);
|
||||
entity_builder.set_name(value, name.to_owned());
|
||||
entity_builder.set_name(value, name.to_string());
|
||||
}
|
||||
|
||||
let mut inst_builder = InstBuilder::new(&mut entity_builder);
|
||||
|
@ -136,38 +61,134 @@ impl ModuleDeclaration {
|
|||
|
||||
module.add_unit(entity_data);
|
||||
|
||||
println!("{}", module.dump());
|
||||
module
|
||||
}
|
||||
|
||||
fn extract<'a>(json: &'a JsonValue, path: Vec<&str>) -> Vec<&'a JsonValue> {
|
||||
let mut ret = Vec::new();
|
||||
for member in json.members() {
|
||||
let path_name = path.first().unwrap();
|
||||
let json_name = &member["tag"].as_str().unwrap();
|
||||
if path_name == json_name {
|
||||
if path.len() == 1 {
|
||||
ret.push(member);
|
||||
} else {
|
||||
ret = [
|
||||
ret,
|
||||
ModuleDeclaration::extract(&member["children"], path[1..].to_vec()),
|
||||
]
|
||||
.concat();
|
||||
}
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
fn get_bit_names(json_io_ports: &Vec<&JsonValue>) -> Vec<String> {
|
||||
// note: possible improvement by merging common path segments
|
||||
let paths = vec![
|
||||
vec![
|
||||
Tag::MODULE_PORT_DECLARATION,
|
||||
Tag::IDENTIFIER_LIST,
|
||||
Tag::IDENTIFIER_UNPACKED_DIMENSIONS,
|
||||
Tag::UNQUALIFIED_ID,
|
||||
Tag::SYMBOL_IDENTIFIER,
|
||||
],
|
||||
vec![
|
||||
Tag::MODULE_PORT_DECLARATION,
|
||||
Tag::IDENTIFIER_LIST,
|
||||
Tag::IDENTIFIER_UNPACKED_DIMENSIONS,
|
||||
Tag::SYMBOL_IDENTIFIER,
|
||||
],
|
||||
];
|
||||
assert_eq!(paths.len(), 2); // remember to modify coherently
|
||||
|
||||
fn extract_children<'a>(json: &'a JsonValue, path: Vec<&str>) -> Vec<&'a JsonValue> {
|
||||
ModuleDeclaration::extract(json, path)
|
||||
json_io_ports
|
||||
.iter()
|
||||
.map(|&x| &x["children"])
|
||||
.map(|&x| {
|
||||
[
|
||||
Tools::extract(vec![&x], paths[0].to_vec()),
|
||||
Tools::extract(vec![&x], paths[1].to_vec()),
|
||||
]
|
||||
.concat()
|
||||
})
|
||||
.flatten()
|
||||
.map(|x| x["text"].to_string())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn extract_node<'a>(json: &'a JsonValue, path: Vec<&str>) -> &'a JsonValue {
|
||||
ModuleDeclaration::extract(json, path).first().unwrap()
|
||||
fn get_vec_names(json_io_ports: &Vec<&JsonValue>) -> Vec<String> {
|
||||
// note: possible improvement by merging common path segments
|
||||
let paths = vec![
|
||||
vec![
|
||||
Tag::MODULE_PORT_DECLARATION,
|
||||
Tag::IDENTIFIER_UNPACKED_DIMENSIONS_LIST,
|
||||
Tag::IDENTIFIER_UNPACKED_DIMENSIONS,
|
||||
Tag::SYMBOL_IDENTIFIER,
|
||||
],
|
||||
vec![
|
||||
Tag::MODULE_PORT_DECLARATION,
|
||||
Tag::PORT_IDENTIFIER_LIST,
|
||||
Tag::PORT_IDENTIFIER,
|
||||
Tag::SYMBOL_IDENTIFIER,
|
||||
],
|
||||
];
|
||||
assert_eq!(paths.len(), 2); // remember to modify coherently
|
||||
|
||||
json_io_ports
|
||||
.iter()
|
||||
.map(|&x| {
|
||||
[
|
||||
Tools::extract(vec![&x], paths[0].to_vec()),
|
||||
Tools::extract(vec![&x], paths[1].to_vec()),
|
||||
]
|
||||
.concat()
|
||||
})
|
||||
.flatten()
|
||||
.map(|x| x["text"].to_string())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_vec_dims(json_io_ports: &Vec<&JsonValue>) -> Vec<(String, String)> {
|
||||
// note: possible improvement by merging common path segments
|
||||
let path = vec![
|
||||
Tag::MODULE_PORT_DECLARATION,
|
||||
Tag::PACKED_DIMENSIONS,
|
||||
Tag::DECLARATION_DIMENSIONS,
|
||||
Tag::DIMENSION_RANGE,
|
||||
Tag::EXPRESSION,
|
||||
Tag::NUMBER,
|
||||
Tag::DEC_NUMBER,
|
||||
];
|
||||
|
||||
let raw_vec_dims: Vec<String> = json_io_ports
|
||||
.iter()
|
||||
.map(|&x| Tools::extract(vec![&x], path.to_vec()))
|
||||
.flatten()
|
||||
.map(|x| x["text"].to_string())
|
||||
.collect();
|
||||
|
||||
let num_ports = raw_vec_dims.len() / 2;
|
||||
let vec_dims: Vec<(String, String)> = raw_vec_dims
|
||||
.iter()
|
||||
.step_by(2)
|
||||
.into_iter()
|
||||
.zip(raw_vec_dims[1..].iter().step_by(2).into_iter())
|
||||
.map(|(x, y)| (x.to_string(), y.to_string()))
|
||||
.collect();
|
||||
assert_eq!(vec_dims.len(), num_ports);
|
||||
|
||||
vec_dims
|
||||
}
|
||||
|
||||
fn get_tagged_info(json_ports: &Vec<&JsonValue>, tag: &str) -> Vec<(String, usize)> {
|
||||
let json_tagged_ports = &json_ports
|
||||
.iter()
|
||||
.filter(|&x| x["children"].members().filter(|&x| x["tag"] == tag).count() > 0)
|
||||
.map(|&x| x)
|
||||
.collect::<Vec<&JsonValue>>();
|
||||
|
||||
let bit_names = &Self::get_bit_names(json_tagged_ports);
|
||||
let vec_names = &Self::get_vec_names(json_tagged_ports);
|
||||
let vec_dims = &Self::get_vec_dims(json_tagged_ports);
|
||||
|
||||
let tagged_info = [
|
||||
bit_names
|
||||
.iter()
|
||||
.map(|x| (x.to_string(), 1))
|
||||
.collect::<Vec<(String, usize)>>(),
|
||||
vec_names
|
||||
.iter()
|
||||
.zip(vec_dims.iter())
|
||||
.map(|(name, (hi, lo))| {
|
||||
let hi_bit = hi.parse::<usize>().unwrap();
|
||||
let lo_bit = lo.parse::<usize>().unwrap();
|
||||
(name.to_string(), hi_bit - lo_bit + 1)
|
||||
})
|
||||
.collect::<Vec<(String, usize)>>(),
|
||||
]
|
||||
.concat();
|
||||
|
||||
tagged_info
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@ impl Tag {
|
|||
pub const MODULE_ITEM_LIST: &'static str = "kModuleItemList";
|
||||
pub const MODULE_PORT_DECLARATION: &'static str = "kModulePortDeclaration";
|
||||
pub const INPUT: &'static str = "input";
|
||||
pub const OUTPUT: &'static str = "output";
|
||||
pub const PORT_IDENTIFIER_LIST: &'static str = "kPortIdentifierList";
|
||||
pub const PORT_IDENTIFIER: &'static str = "kPortIdentifier";
|
||||
pub const IDENTIFIER_LIST: &'static str = "kIdentifierList";
|
||||
pub const IDENTIFIER_UNPACKED_DIMENSIONS_LIST: &'static str =
|
||||
"kIdentifierUnpackedDimensionsList";
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
use json::JsonValue;
|
||||
|
||||
pub struct Tools {}
|
||||
|
||||
impl Tools {
|
||||
pub fn extract<'a>(json: Vec<&'a JsonValue>, path: Vec<&str>) -> Vec<&'a JsonValue> {
|
||||
assert!(path.len() > 0);
|
||||
json.iter()
|
||||
.filter(|&x| x["tag"] == path[0])
|
||||
.map(|&x| match path.len() {
|
||||
1 => vec![x],
|
||||
_ => Tools::extract(x["children"].members().collect(), path[1..].to_vec()),
|
||||
})
|
||||
.flatten()
|
||||
.collect()
|
||||
}
|
||||
}
|
|
@ -44,7 +44,11 @@ fn main_inner() -> Result<(), String> {
|
|||
let json_tree = &json_top[sv_file_name]["tree"];
|
||||
assert!(json_tree["tag"] == cst::Tag::DESCRIPTION_LIST);
|
||||
|
||||
cst::DescriptionList::codegen(json_tree);
|
||||
let module_list = cst::DescriptionList::codegen(json_tree);
|
||||
for module in module_list {
|
||||
println!("{}===", module.dump());
|
||||
println!("");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue