Skip to content

Commit 3590b3e

Browse files
committed
sorting network
1 parent dd31ed7 commit 3590b3e

File tree

6 files changed

+462
-0
lines changed

6 files changed

+462
-0
lines changed

sample/sort/Makefile

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
TARGET=sort.py
2+
TEST=test_sort.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/sort/sim_sort.v

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
2+
module test;
3+
initial begin
4+
$dumpfile("uut.vcd");
5+
$dumpvars(0, uut);
6+
end
7+
8+
parameter WIDTH = 32;
9+
10+
reg CLK;
11+
reg RST;
12+
reg [(WIDTH - 1):0] input_0;
13+
reg [(WIDTH - 1):0] input_1;
14+
reg [(WIDTH - 1):0] input_2;
15+
reg [(WIDTH - 1):0] input_3;
16+
wire [(WIDTH - 1):0] output_0;
17+
wire [(WIDTH - 1):0] output_1;
18+
wire [(WIDTH - 1):0] output_2;
19+
wire [(WIDTH - 1):0] output_3;
20+
reg kick;
21+
wire busy;
22+
23+
sort uut(
24+
CLK,
25+
RST,
26+
input_0,
27+
input_1,
28+
input_2,
29+
input_3,
30+
output_0,
31+
output_1,
32+
output_2,
33+
output_3,
34+
kick,
35+
busy
36+
);
37+
38+
initial begin
39+
CLK = 0;
40+
forever #5 CLK = ~CLK;
41+
end
42+
43+
initial begin
44+
RST = 0;
45+
kick = 0;
46+
input_0 = 4;
47+
input_1 = 3;
48+
input_2 = 2;
49+
input_3 = 1;
50+
#100;
51+
RST = 1;
52+
#100;
53+
RST = 0;
54+
55+
@(posedge CLK);
56+
#1;
57+
58+
@(posedge CLK);
59+
#1;
60+
61+
@(posedge CLK);
62+
#1;
63+
64+
kick = 1;
65+
66+
@(posedge CLK);
67+
#1;
68+
69+
kick = 0;
70+
71+
#500;
72+
$finish;
73+
end
74+
75+
endmodule

sample/sort/sort.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import sys
2+
import os
3+
from veriloggen import *
4+
5+
def mkSort(numports=4):
6+
m = Module('sort')
7+
width = m.Parameter('WIDTH', 32)
8+
clk = m.Input('CLK')
9+
rst = m.Input('RST')
10+
inputs = [ m.Input('input_' + str(i), width) for i in range(numports) ]
11+
outputs = [ m.Output('output_' + str(i), width) for i in range(numports) ]
12+
kick = m.Input('kick')
13+
busy = m.OutputReg('busy')
14+
registers = [ m.Reg('registers_' + str(i), width) for i in range(numports) ]
15+
for i in range(numports): m.Assign(outputs[i](registers[i]))
16+
17+
_i = [0]
18+
def mk_pair():
19+
s = m.Wire('small_' + str(_i[0]), width)
20+
l = m.Wire('large_' + str(_i[0]), width)
21+
_i[0] += 1
22+
return s, l
23+
24+
def prim_net(a, b):
25+
s, l = mk_pair()
26+
m.Assign(s( Cond(a < b, a, b) )) # small
27+
m.Assign(l( Cond(a < b, b, a) )) # large
28+
return s, l
29+
30+
def chain_net(regs, fsm, e):
31+
x = regs[0]
32+
bind = []
33+
for i in range(e):
34+
s, l = prim_net(x, regs[i+1])
35+
bind.append( regs[i](s) )
36+
x = l
37+
bind.append( regs[e](x) )
38+
for i in range(e + 1, len(regs)):
39+
bind.append( regs[i](regs[i]) )
40+
fsm( bind, fsm.next() )
41+
42+
fsm = lib.FSM(m, 'fsm')
43+
idle = fsm.get_index()
44+
45+
fsm([ If(kick)([ registers[i](inputs[i]) for i in range(numports) ] +
46+
[ busy(1), fsm.next()] ) ])
47+
48+
for i in range(numports):
49+
chain_net(registers, fsm, numports-i-1)
50+
51+
fsm( busy(0), fsm.goto(idle) )
52+
53+
init = [ busy(0) ] + [ r(0) for r in registers ] + [ fsm.init() ]
54+
55+
m.Always(Posedge(clk))(
56+
If(rst)(
57+
*init
58+
).Else(
59+
fsm.to_case()
60+
))
61+
62+
return m
63+
64+
if __name__ == '__main__':
65+
led = mkSort()
66+
verilog = led.to_verilog()
67+
print(verilog)

