add port assignment

This commit is contained in:
light-ly 2024-10-29 21:46:26 +08:00
parent 82a21ccf34
commit 3303b65c3f
4 changed files with 171 additions and 17 deletions

View File

@ -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<String>,
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<String>,
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<Range>,
pub intstparams_assignment: Vec<InstParameter>,
pub instports: Option<Range>,
pub intstport_assignment: Vec<InstPort>,
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<InstPort>, 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

View File

@ -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<InstPort> {
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<Locate>) {
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<Locate> {
}
}
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<crate::core::hdlparam::Include> {
let mut includes = Vec::new();

View File

@ -206,6 +206,8 @@ fn parse_tokens(tokens: Vec<Token>) -> Vec<Module> {
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<Token>) -> Vec<Module> {
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<Token>) -> Vec<Module> {
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,

@ -1 +1 @@
Subproject commit 21f3e497e88a108d15be75ea7e2f0f1a409c6e1d
Subproject commit b6ae8b8a1ff22609e2a837b12dd798226f299f71