Skip to content

Commit 96556a6

Browse files
committed
lib-interface is an example of how to use Interface abstraction.
1 parent 6851c91 commit 96556a6

File tree

11 files changed

+206
-30
lines changed

11 files changed

+206
-30
lines changed

sample/Makefile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,4 @@ all: clean
33

44
.PHONY: clean
55
clean:
6-
make clean -C bram
7-
make clean -C led
8-
make clean -C test
6+
find . -maxdepth 1 -type d |grep "./" | xargs -I {} make clean -C {}

sample/bram/bram.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,30 @@
77
#-------------------------------------------------------------------------------
88
# BRAM interface
99
#-------------------------------------------------------------------------------
10-
class BramInterface(Interface):
11-
def __init__(self, m, prefix='', postfix='', addrwidth=10, datawidth=32, direction='in'):
12-
Interface.__init__(self, m, prefix, postfix)
10+
class BramInterface(lib.Interface):
11+
def __init__(self, m, prefix='', postfix='', addrwidth=10, datawidth=32, direction='child'):
12+
lib.Interface.__init__(self, m, prefix, postfix)
1313

14-
if direction != 'in' and direction != 'out':
15-
raise ValueError("direction should be 'in or 'out''")
14+
if direction != 'child' and direction != 'parent':
15+
raise ValueError("direction should be 'in or 'parent''")
1616
self.direction = direction
1717

1818
self.addrwidth = self.Parameter('ADDR_WIDTH', addrwidth)
1919
self.datawidth = self.Parameter('DATA_WIDTH', datawidth)
2020

21-
In = self.Input if self.direction == 'in' else self.Reg # self.Wire
22-
Out = self.Output if self.direction == 'in' else self.Wire
21+
In = self.Input if self.direction == 'child' else self.Reg # self.Wire
22+
Out = self.Output if self.direction == 'child' else self.Wire
2323

2424
self.addr = In('addr', addrwidth)
2525
self.datain = In('datain', datawidth)
2626
self.write = In('write')
2727
self.dataout = Out('dataout', datawidth)
28-
28+
29+
def init(self):
30+
if self.direction == 'parent':
31+
return self.addr(0), self.datain(0), self.write(0)
32+
raise Exception("init() is not allowed.")
33+
2934
#-------------------------------------------------------------------------------
3035
# BRAM module
3136
#-------------------------------------------------------------------------------
@@ -36,7 +41,7 @@ def mkBram(name):
3641
datawidth = m.Parameter('DATA_WIDTH', 32)
3742

3843
clk = m.Input('CLK')
39-
bramif = BramInterface(m, addrwidth=addrwidth, datawidth=datawidth, direction='in')
44+
bramif = BramInterface(m, addrwidth=addrwidth, datawidth=datawidth, direction='child')
4045

4146
d_addr = m.Reg('d_' + bramif.addr.name, datawidth)
4247
mem = m.Reg('mem', datawidth, Int(2)**addrwidth)
@@ -61,7 +66,7 @@ def mkTop():
6166
rst = m.Input('RST')
6267

6368
bramif = BramInterface(m, prefix='bram_',
64-
addrwidth=addrwidth, datawidth=datawidth, direction='out')
69+
addrwidth=addrwidth, datawidth=datawidth, direction='parent')
6570

6671
params = collections.OrderedDict()
6772
params.update(bramif.connect_all_parameters())
@@ -76,7 +81,7 @@ def mkTop():
7681
fsm = lib.FSM(m, 'fsm')
7782
init = fsm.get_index()
7883

79-
fsm( bramif.addr(0), bramif.datain(0), bramif.write(0), fsm.next() )
84+
fsm( bramif.init(), fsm.next() )
8085
first = fsm.get_index()
8186

8287
fsm( bramif.datain(bramif.datain + 4), fsm.next() )

sample/test/Makefile

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
11
.PHONY: clean
22
clean:
3-
make clean -C cat
4-
make clean -C class
5-
make clean -C function
6-
make clean -C lib-fsm
7-
make clean -C slice
3+
find . -maxdepth 1 -type d |grep "./" | xargs -I {} make clean -C {}
84

95
.PHONY: test
106
test:
11-
make test -C cat
12-
make test -C class
13-
make test -C function
14-
make test -C lib-fsm
15-
make test -C slice
7+
find . -maxdepth 1 -type d |grep "./" | xargs -I {} make test -C {}

sample/test/lib-interface/Makefile

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

