Separate module and symbol declarations

This commit is contained in:
Guojie Luo 2022-04-10 11:58:11 +08:00
parent 7ab655df9b
commit eb2b2da020
3 changed files with 363 additions and 349 deletions

View File

@ -10,6 +10,7 @@ mod nonblocking_assignment_statement;
mod number;
mod seq_block;
mod statement;
mod symbol_declaration;
mod tags;
mod tools;
@ -24,6 +25,7 @@ use nonblocking_assignment_statement::NonblockingAssignmentStatement;
use number::Number;
use seq_block::SeqBlock;
use statement::Statement;
use symbol_declaration::SymbolDeclaration;
pub use description_list::DescriptionList;
pub use tags::Tag;

View File

@ -1,7 +1,9 @@
use crate::cst::{AlwaysStatement, ModuleContext, Number, SymbolInfo, SymbolKind, Tag, Tools};
use crate::cst::{
AlwaysStatement, ModuleContext, Number, SymbolDeclaration, SymbolInfo, SymbolKind, Tag, Tools,
};
use json::JsonValue;
use llhd::{
ir::{ExtUnit, Module, Signature, UnitBuilder, UnitData, UnitId, UnitKind, UnitName, Value},
ir::{ExtUnit, Module, Signature, UnitBuilder, UnitData, UnitId, UnitKind, Value},
ty::{int_ty, signal_ty},
};
use std::collections::{HashMap, HashSet};
@ -15,14 +17,14 @@ impl ModuleDeclaration {
pub fn codegen(json: &JsonValue) -> Module {
let mut context = ModuleContext::new();
let (input_info, output_info) = &Self::get_port_info(json);
let reg_info = &Self::get_reg_info(json);
let wire_info = &Self::get_wire_info(json);
let param_info = &Self::get_param_info(json);
let (input_info, output_info) = &SymbolDeclaration::get_port_info(json);
let reg_info = &SymbolDeclaration::get_reg_info(json);
let wire_info = &SymbolDeclaration::get_wire_info(json);
let param_info = &SymbolDeclaration::get_param_info(json);
let mut arg_to_raw_name = HashMap::new();
let entity_name = Self::get_entity_name(json, &mut context);
let entity_name = SymbolDeclaration::get_entity_name(json, &mut context);
let entity_signature = {
let mut signature = Signature::new();
@ -170,346 +172,4 @@ impl ModuleDeclaration {
context.module
}
fn get_entity_name(json: &JsonValue, context: &mut ModuleContext) -> UnitName {
context.name = {
let json_symbol_identifier = Tools::match_tags(
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()
};
UnitName::global(context.name.to_string())
}
fn get_port_info(json: &JsonValue) -> (Vec<(String, usize)>, Vec<(String, usize)>) {
let base_path_2001 = [
Tag::MODULE_DECLARATION,
Tag::MODULE_ITEM_LIST,
Tag::MODULE_PORT_DECLARATION,
];
let base_path_2005 = [
Tag::MODULE_DECLARATION,
Tag::MODULE_HEADER,
Tag::PAREN_GROUP,
Tag::PORT_DECLARATION_LIST,
Tag::PORT_DECLARATION,
];
let json_io_ports_2001 = Tools::match_tags(vec![json], base_path_2001.to_vec());
if json_io_ports_2001.len() == 0 {
let json_io_ports_2005 = Tools::match_tags(vec![json], base_path_2005.to_vec());
info!("version: Verilog-2005");
Self::get_port_info_2005(json_io_ports_2005)
} else {
info!("version: Verilog-2001");
Self::get_port_info_2001(json_io_ports_2001)
}
}
fn get_port_info_2001(
json_io_ports: Vec<&JsonValue>,
) -> (Vec<(String, usize)>, Vec<(String, usize)>) {
let name_paths = [
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,
],
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,
],
];
let dim_path = [
Tag::MODULE_PORT_DECLARATION,
Tag::PACKED_DIMENSIONS,
Tag::DECLARATION_DIMENSIONS,
Tag::DIMENSION_RANGE,
Tag::EXPRESSION,
Tag::NUMBER,
Tag::DEC_NUMBER,
];
let json_input_ports = json_io_ports
.iter()
.filter(|&x| x["children"][0]["tag"] == Tag::INPUT)
.map(|&x| x)
.collect();
let json_output_ports = json_io_ports
.iter()
.filter(|&x| x["children"][0]["tag"] == Tag::OUTPUT)
.map(|&x| x)
.collect();
let get_port_info = |json_ports: Vec<&JsonValue>| -> Vec<(String, usize)> {
json_ports
.iter()
.map(|&json_port| {
let json_port_names: Vec<&JsonValue> = name_paths
.iter()
.map(|path| Tools::match_tags(vec![json_port], path.to_vec()))
.flatten()
.collect();
assert!(json_port_names.len() > 0);
let width = Self::get_var_width(json_port, dim_path.to_vec());
json_port_names
.iter()
.map(|x| (x["text"].to_string(), width))
.collect::<Vec<(String, usize)>>()
})
.flatten()
.collect()
};
(
get_port_info(json_input_ports),
get_port_info(json_output_ports),
)
}
fn get_port_info_2005(
json_io_ports: Vec<&JsonValue>,
) -> (Vec<(String, usize)>, Vec<(String, usize)>) {
let name_paths = [vec![
Tag::PORT_DECLARATION,
Tag::UNQUALIFIED_ID,
Tag::SYMBOL_IDENTIFIER,
]];
let dim_path = [
Tag::PORT_DECLARATION,
Tag::DATA_TYPE,
Tag::PACKED_DIMENSIONS,
Tag::DECLARATION_DIMENSIONS,
Tag::DIMENSION_RANGE,
Tag::EXPRESSION,
Tag::NUMBER,
Tag::DEC_NUMBER,
];
let json_input_ports = json_io_ports
.iter()
.filter(|&x| x["children"][0]["tag"] == Tag::INPUT)
.map(|&x| x)
.collect();
let json_output_ports = json_io_ports
.iter()
.filter(|&x| x["children"][0]["tag"] == Tag::OUTPUT)
.map(|&x| x)
.collect();
let get_port_info = |json_ports: Vec<&JsonValue>| -> Vec<(String, usize)> {
json_ports
.iter()
.map(|&json_port| {
let json_port_names: Vec<&JsonValue> = name_paths
.iter()
.map(|path| Tools::match_tags(vec![json_port], path.to_vec()))
.flatten()
.collect();
assert!(json_port_names.len() > 0);
let width = Self::get_var_width(json_port, dim_path.to_vec());
json_port_names
.iter()
.map(|x| (x["text"].to_string(), width))
.collect::<Vec<(String, usize)>>()
})
.flatten()
.collect()
};
(
get_port_info(json_input_ports),
get_port_info(json_output_ports),
)
}
fn get_reg_info(json: &JsonValue) -> Vec<(String, usize, Option<&JsonValue>)> {
let base_path = [
Tag::MODULE_DECLARATION,
Tag::MODULE_ITEM_LIST,
Tag::DATA_DECLARATION,
Tag::INSTANTIATION_BASE,
];
let type_path = [
Tag::INSTANTIATION_BASE,
Tag::INSTANTIATION_TYPE,
Tag::DATA_TYPE,
Tag::DATA_TYPE_PRIMITIVE,
Tag::REG,
];
let name_path = [
Tag::INSTANTIATION_BASE,
Tag::GATE_INSTANCE_REGISTER_VARIABLE_LIST,
Tag::REGISTER_VARIABLE,
Tag::SYMBOL_IDENTIFIER,
];
let dim_path = [
Tag::INSTANTIATION_BASE,
Tag::INSTANTIATION_TYPE,
Tag::DATA_TYPE,
Tag::PACKED_DIMENSIONS,
Tag::DECLARATION_DIMENSIONS,
Tag::DIMENSION_RANGE,
Tag::EXPRESSION,
Tag::NUMBER,
Tag::DEC_NUMBER,
];
let json_regs: Vec<&JsonValue> = Tools::match_tags(vec![json], base_path.to_vec())
.iter()
.filter(|&x| Tools::match_tags(vec![x], type_path.to_vec()).len() > 0)
.map(|&x| x)
.collect();
Self::get_var_info(json_regs, name_path.to_vec(), dim_path.to_vec())
}
fn get_wire_info(json: &JsonValue) -> Vec<(String, usize, Option<&JsonValue>)> {
let base_path = [
Tag::MODULE_DECLARATION,
Tag::MODULE_ITEM_LIST,
Tag::NET_DECLARATION,
];
let name_path = [
Tag::NET_DECLARATION,
Tag::NET_VARIABLE_DECLARATION_ASSIGN,
Tag::NET_VARIABLE,
Tag::SYMBOL_IDENTIFIER,
];
let dim_path = [
Tag::NET_DECLARATION,
Tag::DATA_TYPE_IMPLICIT_ID_DIMENSIONS,
Tag::DATA_TYPE,
Tag::PACKED_DIMENSIONS,
Tag::DECLARATION_DIMENSIONS,
Tag::DIMENSION_RANGE,
Tag::EXPRESSION,
Tag::NUMBER,
Tag::DEC_NUMBER,
];
let json_wires: Vec<&JsonValue> = Tools::match_tags(vec![json], base_path.to_vec())
.iter()
.filter(|&x| x["children"][0]["tag"] == Tag::WIRE)
.map(|&x| x)
.collect();
Self::get_var_info(json_wires, name_path.to_vec(), dim_path.to_vec())
}
fn get_var_info<'a>(
json_vec: Vec<&'a JsonValue>,
name_path: Vec<&str>,
dim_path: Vec<&str>,
) -> Vec<(String, usize, Option<&'a JsonValue>)> {
json_vec
.iter()
.map(|&json| {
let json_names = Tools::match_tags(vec![json], name_path.to_vec());
assert!(json_names.len() > 0);
let width = Self::get_var_width(json, dim_path.to_vec());
json_names
.iter()
.map(|x| (x["text"].to_string(), width, None)) // hack
.collect::<Vec<(String, usize, Option<&JsonValue>)>>()
})
.flatten()
.collect()
}
fn get_var_width(json: &JsonValue, dim_path: Vec<&str>) -> usize {
let json_dims = Tools::match_tags(vec![json], dim_path);
assert!(json_dims.len() == 0 || json_dims.len() == 2);
match json_dims.len() {
2 => {
let hi_bit = json_dims[0]["text"].to_string().parse::<usize>().unwrap();
let lo_bit = json_dims[1]["text"].to_string().parse::<usize>().unwrap();
hi_bit - lo_bit + 1
}
_ => 1,
}
}
fn get_param_info(json: &JsonValue) -> Vec<(String, usize, Option<&JsonValue>)> {
let base_path = [
Tag::MODULE_DECLARATION,
Tag::MODULE_ITEM_LIST,
Tag::PARAM_DECLARATION,
];
let name_path = [
Tag::PARAM_DECLARATION,
Tag::PARAM_TYPE,
Tag::UNQUALIFIED_ID,
Tag::SYMBOL_IDENTIFIER,
];
let num_path = [
Tag::PARAM_DECLARATION,
Tag::TRAILING_ASSIGN,
Tag::EXPRESSION,
Tag::NUMBER,
];
let json_params: Vec<&JsonValue> = Tools::match_tags(vec![json], base_path.to_vec())
.iter()
.filter(|&x| x["children"][0]["tag"] == Tag::PARAMETER)
.map(|&x| x)
.collect();
json_params
.iter()
.map(|&json| {
let json_names = Tools::match_tags(vec![json], name_path.to_vec());
assert_eq!(json_names.len(), 1);
let json_num = Tools::match_tags(vec![json], num_path.to_vec());
assert_eq!(json_num.len(), 1);
let v = Number::parse(json_num[0]);
(
json_names[0]["text"].to_string(),
v.width,
Some(json_num[0]),
)
})
.collect()
}
}

