diff --git a/src/core/hdlparam.rs b/src/core/hdlparam.rs index ea2e64f..a964adb 100644 --- a/src/core/hdlparam.rs +++ b/src/core/hdlparam.rs @@ -373,6 +373,18 @@ impl FastHdlparam { self.content.push(module); } + pub fn new_vhdl_module(&mut self, name: String, arch_name: String, range: Range) { + let module = Module { + name, + arch_name, + params: Vec::new(), + ports: Vec::new(), + instances: Vec::new(), + range + }; + self.content.push(module); + } + pub fn update_module_range(&mut self, name: &str, end_line: u32, end_character: u32) { if let Some(matched_module) = self.content.iter_mut().find(|module| module.name == name) { matched_module.range.end.line = end_line; diff --git a/src/core/vhdl_parser.rs b/src/core/vhdl_parser.rs index a1cf93b..cb96034 100644 --- a/src/core/vhdl_parser.rs +++ b/src/core/vhdl_parser.rs @@ -1,49 +1,10 @@ -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 vhdl_lang::ast::{ArchitectureBody, ConcurrentStatement, DesignFile, Designator, EntityDeclaration, InstantiatedUnit, InterfaceDeclaration, InterfaceList, LabeledConcurrentStatement, Mode, ModeIndication, Name}; +use vhdl_lang::{kind_str, HasTokenSpan, Token, TokenAccess, TokenSpan, 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); @@ -53,7 +14,9 @@ pub fn vhdl_parse_str(path: &PathBuf, code: &str) -> Option { None } -pub fn new_make_fast_from_design_file(units: Vec<(AnyDesignUnit, Vec)>, design_file: &DesignFile) -> Option { +pub fn make_fast_from_units( + arch_and_entity: Vec<((ArchitectureBody, Vec), (EntityDeclaration, Vec))>, +) -> Option { let mut hdlparam = FastHdlparam { fast_macro: Macro { defines: Vec::new(), @@ -65,577 +28,234 @@ pub fn new_make_fast_from_design_file(units: Vec<(AnyDesignUnit, Vec)>, d file_type: "common".to_string() }; + arch_and_entity.iter().for_each(|((arch, arch_tokens), (entity, entity_tokens))| { + let name = entity.ident.tree.item.name_utf8(); + let arch_name = arch.ident.tree.item.name_utf8(); + let range = get_range_from_token( + entity_tokens.get_token(entity.span().get_start_token()), + entity_tokens.get_token(entity.span().get_end_token()) + ); - info!("get units {:#?}", units); - // for (tokens, design_unit) in &design_file.design_units { - - // } + hdlparam.new_vhdl_module(name, arch_name, range); + if let Some(param_list) = &entity.generic_clause { + parse_interface_list(param_list, &entity_tokens).iter().for_each(|(name, _, net_type, _, init, range)| { + hdlparam.add_parameter(name, net_type, init, range.clone()); + }); + } + + if let Some(port_list) = &entity.port_clause { + parse_interface_list(port_list, &entity_tokens).iter().for_each(|(name, dir_type, net_type, width, init, range)| { + hdlparam.add_port(name, dir_type, net_type, width, range.clone()); + }); + } + + let instances = arch.statements.iter().filter(|statement| { + match statement.statement.item { + ConcurrentStatement::Instance(_) => true, + _ => false + } + }) + .map(|statement| parse_instance(statement, arch_tokens)) + .collect::>(); + + if let Some(last_module) = hdlparam.content.last_mut() { + last_module.instances = instances + } + }); + + info!("get fast {:#?}", hdlparam); 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() +fn parse_instance(statement: &LabeledConcurrentStatement, tokens: &Vec) -> Instance { + let name = if let Some(tree) = &statement.label.tree { tree.item.name_utf8() } else { "unknown".to_string() }; + let range = get_range_from_token( + tokens.get_token(statement.span().get_start_token()), + tokens.get_token(statement.span().get_end_token()) + ); + + let mut parsed_instance = Instance { + name, + inst_type: "".to_string(), + instparams: None, + intstparam_assignments: Vec::new(), + instports: None, + intstport_assignments: Vec::new(), + range }; - 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(), - arch_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 + match &statement.statement.item { + ConcurrentStatement::Instance(instance) => { + parsed_instance.inst_type = match &instance.unit { + InstantiatedUnit::Component(name) => { + match &name.item { + Name::Designator(designator) => { + match &designator.item { + Designator::Identifier(symbol) => symbol.name_utf8(), + _ => "unknown".to_string() } } - }; - last_module_name = entity_name.to_string(); - modules.push(module); - - // 如果内部含有 port,则不能直接跳过,否则直接跳过 - if port_begin > 0 { - i = port_begin; - continue; - } else { - i = next_i; + _ => "unknown".to_string() } - } - } - "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]); - module.arch_name = arch_name; - } - } - } - "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; - } + }, + _ => "unknown".to_string() + }; - // println!("{:?}", modules); - modules + if let Some(parameter_list) = &instance.generic_map { + parsed_instance.instparams = Some(get_range_from_token( + tokens.get_token(parameter_list.span().get_start_token()), + tokens.get_token(parameter_list.span().get_end_token()) + )); -} - - -#[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 { + parsed_instance.intstparam_assignments = parameter_list.list.items.iter().map(|association_ele| { + let formal = association_ele.formal.clone().and_then(|formal| + Some(parse_string_from_tokenspan(formal.span(), tokens)) + ).unwrap_or( "unknown".to_string() - }; - let end_pos = if kind_str(tokens[i+2].kind) == ":=" { - tokens[i+2].pos.range.end + ); + let actual = parse_string_from_tokenspan(association_ele.actual.span(), tokens); + let assign_range = if association_ele.formal.is_some() { + get_range_from_token( + tokens.get_token(association_ele.formal.clone().unwrap().span().get_start_token()), + tokens.get_token(association_ele.actual.span().get_end_token()) + ) } else { - tokens[i+1].pos.range.end + get_range_from_token( + tokens.get_token(association_ele.actual.span().get_start_token()), + tokens.get_token(association_ele.actual.span().get_end_token()) + ) }; - 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); - } - } + InstParameter { parameter: Some(formal), assign_val: Some(actual), assign_type: AssignType::Named, range: assign_range } + }).collect::>(); } - _ => {} - } - i += 1; - } - (params, i) + if let Some(port_list) = &instance.port_map { + parsed_instance.instports = Some(get_range_from_token( + tokens.get_token(port_list.span().get_start_token()), + tokens.get_token(port_list.span().get_end_token()) + )); + parsed_instance.intstport_assignments = port_list.list.items.iter().map(|association_ele| { + let formal = association_ele.formal.clone().and_then(|formal| + Some(parse_string_from_tokenspan(formal.span(), tokens)) + ).unwrap_or( + "unknown".to_string() + ); + let actual = parse_string_from_tokenspan(association_ele.actual.span(), tokens); + let assign_range = if association_ele.formal.is_some() { + get_range_from_token( + tokens.get_token(association_ele.formal.clone().unwrap().span().get_start_token()), + tokens.get_token(association_ele.actual.span().get_end_token()) + ) + } else { + get_range_from_token( + tokens.get_token(association_ele.actual.span().get_start_token()), + tokens.get_token(association_ele.actual.span().get_end_token()) + ) + }; + InstPort { port: Some(formal), assign_val: Some(actual), assign_type: AssignType::Named, range: assign_range } + }).collect::>(); + } + } + _ => () + }; + + parsed_instance } +fn parse_interface_list(list: &InterfaceList, tokens: &Vec) -> Vec<(String, String, String, String, String, Range)> { + let mut interface_list = Vec::new(); + list.items.iter().for_each(|interface| { + let range = get_range_from_token( + tokens.get_token(interface.span().get_start_token()), + tokens.get_token(interface.span().get_end_token()) + ); + match interface { + InterfaceDeclaration::Object(object) => { + let name = object.idents.first().unwrap().tree.item.name_utf8(); + let (dir_type, net_type, width, init) = match &object.mode { + ModeIndication::Simple(simple_mode) => { + let dir_type = if let Some(mode_token) = &simple_mode.mode { + match mode_token.item { + Mode::In => "in", + Mode::Out => "out", + Mode::Buffer | Mode::InOut => "inout", + Mode::Linkage => "unknown" + }.to_string() + } else { + "unknown".to_string() + }; + let net_type = simple_mode.subtype_indication.type_mark.item.to_string(); + let width = if let Some(constraint) = &simple_mode.subtype_indication.constraint { + parse_width_from_tokenspan(constraint.span(), tokens) + } else { + "1".to_string() + }; + let init = if let Some(expression) = &simple_mode.expression { + parse_width_from_tokenspan(expression.span(), tokens) + } else { + "unknown".to_string() + }; + (dir_type, net_type, width, init) + } + _ => ("unknown".to_string(), "unknown".to_string(), "unknown".to_string(), "unknown".to_string()) + }; + interface_list.push((name, dir_type, net_type, width, init, range)); + } + _ => () + } + }); + interface_list +} + +fn parse_string_from_tokenspan(span: TokenSpan, tokens: &Vec) -> String { + span.iter().map(|id| { + if let Some(token) = tokens.get_token(id) { + if get_value(token) == "None" { + kind_str(token.kind).to_string() + } else { + get_value(token) + } + } else { + "".to_string() + } + }).collect() +} + +fn parse_width_from_tokenspan(span: TokenSpan, tokens: &Vec) -> String { + // skip '(' and ')' + span.iter().skip(1).take(span.len() - 2).map(|id| { + if let Some(token) = tokens.get_token(id) { + if get_value(token) == "None" { + if kind_str(token.kind) == "downto" || kind_str(token.kind) == "to" { + ":".to_string() + } else { + kind_str(token.kind).to_string() + } + } else { + get_value(token) + } + } else { + "".to_string() + } + }).collect() +} + +fn get_range_from_token(start_token: Option<&Token>, end_token: Option<&Token>) -> Range { + let start = if let Some(token) = start_token { + Position { line: token.pos.start().line, character: token.pos.start().character } + } else { + Position { line: 0, character: 0 } + }; + + let end = if let Some(token) = end_token { + Position { line: token.pos.end().line, character: token.pos.end().character } + } else { + Position { line: 0, character: 0 } + }; + + Range { start, end } +} #[allow(unused)] fn get_value(token: &Token) -> String { diff --git a/src/definition/mod.rs b/src/definition/mod.rs index 81f5712..fff058f 100644 --- a/src/definition/mod.rs +++ b/src/definition/mod.rs @@ -209,8 +209,7 @@ pub fn get_scopes_from_vhdl_fast(fast: &FastHdlparam, text: &Rope, url: &Url) -> for module in &fast.content { let mut scope: GenericScope = GenericScope::new(url); scope.ident = module.name.clone(); - let mut module_range = module.range.clone(); - module_range.affine(-1, -1); + let module_range = module.range.clone(); scope.start = position_to_byte_idx(text, &module_range.start); scope.end = position_to_byte_idx(text, &module_range.end); scope.byte_idx = scope.start + 7; @@ -218,8 +217,7 @@ pub fn get_scopes_from_vhdl_fast(fast: &FastHdlparam, text: &Rope, url: &Url) -> for parameter in &module.params { let mut def = GenericDec::new(url); def.ident = parameter.name.clone(); - let mut parameter_range = parameter.range.clone(); - parameter_range.affine(-1, -1); + let parameter_range = parameter.range.clone(); def.byte_idx = position_to_byte_idx(text, ¶meter_range.start); def.completion_kind = CompletionItemKind::TYPE_PARAMETER; def.symbol_kind = SymbolKind::TYPE_PARAMETER; @@ -228,8 +226,7 @@ pub fn get_scopes_from_vhdl_fast(fast: &FastHdlparam, text: &Rope, url: &Url) -> for port in &module.ports { let mut port_def = PortDec::new(url); port_def.ident = port.name.clone(); - let mut port_range = port.range.clone(); - port_range.affine(-1, -1); + let port_range = port.range.clone(); port_def.byte_idx = position_to_byte_idx(text, &port_range.start); port_def.type_str = port.dir_type.clone(); scope.defs.push(Box::new(port_def)); @@ -237,8 +234,7 @@ pub fn get_scopes_from_vhdl_fast(fast: &FastHdlparam, text: &Rope, url: &Url) -> for inst in &module.instances { let mut instance = ModInst::new(url); instance.ident = inst.name.clone(); - let mut inst_range = inst.range.clone(); - inst_range.affine(-1, -1); + let inst_range = inst.range.clone(); instance.byte_idx = position_to_byte_idx(text, &inst_range.start); instance.type_str = inst.inst_type.clone(); instance.mod_ident = inst.inst_type.clone(); diff --git a/src/request/fast.rs b/src/request/fast.rs index 4e57268..89dc5bd 100644 --- a/src/request/fast.rs +++ b/src/request/fast.rs @@ -1,19 +1,21 @@ use std::borrow::Cow; use std::str::FromStr; use std::{fs, future}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::sync::Arc; use log::info; use ropey::Rope; use serde::{Deserialize, Serialize}; use tower_lsp::jsonrpc::Result; use tower_lsp::lsp_types::*; +use vhdl_lang::Project; use crate::core::cache_storage::CacheResult; use crate::core::hdlparam::FastHdlparam; use crate::core::sv_parser::make_fast_from_syntaxtree; -use crate::core::vhdl_parser::{make_fast_from_design_file, vhdl_parse}; +use crate::core::vhdl_parser::make_fast_from_units; +use crate::definition::VhdlProject; use crate::{core, utils::*}; use crate::server::Backend; use crate::sources::recovery_sv_parse_with_retry; @@ -218,6 +220,7 @@ fn do_vhdl_fast( let sources = &backend.server.srcs; let pathbuf = PathBuf::from_str(path).unwrap(); let hdl_param = sources.hdl_param.clone(); + let vhdl_project = sources.vhdl_project.clone(); // TODO: 支持对于 synth 下的 vhdl 文件的解析,从而提供更加丰富的 IP 支持 if file_type == "ip" { @@ -251,8 +254,26 @@ fn do_vhdl_fast( }; hdl_param.update_fast(path.to_string(), ip_fast.clone()); return Ok(ip_fast); - } else if let Some(design_file) = vhdl_parse(&pathbuf) { - if let Some(mut fast) = make_fast_from_design_file(&design_file) { + } else if let Some(vhdl_project) = &mut *vhdl_project.write().unwrap() { + vhdl_project.config_file_strs.push(format!("{:?}", pathbuf)); + let mut messages = Vec::new(); + let config_str = format!( + r#" + [libraries] + digital_lsp.files = [{}] + "#, vhdl_project.config_file_strs.join(",") + ); + let config = vhdl_lang::Config::from_str(&config_str, Path::new("")); + if let Ok(mut config) = config { + config.append(&vhdl_project.std_config, &mut messages); + let mut project = Project::from_config(config, &mut messages); + project.analyse(); + *vhdl_project = VhdlProject { project, std_config: vhdl_project.std_config.clone(), config_file_strs: vhdl_project.config_file_strs.clone() }; + } + + let arch_and_entity = vhdl_project.project.get_analyzed_units(&pathbuf); + + if let Some(mut fast) = make_fast_from_units(arch_and_entity) { fast.file_type = file_type.to_string(); // IP 不需要内部的 instance,其实现是加密的,只需要暴露 module 的接口即可 // 所以此处需要清空所有的 module 中的 instance @@ -275,8 +296,26 @@ fn do_vhdl_fast( } // 没有特殊情况,则正常解析并写入 - if let Some(design_file) = vhdl_parse(&pathbuf) { - if let Some(mut fast) = make_fast_from_design_file(&design_file) { + if let Some(vhdl_project) = &mut *vhdl_project.write().unwrap() { + vhdl_project.config_file_strs.push(format!("{:?}", pathbuf)); + let mut messages = Vec::new(); + let config_str = format!( + r#" + [libraries] + digital_lsp.files = [{}] + "#, vhdl_project.config_file_strs.join(",") + ); + let config = vhdl_lang::Config::from_str(&config_str, Path::new("")); + if let Ok(mut config) = config { + config.append(&vhdl_project.std_config, &mut messages); + let mut project = Project::from_config(config, &mut messages); + project.analyse(); + *vhdl_project = VhdlProject { project, std_config: vhdl_project.std_config.clone(), config_file_strs: vhdl_project.config_file_strs.clone() }; + } + + let arch_and_entity = vhdl_project.project.get_analyzed_units(&pathbuf); + info!("for file {} arch_and_entity is empty {}", path, arch_and_entity.is_empty()); + if let Some(mut fast) = make_fast_from_units(arch_and_entity) { fast.file_type = file_type.to_string(); // for module in &fast.content { // if module.name == "None" { diff --git a/src/sources.rs b/src/sources.rs index ce648e0..9b398d8 100644 --- a/src/sources.rs +++ b/src/sources.rs @@ -1,8 +1,7 @@ use crate::core::hdlparam::HdlParam; use crate::core::primitive_parser::PrimitiveText; use crate::core::sv_parser::make_fast_from_syntaxtree; -use crate::core::vhdl_parser::make_fast_from_design_file; -use crate::core::vhdl_parser::new_make_fast_from_design_file; +use crate::core::vhdl_parser::make_fast_from_units; use crate::core::vhdl_parser::vhdl_parse_str; use crate::definition::def_types::*; use crate::definition::get_scopes_from_syntax_tree; @@ -833,8 +832,8 @@ pub fn vhdl_parser_pipeline( let mut file = source_handle.write().unwrap(); let text = doc.to_string(); let mut scope_tree = if let Some(design_file) = vhdl_parse_str(&escape_path, &text) { - let units_in_file = vhdl_project.project.get_analyzed_units(&escape_path); - if let Some(mut fast) = new_make_fast_from_design_file(units_in_file, &design_file) { + let arch_and_entity = vhdl_project.project.get_analyzed_units(&escape_path); + if let Some(mut fast) = make_fast_from_units(arch_and_entity) { let parse_ir = ParseIR::DesignFile(design_file); file.parse_ir = Some(parse_ir); diff --git a/vhdl-parser b/vhdl-parser index efa2b48..cf95eb9 160000 --- a/vhdl-parser +++ b/vhdl-parser @@ -1 +1 @@ -Subproject commit efa2b481aafda0f8361dac8456ab35bda93bfe01 +Subproject commit cf95eb9b901e847b54ed824b6b6a780fd2f6eac3