Skip to content

Commit 865df5b

Browse files
committed
Explicit function definition is supported.
1 parent 202d82f commit 865df5b

File tree

11 files changed

+415
-39
lines changed

11 files changed

+415
-39
lines changed

sample/bram/bram.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
from veriloggen import *
66

7+
#-------------------------------------------------------------------------------
8+
# BRAM interface
9+
#-------------------------------------------------------------------------------
710
class BramInterface(Interface):
811
def __init__(self, m, prefix='', postfix='', addrwidth=10, datawidth=32, direction='in'):
912
Interface.__init__(self, m, prefix, postfix)
@@ -23,6 +26,9 @@ def __init__(self, m, prefix='', postfix='', addrwidth=10, datawidth=32, directi
2326
self.write = In('write')
2427
self.dataout = Out('dataout', datawidth)
2528

29+
#-------------------------------------------------------------------------------
30+
# BRAM module
31+
#-------------------------------------------------------------------------------
2632
def mkBram(name):
2733
m = Module(name + 'bram')
2834

@@ -44,12 +50,16 @@ def mkBram(name):
4450

4551
return m
4652

53+
#-------------------------------------------------------------------------------
54+
# Top module
55+
#-------------------------------------------------------------------------------
4756
def mkTop():
4857
m = Module('TOP')
4958
addrwidth = m.Parameter('ADDR_WIDTH', 10)
5059
datawidth = m.Parameter('DATA_WIDTH', 32)
5160
clk = m.Input('CLK')
5261
rst = m.Input('RST')
62+
5363
bramif = BramInterface(m, prefix='bram_',
5464
addrwidth=addrwidth, datawidth=datawidth, direction='out')
5565

@@ -60,7 +70,7 @@ def mkTop():
6070
ports.update(clk.connect())
6171
ports.update(bramif.connect_all_ports())
6272

63-
m.Instance(bram, 'inst_bram', params, ports)
73+
m.Instance(mkBram('my_'), 'inst_bram', params, ports)
6474

6575
fsm = lib.FSM(m, 'fsm')
6676
m.Always(Posedge(clk))(
@@ -81,7 +91,7 @@ def mkTop():
8191
return m
8292

8393
#-------------------------------------------------------------------------------
84-
bram = mkBram('my_')
8594
top = mkTop()
86-
verilog = ''.join( (bram.to_verilog(), top.to_verilog()) )
95+
# top.to_verilog('tmp.v')
96+
verilog = top.to_verilog()
8797
print(verilog)

sample/test/class/led.py

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,58 @@ def __init__(self, name='blinkled'):
2828
))
2929

3030
#-------------------------------------------------------------------------------
31-
led = Led()
32-
verilog = led.to_verilog()
33-
print(verilog)
31+
import unittest
32+
33+
expected_verilog = """
34+
module blinkled #
35+
(
36+
parameter WIDTH = 8
37+
)
38+
(
39+
input CLK,
40+
input RST,
41+
output reg [WIDTH-1:0] LED
42+
);
43+
reg [32-1:0] count;
44+
45+
always @(posedge CLK) begin
46+
if(RST) begin
47+
count <= 0;
48+
end else begin
49+
count <= count + 1;
50+
end
51+
end
52+
always @(posedge CLK) begin
53+
if(RST) begin
54+
LED <= 0;
55+
end else begin
56+
if(count == 1023) begin
57+
LED <= LED + 1;
58+
end
59+
end
60+
end
61+
endmodule
62+
"""
63+
64+
class TestLed(unittest.TestCase):
65+
def setUp(self):
66+
pass
67+
68+
def test_sample(self):
69+
from pyverilog.vparser.parser import VerilogParser
70+
from pyverilog.ast_code_generator.codegen import ASTCodeGenerator
71+
led = Led()
72+
verilog = led.to_verilog()
73+
parser = VerilogParser()
74+
expected_ast = parser.parse(expected_verilog)
75+
codegen = ASTCodeGenerator()
76+
expected_code = codegen.visit(expected_ast)
77+
self.assertTrue( expected_code == verilog )
78+
79+
#import difflib
80+
#diff = difflib.unified_diff(verilog.splitlines(), expected_code.splitlines())
81+
#print('\n'.join(list(diff)))
82+
#self.assertTrue( len(list(diff)) == 0 )
83+
84+
if __name__ == '__main__':
85+
unittest.main()

