437 lines
14 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use std::collections::HashMap;
use std::sync::RwLock;
use log::info;
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)]
pub struct Position {
pub line: u32,
pub character: u32
}
impl Position {
#[allow(unused)]
pub fn to_lsp_position(&self) -> LspPosition {
LspPosition { line: self.line, character: self.character }
}
}
#[derive(Debug, Clone, Serialize, PartialEq, Deserialize)]
pub struct Range {
pub start: Position,
pub end: Position
}
impl Range {
#[allow(unused)]
pub fn to_lsp_range(&self) -> LspRange {
let start_pos = self.start.to_lsp_position();
let end_pos= self.end.to_lsp_position();
LspRange::new(start_pos, end_pos)
}
/// 判断输入的 position 是否在当前 range 内
pub fn contains(&self, postion: &LspPosition) -> bool {
compare_pos(&self.start.to_lsp_position(), postion) != 1 && compare_pos(postion, &self.end.to_lsp_position()) != 1
}
/// 对所有的 line 或者 所有的 character 进行偏移操作
pub fn affine(&mut self, line_offset: i32, character_offset: i32) -> &Range {
if line_offset > 0 {
self.start.line += line_offset as u32;
self.end.line += line_offset as u32;
} else {
self.start.line -= (- line_offset) as u32;
self.end.line -= (- line_offset) as u32;
}
if character_offset > 0 {
self.start.character += character_offset as u32;
self.end.character += character_offset as u32;
} else {
self.start.character -= (- character_offset) as u32;
self.end.character -= (- character_offset) as u32;
}
self
}
}
fn compare_pos(pos1: &LspPosition, pos2: &LspPosition) -> i32 {
if pos1.line > pos2.line {
1
} else if pos1.line < pos2.line {
-1
} else if pos1.character > pos2.character {
1
} else if pos1.character < pos2.character {
-1
} else {
0
}
}
#[derive(Debug, Serialize, PartialEq, Deserialize, Clone)]
pub struct Port {
pub name: String,
#[serde(rename = "type")]
pub dir_type: String,
pub net_type: String,
pub width: String,
pub signed: String,
pub range: Range
}
#[derive(Debug, Serialize, PartialEq, Deserialize, Clone)]
pub struct Parameter {
pub name: String,
pub net_type: String,
pub init: String,
pub range: Range
}
// #[derive(Debug, Serialize)]
// pub struct InstPort {
// pub name: String,
// pub range: Range
// }
// #[derive(Debug, Serialize)]
// pub struct InstParameter {
// pub name: String,
// pub value: String,
// 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 instports: Option<Range>,
pub range: Range
}
impl Instance {
pub fn gen_dot_completion_port_range(&self) -> Range {
// TODO: 精心调制这个方法
if let Some(port_range) = &self.instports {
let mut new_port_range = port_range.clone();
info!("get port range: {new_port_range:?}, instance: {self:?}");
if let Some(param_range) = &self.instparams {
new_port_range.start.line = param_range.end.line - 1;
new_port_range.start.character = param_range.end.character;
} else {
new_port_range.start.line = self.range.end.line;
new_port_range.start.character = self.range.end.character + 1;
}
new_port_range.end.line += 1;
new_port_range.affine(-1, -1);
return new_port_range;
}
self.range.clone()
}
pub fn gen_dot_completion_param_range(&self) -> Range {
// TODO: 精心调制这个方法
if let Some(param_range) = &self.instparams {
let mut new_param_range = param_range.clone();
new_param_range.start.line = self.range.end.line;
new_param_range.start.character = self.range.end.character;
new_param_range.end.line += 1;
return new_param_range;
}
self.range.clone()
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Module {
pub name: String,
pub params: Vec<Parameter>,
pub ports: Vec<Port>,
pub instances: Vec<Instance>,
pub range: Range
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct DefineParam {
pub name: String,
pub value: String
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Define {
pub name: String,
pub replacement: String,
pub range: Range,
pub params: Vec<DefineParam>
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Include {
pub path: String,
pub range: Range
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Error {
severity: String,
message: String,
source: String,
range: Position,
running_mode: Option<String>,
running_phase: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Macro {
pub defines: Vec<Define>,
pub includes: Vec<Include>,
pub errors: Vec<Error>,
pub invalid: Vec<Range>
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct FastHdlparam {
#[serde(rename = "macro")]
pub fast_macro: Macro,
pub content: Vec<Module>
}
impl FastHdlparam {
pub fn add_define(&mut self, name: &str, replacement: &str, start_line: u32, start_character: u32,
end_line: u32, end_character: u32, params: Vec<DefineParam>) {
let define = Define {
name: name.to_string(),
replacement: replacement.to_string(),
range: Range {
start: Position { line: start_line, character: start_character },
end: Position { line: end_line, character: end_character }
},
params
};
self.fast_macro.defines.push(define);
}
pub fn new_module(&mut self, name: &str, line: u32, character: u32, end_character: u32) {
let module = Module {
name: name.to_string(),
params: Vec::new(),
ports: Vec::new(),
instances: Vec::new(),
range: Range {
start: Position {
line, character
},
end: Position {
line, character: end_character
}
}
};
self.content.push(module);
}
pub fn update_module_range(&mut self, name: &str, end_line: u32, end_character: u32) {
if let Some(matched_module) = self.content.iter_mut().find(|module| module.name == name) {
matched_module.range.end.line = end_line;
matched_module.range.end.character = end_character;
}
}
pub fn add_parameter(&mut self, name: &str, net_type: &str, init: &str,
start_line: u32, start_character: u32, end_line: u32, end_character: u32) {
if let Some(last_module) = self.content.last_mut() {
let parameter = Parameter {
name: name.to_string(),
net_type: net_type.to_string(),
init: init.to_string(),
range: Range {
start: Position {
line: start_line, character: start_character
},
end: Position {
line:end_line, character: end_character
}
}
};
last_module.params.push(parameter);
}
}
pub fn add_port(&mut self, name: &str, dir_type: &str, net_type: &str, width: &str,
start_line: u32, start_character: u32, end_line: u32, end_character: u32) {
if let Some(last_module) = self.content.last_mut() {
let port = Port {
name: name.to_string(),
dir_type: dir_type.to_string(),
net_type: net_type.to_string(),
width: width.to_string(),
signed: "unsigned".to_string(),
range: Range {
start: Position {
line: start_line, character: start_character
},
end: Position {
line:end_line, character: end_character
}
}
};
last_module.ports.push(port);
last_module.ports.dedup();
}
}
pub fn add_instance(&mut self, name: &str, inst_type: &str, 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() {
let instance = Instance {
name: name.to_string(),
inst_type: inst_type.to_string(),
instparams: if param_start_line == 0 {
None
} else {
Some(
Range {
start: Position {
line: param_start_line, character: param_start_character
},
end: Position {
line: param_end_line, character: param_end_character
}
}
)
},
instports: if port_start_line == 0 {
None
} else {
Some(
Range {
start: Position {
line: port_start_line, character: port_start_character
},
end: Position {
line: port_end_line, character: port_end_character
}
}
)
},
range: Range {
start: Position {
line, character
},
end: Position {
line, character: end_character
}
}
};
last_module.instances.push(instance);
}
}
}
pub struct HdlFile {
pub fast: FastHdlparam,
pub name_to_module: HashMap<String, Module>
}
pub struct HdlParam {
/// 路径到 HdlFile 的映射
pub path_to_hdl_file: RwLock<HashMap<String, HdlFile>>,
/// 模块名字到其所在的 HdlFile 路径的映射
pub module_name_to_path: RwLock<HashMap<String, String>>
}
impl HdlParam {
pub fn new() -> Self {
Self {
path_to_hdl_file: RwLock::new(HashMap::<String, HdlFile>::new()),
module_name_to_path: RwLock::new(HashMap::<String, String>::new())
}
}
/// 根据 path 更新 fast
pub fn update_fast(&self, path: String, fast: FastHdlparam) {
let mut fast_map = self.path_to_hdl_file.write().unwrap();
// 构建映射
let mut name_to_module = HashMap::<String, Module>::new();
let mut module_name_to_path = self.module_name_to_path.write().unwrap();
for module in &fast.content {
name_to_module.insert(module.name.to_string(), module.clone());
if !module_name_to_path.contains_key(&module.name) {
module_name_to_path.insert(module.name.to_string(), path.to_string());
}
}
let file = HdlFile { fast, name_to_module };
fast_map.insert(path, file);
}
/// 根据 module 的名字,找到 module 对象,拷贝返回
pub fn find_module_by_name(&self, name: &str) -> Option<Module> {
let module_name_to_path = self.module_name_to_path.read().unwrap();
if let Some(path) = module_name_to_path.get(name) {
let fast_map = self.path_to_hdl_file.read().unwrap();
if let Some(hdl_file) = fast_map.get(path) {
if let Some(module) = hdl_file.name_to_module.get(name) {
return Some(module.clone());
}
}
}
None
}
/// 输入 module 名字,找到 module 定义的文件的路径
pub fn find_module_definition_path(&self, module_name: &str) -> Option<String> {
let module_name_to_path = self.module_name_to_path.read().unwrap();
if let Some(path) = module_name_to_path.get(module_name) {
return Some(path.to_string());
}
None
}
/// 遍历 path_string 下的所有 instance并根据条件返回
pub fn walk_instantiation(&self, path_string: &str, condition: impl Fn(&Module, &Instance) -> bool) -> Option<Instance> {
let path_to_hdl_file = self.path_to_hdl_file.read().unwrap();
if let Some(hdl_file) = path_to_hdl_file.get(path_string) {
for def_module in &hdl_file.fast.content {
for inst in &def_module.instances {
if condition(def_module, inst) {
return Some(inst.clone());
}
}
}
}
None
}
/// 跟随一个路径进行删除
pub fn delete_file(&self, path_string: &str) {
let mut path_to_hdl_file = self.path_to_hdl_file.write().unwrap();
if let Some(hdl_file) = path_to_hdl_file.get(path_string) {
// 根据 hdl_file.fast.content 删除 self.module_name_to_path
let mut module_name_to_path = self.module_name_to_path.write().unwrap();
for module_info in &hdl_file.fast.content {
module_name_to_path.remove(&module_info.name);
}
}
path_to_hdl_file.remove(path_string);
// TODO: 引入前端的 solve unhandled instance 机制
}
}