refactor vhdl fast
This commit is contained in:
parent
d8ddebc744
commit
299e4dc031
@ -373,6 +373,18 @@ impl FastHdlparam {
|
|||||||
self.content.push(module);
|
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) {
|
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) {
|
if let Some(matched_module) = self.content.iter_mut().find(|module| module.name == name) {
|
||||||
matched_module.range.end.line = end_line;
|
matched_module.range.end.line = end_line;
|
||||||
|
@ -1,49 +1,10 @@
|
|||||||
use std::collections::HashSet;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use log::info;
|
use log::info;
|
||||||
use vhdl_lang::ast::{AnyDesignUnit, DesignFile};
|
use vhdl_lang::ast::{ArchitectureBody, ConcurrentStatement, DesignFile, Designator, EntityDeclaration, InstantiatedUnit, InterfaceDeclaration, InterfaceList, LabeledConcurrentStatement, Mode, ModeIndication, Name};
|
||||||
use vhdl_lang::{kind_str, Token, VHDLParser, VHDLStandard};
|
use vhdl_lang::{kind_str, HasTokenSpan, Token, TokenAccess, TokenSpan, VHDLParser, VHDLStandard};
|
||||||
|
|
||||||
use super::hdlparam::*;
|
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<DesignFile> {
|
|
||||||
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<DesignFile> {
|
pub fn vhdl_parse_str(path: &PathBuf, code: &str) -> Option<DesignFile> {
|
||||||
let mut diagnostics = Vec::new();
|
let mut diagnostics = Vec::new();
|
||||||
let parser = VHDLParser::new(VHDLStandard::VHDL2008);
|
let parser = VHDLParser::new(VHDLStandard::VHDL2008);
|
||||||
@ -53,7 +14,9 @@ pub fn vhdl_parse_str(path: &PathBuf, code: &str) -> Option<DesignFile> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_make_fast_from_design_file(units: Vec<(AnyDesignUnit, Vec<Token>)>, design_file: &DesignFile) -> Option<FastHdlparam> {
|
pub fn make_fast_from_units(
|
||||||
|
arch_and_entity: Vec<((ArchitectureBody, Vec<Token>), (EntityDeclaration, Vec<Token>))>,
|
||||||
|
) -> Option<FastHdlparam> {
|
||||||
let mut hdlparam = FastHdlparam {
|
let mut hdlparam = FastHdlparam {
|
||||||
fast_macro: Macro {
|
fast_macro: Macro {
|
||||||
defines: Vec::new(),
|
defines: Vec::new(),
|
||||||
@ -65,577 +28,234 @@ pub fn new_make_fast_from_design_file(units: Vec<(AnyDesignUnit, Vec<Token>)>, d
|
|||||||
file_type: "common".to_string()
|
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);
|
hdlparam.new_vhdl_module(name, arch_name, range);
|
||||||
// for (tokens, design_unit) in &design_file.design_units {
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
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::<Vec<Instance>>();
|
||||||
|
|
||||||
|
if let Some(last_module) = hdlparam.content.last_mut() {
|
||||||
|
last_module.instances = instances
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
info!("get fast {:#?}", hdlparam);
|
||||||
Some(hdlparam)
|
Some(hdlparam)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_fast_from_design_file(design_file: &DesignFile) -> Option<FastHdlparam> {
|
fn parse_instance(statement: &LabeledConcurrentStatement, tokens: &Vec<Token>) -> Instance {
|
||||||
let mut hdlparam = FastHdlparam {
|
let name = if let Some(tree) = &statement.label.tree { tree.item.name_utf8() } else { "unknown".to_string() };
|
||||||
fast_macro: Macro {
|
let range = get_range_from_token(
|
||||||
defines: Vec::new(),
|
tokens.get_token(statement.span().get_start_token()),
|
||||||
errors: Vec::new(),
|
tokens.get_token(statement.span().get_end_token())
|
||||||
includes: Vec::new(),
|
);
|
||||||
invalid: Vec::new()
|
|
||||||
},
|
let mut parsed_instance = Instance {
|
||||||
content: Vec::new(),
|
name,
|
||||||
file_type: "common".to_string()
|
inst_type: "".to_string(),
|
||||||
|
instparams: None,
|
||||||
|
intstparam_assignments: Vec::new(),
|
||||||
|
instports: None,
|
||||||
|
intstport_assignments: Vec::new(),
|
||||||
|
range
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut all_tockens = Vec::new();
|
match &statement.statement.item {
|
||||||
for (tokens, _) in &design_file.design_units {
|
ConcurrentStatement::Instance(instance) => {
|
||||||
all_tockens.extend(tokens.clone());
|
parsed_instance.inst_type = match &instance.unit {
|
||||||
}
|
InstantiatedUnit::Component(name) => {
|
||||||
|
match &name.item {
|
||||||
hdlparam.content.extend(parse_tokens(all_tockens));
|
Name::Designator(designator) => {
|
||||||
Some(hdlparam)
|
match &designator.item {
|
||||||
}
|
Designator::Identifier(symbol) => symbol.name_utf8(),
|
||||||
|
_ => "unknown".to_string()
|
||||||
|
|
||||||
fn parse_tokens(tokens: Vec<Token>) -> Vec<Module> {
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
_ => "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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// println!("{:?}", modules);
|
if let Some(parameter_list) = &instance.generic_map {
|
||||||
modules
|
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())
|
||||||
|
));
|
||||||
|
|
||||||
}
|
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))
|
||||||
#[allow(unused)]
|
).unwrap_or(
|
||||||
fn parse_port(tokens: &[Token], start: usize, is_map: bool) -> (Vec<Port>, 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<Parameter>, 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()
|
"unknown".to_string()
|
||||||
};
|
);
|
||||||
let end_pos = if kind_str(tokens[i+2].kind) == ":=" {
|
let actual = parse_string_from_tokenspan(association_ele.actual.span(), tokens);
|
||||||
tokens[i+2].pos.range.end
|
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 {
|
} 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) == ":=" {
|
InstParameter { parameter: Some(formal), assign_val: Some(actual), assign_type: AssignType::Named, range: assign_range }
|
||||||
i + 3
|
}).collect::<Vec<InstParameter>>();
|
||||||
} 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)
|
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::<Vec<InstPort>>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
};
|
||||||
|
|
||||||
|
parsed_instance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_interface_list(list: &InterfaceList, tokens: &Vec<Token>) -> 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<Token>) -> 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<Token>) -> 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)]
|
#[allow(unused)]
|
||||||
fn get_value(token: &Token) -> String {
|
fn get_value(token: &Token) -> String {
|
||||||
|
@ -209,8 +209,7 @@ pub fn get_scopes_from_vhdl_fast(fast: &FastHdlparam, text: &Rope, url: &Url) ->
|
|||||||
for module in &fast.content {
|
for module in &fast.content {
|
||||||
let mut scope: GenericScope = GenericScope::new(url);
|
let mut scope: GenericScope = GenericScope::new(url);
|
||||||
scope.ident = module.name.clone();
|
scope.ident = module.name.clone();
|
||||||
let mut module_range = module.range.clone();
|
let module_range = module.range.clone();
|
||||||
module_range.affine(-1, -1);
|
|
||||||
scope.start = position_to_byte_idx(text, &module_range.start);
|
scope.start = position_to_byte_idx(text, &module_range.start);
|
||||||
scope.end = position_to_byte_idx(text, &module_range.end);
|
scope.end = position_to_byte_idx(text, &module_range.end);
|
||||||
scope.byte_idx = scope.start + 7;
|
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 {
|
for parameter in &module.params {
|
||||||
let mut def = GenericDec::new(url);
|
let mut def = GenericDec::new(url);
|
||||||
def.ident = parameter.name.clone();
|
def.ident = parameter.name.clone();
|
||||||
let mut parameter_range = parameter.range.clone();
|
let parameter_range = parameter.range.clone();
|
||||||
parameter_range.affine(-1, -1);
|
|
||||||
def.byte_idx = position_to_byte_idx(text, ¶meter_range.start);
|
def.byte_idx = position_to_byte_idx(text, ¶meter_range.start);
|
||||||
def.completion_kind = CompletionItemKind::TYPE_PARAMETER;
|
def.completion_kind = CompletionItemKind::TYPE_PARAMETER;
|
||||||
def.symbol_kind = SymbolKind::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 {
|
for port in &module.ports {
|
||||||
let mut port_def = PortDec::new(url);
|
let mut port_def = PortDec::new(url);
|
||||||
port_def.ident = port.name.clone();
|
port_def.ident = port.name.clone();
|
||||||
let mut port_range = port.range.clone();
|
let port_range = port.range.clone();
|
||||||
port_range.affine(-1, -1);
|
|
||||||
port_def.byte_idx = position_to_byte_idx(text, &port_range.start);
|
port_def.byte_idx = position_to_byte_idx(text, &port_range.start);
|
||||||
port_def.type_str = port.dir_type.clone();
|
port_def.type_str = port.dir_type.clone();
|
||||||
scope.defs.push(Box::new(port_def));
|
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 {
|
for inst in &module.instances {
|
||||||
let mut instance = ModInst::new(url);
|
let mut instance = ModInst::new(url);
|
||||||
instance.ident = inst.name.clone();
|
instance.ident = inst.name.clone();
|
||||||
let mut inst_range = inst.range.clone();
|
let inst_range = inst.range.clone();
|
||||||
inst_range.affine(-1, -1);
|
|
||||||
instance.byte_idx = position_to_byte_idx(text, &inst_range.start);
|
instance.byte_idx = position_to_byte_idx(text, &inst_range.start);
|
||||||
instance.type_str = inst.inst_type.clone();
|
instance.type_str = inst.inst_type.clone();
|
||||||
instance.mod_ident = inst.inst_type.clone();
|
instance.mod_ident = inst.inst_type.clone();
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::{fs, future};
|
use std::{fs, future};
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use log::info;
|
use log::info;
|
||||||
use ropey::Rope;
|
use ropey::Rope;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tower_lsp::jsonrpc::Result;
|
use tower_lsp::jsonrpc::Result;
|
||||||
use tower_lsp::lsp_types::*;
|
use tower_lsp::lsp_types::*;
|
||||||
|
use vhdl_lang::Project;
|
||||||
|
|
||||||
use crate::core::cache_storage::CacheResult;
|
use crate::core::cache_storage::CacheResult;
|
||||||
use crate::core::hdlparam::FastHdlparam;
|
use crate::core::hdlparam::FastHdlparam;
|
||||||
use crate::core::sv_parser::make_fast_from_syntaxtree;
|
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::{core, utils::*};
|
||||||
use crate::server::Backend;
|
use crate::server::Backend;
|
||||||
use crate::sources::recovery_sv_parse_with_retry;
|
use crate::sources::recovery_sv_parse_with_retry;
|
||||||
@ -218,6 +220,7 @@ fn do_vhdl_fast(
|
|||||||
let sources = &backend.server.srcs;
|
let sources = &backend.server.srcs;
|
||||||
let pathbuf = PathBuf::from_str(path).unwrap();
|
let pathbuf = PathBuf::from_str(path).unwrap();
|
||||||
let hdl_param = sources.hdl_param.clone();
|
let hdl_param = sources.hdl_param.clone();
|
||||||
|
let vhdl_project = sources.vhdl_project.clone();
|
||||||
|
|
||||||
// TODO: 支持对于 synth 下的 vhdl 文件的解析,从而提供更加丰富的 IP 支持
|
// TODO: 支持对于 synth 下的 vhdl 文件的解析,从而提供更加丰富的 IP 支持
|
||||||
if file_type == "ip" {
|
if file_type == "ip" {
|
||||||
@ -251,8 +254,26 @@ fn do_vhdl_fast(
|
|||||||
};
|
};
|
||||||
hdl_param.update_fast(path.to_string(), ip_fast.clone());
|
hdl_param.update_fast(path.to_string(), ip_fast.clone());
|
||||||
return Ok(ip_fast);
|
return Ok(ip_fast);
|
||||||
} else if let Some(design_file) = vhdl_parse(&pathbuf) {
|
} else if let Some(vhdl_project) = &mut *vhdl_project.write().unwrap() {
|
||||||
if let Some(mut fast) = make_fast_from_design_file(&design_file) {
|
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();
|
fast.file_type = file_type.to_string();
|
||||||
// IP 不需要内部的 instance,其实现是加密的,只需要暴露 module 的接口即可
|
// IP 不需要内部的 instance,其实现是加密的,只需要暴露 module 的接口即可
|
||||||
// 所以此处需要清空所有的 module 中的 instance
|
// 所以此处需要清空所有的 module 中的 instance
|
||||||
@ -275,8 +296,26 @@ fn do_vhdl_fast(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 没有特殊情况,则正常解析并写入
|
// 没有特殊情况,则正常解析并写入
|
||||||
if let Some(design_file) = vhdl_parse(&pathbuf) {
|
if let Some(vhdl_project) = &mut *vhdl_project.write().unwrap() {
|
||||||
if let Some(mut fast) = make_fast_from_design_file(&design_file) {
|
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();
|
fast.file_type = file_type.to_string();
|
||||||
// for module in &fast.content {
|
// for module in &fast.content {
|
||||||
// if module.name == "None" {
|
// if module.name == "None" {
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use crate::core::hdlparam::HdlParam;
|
use crate::core::hdlparam::HdlParam;
|
||||||
use crate::core::primitive_parser::PrimitiveText;
|
use crate::core::primitive_parser::PrimitiveText;
|
||||||
use crate::core::sv_parser::make_fast_from_syntaxtree;
|
use crate::core::sv_parser::make_fast_from_syntaxtree;
|
||||||
use crate::core::vhdl_parser::make_fast_from_design_file;
|
use crate::core::vhdl_parser::make_fast_from_units;
|
||||||
use crate::core::vhdl_parser::new_make_fast_from_design_file;
|
|
||||||
use crate::core::vhdl_parser::vhdl_parse_str;
|
use crate::core::vhdl_parser::vhdl_parse_str;
|
||||||
use crate::definition::def_types::*;
|
use crate::definition::def_types::*;
|
||||||
use crate::definition::get_scopes_from_syntax_tree;
|
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 mut file = source_handle.write().unwrap();
|
||||||
let text = doc.to_string();
|
let text = doc.to_string();
|
||||||
let mut scope_tree = if let Some(design_file) = vhdl_parse_str(&escape_path, &text) {
|
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);
|
let arch_and_entity = vhdl_project.project.get_analyzed_units(&escape_path);
|
||||||
if let Some(mut fast) = new_make_fast_from_design_file(units_in_file, &design_file) {
|
if let Some(mut fast) = make_fast_from_units(arch_and_entity) {
|
||||||
let parse_ir = ParseIR::DesignFile(design_file);
|
let parse_ir = ParseIR::DesignFile(design_file);
|
||||||
file.parse_ir = Some(parse_ir);
|
file.parse_ir = Some(parse_ir);
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit efa2b481aafda0f8361dac8456ab35bda93bfe01
|
Subproject commit cf95eb9b901e847b54ed824b6b6a780fd2f6eac3
|
Loading…
x
Reference in New Issue
Block a user