sample/sort/test_sort.py

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import sort
2+
3+
expected_verilog = """
4+
module sort #
5+
(
6+
parameter WIDTH = 32
7+
)
8+
(
9+
input CLK,
10+
input RST,
11+
input [WIDTH-1:0] input_0,
12+
input [WIDTH-1:0] input_1,
13+
input [WIDTH-1:0] input_2,
14+
input [WIDTH-1:0] input_3,
15+
output [WIDTH-1:0] output_0,
16+
output [WIDTH-1:0] output_1,
17+
output [WIDTH-1:0] output_2,
18+
output [WIDTH-1:0] output_3,
19+
input kick,
20+
output reg busy
21+
);
22+
23+
reg [WIDTH-1:0] registers_0;
24+
reg [WIDTH-1:0] registers_1;
25+
reg [WIDTH-1:0] registers_2;
26+
reg [WIDTH-1:0] registers_3;
27+
28+
assign output_0 = registers_0;
29+
assign output_1 = registers_1;
30+
assign output_2 = registers_2;
31+
assign output_3 = registers_3;
32+
33+
reg [(32 - 1):0] fsm;
34+
35+
localparam fsm_init = 0;
36+
37+
localparam fsm_1 = 1;
38+
wire [(WIDTH - 1):0] small_0;
39+
wire [(WIDTH - 1):0] large_0;
40+
assign small_0 = (((registers_0 < registers_1))? registers_0 : registers_1);
41+
assign large_0 = (((registers_0 < registers_1))? registers_1 : registers_0);
42+
43+
wire [(WIDTH - 1):0] small_1;
44+
wire [(WIDTH - 1):0] large_1;
45+
assign small_1 = (((large_0 < registers_2))? large_0 : registers_2);
46+
assign large_1 = (((large_0 < registers_2))? registers_2 : large_0);
47+
48+
wire [(WIDTH - 1):0] small_2;
49+
wire [(WIDTH - 1):0] large_2;
50+
assign small_2 = (((large_1 < registers_3))? large_1 : registers_3);
51+
assign large_2 = (((large_1 < registers_3))? registers_3 : large_1);
52+
53+
localparam fsm_2 = 2;
54+
wire [(WIDTH - 1):0] small_3;
55+
wire [(WIDTH - 1):0] large_3;
56+
assign small_3 = (((registers_0 < registers_1))? registers_0 : registers_1);
57+
assign large_3 = (((registers_0 < registers_1))? registers_1 : registers_0);
58+
59+
wire [(WIDTH - 1):0] small_4;
60+
wire [(WIDTH - 1):0] large_4;
61+
assign small_4 = (((large_3 < registers_2))? large_3 : registers_2);
62+
assign large_4 = (((large_3 < registers_2))? registers_2 : large_3);
63+
64+
localparam fsm_3 = 3;
65+
wire [(WIDTH - 1):0] small_5;
66+
wire [(WIDTH - 1):0] large_5;
67+
assign small_5 = (((registers_0 < registers_1))? registers_0 : registers_1);
68+
assign large_5 = (((registers_0 < registers_1))? registers_1 : registers_0);
69+
70+
localparam fsm_4 = 4;
71+
72+
localparam fsm_5 = 5;
73+
74+
always @(posedge CLK) begin
75+
if(RST) begin
76+
busy <= 0;
77+
registers_0 <= 0;
78+
registers_1 <= 0;
79+
registers_2 <= 0;
80+
registers_3 <= 0;
81+
fsm <= fsm_init;
82+
end else begin
83+
case(fsm)
84+
fsm_init: begin
85+
begin
86+
if(kick) begin
87+
begin
88+
registers_0 <= input_0;
89+
registers_1 <= input_1;
90+
registers_2 <= input_2;
91+
registers_3 <= input_3;
92+
busy <= 1;
93+
fsm <= fsm_1;
94+
end
95+
end
96+
end
97+
end
98+
fsm_1: begin
99+
begin
100+
registers_0 <= small_0;
101+
registers_1 <= small_1;
102+
registers_2 <= small_2;
103+
registers_3 <= large_2;
104+
end
105+
fsm <= fsm_2;
106+
end
107+
fsm_2: begin
108+
begin
109+
registers_0 <= small_3;
110+
registers_1 <= small_4;
111+
registers_2 <= large_4;
112+
registers_3 <= registers_3;
113+
end
114+
fsm <= fsm_3;
115+
end
116+
fsm_3: begin
117+
begin
118+
registers_0 <= small_5;
119+
registers_1 <= large_5;
120+
registers_2 <= registers_2;
121+
registers_3 <= registers_3;
122+
end
123+
fsm <= fsm_4;
124+
end
125+
fsm_4: begin
126+
begin
127+
registers_0 <= registers_0;
128+
registers_1 <= registers_1;
129+
registers_2 <= registers_2;
130+
registers_3 <= registers_3;
131+
end
132+
fsm <= fsm_5;
133+
end
134+
fsm_5: begin
135+
busy <= 0;
136+
fsm <= fsm_init;
137+
end
138+
endcase
139+
end
140+
end
141+
endmodule
142+
"""
143+
144+
def test_sort():
145+
sort_module = sort.mkSort()
146+
sort_code = sort_module.to_verilog()
147+
148+
from pyverilog.vparser.parser import VerilogParser
149+
from pyverilog.ast_code_generator.codegen import ASTCodeGenerator
150+
parser = VerilogParser()
151+
expected_ast = parser.parse(expected_verilog)
152+
codegen = ASTCodeGenerator()
153+
expected_code = codegen.visit(expected_ast)
154+
155+
assert(expected_code == sort_code)

0 commit comments

Comments
 (0)