Skip to content

Commit

Permalink
feat: add hdl utils tests
Browse files Browse the repository at this point in the history
  • Loading branch information
qarlosalberto committed Jul 29, 2023
1 parent e075066 commit e5195d5
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 87 deletions.
126 changes: 78 additions & 48 deletions packages/colibri/src/utils/hdl_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@
// along with colibri2. If not, see <https://www.gnu.org/licenses/>.

import { HDL_LANG, HDL_EXTENSIONS, OTHER_EXTENSIONS } from "../common/general";
import * as fs from 'fs';
import * as path_lib from 'path';
import * as file_utils from './file_utils';

/**
* Get file language from extension
* @param extension File extension. E.g: .vhd
* @returns File language
**/
export function get_lang_from_extension(extension: string): HDL_LANG {
if (HDL_EXTENSIONS.VHDL.includes(extension) === true) {
return HDL_LANG.VHDL;
Expand All @@ -39,12 +43,22 @@ export function get_lang_from_extension(extension: string): HDL_LANG {
}
}

/**
* Get file language from path
* @param file_path File path. E.g: /home/user/file.vhd
* @returns File language
**/
export function get_lang_from_path(file_path: string): HDL_LANG {
const extension = path_lib.extname(file_path).toLowerCase();
const extension = file_utils.get_file_extension(file_path);
const lang = get_lang_from_extension(extension);
return lang;
}

/**
* Check if file is HDL
* @param file_path File path. E.g: /home/user/file.vhd
* @returns True if file is HDL
**/
export function check_if_hdl_file(file_path: string): boolean {
const lang = get_lang_from_path(file_path);
let check = false;
Expand All @@ -54,6 +68,11 @@ export function check_if_hdl_file(file_path: string): boolean {
return check;
}

/**
* Remove comments from VHDL code
* @param content VHDL code
* @returns VHDL code without comments
**/
export function remove_comments_vhdl(content: string): string {
const l_comment = new RegExp([
/--.*/
Expand Down Expand Up @@ -81,6 +100,11 @@ export function remove_comments_vhdl(content: string): string {
return content;
}

/**
* Remove comments from Verilog code
* @param content Verilog code
* @returns Verilog code without comments
**/
export function remove_comments_verilog(content: string): string {
const l_comment = new RegExp([
/\/\/.*/].map(x => (typeof x === 'string') ? x : x.source).join(''), 'mg');
Expand All @@ -105,6 +129,12 @@ export function remove_comments_verilog(content: string): string {
return content;
}

/**
* Get top level from code
* @param code HDL code
* @param lang HDL language
* @returns Top level name
**/
export function get_toplevel(code: string, lang: HDL_LANG): string {
let result;
let regex;
Expand All @@ -128,63 +158,63 @@ export function get_toplevel(code: string, lang: HDL_LANG): string {
return '';
}

export function get_declaration(code: string, lang: HDL_LANG) {
let result;
let regex;
const declaration = { name: '', type: '' };
if (lang === HDL_LANG.VHDL) {
code = remove_comments_vhdl(code);
regex = /(entity|package)\s+(?<name>\w+)\s*is\s*/gim;
result = regex.exec(code);
if (result !== null && result !== undefined && result.length >= 3) {
declaration.type = result[1].toLocaleLowerCase();
declaration.name = result[2];
}
}
else {
//Remove comments
code = remove_comments_verilog(code);
regex = /(?<type>module|program|interface|package|primitive|config|property)\s+(?:automatic\s+)?(?<name>\w+)/gm;
result = regex.exec(code);
if (result !== null && result !== undefined && result.length >= 3) {
declaration.type = 'entity';
declaration.name = result[2];
}
}
return declaration;
}
// export function get_declaration(code: string, lang: HDL_LANG) {
// let result;
// let regex;
// const declaration = { name: '', type: '' };
// if (lang === HDL_LANG.VHDL) {
// code = remove_comments_vhdl(code);
// regex = /(entity|package)\s+(?<name>\w+)\s*is\s*/gim;
// result = regex.exec(code);
// if (result !== null && result !== undefined && result.length >= 3) {
// declaration.type = result[1].toLocaleLowerCase();
// declaration.name = result[2];
// }
// }
// else {
// //Remove comments
// code = remove_comments_verilog(code);
// regex = /(?<type>module|program|interface|package|primitive|config|property)\s+(?:automatic\s+)?(?<name>\w+)/gm;
// result = regex.exec(code);
// if (result !== null && result !== undefined && result.length >= 3) {
// declaration.type = 'entity';
// declaration.name = result[2];
// }
// }
// return declaration;
// }

export function get_toplevel_from_path(filepath: string): string {
if (fs.existsSync(filepath) === false) {
if (file_utils.check_if_file(filepath) === false) {
return '';
}
const lang = get_lang_from_path(filepath);
if (lang === HDL_LANG.NONE) {
return '';
}

const code = fs.readFileSync(filepath, "utf8");
const code = file_utils.read_file_sync(filepath);
const entity_name = get_toplevel(code, lang);
return entity_name;
}

export async function get_declaration_from_path(filepath: string) {
if (filepath === undefined) {
return '';
}
if (fs.existsSync(filepath) === false) {
return '';
}
const lang = get_lang_from_path(filepath);
if (lang === HDL_LANG.NONE) {
return '';
}
// export async function get_declaration_from_path(filepath: string) {
// if (filepath === undefined) {
// return '';
// }
// if (fs.existsSync(filepath) === false) {
// return '';
// }
// const lang = get_lang_from_path(filepath);
// if (lang === HDL_LANG.NONE) {
// return '';
// }

const code = fs.readFileSync(filepath, "utf8");
const entity_name = get_declaration(code, lang);
// const code = fs.readFileSync(filepath, "utf8");
// const entity_name = get_declaration(code, lang);

if (entity_name === undefined) {
return '';
}
return entity_name;
}
// if (entity_name === undefined) {
// return '';
// }
// return entity_name;
// }
6 changes: 3 additions & 3 deletions packages/colibri/tests/utils/file_utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ describe('File Utils', () => {
const folder_path = path_lib.join(__dirname, 'helpers');

const files = file_utils.read_directory(folder_path, false);
expect(files.length).toBe(2);
expect(files[0]).toBe(path_lib.join(__dirname, 'helpers', 'other_sample.txt'));
expect(files[1]).toBe(path_lib.join(__dirname, 'helpers', 'sample.txt'));
expect(files.length).toBe(3);
expect(files[1]).toBe(path_lib.join(__dirname, 'helpers', 'other_sample.txt'));
expect(files[2]).toBe(path_lib.join(__dirname, 'helpers', 'sample.txt'));
});

it('find_files_by_extensions_dir_and_subdir', () => {
Expand Down
74 changes: 38 additions & 36 deletions packages/colibri/tests/utils/hdl_utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,40 +19,30 @@
import * as hdl_utils from "../../src/utils/hdl_utils";
import { HDL_LANG } from "../../src/common/general";
import { equal } from "assert";
import * as path_lib from "path";

describe('Check get language', function () {
it(`From path Verilog`, async function () {
const path_dummy = '/home/user/file.v';
const lang_expected = HDL_LANG.VERILOG;
const lang_current = hdl_utils.get_lang_from_path(path_dummy);
equal(lang_current, lang_expected);
});
describe('HDL utils', function () {

it(`From path SystemVerilog`, async function () {
const path_dummy = '/home/user/file.sv';
const lang_expected = HDL_LANG.SYSTEMVERILOG;
const lang_current = hdl_utils.get_lang_from_path(path_dummy);
equal(lang_current, lang_expected);
it(`get_lang_from_extension`, async function () {
expect(hdl_utils.get_lang_from_extension(".vhdl")).toBe(HDL_LANG.VHDL);
expect(hdl_utils.get_lang_from_extension(".v")).toBe(HDL_LANG.VERILOG);
expect(hdl_utils.get_lang_from_extension(".sv")).toBe(HDL_LANG.SYSTEMVERILOG);
expect(hdl_utils.get_lang_from_extension(".cpp")).toBe(HDL_LANG.CPP);
expect(hdl_utils.get_lang_from_extension(".sf")).toBe(HDL_LANG.NONE);
});

it(`From path VHDL`, async function () {
const path_dummy = '/home/user/file.vhd';
const lang_expected = HDL_LANG.VHDL;
const lang_current = hdl_utils.get_lang_from_path(path_dummy);
equal(lang_current, lang_expected);
it(`get_lang_from_path`, async function () {
expect(hdl_utils.get_lang_from_path("/this/my/path.vhdl")).toBe(HDL_LANG.VHDL);
});

it(`From path NONE`, async function () {
const path_dummy = '/home/user/file.txt';
const lang_expected = HDL_LANG.NONE;
const lang_current = hdl_utils.get_lang_from_path(path_dummy);
equal(lang_current, lang_expected);
it(`check_if_hdl_file`, async function () {
expect(hdl_utils.check_if_hdl_file("/this/my/path.vhdl")).toBe(true);
expect(hdl_utils.check_if_hdl_file("/this/my/path.v")).toBe(true);
expect(hdl_utils.check_if_hdl_file("/this/my/path.sv")).toBe(true);
expect(hdl_utils.check_if_hdl_file("/this/my/path.cpp")).toBe(false);
});
});

describe('Check remove comments', function () {

it(`Remove comments VHDL`, async function () {
it(`remove_comments_vhdl`, async function () {
const code_dummy = `
-- One line comment
-- One line comment 2
Expand All @@ -67,7 +57,7 @@ Test no comment 2`;
equal(code_current, code_expected);
});

it(`Remove comments Verilog`, async function () {
it(`remove_comments_verilog`, async function () {
const code_dummy = `
// One line comment
// One line comment 2
Expand All @@ -82,10 +72,8 @@ Test no comment 2`;
equal(code_current, code_expected);
});

});

describe('Check get top level with regex', function () {
it(`Get top level VHDL`, async function () {
it(`get_toplevel VHDL`, function () {
const code_dummy = `
library ieee;
use ieee.std_logic_1164.all;
Expand Down Expand Up @@ -114,11 +102,11 @@ describe('Check get top level with regex', function () {
`;

const expected = 'test_entity_name';
const current = await hdl_utils.get_toplevel(code_dummy, HDL_LANG.VHDL);
const current = hdl_utils.get_toplevel(code_dummy, HDL_LANG.VHDL);
equal(current, expected);
});

it(`Get top level Verilog`, async function () {
it(`get_toplevel Verilog`, function () {
const code_dummy = `
module test_entity_name2
#(
Expand Down Expand Up @@ -177,13 +165,27 @@ describe('Check get top level with regex', function () {
.j (j ),
.k (k ),
.l ( l)
);
});
endmodule
`;

const expected = 'test_entity_name2';
const current = await hdl_utils.get_toplevel(code_dummy, HDL_LANG.VERILOG);
const current = hdl_utils.get_toplevel(code_dummy, HDL_LANG.VERILOG);
equal(current, expected);
});


it(`get_toplevel None`, function () {
const current = hdl_utils.get_toplevel("", HDL_LANG.VERILOG);
equal(current, "");
});

it(`get_toplevel_from_path`, async function () {
const current = hdl_utils.get_toplevel_from_path(path_lib.join(__dirname, "helpers", "mod.vhdl"));
equal(current, "myent");

expect(hdl_utils.get_toplevel_from_path("/sample/fail")).toBe('');
expect(hdl_utils.get_toplevel_from_path(path_lib.join(__dirname, "helpers", "sample.txt"))).toBe('');

});
});
24 changes: 24 additions & 0 deletions packages/colibri/tests/utils/helpers/mod.vhdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity myent is
generic (
a : integer;
b : unsigned;
c : signed;
d : std_logic;
e : std_logic_vector;
f : std_logic_vector(5 downto 0)
);
port(
g : in std_logic;
h : out std_logic;
i : inout std_logic
);
end myent;

architecture e_arch of myent is
begin

end e_arch;

0 comments on commit e5195d5

Please sign in to comment.