diff --git a/src/core/hdlparam.rs b/src/core/hdlparam.rs index e38788a..ffb1ce3 100644 --- a/src/core/hdlparam.rs +++ b/src/core/hdlparam.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; use tower_lsp::lsp_types::Position as LspPosition; use tower_lsp::lsp_types::Range as LspRange; -#[derive(Debug, Clone, Serialize, PartialEq, Deserialize)] +#[derive(Debug, Clone, Serialize, PartialEq, PartialOrd, Eq, Ord, Deserialize)] pub struct Position { pub line: u32, pub character: u32 @@ -18,9 +18,13 @@ impl Position { pub fn to_lsp_position(&self) -> LspPosition { LspPosition { line: self.line, character: self.character } } + + pub fn from_lsp_position(pos: &LspPosition) -> Position { + Position { line: pos.line, character: pos.character } + } } -#[derive(Debug, Clone, Serialize, PartialEq, Deserialize)] +#[derive(Debug, Clone, Serialize, PartialEq, PartialOrd, Eq, Ord, Deserialize)] pub struct Range { pub start: Position, pub end: Position @@ -140,13 +144,37 @@ pub struct Parameter { // pub range: Range // } +#[derive(Debug, Serialize, PartialEq, PartialOrd, Eq, Ord, Deserialize, Clone)] +pub enum AssignType { + Named, + Ordered +} + +#[derive(Debug, Serialize, PartialEq, PartialOrd, Eq, Ord, Deserialize, Clone)] +pub struct InstPort { + pub port: Option, + pub assign_name: String, + pub assign_type: AssignType, + pub range: Range +} + +#[derive(Debug, Serialize, PartialEq, PartialOrd, Eq, Ord, Deserialize, Clone)] +pub struct InstParameter { + pub parameter: Option, + pub assign_name: String, + pub assign_type: AssignType, + pub range: Range +} + #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Instance { pub name: String, #[serde(rename = "type")] pub inst_type: String, pub instparams: Option, + pub intstparams_assignment: Vec, pub instports: Option, + pub intstport_assignment: Vec, pub range: Range } @@ -327,7 +355,7 @@ impl FastHdlparam { } } - pub fn add_instance(&mut self, name: &str, inst_type: &str, line: u32, character: u32, end_character: u32, + pub fn add_instance(&mut self, name: &str, inst_type: &str, port_assign: Vec, line: u32, character: u32, end_character: u32, param_start_line: u32, param_start_character: u32, param_end_line: u32, param_end_character: u32, port_start_line: u32, port_start_character: u32, port_end_line: u32, port_end_character: u32 ) { if let Some(last_module) = self.content.last_mut() { @@ -348,6 +376,7 @@ impl FastHdlparam { } ) }, + intstparams_assignment: Vec::new(), instports: if port_start_line == 0 { None } else { @@ -362,6 +391,7 @@ impl FastHdlparam { } ) }, + intstport_assignment: port_assign, range: Range { start: Position { line, character diff --git a/src/core/sv_parser.rs b/src/core/sv_parser.rs index b09d054..7a5fd44 100644 --- a/src/core/sv_parser.rs +++ b/src/core/sv_parser.rs @@ -1,4 +1,3 @@ -use std::collections::HashSet; use std::fs::{self, File}; use std::io::BufRead; use std::io::BufReader; @@ -9,10 +8,11 @@ use ropey::Rope; use tower_lsp::lsp_types::Url; use sv_parser::{unwrap_locate, unwrap_node, EventIter, ListOfParamAssignments, Locate, NodeEvent, ParamAssignment, ParameterDeclaration, RefNode, SyntaxTree}; +use crate::core::hdlparam::{AssignType, Position, Range}; use crate::sources::{recovery_sv_parse_with_retry, LSPSupport}; use crate::utils::to_escape_path; -use super::hdlparam::{FastHdlparam, Macro}; +use super::hdlparam::{self, FastHdlparam, InstPort, Macro}; macro_rules! advance_until_leave { ($tokens:ident, $tree:ident, $event_iter:ident, $node:path) => {{ @@ -318,9 +318,10 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re _ => (0, 0, 0, 0) }; + let inst_port_assignments = get_instance_ports(&syntax_tree, &doc, hier_node.clone()); let (port_start_line, port_start_character, port_end_line, port_end_character) = get_pp_range(&doc, hier_node); - hdlparam.add_instance(name, inst_type, line, character, end_character, + hdlparam.add_instance(name, inst_type, inst_port_assignments, line, character, end_character, param_start_line, param_start_character, param_end_line, param_end_character, port_start_line, port_start_character, port_end_line, port_end_character ); @@ -341,10 +342,10 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re let end_character = character + id.len as u32; let (param_start_line, param_start_character, param_end_line, param_end_character) = (0, 0, 0, 0); - let (port_start_line, port_start_character, - port_end_line, port_end_character) = get_port_parameter_range(&content, gate_node); + let inst_port_assignments = get_instance_ports(&syntax_tree, &doc, gate_node.clone()); + let (port_start_line, port_start_character, port_end_line, port_end_character) = get_pp_range(&doc, gate_node); - hdlparam.add_instance(name, inst_type, line, character, end_character, + hdlparam.add_instance(name, inst_type, inst_port_assignments, line, character, end_character, param_start_line, param_start_character, param_end_line, param_end_character, port_start_line, port_start_character, port_end_line, port_end_character ); @@ -396,13 +397,10 @@ fn get_first_last_locate(node: RefNode) -> Option<(Locate, Locate)> { let mut last_locate = Locate { offset: 0, line: 0, len: 0 }; for n in node { - match n { - RefNode::Symbol(x) => { - let locate = x.nodes.0; - if locate != last_locate { last_locate = locate; } - if first_locate.offset == 0 { first_locate = locate; }; - } - _ => () + if let RefNode::Symbol(x) = n { + let locate = x.nodes.0; + if locate != last_locate { last_locate = locate; } + if first_locate.offset == 0 { first_locate = locate; }; } } @@ -413,6 +411,120 @@ fn get_first_last_locate(node: RefNode) -> Option<(Locate, Locate)> { } } +fn get_instance_ports(syntax_tree: &SyntaxTree, doc: &Rope, node: RefNode) -> Vec { + let mut ports = Vec::new(); + for list in node { + match unwrap_node!(list, ListOfPortConnectionsNamed, ListOfPortConnectionsOrdered, InputTerminal, OutputTerminal) { + Some(RefNode::ListOfPortConnectionsNamed(x)) => { + for connect in x { + if let RefNode::NamedPortConnectionIdentifier(ident) = connect { + let (start_line, start_character, end_line, end_character) = get_pp_range(doc, connect); + let port_name_locate = get_identifier(RefNode::PortIdentifier(&(ident.nodes.2))); + let port_name = syntax_tree.get_str(&port_name_locate).unwrap(); + let name = if ident.nodes.3.is_some() { + if let (_, Some(name_expr), _) = ident.nodes.3.clone().unwrap().nodes { + let expr = sv_parser::NeedParseExpression::Expression(name_expr); + let (expr, _) = parse_expression(syntax_tree, &expr); + expr + } else { + "".to_string() + } + } else { + "".to_string() + }; + let port = InstPort { + port: Some(port_name.to_string()), + assign_name: name, + assign_type: AssignType::Named, + range: Range { + start: Position { line: start_line, character: start_character }, + end: Position { line: end_line, character: end_character } + } + }; + ports.push(port); + }; + } + } + Some(RefNode::ListOfPortConnectionsOrdered(x)) => { + for connect in x { + if let RefNode::OrderedPortConnection(ident) = connect { + if let Some(expr) = ident.nodes.1.clone() { + let start_locate = get_identifier(RefNode::Expression(&expr)); + let expr = sv_parser::NeedParseExpression::Expression(expr); + let (expr, locate) = parse_expression(syntax_tree, &expr); + let start_locate = start_locate.unwrap_or(Locate { offset: 0, line: 0, len: 0 }); + let locate = locate.unwrap_or(start_locate); + let port = InstPort { + port: None, + assign_name: expr, + assign_type: AssignType::Ordered, + range: Range { + start: get_position(doc, start_locate), + end: get_position(doc, Locate { + offset: locate.offset + locate.len, + line: locate.line, + len: 0 + }) + } + }; + ports.push(port); + } + }; + } + } + Some(RefNode::InputTerminal(x)) => { + let expr = x.nodes.0.clone(); + let start_locate = get_identifier(RefNode::Expression(&expr)); + let expr = sv_parser::NeedParseExpression::Expression(expr); + let (expr, locate) = parse_expression(syntax_tree, &expr); + let start_locate = start_locate.unwrap_or(Locate { offset: 0, line: 0, len: 0 }); + let locate = locate.unwrap_or(start_locate); + let port = InstPort { + port: None, + assign_name: expr, + assign_type: AssignType::Ordered, + range: Range { + start: get_position(doc, start_locate), + end: get_position(doc, Locate { + offset: locate.offset + locate.len, + line: locate.line, + len: 0 + }) + } + }; + ports.push(port); + } + Some(RefNode::OutputTerminal(x)) => { + let expr = x.nodes.0.clone(); + let start_locate = get_identifier(RefNode::NetLvalue(&expr)); + let expr = sv_parser::NeedParseExpression::NetValue(expr); + let (expr, locate) = parse_expression(syntax_tree, &expr); + let start_locate = start_locate.unwrap_or(Locate { offset: 0, line: 0, len: 0 }); + let locate = locate.unwrap_or(start_locate); + let port = InstPort { + port: None, + assign_name: expr, + assign_type: AssignType::Ordered, + range: Range { + start: get_position(doc, start_locate), + end: get_position(doc, Locate { + offset: locate.offset + locate.len, + line: locate.line, + len: 0 + }) + } + }; + ports.push(port); + } + _ => () + } + } + + ports.sort_by_key(|p| p.range.clone()); + ports.dedup_by_key(|p| p.range.clone()); + ports +} + fn parse_expression(syntax_tree: &SyntaxTree, x: &sv_parser::NeedParseExpression) -> (String, Option) { let mut last_locate = Locate { offset: 0, line: 0, len: 0 }; let mut expression = String::new(); @@ -507,6 +619,12 @@ fn get_identifier(node: RefNode) -> Option { } } +fn get_position(doc: &Rope, locate: Locate) -> Position { + let byte = locate.offset; + let pos = doc.byte_to_pos(byte); + hdlparam::Position::from_lsp_position(&pos) +} + fn get_includes(path: &PathBuf) -> Vec { let mut includes = Vec::new(); diff --git a/src/core/vhdl_parser.rs b/src/core/vhdl_parser.rs index 7321b59..09d9732 100644 --- a/src/core/vhdl_parser.rs +++ b/src/core/vhdl_parser.rs @@ -206,6 +206,8 @@ fn parse_tokens(tokens: Vec) -> Vec { inst_type: get_value(&tokens[i+1]), instports: None, instparams: None, + intstport_assignment: Vec::new(), + intstparams_assignment: Vec::new(), range: Range { start: Position { line: tokens[i-1].pos.range.start.line + 1, @@ -226,6 +228,8 @@ fn parse_tokens(tokens: Vec) -> Vec { inst_type: get_value(&tokens[i+2]), instports: None, instparams: None, + intstport_assignment: Vec::new(), + intstparams_assignment: Vec::new(), range: Range { start: Position { line: tokens[i-1].pos.range.start.line + 1, @@ -257,6 +261,8 @@ fn parse_tokens(tokens: Vec) -> Vec { inst_type, instports: None, instparams: None, + intstport_assignment: Vec::new(), + intstparams_assignment: Vec::new(), range: Range { start: Position { line: tokens[i-1].pos.range.start.line + 1, diff --git a/sv-parser b/sv-parser index 21f3e49..b6ae8b8 160000 --- a/sv-parser +++ b/sv-parser @@ -1 +1 @@ -Subproject commit 21f3e497e88a108d15be75ea7e2f0f1a409c6e1d +Subproject commit b6ae8b8a1ff22609e2a837b12dd798226f299f71