View File

@ -0,0 +1,352 @@
use crate::cst::{ModuleContext, Number, Tag, Tools};
use json::JsonValue;
use llhd::ir::UnitName;
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
pub struct SymbolDeclaration {}
impl SymbolDeclaration {
pub fn get_entity_name(json: &JsonValue, context: &mut ModuleContext) -> UnitName {
context.name = {
let json_symbol_identifier = Tools::match_tags(
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()
};
UnitName::global(context.name.to_string())
}
pub fn get_port_info(json: &JsonValue) -> (Vec<(String, usize)>, Vec<(String, usize)>) {
let base_path_2001 = [
Tag::MODULE_DECLARATION,
Tag::MODULE_ITEM_LIST,
Tag::MODULE_PORT_DECLARATION,
];
let base_path_2005 = [
Tag::MODULE_DECLARATION,
Tag::MODULE_HEADER,
Tag::PAREN_GROUP,
Tag::PORT_DECLARATION_LIST,
Tag::PORT_DECLARATION,
];
let json_io_ports_2001 = Tools::match_tags(vec![json], base_path_2001.to_vec());
if json_io_ports_2001.len() == 0 {
let json_io_ports_2005 = Tools::match_tags(vec![json], base_path_2005.to_vec());
info!("version: Verilog-2005");
Self::get_port_info_2005(json_io_ports_2005)
} else {
info!("version: Verilog-2001");
Self::get_port_info_2001(json_io_ports_2001)
}
}
fn get_port_info_2001(
json_io_ports: Vec<&JsonValue>,
) -> (Vec<(String, usize)>, Vec<(String, usize)>) {
let name_paths = [
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,
],
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,
],
];
let dim_path = [
Tag::MODULE_PORT_DECLARATION,
Tag::PACKED_DIMENSIONS,
Tag::DECLARATION_DIMENSIONS,
Tag::DIMENSION_RANGE,
Tag::EXPRESSION,
Tag::NUMBER,
Tag::DEC_NUMBER,
];
let json_input_ports = json_io_ports
.iter()
.filter(|&x| x["children"][0]["tag"] == Tag::INPUT)
.map(|&x| x)
.collect();
let json_output_ports = json_io_ports
.iter()
.filter(|&x| x["children"][0]["tag"] == Tag::OUTPUT)
.map(|&x| x)
.collect();
let get_port_info = |json_ports: Vec<&JsonValue>| -> Vec<(String, usize)> {
json_ports
.iter()
.map(|&json_port| {
let json_port_names: Vec<&JsonValue> = name_paths
.iter()
.map(|path| Tools::match_tags(vec![json_port], path.to_vec()))
.flatten()
.collect();
assert!(json_port_names.len() > 0);
let width = Self::get_var_width(json_port, dim_path.to_vec());
json_port_names
.iter()
.map(|x| (x["text"].to_string(), width))
.collect::<Vec<(String, usize)>>()
})
.flatten()
.collect()
};
(
get_port_info(json_input_ports),
get_port_info(json_output_ports),
)
}
fn get_port_info_2005(
json_io_ports: Vec<&JsonValue>,
) -> (Vec<(String, usize)>, Vec<(String, usize)>) {
let name_paths = [vec![
Tag::PORT_DECLARATION,
Tag::UNQUALIFIED_ID,
Tag::SYMBOL_IDENTIFIER,
]];
let dim_path = [
Tag::PORT_DECLARATION,
Tag::DATA_TYPE,
Tag::PACKED_DIMENSIONS,
Tag::DECLARATION_DIMENSIONS,
Tag::DIMENSION_RANGE,
Tag::EXPRESSION,
Tag::NUMBER,
Tag::DEC_NUMBER,
];
let json_input_ports = json_io_ports
.iter()
.filter(|&x| x["children"][0]["tag"] == Tag::INPUT)
.map(|&x| x)
.collect();
let json_output_ports = json_io_ports
.iter()
.filter(|&x| x["children"][0]["tag"] == Tag::OUTPUT)
.map(|&x| x)
.collect();
let get_port_info = |json_ports: Vec<&JsonValue>| -> Vec<(String, usize)> {
json_ports
.iter()
.map(|&json_port| {
let json_port_names: Vec<&JsonValue> = name_paths
.iter()
.map(|path| Tools::match_tags(vec![json_port], path.to_vec()))
.flatten()
.collect();
assert!(json_port_names.len() > 0);
let width = Self::get_var_width(json_port, dim_path.to_vec());
json_port_names
.iter()
.map(|x| (x["text"].to_string(), width))
.collect::<Vec<(String, usize)>>()
})
.flatten()
.collect()
};
(
get_port_info(json_input_ports),
get_port_info(json_output_ports),
)
}
pub fn get_reg_info(json: &JsonValue) -> Vec<(String, usize, Option<&JsonValue>)> {
let base_path = [
Tag::MODULE_DECLARATION,
Tag::MODULE_ITEM_LIST,
Tag::DATA_DECLARATION,
Tag::INSTANTIATION_BASE,
];
let type_path = [
Tag::INSTANTIATION_BASE,
Tag::INSTANTIATION_TYPE,
Tag::DATA_TYPE,
Tag::DATA_TYPE_PRIMITIVE,
Tag::REG,
];
let name_path = [
Tag::INSTANTIATION_BASE,
Tag::GATE_INSTANCE_REGISTER_VARIABLE_LIST,
Tag::REGISTER_VARIABLE,
Tag::SYMBOL_IDENTIFIER,
];
let dim_path = [
Tag::INSTANTIATION_BASE,
Tag::INSTANTIATION_TYPE,
Tag::DATA_TYPE,
Tag::PACKED_DIMENSIONS,
Tag::DECLARATION_DIMENSIONS,
Tag::DIMENSION_RANGE,
Tag::EXPRESSION,
Tag::NUMBER,
Tag::DEC_NUMBER,
];
let json_regs: Vec<&JsonValue> = Tools::match_tags(vec![json], base_path.to_vec())
.iter()
.filter(|&x| Tools::match_tags(vec![x], type_path.to_vec()).len() > 0)
.map(|&x| x)
.collect();
Self::get_var_info(json_regs, name_path.to_vec(), dim_path.to_vec())
}
pub fn get_wire_info(json: &JsonValue) -> Vec<(String, usize, Option<&JsonValue>)> {
let base_path = [
Tag::MODULE_DECLARATION,
Tag::MODULE_ITEM_LIST,
Tag::NET_DECLARATION,
];
let name_path = [
Tag::NET_DECLARATION,
Tag::NET_VARIABLE_DECLARATION_ASSIGN,
Tag::NET_VARIABLE,
Tag::SYMBOL_IDENTIFIER,
];
let dim_path = [
Tag::NET_DECLARATION,
Tag::DATA_TYPE_IMPLICIT_ID_DIMENSIONS,
Tag::DATA_TYPE,
Tag::PACKED_DIMENSIONS,
Tag::DECLARATION_DIMENSIONS,
Tag::DIMENSION_RANGE,
Tag::EXPRESSION,
Tag::NUMBER,
Tag::DEC_NUMBER,
];
let json_wires: Vec<&JsonValue> = Tools::match_tags(vec![json], base_path.to_vec())
.iter()
.filter(|&x| x["children"][0]["tag"] == Tag::WIRE)
.map(|&x| x)
.collect();
Self::get_var_info(json_wires, name_path.to_vec(), dim_path.to_vec())
}
fn get_var_info<'a>(
json_vec: Vec<&'a JsonValue>,
name_path: Vec<&str>,
dim_path: Vec<&str>,
) -> Vec<(String, usize, Option<&'a JsonValue>)> {
json_vec
.iter()
.map(|&json| {
let json_names = Tools::match_tags(vec![json], name_path.to_vec());
assert!(json_names.len() > 0);
let width = Self::get_var_width(json, dim_path.to_vec());
json_names
.iter()
.map(|x| (x["text"].to_string(), width, None)) // hack
.collect::<Vec<(String, usize, Option<&JsonValue>)>>()
})
.flatten()
.collect()
}
fn get_var_width(json: &JsonValue, dim_path: Vec<&str>) -> usize {
let json_dims = Tools::match_tags(vec![json], dim_path);
assert!(json_dims.len() == 0 || json_dims.len() == 2);
match json_dims.len() {
2 => {
let hi_bit = json_dims[0]["text"].to_string().parse::<usize>().unwrap();
let lo_bit = json_dims[1]["text"].to_string().parse::<usize>().unwrap();
hi_bit - lo_bit + 1
}
_ => 1,
}
}
pub fn get_param_info(json: &JsonValue) -> Vec<(String, usize, Option<&JsonValue>)> {
let base_path = [
Tag::MODULE_DECLARATION,
Tag::MODULE_ITEM_LIST,
Tag::PARAM_DECLARATION,
];
let name_path = [
Tag::PARAM_DECLARATION,
Tag::PARAM_TYPE,
Tag::UNQUALIFIED_ID,
Tag::SYMBOL_IDENTIFIER,
];
let num_path = [
Tag::PARAM_DECLARATION,
Tag::TRAILING_ASSIGN,
Tag::EXPRESSION,
Tag::NUMBER,
];
let json_params: Vec<&JsonValue> = Tools::match_tags(vec![json], base_path.to_vec())
.iter()
.filter(|&x| x["children"][0]["tag"] == Tag::PARAMETER)
.map(|&x| x)
.collect();
json_params
.iter()
.map(|&json| {
let json_names = Tools::match_tags(vec![json], name_path.to_vec());
assert_eq!(json_names.len(), 1);
let json_num = Tools::match_tags(vec![json], num_path.to_vec());
assert_eq!(json_num.len(), 1);
let v = Number::parse(json_num[0]);
(
json_names[0]["text"].to_string(),
v.width,
Some(json_num[0]),
)
})
.collect()
}
}