sample/test/function/Makefile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
TARGET=led.py
2+
ARGS=
3+
4+
PYTHON=python3
5+
#PYTHON=python
6+
#OPT=-m pdb
7+
#OPT=-m cProfile -s time
8+
#OPT=-m cProfile -o profile.rslt
9+
10+
.PHONY: all
11+
all: run
12+
13+
.PHONY: run
14+
run:
15+
$(PYTHON) $(OPT) $(TARGET) $(ARGS)
16+
17+
.PHONY: check
18+
check:
19+
$(PYTHON) $(OPT) $(TARGET) $(ARGS) > tmp.v
20+
iverilog -tnull -Wall tmp.v
21+
rm -f tmp.v
22+
23+
.PHONY: clean
24+
clean:
25+
rm -rf *.pyc __pycache__ parsetab.py *.out

sample/test/function/led.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import sys
2+
import os
3+
4+
from veriloggen import *
5+
6+
def mkLed():
7+
m = Module('blinkled')
8+
width = m.Parameter('WIDTH', 8)
9+
clk = m.Input('CLK')
10+
rst = m.Input('RST')
11+
led = m.OutputReg('LED', width)
12+
count = m.Reg('count', 32)
13+
14+
inc = m.Function('inc', width)
15+
inc_v = inc.Input('v', width)
16+
inc_o = inc.Input('o', width)
17+
inc_tmp = inc.Reg('tmp', width)
18+
inc.Body(
19+
inc_tmp(inc_v + 1),
20+
inc(inc_tmp)
21+
)
22+
23+
m.Always(Posedge(clk))(
24+
If(rst)(
25+
count(0)
26+
).Else(
27+
count( inc.call(count, 1) )
28+
))
29+
30+
m.Always(Posedge(clk))(
31+
If(rst)(
32+
led(1)
33+
).Else(
34+
If(count == 1024 - 1)(
35+
led[0](led[width-1]),
36+
led[width-1:1](led[width-2:0])
37+
)
38+
))
39+
40+
return m
41+
42+
#-------------------------------------------------------------------------------
43+
import unittest
44+
45+
expected_verilog = """
46+
module blinkled #
47+
(
48+
parameter WIDTH = 8
49+
)
50+
(
51+
input CLK,
52+
input RST,
53+
output reg [(WIDTH - 1):0] LED
54+
);
55+
reg [(32 - 1):0] count;
56+
57+
function [(WIDTH - 1):0] inc;
58+
input [(WIDTH - 1):0] v;
59+
input [(WIDTH - 1):0] o;
60+
reg [(WIDTH - 1):0] tmp;
61+
begin
62+
tmp = (v + 1);
63+
inc = tmp;
64+
end
65+
endfunction
66+
67+
always @(posedge CLK)
68+
begin
69+
if(RST) begin
70+
count <= 0;
71+
end
72+
else begin
73+
count <= inc(count, 1);
74+
end
75+
end
76+
77+
always @(posedge CLK)
78+
begin
79+
if(RST) begin
80+
LED <= 1;
81+
end
82+
else begin
83+
if((count == 1023)) begin
84+
LED[0] <= LED[(WIDTH - 1)];
85+
LED[(WIDTH - 1):1] <= LED[(WIDTH - 2):0];
86+
end
87+
end
88+
end
89+
90+
endmodule
91+
"""
92+
93+
class TestLed(unittest.TestCase):
94+
def setUp(self):
95+
pass
96+
97+
def test_sample(self):
98+
from pyverilog.vparser.parser import VerilogParser
99+
from pyverilog.ast_code_generator.codegen import ASTCodeGenerator
100+
led = mkLed()
101+
verilog = led.to_verilog()
102+
parser = VerilogParser()
103+
expected_ast = parser.parse(expected_verilog)
104+
codegen = ASTCodeGenerator()
105+
expected_code = codegen.visit(expected_ast)
106+
self.assertTrue( expected_code == verilog )
107+
108+
#import difflib
109+
#diff = difflib.unified_diff(verilog.splitlines(), expected_code.splitlines())
110+
#print('\n'.join(list(diff)))
111+
#self.assertTrue( len(list(diff)) == 0 )
112+
113+
if __name__ == '__main__':
114+
unittest.main()

sample/test/function/veriloggen

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../veriloggen

veriloggen/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from module import Module
1919
from interface import Interface
20+
from function import Function
2021
from vtypes import *
2122

