Skip to content

Commit

Permalink
index include paths, do macros, refactor module inst
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewNolte committed Apr 9, 2024
1 parent 4490e72 commit 509df3b
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 178 deletions.
9 changes: 9 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,15 @@
"configuration": {
"title": "Verilog configuration",
"properties": {
"verilog.includes": {
"scope": "machine-overridable",
"type": "array",
"items": {
"type": "string"
},
"default": "",
"description": "verilog include directories, applied to each tool"
},
"verilog.subdir": {
"scope": "window",
"type": "string",
Expand Down
195 changes: 41 additions & 154 deletions src/commands/ModuleInstantiation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,146 +5,57 @@ import * as vscode from 'vscode';
import { logger } from '../extension';
import { CtagsParser, Symbol } from '../parsers/ctagsParser';
import { getWorkspaceFolder } from '../utils';
import { CtagsManager } from '../ctags';
import { Logger } from '../logger';

export async function instantiateModuleInteract() {
if (vscode.window.activeTextEditor === undefined) {
return;
}
let filePath = path.dirname(vscode.window.activeTextEditor.document.fileName);
let srcPath = await selectFile(filePath);
if (srcPath === undefined) {
return;
}
let snippet = await instantiateModule(srcPath);
if (snippet === undefined) {
return;
}
vscode.window.activeTextEditor?.insertSnippet(snippet);
}

export async function instantiateModule(
srcpath: string
): Promise<vscode.SnippetString | undefined> {
// Using Ctags to get all the modules in the file
let moduleName: string | undefined = undefined;

let file: vscode.TextDocument | undefined = vscode.window.activeTextEditor?.document;
if (file === undefined) {
logger.warn('file undefined... returning');
return;
export class CommandExcecutor {
private logger: Logger;
private ctagsManager: CtagsManager;
constructor(logger: Logger, ctagsManager: CtagsManager) {
this.logger = logger;
this.ctagsManager = ctagsManager;
}
let ctags: ModuleTags = new ModuleTags(logger, file);
logger.info('Executing ctags for module instantiation');
let output = await ctags.execCtags(srcpath);
await ctags.buildSymbolsList(output);


let modules: Symbol[] = ctags.symbols.filter((tag) => tag.type === 'module' || tag.type === 'interface');
// No modules found
if (modules.length <= 0) {
vscode.window.showErrorMessage('Verilog-HDL/SystemVerilog: No modules found in the file');
return undefined;
}
let module: Symbol = modules[0];
if (modules.length > 1) {
// many modules found
moduleName = await vscode.window.showQuickPick(
ctags.symbols.filter((tag) => tag.type === 'module').map((tag) => tag.name),
{
placeHolder: 'Choose a module to instantiate',
}
);
if (moduleName === undefined) {
return undefined;
async instantiateModuleInteract() {
if (vscode.window.activeTextEditor === undefined) {
return;
}
module = modules.filter((tag) => tag.name === moduleName)[0];
}

return moduleSnippet(ctags, module, true);
}

export async function moduleFromFile(srcpath: string): Promise<vscode.SnippetString | undefined> {
let file: vscode.TextDocument | undefined = vscode.window.activeTextEditor?.document;
if (file === undefined) {
logger.warn('file undefined... returning');
return;
}
let ctags: ModuleTags = new ModuleTags(logger, file);
logger.info('Executing ctags for module instantiation');
let output = await ctags.execCtags(srcpath);
await ctags.buildSymbolsList(output);

let modules: Symbol[] = ctags.symbols.filter((tag) => tag.type === 'module' || tag.type === 'interface');
// No modules found
if (modules.length <= 0) {
vscode.window.showErrorMessage('Verilog-HDL/SystemVerilog: No modules found in the file');
return undefined;
}

return moduleSnippet(ctags, modules[0], false);
}

export async function moduleSnippet(ctags: CtagsParser, module: Symbol, fullModule: boolean) {
let portsName: string[] = [];
let parametersName: string[] = [];

let scope = module.parentScope !== '' ? module.parentScope + '.' + module.name : module.name;
let ports: Symbol[] = ctags.symbols.filter(
(tag) => tag.type === 'port' && tag.parentScope === scope
);
portsName = ports.map((tag) => tag.name);
let params: Symbol[] = ctags.symbols.filter(
(tag) => tag.type === 'parameter' && tag.parentScope === scope
);
parametersName = params.map((tag) => tag.name);
logger.info('Module name: ' + module.name);
let paramString = ``;
if (parametersName.length > 0) {
paramString = `\n${instantiatePort(parametersName)}`;
}
logger.info('portsName: ' + portsName.toString());

if (fullModule) {
return new vscode.SnippetString()
.appendText(module.name + ' ')
.appendText('#(')
.appendText(paramString)
.appendText(') ')
.appendPlaceholder('u_')
.appendPlaceholder(`${module.name} (\n`)
.appendText(instantiatePort(portsName))
.appendText(');\n');
}
return (
new vscode.SnippetString()
// .appendText('#(')
.appendText(paramString)
.appendText(') ')
.appendPlaceholder('u_')
.appendPlaceholder(`${module.name} (\n`)
.appendText(instantiatePort(portsName))
);
}
let srcPath = await selectFile(path.dirname(vscode.window.activeTextEditor.document.fileName));
if (srcPath === undefined) {
return;
}
let doc = await vscode.workspace.openTextDocument(srcPath);
let ctags = this.ctagsManager.getCtags(doc);

function instantiatePort(ports: string[]): string {
let port = '';
let maxLen = 0;
for (let i = 0; i < ports.length; i++) {
if (ports[i].length > maxLen) {
maxLen = ports[i].length;
let modules: Symbol[] = await ctags.getModules();
// No modules found
if (modules.length <= 0) {
vscode.window.showErrorMessage('Verilog-HDL/SystemVerilog: No modules found in the file');
return undefined;
}
}
// .NAME(NAME)
for (let i = 0; i < ports.length; i++) {
let element = ports[i];
let padding = maxLen - element.length;
element = element + ' '.repeat(padding);
port += `\t.${element}(${ports[i]})`;
if (i !== ports.length - 1) {
port += ',';
let module: Symbol = modules[0];
if (modules.length > 1) {
let moduleName = await vscode.window.showQuickPick(
modules.map((sym) => sym.name),
{
placeHolder: 'Choose a module to instantiate',
}
);
if (moduleName === undefined) {
return undefined;
}
module = modules.filter((tag) => tag.name === moduleName)[0];
}
let snippet = ctags.getModuleSnippet(module, true);
if (snippet === undefined) {
return;
}
port += '\n';
vscode.window.activeTextEditor?.insertSnippet(snippet);
}
return port;

}

async function selectFile(currentDir?: string): Promise<string | undefined> {
Expand Down Expand Up @@ -202,27 +113,3 @@ function getDirectories(srcpath: string): string[] {
function getFiles(srcpath: string): string[] {
return fs.readdirSync(srcpath).filter((file) => fs.statSync(path.join(srcpath, file)).isFile());
}

class ModuleTags extends CtagsParser {
buildSymbolsList(tags: string): Promise<void> {
if (tags === '') {
return Promise.resolve();
}
// Parse ctags output
let lines: string[] = tags.split(/\r?\n/);
lines.forEach((line) => {
if (line !== '') {
let tag: Symbol | undefined = this.parseTagLine(line);
if (tag === undefined) {
return;
}
// add only modules and ports
if (tag.type === 'interface' || tag.type === 'module' || tag.type === 'port' || tag.type === 'parameter') {
this.symbols.push(tag);
}
}
});
// skip finding end tags
return Promise.resolve();
}
}
10 changes: 10 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { getVSCodeDownloadUrl } from "@vscode/test-electron/out/util";

import * as vscode from 'vscode';


export class Config {
static getIncludePaths(): string[] {
return vscode.workspace.getConfiguration().get('verilog.includes', []);
}
}
48 changes: 44 additions & 4 deletions src/ctags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as vscode from 'vscode';
import { Logger } from './logger';
import { CtagsParser, Symbol } from './parsers/ctagsParser';
import { getParentText, getPrevChar, getWorkspaceFolder } from './utils';
import { Config } from './config';

// Internal representation of a symbol

Expand All @@ -11,6 +12,9 @@ export class CtagsManager {
private logger: Logger;
private searchPrefix: string;

// top level
private symbolMap: Map<string, Symbol[]> = new Map();

constructor(logger: Logger, hdlDir: string) {
this.logger = logger;
this.logger.info('ctags manager configure');
Expand All @@ -22,6 +26,34 @@ export class CtagsManager {

vscode.workspace.onDidSaveTextDocument(this.onSave.bind(this));
vscode.workspace.onDidCloseTextDocument(this.onClose.bind(this));
this.indexIncludes();
vscode.workspace.onDidChangeConfiguration(async (e) => {
if (e.affectsConfiguration('verilog.includes')) {
this.indexIncludes();
}
});

}

async indexIncludes(): Promise<void> {
this.logger.info('indexIncludes');
Config.getIncludePaths().forEach(async (path: string) => {
let files: vscode.Uri[] = await this.findFiles(`${path}/*.{sv,svh}`);

files.forEach(async (file: vscode.Uri) => {
this.logger.info(`indexing ${file}`);
let doc = await vscode.workspace.openTextDocument(file);
let syms = await this.getCtags(doc).getSymbols();
syms.forEach((element: Symbol) => {
// this.logger.info(`adding ${element.name}`);
if(this.symbolMap.has(element.name)) {
this.symbolMap.get(element.name)?.push(element);
} else {
this.symbolMap.set(element.name, [element]);
}
});
});
});
}

getCtags(doc: vscode.TextDocument): CtagsParser {
Expand All @@ -42,13 +74,17 @@ export class CtagsManager {
ctags.clearSymbols();
}

async findModule(moduleName: string): Promise<vscode.TextDocument | undefined> {
async findFiles(pattern: string): Promise<vscode.Uri[]> {
let ws = getWorkspaceFolder();
if (ws === undefined) {
return undefined;
return [];
}
let searchPattern = new vscode.RelativePattern(ws, `${this.searchPrefix}/${moduleName}.{sv,v}`);
let files = await vscode.workspace.findFiles(searchPattern);
let searchPattern = new vscode.RelativePattern(ws, pattern);
return await vscode.workspace.findFiles(searchPattern);
}

async findModule(moduleName: string): Promise<vscode.TextDocument | undefined> {
let files = await this.findFiles(`${this.searchPrefix}/${moduleName}.{sv,v}`);
if (files.length === 0) {
return undefined;
}
Expand Down Expand Up @@ -95,6 +131,10 @@ export class CtagsManager {
}
}

if (this.symbolMap.has(targetText)){
return this.symbolMap.get(targetText) ?? [];
}

const results: Symbol[][] = await Promise.all([
// find def in current document
parser.getSymbols({ name: targetText }),
Expand Down
14 changes: 9 additions & 5 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import * as DefinitionProvider from './providers/DefinitionProvider';
import * as DocumentSymbolProvider from './providers/DocumentSymbolProvider';
import * as FormatProvider from './providers/FormatPrivider';
import * as HoverProvider from './providers/HoverProvider';
import { CommandExcecutor } from './commands/ModuleInstantiation';

export var logger: Logger; // Global logger
var ctagsManager: CtagsManager;
Expand Down Expand Up @@ -113,18 +114,21 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.workspace.onDidCloseTextDocument(lintManager.removeFileDiagnostics, lintManager)
);
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(lintManager.configLinter, lintManager));


context.subscriptions.push(
vscode.workspace.onDidChangeConfiguration(lintManager.configLinter, lintManager)
);

/////////////////////////////////////////////
// Register Commands
/////////////////////////////////////////////

let commandExcecutor = new CommandExcecutor(logger.getChild('CommandExcecutor'), ctagsManager);
vscode.commands.registerCommand(
'verilog.instantiateModule',
ModuleInstantiation.instantiateModuleInteract
commandExcecutor.instantiateModuleInteract,
commandExcecutor
);
vscode.commands.registerCommand('verilog.lint', lintManager.runLintTool);
vscode.commands.registerCommand('verilog.lint', lintManager.runLintTool, lintManager);

/////////////////////////////////////////////
// Language Servers
Expand Down
Loading

0 comments on commit 509df3b

Please sign in to comment.