将 vhdl
This commit is contained in:
parent
c8aa5e2dcc
commit
15cfaccec1
20
.vscode/lsp.code-snippets
vendored
20
.vscode/lsp.code-snippets
vendored
@ -15,5 +15,25 @@
|
||||
"#[allow(unused)]"
|
||||
],
|
||||
"description": "#[allow(unused)]"
|
||||
},
|
||||
"match file_type": {
|
||||
"scope": "rust",
|
||||
"prefix": "matchfiletype",
|
||||
"body": [
|
||||
"match file_type.as_str() {",
|
||||
"\t\"common\" => {",
|
||||
"\t\t",
|
||||
"\t}",
|
||||
"\t\"ip\" => {",
|
||||
"\t\t",
|
||||
"\t}",
|
||||
"\t\"primitives\" => {",
|
||||
"\t\t",
|
||||
"\t}",
|
||||
"\t_ => {",
|
||||
"\t\t",
|
||||
"\t}",
|
||||
"}",
|
||||
]
|
||||
}
|
||||
}
|
@ -156,18 +156,16 @@ fn get_position_port_param_completion(
|
||||
let path = PathBuf::from_str(url.path()).unwrap();
|
||||
let path = to_escape_path(&path);
|
||||
let path_string = path.to_str().unwrap();
|
||||
info!("enter get_position_port_param_completion, pos: {pos:?}");
|
||||
// info!("enter get_position_port_param_completion, pos: {pos:?}");
|
||||
if let Some(hdl_file) = fast_map.get(path_string) {
|
||||
info!("find hdl_file, content: {:?}", hdl_file.fast.content);
|
||||
// info!("find hdl_file, content: {:?}", hdl_file.fast.content);
|
||||
// 在当前文件的 fast 中寻找
|
||||
for module in &hdl_file.fast.content {
|
||||
for instance in &module.instances {
|
||||
if let Some(_) = &instance.instparams {
|
||||
if instance.gen_dot_completion_param_range().contains(pos) {
|
||||
// 补全当前 module 的所有 param
|
||||
let inst_module = hdl_param.find_module_by_name(&instance.inst_type);
|
||||
if inst_module.is_some() {
|
||||
let inst_module = inst_module.unwrap();
|
||||
if let Some((inst_module, file_type, _)) = hdl_param.find_module_context_by_name(&instance.inst_type) {
|
||||
let mut completion_items = Vec::<CompletionItem>::new();
|
||||
for param in inst_module.params {
|
||||
let label_details = CompletionItemLabelDetails {
|
||||
@ -175,7 +173,21 @@ fn get_position_port_param_completion(
|
||||
..CompletionItemLabelDetails::default()
|
||||
};
|
||||
|
||||
let param_desc = make_param_desc(¶m);
|
||||
let param_desc = match file_type.as_str() {
|
||||
"common" => {
|
||||
param.to_vlog_description()
|
||||
}
|
||||
"ip" => {
|
||||
param.to_vhdl_description()
|
||||
}
|
||||
"primitives" => {
|
||||
param.to_vlog_description()
|
||||
}
|
||||
_ => {
|
||||
param.to_vlog_description()
|
||||
}
|
||||
};
|
||||
|
||||
let c_item = CompletionItem {
|
||||
label: param.name,
|
||||
detail: Some(param_desc),
|
||||
@ -196,9 +208,7 @@ fn get_position_port_param_completion(
|
||||
if instance.instports.is_some() {
|
||||
let port_range = instance.gen_dot_completion_port_range();
|
||||
if port_range.contains(pos) {
|
||||
let inst_module = hdl_param.find_module_by_name(&instance.inst_type);
|
||||
if inst_module.is_some() {
|
||||
let inst_module = inst_module.unwrap();
|
||||
if let Some((inst_module, file_type, _)) = hdl_param.find_module_context_by_name(&instance.inst_type) {
|
||||
let mut completion_items = Vec::<CompletionItem>::new();
|
||||
for port in inst_module.ports {
|
||||
let label_details = CompletionItemLabelDetails {
|
||||
@ -206,7 +216,21 @@ fn get_position_port_param_completion(
|
||||
..CompletionItemLabelDetails::default()
|
||||
};
|
||||
|
||||
let port_desc = make_port_desc(&port);
|
||||
let port_desc = match file_type.as_str() {
|
||||
"common" => {
|
||||
port.to_vlog_description()
|
||||
}
|
||||
"ip" => {
|
||||
port.to_vhdl_description()
|
||||
}
|
||||
"primitives" => {
|
||||
port.to_vlog_description()
|
||||
}
|
||||
_ => {
|
||||
port.to_vlog_description()
|
||||
}
|
||||
};
|
||||
|
||||
let c_item = CompletionItem {
|
||||
label: port.name,
|
||||
detail: Some(port_desc),
|
||||
@ -228,36 +252,3 @@ fn get_position_port_param_completion(
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn make_port_desc(port: &crate::core::hdlparam::Port) -> String {
|
||||
let mut port_desc_array = Vec::<String>::new();
|
||||
port_desc_array.push(port.dir_type.to_string());
|
||||
if port.net_type != "unknown" {
|
||||
port_desc_array.push(port.net_type.to_string());
|
||||
}
|
||||
|
||||
if port.signed != "unsigned" {
|
||||
port_desc_array.push("signed".to_string());
|
||||
}
|
||||
|
||||
if port.width != "1" {
|
||||
port_desc_array.push(port.width.to_string());
|
||||
}
|
||||
|
||||
port_desc_array.push(port.name.to_string());
|
||||
let port_desc = port_desc_array.join(" ");
|
||||
port_desc
|
||||
}
|
||||
|
||||
fn make_param_desc(param: &crate::core::hdlparam::Parameter) -> String {
|
||||
let mut param_desc_array = Vec::<String>::new();
|
||||
param_desc_array.push(format!("parameter {}", param.name));
|
||||
|
||||
if param.init != "unknown" {
|
||||
param_desc_array.push("=".to_string());
|
||||
param_desc_array.push(param.init.to_string());
|
||||
}
|
||||
|
||||
let param_desc = param_desc_array.join(" ");
|
||||
param_desc
|
||||
}
|
||||
|
@ -156,26 +156,7 @@ pub struct Parameter {
|
||||
}
|
||||
|
||||
impl Port {
|
||||
pub fn to_description(&self) -> String {
|
||||
let mut port_desc_array = Vec::<String>::new();
|
||||
port_desc_array.push(self.dir_type.to_string());
|
||||
if self.net_type != "unknown" {
|
||||
port_desc_array.push(self.net_type.to_string());
|
||||
}
|
||||
|
||||
if self.signed != "unsigned" {
|
||||
port_desc_array.push("signed".to_string());
|
||||
}
|
||||
|
||||
if self.width != "1" {
|
||||
port_desc_array.push(self.width.to_string());
|
||||
}
|
||||
|
||||
port_desc_array.push(self.name.to_string());
|
||||
let port_desc = port_desc_array.join(" ");
|
||||
port_desc
|
||||
}
|
||||
pub fn vhdl_to_vlog_description(&self) -> String {
|
||||
pub fn to_vlog_description(&self) -> String {
|
||||
let mut port_desc_array = Vec::<String>::new();
|
||||
let dir_type = match self.dir_type.as_str() {
|
||||
"in" => "input",
|
||||
@ -215,7 +196,7 @@ impl Port {
|
||||
}
|
||||
|
||||
impl Parameter {
|
||||
pub fn to_description(&self) -> String {
|
||||
pub fn to_vlog_description(&self) -> String {
|
||||
let mut param_desc_array = Vec::<String>::new();
|
||||
param_desc_array.push(format!("parameter {}", self.name));
|
||||
|
||||
@ -226,13 +207,12 @@ impl Parameter {
|
||||
let param_desc = param_desc_array.join(" ");
|
||||
param_desc
|
||||
}
|
||||
pub fn vhdl_to_vlog_description(&self) -> String {
|
||||
pub fn to_vhdl_description(&self) -> String {
|
||||
let mut param_desc_array = Vec::<String>::new();
|
||||
param_desc_array.push(format!("parameter {}", self.name));
|
||||
param_desc_array.push(format!("{} : {}", self.name, self.net_type.to_lowercase()));
|
||||
|
||||
if self.init != "unknown" {
|
||||
param_desc_array.push("=".to_string());
|
||||
param_desc_array.push(self.init.to_string());
|
||||
param_desc_array.push(format!(" := {}", self.init));
|
||||
}
|
||||
let param_desc = param_desc_array.join(" ");
|
||||
param_desc
|
||||
|
@ -35,14 +35,21 @@ pub fn vhdl_parser(path: &str) -> FastHdlparam {
|
||||
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);
|
||||
if let Ok((_, design_file)) = parser.parse_vhdl_str(code, path, &mut diagnostics) {
|
||||
return Some(design_file);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -301,16 +301,16 @@ fn make_port_desc_hover(file_type: &str, port: &crate::core::hdlparam::Port, ran
|
||||
|
||||
let (language, value) = match file_type {
|
||||
"common" => {
|
||||
(language_id.to_string(), port.to_description())
|
||||
(language_id.to_string(), port.to_vlog_description())
|
||||
}
|
||||
"ip" => {
|
||||
("vhdl".to_string(), port.to_vhdl_description())
|
||||
}
|
||||
"primitives" => {
|
||||
(language_id.to_string(), port.to_description())
|
||||
(language_id.to_string(), port.to_vlog_description())
|
||||
}
|
||||
_ => {
|
||||
(language_id.to_string(), port.to_description())
|
||||
(language_id.to_string(), port.to_vlog_description())
|
||||
}
|
||||
};
|
||||
|
||||
@ -324,16 +324,16 @@ fn make_port_desc_hover(file_type: &str, port: &crate::core::hdlparam::Port, ran
|
||||
fn make_param_desc_hover(file_type: &str, param: &crate::core::hdlparam::Parameter, range: &Range, language_id: &str) -> Hover {
|
||||
let value = match file_type {
|
||||
"common" => {
|
||||
param.to_description()
|
||||
param.to_vlog_description()
|
||||
}
|
||||
"ip" => {
|
||||
param.vhdl_to_vlog_description()
|
||||
param.to_vhdl_description()
|
||||
}
|
||||
"primitives" => {
|
||||
param.to_description()
|
||||
param.to_vlog_description()
|
||||
}
|
||||
_ => {
|
||||
param.to_description()
|
||||
param.to_vlog_description()
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -155,17 +155,17 @@ fn make_instport_hints(
|
||||
|
||||
let port_desc_value = match file_type.as_str() {
|
||||
"common" => {
|
||||
format!("```{}\n{}\n```", language_id, port_info.to_description())
|
||||
format!("```{}\n{}\n```", language_id, port_info.to_vlog_description())
|
||||
}
|
||||
"ip" => {
|
||||
// TODO: 支持更多的 IP
|
||||
format!("```verilog\n{}\n```", port_info.vhdl_to_vlog_description())
|
||||
format!("```verilog\n{}\n```", port_info.to_vhdl_description())
|
||||
}
|
||||
"primitives" => {
|
||||
format!("```{}\n{}\n```", language_id, port_info.to_description())
|
||||
format!("```{}\n{}\n```", language_id, port_info.to_vlog_description())
|
||||
}
|
||||
_ => {
|
||||
format!("```{}\n{}\n```", language_id, port_info.to_description())
|
||||
format!("```{}\n{}\n```", language_id, port_info.to_vlog_description())
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -118,11 +118,21 @@ pub fn do_fast(
|
||||
let parse_fast_by_language_id = |language_id: &str| {
|
||||
match language_id {
|
||||
"vhdl" => {
|
||||
do_vhdl_fast(&path, &file_type, &tool_chain, backend)
|
||||
do_vhdl_fast(
|
||||
&path,
|
||||
&file_type,
|
||||
&tool_chain,
|
||||
backend
|
||||
)
|
||||
}
|
||||
|
||||
"verilog" | "systemverilog" => {
|
||||
do_sv_fast(&path, &file_type, &tool_chain, backend)
|
||||
do_sv_fast(
|
||||
&path,
|
||||
&file_type,
|
||||
&tool_chain,
|
||||
backend
|
||||
)
|
||||
}
|
||||
|
||||
_ => Err(tower_lsp::jsonrpc::Error {
|
||||
|
@ -285,6 +285,10 @@ impl LanguageServer for Backend {
|
||||
|
||||
async fn did_change(&self, params: DidChangeTextDocumentParams) {
|
||||
info!("file did change: {:?}", params.text_document.uri);
|
||||
for change in ¶ms.content_changes {
|
||||
info!("change: {:?}", change);
|
||||
}
|
||||
|
||||
// // 如果文件太大则显示错误
|
||||
// if CacheManager::uri_is_big_file(¶ms.text_document.uri) {
|
||||
// // self.client.show_message(MessageType::WARNING, "考虑到性能问题,对于大于 1MB 的文件不会主动提供语言服务")
|
||||
|
@ -1,8 +1,7 @@
|
||||
use crate::core::cache_storage::CacheManager;
|
||||
use crate::core::hdlparam::HdlParam;
|
||||
use crate::core::sv_parser::make_fast_from_syntaxtree;
|
||||
use crate::core::vhdl_parser::make_fast_from_design_file;
|
||||
use crate::core::vhdl_parser::vhdl_parse;
|
||||
use crate::core::vhdl_parser::vhdl_parse_str;
|
||||
use crate::definition::def_types::*;
|
||||
use crate::definition::get_scopes_from_syntax_tree;
|
||||
use crate::definition::get_scopes_from_vhdl_fast;
|
||||
@ -18,7 +17,6 @@ use ropey::{Rope, RopeSlice};
|
||||
use std::cmp::min;
|
||||
use std::collections::HashMap;
|
||||
use std::env::current_dir;
|
||||
use std::fs;
|
||||
#[allow(unused)]
|
||||
use std::ops::Deref;
|
||||
use std::ops::Range as StdRange;
|
||||
@ -79,7 +77,7 @@ impl LSPServer {
|
||||
if let Some(file) = self.srcs.get_file(file_id) {
|
||||
let mut file = file.write().unwrap();
|
||||
|
||||
// loop through changes and apply
|
||||
// 根据输入的 change 动态更新对应的代码的文本片段
|
||||
for change in params.content_changes {
|
||||
if change.range.is_none() {
|
||||
file.text = Rope::from_str(&change.text);
|
||||
@ -225,8 +223,6 @@ pub struct Sources {
|
||||
pub scope_tree: Arc<RwLock<Option<GenericScope>>>,
|
||||
// include directories, passed to parser to resolve `include
|
||||
pub include_dirs: Arc<RwLock<Vec<PathBuf>>>,
|
||||
// source directories
|
||||
pub source_dirs: Arc<RwLock<Vec<PathBuf>>>,
|
||||
/// hdlparam 后端实现
|
||||
pub hdl_param: Arc<HdlParam>,
|
||||
// 同步解析线程和发送 fast 请求的
|
||||
@ -247,7 +243,6 @@ impl Sources {
|
||||
meta: Arc::new(RwLock::new(Vec::new())),
|
||||
scope_tree: Arc::new(RwLock::new(None)),
|
||||
include_dirs: Arc::new(RwLock::new(Vec::new())),
|
||||
source_dirs: Arc::new(RwLock::new(Vec::new())),
|
||||
hdl_param: Arc::new(HdlParam::new()),
|
||||
fast_sync_controller: Arc::new(RwLock::new(HashMap::<String, Arc<RwLock<bool>>>::new()))
|
||||
}
|
||||
@ -273,6 +268,8 @@ impl Sources {
|
||||
let hdl_param_handle = self.hdl_param.clone();
|
||||
let inc_dirs = self.include_dirs.clone();
|
||||
|
||||
let uri = doc.uri.clone();
|
||||
|
||||
let conf = server.conf.clone();
|
||||
|
||||
info!("launch worker to parse {:?}", doc.uri.to_string());
|
||||
@ -291,17 +288,18 @@ impl Sources {
|
||||
let parse_handle = thread::spawn(move || {
|
||||
let (lock, cvar) = &*valid_parse2;
|
||||
loop {
|
||||
let file = source_handle.read().unwrap();
|
||||
let text = file.text.clone();
|
||||
let uri = &file.uri.clone();
|
||||
let range = &file.last_change_range.clone();
|
||||
drop(file);
|
||||
|
||||
info!("do parse in {:?}, language_id: {:?}", uri.to_string(), language_id);
|
||||
|
||||
// 此时 update fast 的地方为 write 会进行阻塞
|
||||
{
|
||||
let _unused = fast_lock.read().unwrap();
|
||||
// 从内存中直接获取增量更新系统维护的代码文本
|
||||
let file = source_handle.read().unwrap();
|
||||
let text = file.text.clone();
|
||||
let uri = &file.uri.clone();
|
||||
|
||||
let range = &file.last_change_range.clone();
|
||||
drop(file);
|
||||
match language_id.as_str() {
|
||||
"vhdl" => {
|
||||
vhdl_parser_pipeline(
|
||||
@ -692,11 +690,16 @@ pub fn vhdl_parser_pipeline(
|
||||
};
|
||||
|
||||
let mut file = source_handle.write().unwrap();
|
||||
let mut scope_tree = if let Some(design_file) = vhdl_parse(&escape_path) {
|
||||
let text = doc.to_string();
|
||||
let mut scope_tree = if let Some(design_file) = vhdl_parse_str(&escape_path, &text) {
|
||||
if let Some(mut fast) = make_fast_from_design_file(&design_file) {
|
||||
let parse_ir = ParseIR::DesignFile(design_file);
|
||||
file.parse_ir = Some(parse_ir);
|
||||
|
||||
for module in &fast.content {
|
||||
info!("parse port number: {:?}", module.ports.len());
|
||||
}
|
||||
|
||||
let file_type = {
|
||||
let fast_map = hdl_param_handle.path_to_hdl_file.read().unwrap();
|
||||
if let Some(hdl_file) = fast_map.get(escape_path_string) {
|
||||
@ -763,7 +766,6 @@ pub trait LSPSupport {
|
||||
fn range_to_char_range(&self, range: &Range) -> StdRange<usize>;
|
||||
fn char_range_to_range(&self, range: StdRange<usize>) -> Range;
|
||||
fn apply_change(&mut self, change: &TextDocumentContentChangeEvent);
|
||||
fn find_first_str(&self, target: &str) -> Option<usize>;
|
||||
}
|
||||
|
||||
/// Extend ropey's Rope type with lsp convenience functions
|
||||
@ -806,9 +808,6 @@ impl LSPSupport for Rope {
|
||||
}
|
||||
}
|
||||
}
|
||||
fn find_first_str(&self, _: &str) -> Option<usize> {
|
||||
panic!("haven't impl this method");
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> LSPSupport for RopeSlice<'a> {
|
||||
@ -843,12 +842,4 @@ impl<'a> LSPSupport for RopeSlice<'a> {
|
||||
fn apply_change(&mut self, _: &TextDocumentContentChangeEvent) {
|
||||
panic!("can't edit a rope slice");
|
||||
}
|
||||
fn find_first_str(&self, target: &str) -> Option<usize> {
|
||||
for (i, c) in self.chars().enumerate() {
|
||||
if c.to_string() == target {
|
||||
return Some(i)
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user