Skip to content

Added support for automatic functions #119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyverilog/ast_code_generator/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,7 @@ def visit_Function(self, node):
'name': escape(node.name),
'retwidth': self.visit(node.retwidth),
'statement': statement,
'automatic': 'automatic' if node.automatic else ''
}
rslt = template.render(template_dict)
return rslt
Expand Down
2 changes: 1 addition & 1 deletion pyverilog/ast_code_generator/template/function.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

function {{ retwidth }} {{ name }};
function {{automatic}} {{ retwidth }} {{ name }};
{%- for s in statement %}
{{ s }}
{%- endfor %}
Expand Down
3 changes: 2 additions & 1 deletion pyverilog/vparser/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -1074,11 +1074,12 @@ def children(self):
class Function(Node):
attr_names = ('name',)

def __init__(self, name, retwidth, statement, lineno=0):
def __init__(self, name, retwidth, statement, automatic=False, lineno=0):
self.lineno = lineno
self.name = name
self.retwidth = retwidth
self.statement = statement
self.automatic = automatic

def children(self):
nodelist = []
Expand Down
2 changes: 1 addition & 1 deletion pyverilog/vparser/lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def token(self):

keywords = (
'MODULE', 'ENDMODULE', 'BEGIN', 'END', 'GENERATE', 'ENDGENERATE', 'GENVAR',
'FUNCTION', 'ENDFUNCTION', 'TASK', 'ENDTASK',
'FUNCTION', 'ENDFUNCTION', 'AUTOMATIC', 'TASK', 'ENDTASK',
'INPUT', 'INOUT', 'OUTPUT', 'TRI', 'REG', 'LOGIC', 'WIRE', 'INTEGER', 'REAL', 'SIGNED',
'PARAMETER', 'LOCALPARAM', 'SUPPLY0', 'SUPPLY1',
'ASSIGN', 'ALWAYS', 'ALWAYS_FF', 'ALWAYS_COMB', 'ALWAYS_LATCH', 'SENS_OR', 'POSEDGE', 'NEGEDGE', 'INITIAL',
Expand Down
23 changes: 23 additions & 0 deletions pyverilog/vparser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2092,6 +2092,11 @@ def p_function(self, p):
p.set_lineno(0, p.lineno(1))
p[0].end_lineno = p.lineno(6)

def p_function_automatic(self, p):
'function : FUNCTION AUTOMATIC width ID SEMICOLON function_statement ENDFUNCTION'
p[0] = Function(p[4], p[3], p[6], automatic=True, lineno=p.lineno(1))
p.set_lineno(0, p.lineno(1))

def p_function_nowidth(self, p):
'function : FUNCTION ID SEMICOLON function_statement ENDFUNCTION'
p[0] = Function(p[2],
Expand All @@ -2102,6 +2107,15 @@ def p_function_nowidth(self, p):
p.set_lineno(0, p.lineno(1))
p[0].end_lineno = p.lineno(5)

def p_function_automatic_nowidth(self, p):
'function : FUNCTION AUTOMATIC ID SEMICOLON function_statement ENDFUNCTION'
p[0] = Function(p[3],
Width(IntConst('0', lineno=p.lineno(1)),
IntConst('0', lineno=p.lineno(1)),
lineno=p.lineno(1)),
p[5], automatic=True, lineno=p.lineno(1))
p.set_lineno(0, p.lineno(1))

def p_function_integer(self, p):
'function : FUNCTION INTEGER ID SEMICOLON function_statement ENDFUNCTION'
p[0] = Function(p[3],
Expand All @@ -2112,6 +2126,15 @@ def p_function_integer(self, p):
p.set_lineno(0, p.lineno(1))
p[0].end_lineno = p.lineno(6)

def p_function_integer_automatic(self, p):
'function : FUNCTION AUTOMATIC INTEGER ID SEMICOLON function_statement ENDFUNCTION'
p[0] = Function(p[4],
Width(IntConst('31', lineno=p.lineno(1)),
IntConst('0', lineno=p.lineno(1)),
lineno=p.lineno(1)),
p[6], automatic=True, lineno=p.lineno(1))
p.set_lineno(0, p.lineno(1))

def p_function_statement(self, p):
'function_statement : funcvardecls function_calc'
p[0] = p[1] + (p[2],)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from __future__ import absolute_import
from __future__ import print_function
import os
import sys
from pyverilog.vparser.parser import VerilogCodeParser
from pyverilog.ast_code_generator.codegen import ASTCodeGenerator

try:
from StringIO import StringIO
except:
from io import StringIO

codedir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + '/verilogcode/'

expected = """\


module TOP
(
CLK,
RST_X
);

input CLK;
input RST_X;
reg [3:0] cnt;

function automatic [3:0] inc;
input [3:0] in;
begin
if(&inc) begin
inc = 0;
end else begin
inc = in + 1;
end
end
endfunction


always @(posedge CLK or negedge RST_X) begin
if(!RST_X) begin
cnt <= 0;
end else begin
cnt <= inc(cnt);
end
end


endmodule

"""

def test():
filelist = [codedir + 'automatic_function.v']
output = 'preprocess.out'
include = None
define = None

parser = VerilogCodeParser(filelist,
preprocess_include=include,
preprocess_define=define)
ast = parser.parse()
directives = parser.get_directives()

codegen = ASTCodeGenerator()
rslt = codegen.visit(ast)
print(rslt)
assert(expected == rslt)

if __name__ == '__main__':
test()
108 changes: 108 additions & 0 deletions tests/parser_test/test_automatic_function.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
from __future__ import absolute_import
from __future__ import print_function
import os
import sys
from pyverilog.vparser.parser import VerilogCodeParser

try:
from StringIO import StringIO
except:
from io import StringIO

codedir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + '/verilogcode/'

expected = """\
Source: (at 1)
Description: (at 1)
ModuleDef: TOP (from 1 to 25)
Paramlist: (at 0)
Portlist: (at 1)
Port: CLK, None (at 1)
Port: RST_X, None (at 1)
Decl: (at 2)
Input: CLK, False (at 2)
Decl: (at 3)
Input: RST_X, False (at 3)
Decl: (at 4)
Reg: cnt, False (at 4)
Width: (at 4)
IntConst: 3 (at 4)
IntConst: 0 (at 4)
Function: inc (at 6)
Width: (at 6)
IntConst: 3 (at 6)
IntConst: 0 (at 6)
Decl: (at 7)
Input: in, False (at 7)
Width: (at 7)
IntConst: 3 (at 7)
IntConst: 0 (at 7)
Block: None (from 8 to 14)
IfStatement: (from 9 to 13)
Uand: (at 9)
Identifier: inc (at 9)
Block: None (from 9 to 11)
BlockingSubstitution: (from 10 to 10)
Lvalue: (at 10)
Identifier: inc (at 10)
Rvalue: (at 10)
IntConst: 0 (at 10)
Block: None (from 11 to 13)
BlockingSubstitution: (from 12 to 12)
Lvalue: (at 12)
Identifier: inc (at 12)
Rvalue: (at 12)
Plus: (at 12)
Identifier: in (at 12)
IntConst: 1 (at 12)
Always: (from 17 to 23)
SensList: (at 17)
Sens: posedge (at 17)
Identifier: CLK (at 17)
Sens: negedge (at 17)
Identifier: RST_X (at 17)
Block: None (from 17 to 23)
IfStatement: (from 18 to 22)
Ulnot: (at 18)
Identifier: RST_X (at 18)
Block: None (from 18 to 20)
NonblockingSubstitution: (from 19 to 19)
Lvalue: (at 19)
Identifier: cnt (at 19)
Rvalue: (at 19)
IntConst: 0 (at 19)
Block: None (from 20 to 22)
NonblockingSubstitution: (from 21 to 21)
Lvalue: (at 21)
Identifier: cnt (at 21)
Rvalue: (at 21)
FunctionCall: (at 21)
Identifier: inc (at 21)
Identifier: cnt (at 21)
"""

def test():
filelist = [codedir + 'automatic_function.v']
output = 'preprocess.out'
include = None
define = None

parser = VerilogCodeParser(filelist,
preprocess_include=include,
preprocess_define=define)
ast = parser.parse()
directives = parser.get_directives()

output = StringIO()
ast.show(buf=output)

for lineno, directive in directives:
output.write('Line %d : %s' % (lineno, directive))

rslt = output.getvalue()

print(rslt)
assert(expected == rslt)

if __name__ == '__main__':
test()
25 changes: 25 additions & 0 deletions verilogcode/automatic_function.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module TOP(CLK, RST_X);
input CLK;
input RST_X;
reg [3:0] cnt;

function automatic [3:0] inc;
input [3:0] in;
begin
if(&inc) begin
inc = 0;
end else begin
inc = in + 1;
end
end
endfunction

always @(posedge CLK or negedge RST_X) begin
if(!RST_X) begin
cnt <= 0;
end else begin
cnt <= inc(cnt);
end
end

endmodule