refactor vhdl fast

This commit is contained in:
light-ly 2024-12-04 01:23:42 +08:00
parent d8ddebc744
commit 299e4dc031
6 changed files with 279 additions and 613 deletions

View File

@ -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;

View File

@ -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<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> {
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<DesignFile> {
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 {
fast_macro: Macro {
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()
};
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::<Vec<Instance>>();
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<FastHdlparam> {
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<Token>) -> 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<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
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<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 {
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::<Vec<InstParameter>>();
}
_ => {}
}
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)]
fn get_value(token: &Token) -> String {

View File

@ -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, &parameter_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();

View File

@ -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" {

View File

@ -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);

@ -1 +1 @@
Subproject commit efa2b481aafda0f8361dac8456ab35bda93bfe01
Subproject commit cf95eb9b901e847b54ed824b6b6a780fd2f6eac3