use std::collections::HashSet; use std::path::PathBuf; use log::info; use vhdl_lang::ast::{AnyDesignUnit, DesignFile}; use vhdl_lang::{kind_str, Token, VHDLParser, VHDLStandard}; use super::hdlparam::*; #[allow(unused)] pub fn vhdl_parser(path: &str) -> FastHdlparam { // The path of SystemVerilog source file let path = PathBuf::from(path); let mut hdlparam = FastHdlparam { fast_macro: Macro { defines: Vec::new(), errors: Vec::new(), includes: Vec::new(), invalid: Vec::new() }, content: Vec::new(), file_type: "common".to_string() }; let parser = VHDLParser::new(VHDLStandard::VHDL2008); let mut diagnostics = Vec::new(); let (_, design_file) = parser.parse_design_file(&path, &mut diagnostics).unwrap(); let mut all_tockens = Vec::new(); for (tokens, _) in design_file.design_units { all_tockens.extend(tokens); } hdlparam.content.extend(parse_tokens(all_tockens)); hdlparam } pub fn vhdl_parse(path: &PathBuf) -> Option { let mut diagnostics = Vec::new(); let parser = VHDLParser::new(VHDLStandard::VHDL2008); if let Ok((_, design_file)) = parser.parse_design_file(path, &mut diagnostics) { return Some(design_file); } None } pub fn vhdl_parse_str(path: &PathBuf, code: &str) -> Option { let mut diagnostics = Vec::new(); let parser = VHDLParser::new(VHDLStandard::VHDL2008); if let Ok((_, design_file)) = parser.parse_vhdl_str(code, path, &mut diagnostics) { return Some(design_file); } None } pub fn new_make_fast_from_design_file(units: Vec<(AnyDesignUnit, Vec)>, design_file: &DesignFile) -> Option { let mut hdlparam = FastHdlparam { fast_macro: Macro { defines: Vec::new(), errors: Vec::new(), includes: Vec::new(), invalid: Vec::new() }, content: Vec::new(), file_type: "common".to_string() }; info!("get units {:#?}", units); // for (tokens, design_unit) in &design_file.design_units { // } Some(hdlparam) } pub fn make_fast_from_design_file(design_file: &DesignFile) -> Option { let mut hdlparam = FastHdlparam { fast_macro: Macro { defines: Vec::new(), errors: Vec::new(), includes: Vec::new(), invalid: Vec::new() }, content: Vec::new(), file_type: "common".to_string() }; let mut all_tockens = Vec::new(); for (tokens, _) in &design_file.design_units { all_tockens.extend(tokens.clone()); } hdlparam.content.extend(parse_tokens(all_tockens)); Some(hdlparam) } fn parse_tokens(tokens: Vec) -> Vec { let mut modules = Vec::new(); let mut last_module_name = String::new(); let mut instance_type = HashSet::new(); let mut i = 0; while i < tokens.len() { let token = &tokens[i]; match kind_str(token.kind) { "entity" => { let start_pos = tokens[i].pos.range.start; i += 1; let entity_name = get_value(&tokens[i]); if (i >= 2 as usize) && (kind_str(tokens[i - 2].kind) != "use") || (i < 2) { // 遍历整个 entity 内部的 token,找到结束的 token 和代表 port 的 token let mut end = i; let mut port_begin: usize = 0; while ( end + 1 < tokens.len()) && !(kind_str(tokens[end].kind) == "end" && (kind_str(tokens[end + 1].kind) == "entity" || get_value(&tokens[end + 1]) == entity_name) ) { if kind_str(tokens[end].kind) == "port" { port_begin = end; } end += 1; } let (next_i, end_pos) = if end + 1 < tokens.len() && get_value(&tokens[end + 1]) == entity_name { (end + 1, tokens[end + 2].pos.range.end) } else if end + 3 < tokens.len() { (end + 2, tokens[end + 3].pos.range.end) } else { (i, tokens[end].pos.range.end) }; // 创建一个空的 module 并标记上 last_module_name let module = Module { name: entity_name.to_string(), params: Vec::new(), ports: Vec::new(), instances: Vec::new(), range: Range { start: Position { line: start_pos.line + 1, character: start_pos.character + 1 }, end: Position { line: end_pos.line + 1, character: end_pos.character + 1 } } }; last_module_name = entity_name.to_string(); modules.push(module); // 如果内部含有 port,则不能直接跳过,否则直接跳过 if port_begin > 0 { i = port_begin; continue; } else { i = next_i; } } } "architecture" => { if (i >= 1 as usize) && (kind_str(tokens[i-1].kind) != "end") || (i < 1) { // !!! We not think of Architecture as VHDL Module Now // !!! So skip all Architecture Parse when there is no it's Entity let name = get_value(&tokens[i+3]); if let None = modules.iter().find(|module| module.name == name) { // let start_pos = tokens[i].pos.range.start; i += 1; let arch_name = get_value(&tokens[i]); // println!("arch name {:?}", arch_name); let mut end = i; while (end+1 < tokens.len()) && !(kind_str(tokens[end].kind) == "end" && (kind_str(tokens[end+1].kind) == "architecture" || get_value(&tokens[end+1]) == arch_name)) { end += 1; } if end+1 < tokens.len() && get_value(&tokens[end+1]) == arch_name { i = end + 2; } else if end + 3 < tokens.len() { i = end + 3; } else { i = end; }; // let end_pos = if end+1 < tokens.len() && get_value(&tokens[end+1]) == arch_name { // i = end + 2; // tokens[end+2].pos.range.end // } else if end + 3 < tokens.len() { // i = end + 3; // tokens[end+3].pos.range.end // } else { // i = end; // tokens[end].pos.range.end // }; // let module = Module { // name: name.to_string(), // params: Vec::new(), // ports: Vec::new(), // instances: Vec::new(), // range: Range { // start: Position { // line: start_pos.line + 1, // character: start_pos.character + 1 // }, // end: Position { // line: end_pos.line + 1, // character: end_pos.character + 1 // } // } // }; // last_module_name = name.to_string(); // modules.push(module); } else { let module = modules.iter_mut().find(|module| module.name == name).unwrap(); let arch_name = get_value(&tokens[i+1]); let entity_name = module.name.clone(); module.name = entity_name + "(" + arch_name.as_str() + ")"; } } } "configuration" => { i += 1; while i < tokens.len() && !(kind_str(tokens[i].kind) == "end" && kind_str(tokens[i+1].kind) == "configuration") { i += 1; } i += 1; } "package" => { i += 1; // println!("get package"); while i < tokens.len() && !(kind_str(tokens[i].kind) == "end" && kind_str(tokens[i+1].kind) == "package") { i += 1; } i += 1; } "component" => { i += 1; instance_type.insert(get_value(&tokens[i])); // println!("instance {:?}", kind_str(tokens[i].kind)); while i < tokens.len() && !(kind_str(tokens[i].kind) == "end" && kind_str(tokens[i+1].kind) == "component") { i += 1; } i += 1; } "signal" => { i += 1; while !(kind_str(tokens[i+1].kind) == ";") { i += 1; } } "attribute" => { i += 1; while !(kind_str(tokens[i+1].kind) == ";") { i += 1; } } ":" => { if (i+2 < tokens.len()) && (kind_str(tokens[i+2].kind) != "use") { if instance_type.contains(&get_value(&tokens[i+1])) { let instance = Instance { name: get_value(&tokens[i-1]), inst_type: get_value(&tokens[i+1]), instports: None, instparams: None, intstport_assignments: Vec::new(), intstparam_assignments: Vec::new(), range: Range { start: Position { line: tokens[i-1].pos.range.start.line + 1, character: tokens[i-1].pos.range.start.character + 1 }, end: Position { line: tokens[i+1].pos.range.start.line + 1, character: tokens[i+1].pos.range.start.character + 1 } } }; if let Some(module) = modules.iter_mut().find(|module| module.name == last_module_name) { module.instances.push(instance); } } else if kind_str(tokens[i+1].kind) == "entity" { let instance = Instance { name: get_value(&tokens[i-1]), inst_type: get_value(&tokens[i+2]), instports: None, instparams: None, intstport_assignments: Vec::new(), intstparam_assignments: Vec::new(), range: Range { start: Position { line: tokens[i-1].pos.range.start.line + 1, character: tokens[i-1].pos.range.start.character + 1 }, end: Position { line: tokens[i+2].pos.range.start.line + 1, character: tokens[i+2].pos.range.start.character + 1 } } }; if let Some(module) = modules.iter_mut().find(|module| module.name == last_module_name) { module.instances.push(instance); } i += 1; } else { let name = get_value(&tokens[i-1]); let mut inst_type = String::new(); while i < tokens.len() { if kind_str(tokens[i].kind) == "generic" || kind_str(tokens[i].kind) == "port" || kind_str(tokens[i].kind) == "end" { i = i - 1; break; } inst_type = inst_type + &get_value(&tokens[i]); i += 1; } let instance = Instance { name, inst_type, instports: None, instparams: None, intstport_assignments: Vec::new(), intstparam_assignments: Vec::new(), range: Range { start: Position { line: tokens[i-1].pos.range.start.line + 1, character: tokens[i-1].pos.range.start.character + 1 }, end: Position { line: tokens[i+1].pos.range.start.line + 1, character: tokens[i+1].pos.range.start.character + 1 } } }; if let Some(module) = modules.iter_mut().find(|module| module.name == last_module_name) { module.instances.push(instance); } } } } "generic" => { let is_map = kind_str(tokens[i+1].kind) == "map"; let (params, next_index) = parse_parameters(&tokens, i + 1, is_map); if is_map { let start = params.first().unwrap().range.start.clone(); let end = params.last().unwrap().range.start.clone(); if let Some(module) = modules.iter_mut().find(|module| module.name == last_module_name) { module.instances.last_mut().unwrap().instparams = Some(Range { start, end }); } } else { if let Some(module) = modules.iter_mut().find(|module| module.name == last_module_name) { module.params.extend(params); } } i = next_index; } "port" => { let is_map = kind_str(tokens[i+1].kind) == "map"; let (ports, next_index) = parse_port(&tokens, i + 1, is_map); if is_map { let start = ports.first().unwrap().range.start.clone(); let end = ports.last().unwrap().range.start.clone(); if let Some(module) = modules.iter_mut().find(|module| module.name == last_module_name) { module.instances.last_mut().unwrap().instports = Some(Range { start, end }); } } else { if let Some(module) = modules.iter_mut().find(|module| module.name == last_module_name) { module.ports.extend(ports); } } i = next_index; } _ => {} } i += 1; } // println!("{:?}", modules); modules } #[allow(unused)] fn parse_port(tokens: &[Token], start: usize, is_map: bool) -> (Vec, usize) { let mut ports = Vec::new(); let mut i = start; let mut stack = Vec::new(); while i < tokens.len() { let token = &tokens[i]; match kind_str(token.kind) { "(" => { stack.push(token); } ")" => { if stack.is_empty() { break; } stack.pop(); } ";" => { if stack.is_empty() { break; } } "{identifier}" => { if is_map { let start_pos = tokens[i].pos.range.start; while kind_str(tokens[i+1].kind) != ")" { i += 1; } let end_pos = tokens[i].pos.range.end; let port = Port { name: "none".to_string(), dir_type: "none".to_string(), net_type: "none".to_string(), width: "none".to_string(), signed: "unsigned".to_string(), range: Range { start: Position { line: start_pos.line + 1, character: start_pos.character + 1 }, end: Position { line: end_pos.line + 1, character: end_pos.character + 1 } }, }; ports.push(port); } else { let mut ports_token = Vec::new(); while kind_str(tokens[i].kind) != ":" { // println!("{:?}", kind_str(tokens[i].kind)); if kind_str(tokens[i].kind) == "{identifier}" { ports_token.push(&tokens[i]); } i += 1; } // let start_pos = tokens[i].pos.range.start; let width ; let end_idx; let direction = if kind_str(tokens[i+1].kind) == "buffer" || kind_str(tokens[i+1].kind) == "out" { i += 1; "out" } else if kind_str(tokens[i+1].kind) == "in" { i += 1; "in" } else { "unknown" }; if kind_str(tokens[i+2].kind) == "(" { let (width_str, index) = parse_width(&tokens, i+2); width = "[".to_string() + &width_str + "]"; end_idx = index-1; } else if kind_str(tokens[i+2].kind) == "range" { width = "[".to_string() + &get_value(&tokens[i+3]) + ":" + &get_value(&tokens[i+5]) + "]"; end_idx = i+5; } else { width = "1".to_string(); end_idx = i+1; } let end_pos = tokens[end_idx].pos.range.end; for tok in ports_token { let port = Port { name: get_value(&tok), dir_type: direction.to_string(), net_type: get_value(&tokens[i+1]), width: width.to_string(), signed: "unsigned".to_string(), range: Range { start: Position { line: tok.pos.range.start.line + 1, character: tok.pos.range.start.character + 1 }, end: Position { line: end_pos.line + 1, character: end_pos.character + 1 } }, }; ports.push(port); } i = end_idx; } } _ => {} } i += 1; } (ports, i) } #[allow(unused)] fn parse_width(tokens: &[Token], start: usize) -> (String, usize) { let mut width = String::new(); let mut i = start; let mut stack = Vec::new(); while i < tokens.len() { match kind_str(tokens[i].kind) { "(" => { stack.push(&tokens[i]); } ")" => { if stack.is_empty() { break; } stack.pop(); } ";" => { if stack.is_empty() { break; } } _ => { if stack.len() >= 1 { if get_value(&tokens[i]) == "None" { if kind_str(tokens[i].kind) == "downto" || kind_str(tokens[i].kind) == "to" { width = width + ":"; } else { width = width + kind_str(tokens[i].kind); } } else { width = width + &get_value(&tokens[i]); } } } } i += 1; } (width, i) } #[allow(unused)] fn parse_parameters(tokens: &[Token], start: usize, is_map: bool) -> (Vec, usize) { // println!("I am here, start {start}"); let mut params = Vec::new(); let mut i = start; let mut stack = Vec::new(); while i < tokens.len() { let token = &tokens[i]; match kind_str(token.kind) { "(" => { stack.push(token); } ")" => { if stack.is_empty() { break; } stack.pop(); } ";" => { if stack.is_empty() { break; } } "{identifier}" => { if is_map { let start_pos = tokens[i].pos.range.start; let end_pos = tokens[i+2].pos.range.end; let param = Parameter { name: get_value(&tokens[i]), net_type: get_value(&tokens[i+2]), init: get_value(&tokens[i+2]), range: Range { start: Position { line: start_pos.line + 1, character: start_pos.character + 1 }, end: Position { line: end_pos.line + 1, character: end_pos.character + 1 } }, }; i += 2; params.push(param); } else { let mut parameters = Vec::new(); while kind_str(tokens[i].kind) != ":" { // println!("{:?}", kind_str(tokens[i].kind)); if kind_str(tokens[i].kind) == "{identifier}" { parameters.push(&tokens[i]); } i += 1; } let net_type = get_value(&tokens[i+1]); let init = if kind_str(tokens[i+2].kind) == ":=" { get_value(&tokens[i+3]) } else { "unknown".to_string() }; let end_pos = if kind_str(tokens[i+2].kind) == ":=" { tokens[i+2].pos.range.end } else { tokens[i+1].pos.range.end }; i = if kind_str(tokens[i+2].kind) == ":=" { i + 3 } else { i + 1 }; for param_token in parameters { let start_pos = param_token.pos.range.start; let param = Parameter { name: get_value(param_token), net_type: net_type.to_string(), init: init.to_string(), range: Range { start: Position { line: start_pos.line + 1, character: start_pos.character + 1 }, end: Position { line: end_pos.line + 1, character: end_pos.character + 1 } }, }; params.push(param); } } } _ => {} } i += 1; } (params, i) } #[allow(unused)] fn get_value(token: &Token) -> String { match &token.value { vhdl_lang::Value::Identifier(symbol) => { return symbol.name_utf8(); } vhdl_lang::Value::String(latin1_string) => { return latin1_string.to_string(); } vhdl_lang::Value::BitString(latin1_string, _) => { return latin1_string.to_string().replace("\\", ""); } vhdl_lang::Value::AbstractLiteral(latin1_string, _) => { return latin1_string.to_string(); } vhdl_lang::Value::Character(character) => { return character.to_string(); } vhdl_lang::Value::Text(latin1_string) => { return latin1_string.to_string(); } vhdl_lang::Value::None => { return "None".to_string(); } } }