sample/test/lib-interface/led.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import sys
2+
import os
3+
import collections
4+
5+
from veriloggen import *
6+
7+
class LedInterface(lib.Interface):
8+
def __init__(self, m, prefix='', postfix='', width=8, maxvalue=1024, direction='child'):
9+
lib.Interface.__init__(self, m, prefix, postfix)
10+
11+
if direction != 'child' and direction != 'parent':
12+
raise ValueError("direction should be 'in or 'parent''")
13+
self.direction = direction
14+
15+
self.width = width
16+
self.maxvalue = maxvalue
17+
18+
In = self.Input if self.direction == 'child' else self.Wire
19+
Out = self.OutputReg if self.direction == 'child' else self.Output
20+
21+
self.led = Out('LED', self.width)
22+
if direction == 'child':
23+
self.count = self.Reg('count', 32)
24+
25+
def init(self):
26+
if self.direction == 'child':
27+
return self.count(0), self.led(0)
28+
raise Exception("init() is not allowed.")
29+
30+
def step(self):
31+
ret = If( self.count == self.maxvalue -1 )(
32+
self.count( 0 ),
33+
self.led( self.led + 1 )
34+
).Else(
35+
self.count( self.count + 1 )
36+
)
37+
return ret
38+
39+
def mkLed():
40+
m = Module('blinkled')
41+
width = m.Parameter('WIDTH', 8)
42+
clk = m.Input('CLK')
43+
rst = m.Input('RST')
44+
ledif = LedInterface(m, width=width, direction='child')
45+
46+
m.Always(Posedge(clk))(
47+
If(rst)(
48+
*ledif.init()
49+
50+
).Else(
51+
ledif.step()
52+
))
53+
54+
return m
55+
56+
def mkTop(wid=8):
57+
m = Module('top')
58+
width = m.Parameter('WIDTH', wid)
59+
clk = m.Input('CLK')
60+
rst = m.Input('RST')
61+
ledif = LedInterface(m, width=width, direction='parent')
62+
63+
params = collections.OrderedDict()
64+
params.update(width.connect())
65+
params.update(ledif.connect_all_parameters())
66+
67+
ports = collections.OrderedDict()
68+
ports.update(clk.connect())
69+
ports.update(rst.connect())
70+
ports.update(ledif.connect_all_ports())
71+
72+
m.Instance(mkLed(), 'inst_led', params, ports)
73+
74+
return m
75+
76+
if __name__ == '__main__':
77+
led_module = mkTop()
78+
led_code = led_module.to_verilog()
79+
print(led_code)

sample/test/lib-interface/test_led.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import led
2+
3+
expected_verilog = """
4+
module top #
5+
(
6+
parameter WIDTH = 8
7+
)
8+
(
9+
input CLK,
10+
input RST,
11+
output [WIDTH-1:0] LED
12+
);
13+
blinkled #
14+
(
15+
.WIDTH(WIDTH)
16+
)
17+
inst_led
18+
(
19+
.CLK(CLK),
20+
.RST(RST),
21+
.LED(LED)
22+
);
23+
endmodule
24+
25+
module blinkled #
26+
(
27+
parameter WIDTH = 8
28+
)
29+
(
30+
input CLK,
31+
input RST,
32+
output reg [WIDTH-1:0] LED
33+
);
34+
reg [32-1:0] count;
35+
always @(posedge CLK) begin
36+
if(RST) begin
37+
count <= 0;
38+
LED <= 0;
39+
end else begin
40+
if(count == 1023) begin
41+
count <= 0;
42+
LED <= LED + 1;
43+
end else begin
44+
count <= count + 1;
45+
end
46+
end
47+
end
48+
endmodule
49+
"""
50+
51+
def test_led():
52+
led_module = led.mkTop()
53+
led_code = led_module.to_verilog()
54+
55+
from pyverilog.vparser.parser import VerilogParser
56+
from pyverilog.ast_code_generator.codegen import ASTCodeGenerator
57+
parser = VerilogParser()
58+
expected_ast = parser.parse(expected_verilog)
59+
codegen = ASTCodeGenerator()
60+
expected_code = codegen.visit(expected_ast)
61+
62+
assert(led_code == expected_code)

sample/test/lib-interface/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: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import vtypes
1717

1818
from module import Module
19-
from interface import Interface
2019
from function import Function
2120
from vtypes import *
2221

veriloggen/lib/__init__.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
1+
#-------------------------------------------------------------------------------
2+
# lib/__init__.py
3+
#
4+
# Veriloggen library
5+
#
6+
# Copyright (C) 2015, Shinya Takamaeda-Yamazaki
7+
# License: Apache 2.0
8+
#-------------------------------------------------------------------------------
9+
110
import os
211
import sys
312
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
413

14+
## Please add import notations here for additional library
15+
from interface import Interface
516
from fsm import FSM

veriloggen/lib/fsm.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import os
22
import sys
3-
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
4-
53
import collections
4+
5+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
66
import vtypes
77

8-
class FSM(object):
8+
class FSM(vtypes.VeriloggenNode):
99
""" Finite State Machine Generator """
1010
def __init__(self, m, name, width=32, initname='init'):
1111
self.m = m

veriloggen/interface.py renamed to veriloggen/lib/interface.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
import sys
33
import collections
44
import re
5-
6-
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
5+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
76

87
import vtypes
98
import module

0 commit comments

Comments
 (0)