完成前后端对接 | 完成 sv_parser 单元测试
This commit is contained in:
parent
ebc6e79cf0
commit
759c05f048
@ -511,3 +511,47 @@ fn get_column_by_offset(content: &[String], offset: usize) -> usize {
|
||||
|
||||
1 // if offset over the file lentgh,return 1
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use super::sv_parser;
|
||||
|
||||
const testfiles_dir: &str = "testfiles";
|
||||
|
||||
macro_rules! unwrap_result {
|
||||
($expr:expr) => {
|
||||
match $expr {
|
||||
Ok(e) => e,
|
||||
Err(_) => return
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! unwrap_option {
|
||||
($expr:expr) => {
|
||||
match $expr {
|
||||
Some(e) => e,
|
||||
None => return
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sv_parse() {
|
||||
let entries = unwrap_result!(fs::read_dir(testfiles_dir));
|
||||
for entry in entries {
|
||||
let entry = unwrap_result!(entry);
|
||||
let file_path = entry.path();
|
||||
if file_path.is_file() {
|
||||
let extension = unwrap_option!(file_path.extension());
|
||||
let file_path = unwrap_option!(file_path.to_str());
|
||||
if extension == "v" || extension == "sv" {
|
||||
let _ = sv_parser(file_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,26 +1,20 @@
|
||||
use std::future;
|
||||
use std::{fs, future};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use log::info;
|
||||
use ropey::Rope;
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tower_lsp::jsonrpc::Result;
|
||||
use tower_lsp::lsp_types::*;
|
||||
use tower_lsp::{lsp_types::*, LanguageServer};
|
||||
|
||||
use crate::core::fast_hdlparam::FastHdlparam;
|
||||
use crate::core::sv_parser::make_fast_from_syntaxtree;
|
||||
|
||||
use crate::definition::get_language_id_by_uri;
|
||||
use crate::server::Backend;
|
||||
use crate::sources::parse;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct CustomRequestParams {
|
||||
// 定义你需要的参数
|
||||
pub data: Value,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CustomRequest;
|
||||
@ -37,24 +31,77 @@ pub fn custom_request() -> Result<i32> {
|
||||
Ok(123)
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct CustomParamRequestParams {
|
||||
param: String,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DoFastApi;
|
||||
pub struct CustomParamRequest;
|
||||
|
||||
impl <'a>tower_lsp::jsonrpc::Method<&'a Arc<Backend>, (TextDocumentItem, ), Result<FastHdlparam>> for DoFastApi {
|
||||
type Future = future::Ready<Result<FastHdlparam>>;
|
||||
impl <'a>tower_lsp::jsonrpc::Method<&'a Arc<Backend>, (CustomParamRequestParams, ), Result<i32>> for CustomParamRequest {
|
||||
type Future = future::Ready<Result<i32>>;
|
||||
|
||||
fn invoke(&self, _server: &'a Arc<Backend>, _params: (TextDocumentItem, )) -> Self::Future {
|
||||
let doc = _params.0;
|
||||
future::ready(do_fast(doc))
|
||||
fn invoke(&self, _server: &'a Arc<Backend>, _params: (CustomParamRequestParams, )) -> Self::Future {
|
||||
future::ready(custom_param_request(_params.0.param))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn custom_param_request(param: String) -> Result<i32> {
|
||||
info!("receive param: {:?}", param);
|
||||
Ok(123)
|
||||
}
|
||||
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct DoFastApiRequestParams {
|
||||
path: String,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DoFastApi;
|
||||
|
||||
impl <'a>tower_lsp::jsonrpc::Method<&'a Arc<Backend>, (DoFastApiRequestParams, ), Result<FastHdlparam>> for DoFastApi {
|
||||
type Future = future::Ready<Result<FastHdlparam>>;
|
||||
|
||||
fn invoke(&self, _server: &'a Arc<Backend>, _params: (DoFastApiRequestParams, )) -> Self::Future {
|
||||
let request_param = _params.0;
|
||||
let path = request_param.path;
|
||||
future::ready(do_fast(path))
|
||||
}
|
||||
}
|
||||
|
||||
fn make_textdocumenitem_from_path(path_buf: &PathBuf) -> Option<TextDocumentItem> {
|
||||
if let Ok(url) = Url::from_file_path(path_buf) {
|
||||
if let Ok(text) = fs::read_to_string(path_buf) {
|
||||
let language_id = get_language_id_by_uri(&url);
|
||||
return Some(TextDocumentItem::new(url, language_id, -1, text));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// 前端交互接口: do_fast,输入文件路径,计算出对应的 fast 结构
|
||||
pub fn do_fast(doc: TextDocumentItem) -> Result<FastHdlparam> {
|
||||
info!("lsp get doc: {:?}", doc);
|
||||
pub fn do_fast(path: String) -> Result<FastHdlparam> {
|
||||
info!("parse hdl path: {:?}", path);
|
||||
let path_buf = PathBuf::from(&path);
|
||||
|
||||
let doc = match make_textdocumenitem_from_path(&path_buf) {
|
||||
Some(doc) => doc,
|
||||
None => {
|
||||
let api_error = tower_lsp::jsonrpc::Error {
|
||||
code: tower_lsp::jsonrpc::ErrorCode::InvalidParams,
|
||||
message: std::borrow::Cow::Owned(format!("cannot make doc from path : {path}")),
|
||||
data: None
|
||||
};
|
||||
|
||||
return Err(api_error);
|
||||
}
|
||||
};
|
||||
|
||||
let uri = doc.uri;
|
||||
let text = Rope::from_str(&doc.text);
|
||||
let text = Rope::from(doc.text);
|
||||
// fast 解析不需要 include
|
||||
let includes: Vec<PathBuf> = Vec::new();
|
||||
|
||||
|
@ -147,7 +147,7 @@ fn get_definition_token(line: RopeSlice, pos: Position) -> String {
|
||||
}
|
||||
|
||||
|
||||
fn get_language_id_by_uri(uri: &Url) -> String {
|
||||
pub fn get_language_id_by_uri(uri: &Url) -> String {
|
||||
let path = uri.path();
|
||||
let ext_name = std::path::Path::new(path)
|
||||
.extension()
|
||||
|
@ -224,19 +224,6 @@ pub trait Scope: std::fmt::Debug + Definition + Sync + Send {
|
||||
}
|
||||
|
||||
|
||||
/// 计算并得到有关 macro 的定义,保证 token 是以 ` 开头的
|
||||
fn get_macro_definition(&self, token: &str, byte_idx: usize, url: &Url) -> Option<GenericDec> {
|
||||
let mut definition: Option<GenericDec> = None;
|
||||
|
||||
if !token.starts_with("`") {
|
||||
return definition;
|
||||
}
|
||||
|
||||
// 计算 macro 的位置,需要 global scope 下的所有 defs 加上 current scope 上的位置
|
||||
|
||||
definition
|
||||
}
|
||||
|
||||
/// returns all symbols in a document
|
||||
fn document_symbols(&self, uri: &Url, doc: &Rope) -> Vec<DocumentSymbol> {
|
||||
let mut symbols: Vec<DocumentSymbol> = Vec::new();
|
||||
|
@ -1,6 +1,7 @@
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
use custom_request::CustomRequest;
|
||||
use custom_request::{ CustomParamRequest, CustomRequest, DoFastApi };
|
||||
|
||||
use log::info;
|
||||
use std::sync::Arc;
|
||||
use structopt::StructOpt;
|
||||
@ -14,6 +15,7 @@ mod format;
|
||||
mod server;
|
||||
mod sources;
|
||||
mod custom_request;
|
||||
|
||||
#[cfg(test)]
|
||||
mod support;
|
||||
use server::Backend;
|
||||
@ -38,6 +40,8 @@ async fn main() {
|
||||
|
||||
let (service, socket) = LspService::build(|client| Arc::new(Backend::new(client, log_handle)))
|
||||
.custom_method("custom/request", CustomRequest)
|
||||
.custom_method("custom/paramRequest", CustomParamRequest)
|
||||
.custom_method("api/fast", DoFastApi)
|
||||
.finish();
|
||||
|
||||
Server::new(stdin, stdout, socket)
|
||||
|
@ -2,6 +2,7 @@ use crate::definition::def_types::*;
|
||||
use crate::definition::get_scopes;
|
||||
use crate::diagnostics::{get_diagnostics, is_hidden};
|
||||
use crate::server::LSPServer;
|
||||
use log::info;
|
||||
use log::{debug, error};
|
||||
use pathdiff::diff_paths;
|
||||
use ropey::{Rope, RopeSlice};
|
||||
@ -170,6 +171,7 @@ impl Sources {
|
||||
}
|
||||
// find and add all source/header files recursively from configured include and source directories
|
||||
let src_paths = find_src_paths(&paths);
|
||||
|
||||
for path in src_paths {
|
||||
if let Ok(url) = Url::from_file_path(&path) {
|
||||
if let Ok(text) = fs::read_to_string(&path) {
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 4960ea3fb7c848462ce6e78dbae454ffc775803f
|
||||
Subproject commit af11f5ff1ef091562d2b17cdf4de3614aedf2286
|
19
testfiles/child_1.v
Normal file
19
testfiles/child_1.v
Normal file
@ -0,0 +1,19 @@
|
||||
module dependence_1 (
|
||||
// this is a test
|
||||
input a, b, c,
|
||||
// a test
|
||||
output Result // balabalabala for result
|
||||
);
|
||||
|
||||
// a & b | ((b & c) & (b | c))
|
||||
// &=*, |=+ AB + BC(B+C)
|
||||
// Distribute AB + BBC + BCC
|
||||
// Simplify AA = A AB + BC + BC
|
||||
// Simplify A + A = A AB + BC
|
||||
// Factor B(A+C)
|
||||
|
||||
assign Result = a & (b | c);
|
||||
assign a = 11;
|
||||
|
||||
|
||||
endmodule
|
9
testfiles/child_2.v
Normal file
9
testfiles/child_2.v
Normal file
@ -0,0 +1,9 @@
|
||||
module dependence_2 (
|
||||
input a, b, c,
|
||||
output Q
|
||||
);
|
||||
|
||||
assign Q = a & b | ((b & c) & (b | c));
|
||||
|
||||
|
||||
endmodule
|
28
testfiles/head_1.v
Normal file
28
testfiles/head_1.v
Normal file
@ -0,0 +1,28 @@
|
||||
`define cow 34
|
||||
|
||||
module dependence_1 (
|
||||
input port_a, port_b, port_c,
|
||||
output out_q
|
||||
);
|
||||
// a & b | ((b & c) & (b | c))
|
||||
// &=*, |=+ AB + BC(B+C)
|
||||
// Distribute AB + BBC + BCC
|
||||
// Simplify AA = A AB + BC + BC
|
||||
// Simplify A + A = A AB + BC
|
||||
// Factor B(A+C)
|
||||
|
||||
assign out_q = port_b & (port_a | port_c);
|
||||
endmodule
|
||||
|
||||
|
||||
module test_1 (
|
||||
input port_a, port_b,
|
||||
output Q
|
||||
);
|
||||
assign Q = port_b & port_a;
|
||||
endmodule
|
||||
|
||||
module helloTest();
|
||||
assign a = 123;
|
||||
|
||||
endmodule //helloTest
|
11
testfiles/hello.v
Normal file
11
testfiles/hello.v
Normal file
@ -0,0 +1,11 @@
|
||||
`define awda adwwa
|
||||
|
||||
module hello;
|
||||
|
||||
initial begin
|
||||
$display("hello world");
|
||||
$finish;
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
79
testfiles/parent.v
Normal file
79
testfiles/parent.v
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* EN: A simple demo to test search order of dependence
|
||||
* current file -> macro include -> whole project
|
||||
* expect dependence_1 from child_1.v (macro include)
|
||||
* expect dependence_2 from child_2.v (whole project)
|
||||
* cannot find dependence_3 `main
|
||||
*/
|
||||
|
||||
`include "child_1.v"
|
||||
`include "child_2.v"
|
||||
`define main out
|
||||
`define simple ss
|
||||
|
||||
|
||||
module Main (
|
||||
// Main input
|
||||
input a, b, c,
|
||||
// Main output
|
||||
output Qus, Qs, `main
|
||||
);
|
||||
|
||||
|
||||
initial begin
|
||||
$display("hello world");
|
||||
end
|
||||
|
||||
|
||||
dependence_1 u_dependence_1_1(
|
||||
.a(a),
|
||||
.b(b),
|
||||
.c(c),
|
||||
.Result(Qus)
|
||||
);
|
||||
|
||||
dependence_1 u_dependence_1_2(
|
||||
.a(a),
|
||||
.b(b),
|
||||
.c(c),
|
||||
.Result(Qus)
|
||||
);
|
||||
|
||||
dependence_3 u_dependence_3(
|
||||
.a(a),
|
||||
.b(b),
|
||||
.c(c),
|
||||
.Q(Qs)
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
/* @wavedrom this is wavedrom demo1
|
||||
{
|
||||
signal : [
|
||||
{ name: "clk", wave: "p......" },
|
||||
{ name: "bus", wave: "x.34.5x", data: "head body tail" },
|
||||
{ name: "wire", wave: "0.1..0." }
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/* @wavedrom this is wavedrom demo2
|
||||
{
|
||||
signal: [
|
||||
{ name: "pclk", wave: "p......." },
|
||||
{ name: "Pclk", wave: "P......." },
|
||||
{ name: "nclk", wave: "n......." },
|
||||
{ name: "Nclk", wave: "N......." },
|
||||
{},
|
||||
{ name: "clk0", wave: "phnlPHNL" },
|
||||
{ name: "clk1", wave: "xhlhLHl." },
|
||||
{ name: "clk2", wave: "hpHplnLn" },
|
||||
{ name: "clk3", wave: "nhNhplPl" },
|
||||
{ name: "clk4", wave: "xlh.L.Hx" },
|
||||
]}
|
||||
*/
|
||||
|
||||
|
47
testfiles/test copy.v
Normal file
47
testfiles/test copy.v
Normal file
@ -0,0 +1,47 @@
|
||||
`timescale 1ns / 1ps
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Company:
|
||||
// Engineer:
|
||||
//
|
||||
// Create Date: 2024 年 05 月 15 日 星期三
|
||||
// Design Name: test
|
||||
// Module Name: test.v
|
||||
// Project Name:
|
||||
// Target Devices:
|
||||
// Tool Versions:
|
||||
// Description:
|
||||
//
|
||||
// Dependencies:
|
||||
//
|
||||
// Revision:
|
||||
// Revision 0.01 - File Created
|
||||
// Additional Comments:
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
module TOP
|
||||
(
|
||||
|
||||
);
|
||||
//============================================================================
|
||||
//Input and output declaration.
|
||||
//============================================================================
|
||||
output spi_adc_csn;
|
||||
output spi_dac_csn;
|
||||
// output spi_iop_csn;
|
||||
input spi_iop_csn;
|
||||
// output spi_mul_sdt;
|
||||
output spi_mul_sdi;
|
||||
input spi_mul_sdo;
|
||||
//============================================================================
|
||||
//Wire and reg declaration.
|
||||
//============================================================================
|
||||
|
||||
//============================================================================
|
||||
//Wire and reg in this module.
|
||||
//============================================================================
|
||||
|
||||
//============================================================================
|
||||
//logic.
|
||||
//============================================================================
|
||||
|
||||
|
||||
endmodule
|
82
testfiles/test.sv
Normal file
82
testfiles/test.sv
Normal file
@ -0,0 +1,82 @@
|
||||
// Test Scenario to validate correct translation
|
||||
// Refer: https://github.com/Nic30/hdlConvertor/issues/173
|
||||
`define ADD 64
|
||||
module dummy #(
|
||||
parameter reg ADDR_WIDTH = 4,
|
||||
parameter interger ADDER_OOO = 25,
|
||||
parameter [63:0] ADDER_OOO_1 = (1 << ADDER_OOO) + 1,
|
||||
parameter logic [63:0] ADD_OTHER = `ADD'hff1
|
||||
) (c, a, b, d, f);
|
||||
output reg c;
|
||||
output logic [61:0] f;
|
||||
input [ADDR_WIDTH_ANSI - 1:0] d;
|
||||
input a, b;
|
||||
and a1(c, a, b);
|
||||
endmodule
|
||||
|
||||
module d2(y, a);
|
||||
output [3:0] y;
|
||||
input reg [2:0] a;
|
||||
|
||||
not n1 (y, a);
|
||||
endmodule
|
||||
|
||||
module example (a, b, c, d);
|
||||
input a, b, c;
|
||||
output d;
|
||||
|
||||
wire tmp;
|
||||
wire tmp2;
|
||||
wire tmp3;
|
||||
and a1 (tmp, a, b);
|
||||
dummy du(
|
||||
.c(tmp2), .a(b), .b(c));
|
||||
dummy #(
|
||||
.ADDR_WIDTH(8)
|
||||
) duu(tmp3, b, c);
|
||||
or o1 (d, tmp, tmp2);
|
||||
endmodule
|
||||
|
||||
// test dummy comment
|
||||
module dummy_ansi #(
|
||||
parameter ADDR_WIDTH = 4,
|
||||
parameter interger ADDER_OOO = 25,
|
||||
parameter [63:0] ADDER_OOO_1 = (1 << ADDER_OOO) + 1,
|
||||
parameter logic [63:0] ADD_OTHER = `ADD'hff1
|
||||
) (
|
||||
output [ADDR_WIDTH_ANSI - 1:0] c,
|
||||
input [ADDR_WIDTH_ANSI-1: 0] a,
|
||||
input [ADDR_WIDTH_ANSI-1:0] b
|
||||
);
|
||||
and a1(c, a, b);
|
||||
assign c = a & b;
|
||||
endmodule
|
||||
|
||||
module d2_ansi(
|
||||
output [3:0] y,
|
||||
input reg [2:0] a
|
||||
);
|
||||
|
||||
not n1 (y, a);
|
||||
endmodule
|
||||
|
||||
module example_ansi (
|
||||
input a, b, c,
|
||||
output d
|
||||
);
|
||||
|
||||
wire tmp;
|
||||
wire tmp2;
|
||||
wire tmp3;
|
||||
and a1 (tmp, a, b);
|
||||
dummy_ansi du_ansi(
|
||||
.c(tmp2), .b(b), .a(c));
|
||||
dummy_ansi #(
|
||||
.ADDR_WIDTH_ANSI(8)
|
||||
) duu_ansi(
|
||||
tmp3,
|
||||
b,
|
||||
c
|
||||
);
|
||||
or o1 (d, tmp, tmp2);
|
||||
endmodule
|
16
testfiles/test.v
Normal file
16
testfiles/test.v
Normal file
@ -0,0 +1,16 @@
|
||||
module testModule();
|
||||
reg clk, rst;
|
||||
reg port_1;
|
||||
|
||||
|
||||
always @(posedge clk or negedge rst) begin
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
always @(posedge clk or negedge rst) begin
|
||||
|
||||
end
|
||||
|
||||
endmodule //testModule
|
42
testfiles/test.vhd
Normal file
42
testfiles/test.vhd
Normal file
@ -0,0 +1,42 @@
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
entity top_level is
|
||||
generic (
|
||||
WIDTH : integer := 4
|
||||
);
|
||||
port (
|
||||
A : in STD_LOGIC_VECTOR(WIDTH-1 downto 0);
|
||||
B : in STD_LOGIC_VECTOR(WIDTH-1 downto 0);
|
||||
Cin : in STD_LOGIC;
|
||||
Sum : out STD_LOGIC_VECTOR(WIDTH-1 downto 0);
|
||||
Cout : out STD_LOGIC
|
||||
);
|
||||
end top_level;
|
||||
|
||||
architecture Behavioral of top_level is
|
||||
component adder is
|
||||
generic (
|
||||
WIDTH : integer := 4
|
||||
);
|
||||
port (
|
||||
A : in STD_LOGIC_VECTOR(WIDTH-1 downto 0);
|
||||
B : in STD_LOGIC_VECTOR(WIDTH-1 downto 0);
|
||||
Cin : in STD_LOGIC;
|
||||
Sum : out STD_LOGIC_VECTOR(WIDTH-1 downto 0);
|
||||
Cout : out STD_LOGIC
|
||||
);
|
||||
end component;
|
||||
begin
|
||||
adder_instance: adder
|
||||
generic map (
|
||||
WIDTH => X"100c00"
|
||||
);
|
||||
port map (
|
||||
A => A,
|
||||
B => B,
|
||||
Cin => Cin,
|
||||
Sum => Sum,
|
||||
Cout => Cout
|
||||
);
|
||||
end Behavioral;
|
Loading…
x
Reference in New Issue
Block a user