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, pub instports: Option, 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, pub ports: Vec, pub instances: Vec, 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 } #[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, running_phase: Option, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Macro { pub defines: Vec, pub includes: Vec, pub errors: Vec, pub invalid: Vec } #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "camelCase")] pub struct FastHdlparam { #[serde(rename = "macro")] pub fast_macro: Macro, pub content: Vec } 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) { 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); last_module.params.dedup(); } } 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 } pub struct HdlParam { /// 路径到 HdlFile 的映射 pub path_to_hdl_file: RwLock>, /// 模块名字到其所在的 HdlFile 路径的映射 pub module_name_to_path: RwLock> } impl HdlParam { pub fn new() -> Self { Self { path_to_hdl_file: RwLock::new(HashMap::::new()), module_name_to_path: RwLock::new(HashMap::::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::::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 { 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 { 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 { 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 机制 } }