diff --git a/Cargo.lock b/Cargo.lock index aefd5e4..253dd7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -210,6 +210,7 @@ dependencies = [ "once_cell", "path-clean", "pathdiff", + "percent-encoding", "regex", "ropey", "serde", diff --git a/Cargo.toml b/Cargo.toml index 6459eb5..619fbc7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" sv-parser = { version = "0.13.3", path = "sv-parser/sv-parser"} once_cell = "1.8" futures = "0.3" +percent-encoding = "2.1.0" log = "0.4.19" tower-lsp = "0.20.0" flexi_logger = "0.29.0" diff --git a/src/core/sv_parser.rs b/src/core/sv_parser.rs index 0a18797..82270a5 100644 --- a/src/core/sv_parser.rs +++ b/src/core/sv_parser.rs @@ -4,6 +4,8 @@ use std::{collections::HashMap, io::BufReader}; use std::path::PathBuf; use anyhow::Error; use log::info; +use percent_encoding::percent_decode_str; +use std::env::consts::OS; use sv_parser::{parse_sv, unwrap_node, ConstantMintypmaxExpression, GateInstantiation, ListOfParameterAssignments, ListOfPortConnections, Locate, PackedDimensionRange, RefNode, SyntaxTree}; use super::fast_hdlparam::{FastHdlparam, Macro}; @@ -27,11 +29,26 @@ pub fn sv_parser(path: &str) -> Option { } pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Result { + // 对不同操作系统文件路径的支持 + let decoded_path = percent_decode_str(path.to_str().unwrap()).decode_utf8_lossy(); + let decoded_path_str = decoded_path.as_ref(); + let path = match OS { + "windows" => { + // 去掉开头的斜杠 + let trimmed_path_str = decoded_path_str.trim_start_matches('/'); + PathBuf::from(trimmed_path_str) + }, + _ => { + // 其他操作系统(如 Linux)保持原样 + PathBuf::from(decoded_path_str) + }, + }; + let mut hdlparam = FastHdlparam { fast_macro: Macro { defines: Vec::new(), errors: Vec::new(), - includes: get_includes(path), + includes: get_includes(&path), invalid: Vec::new() }, content: Vec::new() @@ -71,7 +88,8 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re let replacement = match unwrap_node!(x, MacroText) { Some(RefNode::MacroText(x)) => Some(x.nodes.0), - _ => None + // TODO : 把下面的 contine 替换为 None 会报错 + _ => continue }.unwrap(); let (end_line, end_character) = (replacement.line, get_column_by_offset(&content, replacement.offset) + replacement.len); let replacement = syntax_tree.get_str(&replacement).unwrap(); @@ -602,10 +620,11 @@ fn get_column_by_offset(content: &[String], offset: usize) -> usize { #[cfg(test)] mod tests { - use std::fs; + use std::{fs, path::Path}; use super::sv_parser; const TESTFILES_DIR: &str = "testfiles"; + const DIGTIAL_IDE_TEST: &str = "/home/dide/project/Digital-Test/Digital-IDE-test/user"; macro_rules! unwrap_result { ($expr:expr) => { @@ -640,4 +659,42 @@ mod tests { } } } + + #[test] + fn test_digital_ide_test() { + // 判断路径是否存在且为文件夹 + let path = Path::new(DIGTIAL_IDE_TEST); + if path.exists() && path.is_dir() { + // 递归遍历文件夹 + if let Err(e) = traverse_directory(path) { + eprintln!("Error: {}", e); + } + } else { + eprintln!("Path does not exist or is not a directory"); + } + } + + fn traverse_directory(dir: &Path) -> Result<(), Box> { + if dir.is_dir() { + for entry in fs::read_dir(dir)? { + let entry = entry?; + let path = entry.path(); + + if path.is_dir() { + // 递归遍历子文件夹 + traverse_directory(&path)?; + } else if path.is_file() { + // 检查文件扩展名 + if let Some(ext) = path.extension() { + if ext == "v" || ext == "sv" { + println!("Test file: {:?}", path); + let file_path = path.to_str().unwrap(); + let _ = sv_parser(file_path); + } + } + } + } + } + Ok(()) + } } \ No newline at end of file diff --git a/testfiles/crc_functions.sv b/testfiles/crc_functions.sv new file mode 100644 index 0000000..4b763dc --- /dev/null +++ b/testfiles/crc_functions.sv @@ -0,0 +1,51 @@ +//https://stackoverflow.com/questions/17647819/looking-for-a-crc-implementation-in-systemverilog + +module top; + +function byte calc_crc(byte unsigned cmd[]); + bit [7:0] crc, d, c; + int i; + crc = 0; + + for (i=0; i> 1) ^ CRC32POL; + end else begin + crc32_val >>= 1; + end + data >>= 1; + end + end + crc32_val ^= 32'hffffffff; //invert results + return crc32_val; +endfunction : genCRC32 + +endmodule \ No newline at end of file diff --git a/testfiles/hierarchical_name_of_type copy.sv b/testfiles/hierarchical_name_of_type copy.sv new file mode 100644 index 0000000..e7b8d44 --- /dev/null +++ b/testfiles/hierarchical_name_of_type copy.sv @@ -0,0 +1,8 @@ +module ibex_alu #( + parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone +) ( + input ibex_pkg::alu_op_e operator_i, + input logic [31:0] operand_a_i, + input logic [31:0] operand_b_i); + +endmodule \ No newline at end of file diff --git a/testfiles/mem_base_object.sv b/testfiles/mem_base_object.sv new file mode 100644 index 0000000..d0a44fb --- /dev/null +++ b/testfiles/mem_base_object.sv @@ -0,0 +1,9 @@ +`ifndef MEM_BASE_OBJECT_SV +`define MEM_BASE_OBJECT_SV +class mem_base_object; + bit [7:0] addr; + bit [7:0] data; + // Read = 0, Write = 1 + bit rd_wr; +endclass +`endif diff --git a/testfiles/operator_type.sv b/testfiles/operator_type.sv new file mode 100644 index 0000000..a8895e2 --- /dev/null +++ b/testfiles/operator_type.sv @@ -0,0 +1,5 @@ +module top(); + real a = 4.76; + real b = 0.74; + var type(a+b) c; +endmodule \ No newline at end of file diff --git a/testfiles/stm_import.sv b/testfiles/stm_import.sv new file mode 100644 index 0000000..990b336 --- /dev/null +++ b/testfiles/stm_import.sv @@ -0,0 +1,3 @@ +module chip; + import chip_pkg::*; +endmodule