= {
+ 'left': '',
+ 'right': '',
+ 'left-right': '',
+ 'left-dot': '',
+ 'right-dot': ''
+};
+
+function getArrowSvgString(name: 'left' | 'right' | 'left-right' | 'left-dot' | 'right-dot'): string {
+ let svgString = arrowSvgCache[name];
+ if (svgString.length === 0) {
+ const themeType = getThemeColorKind();
+ const iconFile = name + '-arrow.svg';
+ const svgDir = hdlPath.join(opeParam.extensionPath, 'images', 'svg');
+ const svgPath = hdlPath.join(svgDir, themeType, iconFile);
+ const readSvgString = hdlFile.readFile(svgPath);
+ if (readSvgString) {
+ svgString = readSvgString;
+ arrowSvgCache[name] = readSvgString;
+ }
+ }
+ return svgString;
+}
+
+function makeDiagram(params: HdlModuleParam[], ports: HdlModulePort[]): string {
+ // make params block
+ const diagramParamWrapper = makeDiagramParamWrapper(params);
+
+ // make ports block
+ const diagramPortWrapper = makeDiagramPortWrapper(ports);
+
+ const diagram = `${diagramParamWrapper}${diagramPortWrapper}
`;
+ return diagram;
+}
+
+
+function makeDiagramParamWrapper(params: HdlModuleParam[]): string {
+ if (params.length === 0) {
+ return '';
+ }
+ let diagramParams = '';
+ for (const param of params) {
+ let diagramParam = '' + param.name;
+ if (param.init && param.init.length > 0) {
+ diagramParam += `(${param.init})`;
+ }
+ diagramParam += '
';
+ diagramParams += diagramParam;
+ }
+ const diagramParamWrapper = ``;
+ return diagramParamWrapper;
+}
+
+
+function makeDiagramPortWrapper(ports: HdlModulePort[]): string {
+ if (ports.length === 0) {
+ return '';
+ }
+
+ const leftPorts = ports.filter(port => port.type === HdlModulePortType.Input || port.type === HdlModulePortType.Inout);
+ const rightPorts = ports.filter(port => port.type === HdlModulePortType.Output);
+
+ const leftDirection = makeLeftDirection(leftPorts);
+ const diagramPorts = makeDiagramPorts(leftPorts, rightPorts);
+ const rightDirection = makeRightDirection(rightPorts);
+
+ const diagramPortWrapper = `${leftDirection}${diagramPorts}${rightDirection}
`;
+ return diagramPortWrapper;
+}
+
+function isValidWidth(portWidth: string | undefined): boolean {
+ if (portWidth === undefined || portWidth === '' || portWidth === '1') {
+ return false;
+ }
+ return true;
+}
+
+function makePortCaption(port: HdlModulePort, direction: 'left' | 'right'): string {
+ if (!isValidWidth(port.width)) {
+ return '';
+ }
+ return `${port.width}
`;
+}
+
+function makePortArrow(port: HdlModulePort, direction: 'left' | 'right'): string {
+ if (port.type === HdlModulePortType.Inout) {
+ return getArrowSvgString('left-right');
+ }
+ if (direction === 'left') {
+ if (port.type === HdlModulePortType.Input) {
+ if (isValidWidth(port.width)) {
+ return getArrowSvgString('right-dot');
+ } else {
+ return getArrowSvgString('right');
+ }
+ } else if (port.type === HdlModulePortType.Output) {
+ if (isValidWidth(port.width)) {
+ return getArrowSvgString('left-dot');
+ } else {
+ return getArrowSvgString('left');
+ }
+ }
+ } else if (direction === 'right') {
+ if (port.type === HdlModulePortType.Input) {
+ if (isValidWidth(port.width)) {
+ return getArrowSvgString('left-dot');
+ } else {
+ return getArrowSvgString('left');
+ }
+ } else if (port.type === HdlModulePortType.Output) {
+ if (isValidWidth(port.width)) {
+ return getArrowSvgString('right-dot');
+ } else {
+ return getArrowSvgString('right');
+ }
+ }
+ }
+ return '';
+}
+
+function makeLeftDirection(leftPorts: HdlModulePort[]): string {
+ let leftDirection = '';
+ for (const port of leftPorts) {
+ const portCaption = makePortCaption(port, 'left');
+ const portArrow = makePortArrow(port, 'left');
+ const arrow = `${portCaption}${portArrow}
`;
+ leftDirection += arrow;
+ }
+ return `${leftDirection}
`;
+}
+
+function makePortName(port: HdlModulePort): string {
+ let portClass = '';
+ if (port.type === HdlModulePortType.Input) {
+ portClass = 'i-port-name';
+ } else if (port.type === HdlModulePortType.Output) {
+ portClass = 'o-port-name';
+ } else {
+ portClass = 'io-port-name';
+ }
+ return `${port.name}
`;
+}
+
+function makeDiagramPorts(leftPorts: HdlModulePort[], rightPorts: HdlModulePort[]): string {
+ let leftIndex = 0;
+ let rightIndex = 0;
+ let diagramePorts = '';
+ while (leftIndex < leftPorts.length && rightIndex < rightPorts.length) {
+ const leftPortName = makePortName(leftPorts[leftIndex ++]);
+ const rightPortName = makePortName(rightPorts[rightIndex ++]);
+ const diagramPortItem = `${leftPortName}${rightPortName}
`;
+ diagramePorts += diagramPortItem;
+ }
+ while (leftIndex < leftPorts.length) {
+ const leftPortName = makePortName(leftPorts[leftIndex ++]);
+ const diagramPortItem = ``;
+ diagramePorts += diagramPortItem;
+ }
+ while (rightIndex < rightPorts.length) {
+ const rightPortName = makePortName(leftPorts[leftIndex ++]);
+ const diagramPortItem = ``;
+ diagramePorts += diagramPortItem;
+ }
+ return `${diagramePorts}
`;
+}
+
+function makeRightDirection(rightPorts: HdlModulePort[]): string {
+ let rightDirection = '';
+ for (const port of rightPorts) {
+ const portCaption = makePortCaption(port, 'right');
+ let portArrow = makePortArrow(port, 'right');
+ portArrow = portArrow.replace('-0.5 -0.5 125 45', '20 -0.5 125 45');
+ console.log(portArrow);
+
+ const arrow = `${portCaption}${portArrow}
`;
+ rightDirection += arrow;
+ }
+ return `${rightDirection}
`;
+}
+
+export {
+ makeDiagram
+};
\ No newline at end of file
diff --git a/src/function/hdlDoc/html.ts b/src/function/hdlDoc/html.ts
index 7b1e0a1..58ac321 100644
--- a/src/function/hdlDoc/html.ts
+++ b/src/function/hdlDoc/html.ts
@@ -110,6 +110,7 @@ async function makeShowHTML(usage: string): Promise {
// start to render the real html
let body = '';
+
for (const r of renderList) {
const renderResult = r.render();
if (renderResult) {
@@ -150,6 +151,7 @@ async function showDocWebview() {
webview.iconPath = hdlIcon.getIconConfig('documentation');
webview.webview.html = await htmlPromise;
+
}
diff --git a/src/function/hdlDoc/markdown.ts b/src/function/hdlDoc/markdown.ts
index df5ac17..0f6c484 100644
--- a/src/function/hdlDoc/markdown.ts
+++ b/src/function/hdlDoc/markdown.ts
@@ -1,5 +1,6 @@
import * as vscode from 'vscode';
import * as fs from 'fs';
+import * as fspath from 'path';
import { AbsPath, opeParam, MainOutput, ReportType } from '../../global';
import { hdlParam, HdlModule } from '../../hdlParser/core';
@@ -10,6 +11,8 @@ import { MarkdownString, RenderString, RenderType,
import { hdlPath, hdlFile } from '../../hdlFs';
import { getSymbolComments } from '../lsp/util/feature';
+import { HdlLangID } from '../../global/enum';
+import { makeDiagram } from './diagram';
function makeSVGElementByLink(link: AbsPath, caption?: string) {
@@ -22,6 +25,26 @@ function makeSVGElementByLink(link: AbsPath, caption?: string) {
return '
' + mainHtml + '
\n';
}
+function selectFieldValue(obj: any, subName: string, ws: string, name: string): string {
+ if (subName === 'empty') {
+ return '——';
+ }
+ let value = obj[subName];
+ if (subName === 'instModPath' && value) {
+ value = value.replace(ws, '');
+ }
+
+ if (value && value.trim().length === 0) {
+ return '——';
+ }
+
+ // TODO : 1 not known
+ if (name === 'ports' && value === '1') {
+ return '——';
+ }
+ return value;
+}
+
function makeTableFromObjArray(md: MarkdownString, array: any[], name: string, fieldNames: string[], displayNames: string[]) {
const ws = hdlPath.toSlash(opeParam.workspacePath) + '/';
@@ -32,19 +55,7 @@ function makeTableFromObjArray(md: MarkdownString, array: any[], name: string, f
for (const obj of array) {
const data = [];
for (const subName of fieldNames) {
- let value = obj[subName];
- if (subName === 'instModPath' && value) {
- value = value.replace(ws, '');
- }
-
- if (value && value.trim().length === 0) {
- value = ' ';
- }
-
- // TODO : 1 not known
- if (name === 'ports' && value === 'Unknown') {
- value = '1';
- }
+ const value = selectFieldValue(obj, subName, ws, name);
data.push(value);
}
rows.push(data);
@@ -63,7 +74,7 @@ function makeTableFromObjArray(md: MarkdownString, array: any[], name: string, f
* @param {string} path
* @param {Array} ports
*/
-async function patchComment(path: AbsPath, ports: (HdlModulePort | HdlModuleParam)[]) {
+async function patchComment(path: AbsPath, ports: (HdlModulePort | HdlModuleParam)[]) {
if (!ports || !ports.length) {
return;
}
@@ -71,7 +82,7 @@ async function patchComment(path: AbsPath, ports: (HdlModulePort | HdlModulePara
const comments = await getSymbolComments(path, ranges);
for (let i = 0; i < ports.length; ++ i) {
let inlineComment = comments[i].replace(/\n/, ' ');
- if (inlineComment.startsWith('//')) {
+ if (inlineComment.startsWith('//') || inlineComment.startsWith('--')) {
inlineComment = inlineComment.substring(2);
}
ports[i].desc = inlineComment;
@@ -100,33 +111,46 @@ async function getDocsFromModule(module: HdlModule): Promise {
}
const md = new MarkdownString(module.range.start.line);
+
+ if (module.languageId === HdlLangID.Vhdl) {
+ md.addTitle('Entity: `' + moduleName + '`', 1);
+ } else if (module.languageId === HdlLangID.Verilog) {
+ md.addTitle('Module: `' + moduleName + '`', 1);
+ } else if (module.languageId === HdlLangID.SystemVerilog) {
+ md.addTitle('Module: `' + moduleName + '`', 1);
+ }
+
// add module name
- md.addTitle(moduleName, 1);
md.addTitle('Basic Info', 2);
+
const infos = [
+ `**File:** ${fspath.basename(module.file.path)}`,
`${portNum} params, ${paramNum} ports`,
'top module ' + topModuleDesc
];
md.addUnorderedList(infos);
md.addEnter();
+ const diagram = makeDiagram(module.params, module.ports);
+ md.addText(diagram);
+
// wait param and port patch
await paramPP;
await portPP;
// param section
- md.addTitle('params', 2);
+ md.addTitle('Params', 2);
makeTableFromObjArray(md, module.params, 'params',
- ['name', 'init', 'desc'],
- ['name', 'init', 'description']);
+ ['name', 'init', 'empty', 'desc'],
+ ['Param Name', 'Init', 'Range', 'Description']);
md.addEnter();
// port section
- md.addTitle('ports', 2);
+ md.addTitle('Ports', 2);
makeTableFromObjArray(md, module.ports, 'ports',
['name', 'type', 'width', 'desc'],
- ['name', 'type', 'width', 'description']);
+ ['Port Name', 'Direction', 'Range', 'Description']);
md.addEnter();
diff --git a/src/function/lsp/completion/vlog.ts b/src/function/lsp/completion/vlog.ts
index e052f0d..981666f 100644
--- a/src/function/lsp/completion/vlog.ts
+++ b/src/function/lsp/completion/vlog.ts
@@ -195,6 +195,7 @@ class VlogCompletionProvider implements vscode.CompletionItemProvider {
completions.push(...this.makeCompilerKeywordItems(document, position));
completions.push(...this.makeSystemKeywordItems(document, position));
+
const symbolResult = await hdlSymbolStorage.getSymbol(filePath);
if (!symbolResult) {
return completions;
@@ -215,6 +216,7 @@ class VlogCompletionProvider implements vscode.CompletionItemProvider {
return completions;
}
+
// 3. provide modules
const suggestModulesPromise = this.provideModules(document, position, filePath, symbolResult.macro.includes);
diff --git a/src/function/lsp/util/feature.ts b/src/function/lsp/util/feature.ts
index 8fd5eb1..8c70c53 100644
--- a/src/function/lsp/util/feature.ts
+++ b/src/function/lsp/util/feature.ts
@@ -131,17 +131,17 @@ async function getFullSymbolInfo(document: vscode.TextDocument, range: Range, no
let content = '';
let is_b_comment = false;
- let line = range.start.line + 1;
- const firstLine = range.start.line - 1;
- console.log('enter getFullSymbolInfo');
-
+ let line = range.start.line;
+
+ // vscode 的行编号从 0 开始算
+ const firstLine = range.start.line - 1;
+
while (line) {
line --;
content = document.lineAt(line).text;
-
+
// 首先判断该行是否是空白
- let isblank = content.match(nonblank);
- if (!isblank) {
+ if (content.trim().length === 0) {
continue;
}
@@ -150,7 +150,7 @@ async function getFullSymbolInfo(document: vscode.TextDocument, range: Range, no
if (b_comment_begin_index === -1) {
comments.push(content + '\n');
continue;
- }
+ }
comments.push(content.slice(b_comment_begin_index, content.length) + '\n');
is_b_comment = false;
content = content.slice(0, b_comment_begin_index);
@@ -161,24 +161,22 @@ async function getFullSymbolInfo(document: vscode.TextDocument, range: Range, no
}
// 判断该行是否存在行注释
- let l_comment_index = content.indexOf(l_comment_symbol);
-
- if (l_comment_index >= 0) {
- let before_l_comment = content.slice(0, l_comment_index);
- if (before_l_comment.match(nonblank)) {
- // TODO : check again if bug takes place
- comments.push(content.slice(l_comment_index, content.length) + '\n');
- break;
- }
-
- // 否则该行全为该定义的注释
- comments.push(content + '\n');
- continue;
- }
-
+ let l_comment_index = content.indexOf(l_comment_symbol);
// 判断该行是否存在块注释
let b_comment_end_index = content.indexOf('*/');
- if (b_comment_end_index >= 0) {
+
+ if (l_comment_index >= 0) {
+ let before_l_comment = content.slice(0, l_comment_index);
+ // 判断当前的行注释的注释前面是不是还有字符串
+ if (!before_l_comment.match(nonblank) || line === firstLine) {
+ const l_comment = content.slice(l_comment_index, content.length) + '\n';
+ comments.push(l_comment);
+ break;
+ }
+ // 否则该行全为该定义的注释
+ comments.push(content + '\n');
+
+ } else if (b_comment_end_index >= 0) {
b_comment_end_index += 2;
let behind_b_comment = content.slice(b_comment_end_index, content.length);
behind_b_comment = del_comments(behind_b_comment, l_comment_regExp);
@@ -191,18 +189,12 @@ async function getFullSymbolInfo(document: vscode.TextDocument, range: Range, no
}
break;
}
-
+
comments.push(content + '\n');
is_b_comment = true;
- continue;
- }
-
- // 说明既不是块注释又不是行注释所以就是到了代码块
- if (line !== firstLine) {
- break;
}
}
-
+
// 清除空前行
let resultComment = '';
for (const c of comments.reverse()) {
diff --git a/src/function/sim/instance.ts b/src/function/sim/instance.ts
index 07a0f59..f450b11 100644
--- a/src/function/sim/instance.ts
+++ b/src/function/sim/instance.ts
@@ -44,13 +44,14 @@ function instanceVlogCode(module: HdlModule, prefix: string = '', returnSnippetS
}
content.appendText(prefix + module.name + ' ');
+ makeVlogParamAssignments(content, module.params, prefix, returnSnippetString, needComment);
+
if (returnSnippetString) {
content.appendPlaceholder('u_' + module.name);
} else {
content.appendText('u_' + module.name);
}
- makeVlogParamAssignments(content, module.params, prefix, returnSnippetString, needComment);
makeVlogPortAssignments(content, module.ports, prefix, returnSnippetString, needComment);
const instanceString = content.value;
@@ -165,8 +166,8 @@ function makeVlogParamAssignments(content: vscode.SnippetString, params: HdlModu
content.appendText(' '.repeat(maxInitLength - param.init.length + 1) + ' )');
if (i < params.length - 1) {
content.appendText(',');
+ content.appendText('\n');
}
- content.appendText('\n');
}
content.appendText(prefix + ')\n');
}