Skip to content

Commit 2296daa

Browse files
committed
Improve HDLReader and its test
1 parent 3dd16e7 commit 2296daa

File tree

2 files changed

+108
-24
lines changed

2 files changed

+108
-24
lines changed

hdltools/hdl_reader.py

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
#
2-
# Copyright (C) 2025 HDLtools Project
2+
# Copyright (C) 2025-2026 HDLtools Project
33
#
44
# SPDX-License-Identifier: GPL-3.0-or-later
55
#
66

77
"""
8-
Reads and sanitizes the input HDL code by removing comments, extra whitespaces
9-
and newlines.
8+
Reads and sanitizes the input HDL code by removing comments, trailing espaces
9+
and multiple empty lines.
1010
"""
1111

1212
import re
@@ -27,15 +27,30 @@ def set_code(self, code):
2727
"""Directly sets the HDL code."""
2828
self.code = code
2929

30-
def is_vhdl(self):
31-
"""Return True if the code seems to be VHDL."""
32-
return 'endmodule' not in self.code.lower()
33-
3430
def get_code(self):
3531
"""Retrieves the sanitized HDL code."""
36-
if self.is_vhdl():
37-
text = re.sub(r'--[^\n]*', '', self.code)
32+
text = self.code
33+
text = re.sub(r'/\*.*?\*/', '', text, flags=re.DOTALL)
34+
if self._is_vhdl(text):
35+
text = re.sub(r'--.*', '', text)
3836
else:
39-
text = re.sub(r'//[^\n]*', '', self.code)
40-
text = re.sub(r'/\*.*?\*/', '', text, flags=re.DOTALL)
41-
return re.sub(r'\s+', ' ', text).strip()
37+
text = re.sub(r'//.*', '', text)
38+
text = re.sub(r'[ \t]+$', '', text, flags=re.MULTILINE)
39+
text = re.sub(r'\n{3,}', '\n\n', text)
40+
return text.strip()
41+
42+
def _is_vhdl(self, text):
43+
"""Heuristic to determine if the code is VHDL or Verilog."""
44+
vhdl_score = 0
45+
vlog_score = 0
46+
47+
vhdl_keywords = r'\b(library|entity|architecture|signal|begin)\b'
48+
vlog_keywords = r'\b(endmodule|assign|logic|wire|reg|parameter)\b'
49+
50+
vhdl_matches = re.findall(vhdl_keywords, text, re.IGNORECASE)
51+
vhdl_score += len(set(vhdl_matches))
52+
53+
vlog_matches = re.findall(vlog_keywords, text)
54+
vlog_score += len(set(vlog_matches))
55+
56+
return vhdl_score > vlog_score

tests/test_reader.py

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,89 @@
33
from pathlib import Path
44
from hdltools.hdl_reader import HDLReader
55

6+
INPUT = {}
7+
OUTPUT = {}
68

7-
@pytest.fixture
8-
def vcode():
9-
vfile = Path(__file__).parent.resolve() / 'hdl' / 'modules.sv'
10-
vobj = HDLReader()
11-
vobj.read_file(vfile)
12-
return vobj.get_code()
9+
INPUT['vhdl'] = '''
10+
/*
11+
Block comments (added in VHDL 2008)
12+
*/
13+
library IEEE; -- aaa
14+
use IEEE.STD_LOGIC_1164.ALL; -- bbb
15+
-- ccc
16+
entity dut is
17+
port (
18+
data_i : in std_logic; -- input
19+
data_o : out std_logic -- output
20+
);
21+
end dut;
22+
-- ddd
23+
-- eee
24+
architecture behav of dut /* fff */is
25+
begin
26+
/* ggg -- */
27+
data_o <= data_i;
28+
/*
29+
hhh
30+
-- */
31+
end behav;
32+
'''
33+
34+
OUTPUT['vhdl'] = '''
35+
library IEEE;
36+
use IEEE.STD_LOGIC_1164.ALL;
37+
38+
entity dut is
39+
port (
40+
data_i : in std_logic;
41+
data_o : out std_logic
42+
);
43+
end dut;
44+
45+
architecture behav of dut is
46+
begin
47+
48+
data_o <= data_i;
1349
50+
end behav;
51+
'''
1452

15-
def test_comments(vcode):
16-
comment_patterns = ['//', '/*', '*/', '--']
17-
assert not any(pattern in vcode for pattern in comment_patterns)
53+
INPUT['vlog'] = '''
54+
/*
55+
Block comments
56+
*/
57+
// aaa
58+
module dut (
59+
input data_i, // input
60+
output data_o // output
61+
);
62+
// bbb
63+
// ccc
64+
/* ddd // */
65+
assign /* eee // */data_o = data_i;
66+
/*
67+
fff
68+
// */
69+
endmodule
70+
'''
1871

72+
OUTPUT['vlog'] = '''
73+
module dut (
74+
input data_i,
75+
output data_o
76+
);
1977
20-
def test_spaces(vcode):
21-
assert '\n' not in vcode
22-
assert ' ' not in vcode
78+
assign data_o = data_i;
79+
80+
endmodule
81+
'''
82+
83+
84+
@pytest.mark.parametrize("input_code, expected_output", [
85+
(INPUT['vhdl'], OUTPUT['vhdl']),
86+
(INPUT['vlog'], OUTPUT['vlog']),
87+
], ids=["VHDL", "Verilog"])
88+
def test_remove_comments(input_code, expected_output):
89+
vobj = HDLReader()
90+
vobj.set_code(input_code)
91+
assert vobj.get_code() == expected_output.strip()

0 commit comments

Comments
 (0)