2223
import lib

veriloggen/function.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import os
2+
import sys
3+
import collections
4+
5+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
6+
7+
import vtypes
8+
9+
class Function(vtypes.VeriloggenNode):
10+
def __init__(self, name, width=1):
11+
self.name = name
12+
self.width = width
13+
self.io_variable = collections.OrderedDict()
14+
self.variable = collections.OrderedDict()
15+
self.statement = None
16+
17+
#---------------------------------------------------------------------------
18+
def Input(self, name, width=None, length=None, signed=False, value=None):
19+
t = vtypes.Input(name, width, length, signed, value)
20+
self.io_variable[name] = t
21+
return t
22+
23+
def Reg(self, name, width=None, length=None, signed=False, value=None):
24+
t = vtypes.Reg(name, width, length, signed, value)
25+
self.variable[name] = t
26+
return t
27+
28+
def Integer(self, name, width=None, length=None, signed=False, value=None):
29+
t = vtypes.Integer(name, width, length, signed, value)
30+
self.variable[name] = t
31+
return t
32+
33+
def Body(self, *statement):
34+
if self.statement is not None:
35+
raise ValueError("Statement is already assigned.")
36+
self.statement = tuple(statement)
37+
return self
38+
39+
def __call__(self, r):
40+
return vtypes.Subst(self, r)
41+
42+
def next(self, r):
43+
return self.__call__(r)
44+
45+
def call(self, *args):
46+
return FunctionCall(self.name, *args)
47+
48+
class FunctionCall(vtypes.VeriloggenNode):
49+
def __init__(self, name, *args):
50+
self.name = name
51+
self.args = tuple(args)

veriloggen/interface.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
77

88
import vtypes
9+
import module
910

1011
class Interface(vtypes.VeriloggenNode):
11-
def __init__(self, module, prefix='', postfix=''):
12-
self.module = module
12+
def __init__(self, m, prefix='', postfix=''):
13+
if not isinstance(m, module.Module):
14+
raise TypeError("module should be an instance of module.Module.")
15+
self.module = m
1316
self.prefix = prefix
1417
self.postfix = postfix
1518

veriloggen/module.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
66

77
import vtypes
8+
import function
9+
810
import to_verilog
911

1012
class Module(object):
@@ -15,9 +17,11 @@ def __init__(self, name=None):
1517
self.io_variable = collections.OrderedDict()
1618
self.constant = collections.OrderedDict()
1719
self.global_constant = collections.OrderedDict()
20+
self.function = []
1821
self.assign = []
1922
self.always = []
2023
self.instance = collections.OrderedDict()
24+
self.submodule = {}
2125

2226
#---------------------------------------------------------------------------
2327
def Input(self, name, width=None, length=None, signed=False, value=None):
@@ -52,6 +56,21 @@ def Reg(self, name, width=None, length=None, signed=False, value=None):
5256
self.variable[name] = t
5357
return t
5458

59+
def Integer(self, name, width=None, length=None, signed=False, value=None):
60+
t = vtypes.Integer(name, width, length, signed, value)
61+
self.variable[name] = t
62+
return t
63+
64+
def Real(self, name, width=None, length=None, signed=False, value=None):
65+
t = vtypes.Real(name, width, length, signed, value)
66+
self.variable[name] = t
67+
return t
68+
69+
def Genvar(self, name, width=None, length=None, signed=False, value=None):
70+
t = vtypes.Genvar(name, width, length, signed, value)
71+
self.variable[name] = t
72+
return t
73+
5574
def Parameter(self, name, value, width=None, signed=False, length=None):
5675
t = vtypes.Parameter(name, value, width, signed)
5776
self.global_constant[name] = t
@@ -73,9 +92,17 @@ def Assign(self, statement):
7392
self.assign.append(t)
7493
return t
7594

95+
#---------------------------------------------------------------------------
96+
def Function(self, name, width=1):
97+
t = function.Function(name, width)
98+
self.function.append(t)
99+
return t
100+
101+
#---------------------------------------------------------------------------
76102
def Instance(self, module, instname, params, ports):
77103
t = vtypes.Instance(module, instname, params, ports)
78104
self.instance[instname] = t
105+
self.submodule[module.name] = module
79106
return t
80107

81108
#---------------------------------------------------------------------------

0 commit comments

Comments
 (0)