HDLRuby 2.4.14 → 2.4.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/HDLRuby/hdr_samples/WithMultiChannelExpVerilog/with_multi_channels_hs_32.v +1277 -0
- data/lib/HDLRuby/hdr_samples/WithMultiChannelExpVerilog/with_multi_channels_qu_213.v +1345 -0
- data/lib/HDLRuby/hdr_samples/WithMultiChannelExpVerilog/with_multi_channels_qu_222.v +1339 -0
- data/lib/HDLRuby/hdr_samples/WithMultiChannelExpVerilog/with_multi_channels_rg_23.v +1248 -0
- data/lib/HDLRuby/hdr_samples/make_multi_channels_v.rb +24 -0
- data/lib/HDLRuby/hdr_samples/with_connector.rb +64 -17
- data/lib/HDLRuby/hdr_samples/with_connector_memory.rb +98 -0
- data/lib/HDLRuby/hdr_samples/with_multi_channels.rb +0 -12
- data/lib/HDLRuby/hruby_tools.rb +7 -1
- data/lib/HDLRuby/sim/hruby_sim_calc.c +3 -1
- data/lib/HDLRuby/std/connector.rb +100 -13
- data/lib/HDLRuby/std/memory.rb +121 -0
- data/lib/HDLRuby/version.rb +1 -1
- metadata +8 -2
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# Script for generating the vcd files.
|
3
|
+
|
4
|
+
# The configuration scenarii
|
5
|
+
$scenarii = [
|
6
|
+
[:_clk2_clk2, :register], # 0
|
7
|
+
[:_clk2_nclk2, :register], # 1
|
8
|
+
[:_clk2_clk3, :register], # 2
|
9
|
+
[:_clk3_clk2, :register], # 3
|
10
|
+
[:_clk2_clk2, :handshake], # 4
|
11
|
+
[:_clk2_nclk2, :handshake], # 5
|
12
|
+
[:_clk2_clk3, :handshake], # 6
|
13
|
+
[:_clk3_clk2, :handshake], # 7
|
14
|
+
[:clk2_clk2_clk2, :queue], # 8
|
15
|
+
[:clk2_clk2_nclk2, :queue], # 9
|
16
|
+
[:clk1_clk2_clk3, :queue], # 10
|
17
|
+
[:clk3_clk2_clk1, :queue], # 11
|
18
|
+
[:clk2_clk3_clk1, :queue], # 12
|
19
|
+
[:clk2_clk1_clk3, :queue], # 13
|
20
|
+
]
|
21
|
+
$scenarii.each_with_index do |scenarii,i|
|
22
|
+
puts "scenario: [#{i}] #{scenarii}"
|
23
|
+
`bundle exec ../hdrcc.rb --verilog with_multi_channels.rb WithMultiChannelPaper.V#{i} #{i}`
|
24
|
+
end
|
@@ -125,20 +125,45 @@ end
|
|
125
125
|
# Module for testing the connector.
|
126
126
|
system :with_connectors do
|
127
127
|
inner :clk, :rst
|
128
|
-
|
128
|
+
|
129
|
+
# First tester.
|
130
|
+
[4].inner :counter
|
131
|
+
[4*4].inner :res
|
129
132
|
inner :ack_in, :ack_out
|
133
|
+
inner :dup_req, :dup_ack
|
130
134
|
|
131
135
|
# The input queue.
|
132
136
|
queue(bit[4],4,clk,rst).(:in_qu)
|
133
137
|
|
134
|
-
# The
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
138
|
+
# The middle queues.
|
139
|
+
mid_qus = 4.times.map do |i|
|
140
|
+
queue(bit[4],4,clk,rst).(:"mid_qu#{i}")
|
141
|
+
end
|
142
|
+
|
143
|
+
# The output queue.
|
144
|
+
queue(bit[4*4],4,clk,rst).(:out_qu)
|
145
|
+
|
146
|
+
# Connect the input queue to the middle queues.
|
147
|
+
duplicator(bit[4],clk.negedge,in_qu,mid_qus,dup_req,dup_ack)
|
148
|
+
|
149
|
+
# Connect the middle queues to the output queue.
|
150
|
+
merger([bit[4]]*4,clk.negedge,mid_qus,out_qu)
|
139
151
|
|
140
|
-
|
141
|
-
|
152
|
+
|
153
|
+
# Second tester.
|
154
|
+
[4].inner :counterb
|
155
|
+
[4].inner :resb
|
156
|
+
inner :ack_inb0, :ack_inb1, :ack_outb
|
157
|
+
|
158
|
+
# The input queues.
|
159
|
+
queue(bit[4],4,clk,rst).(:in_qub0)
|
160
|
+
queue(bit[4],4,clk,rst).(:in_qub1)
|
161
|
+
|
162
|
+
# The output queue.
|
163
|
+
queue(bit[4],4,clk,rst).(:out_qub)
|
164
|
+
|
165
|
+
# Connect then with a serializer.
|
166
|
+
serializer(bit[4],clk.negedge,[in_qub0,in_qub1],out_qub)
|
142
167
|
|
143
168
|
# # Slow version, always work
|
144
169
|
# par(clk.posedge) do
|
@@ -154,10 +179,10 @@ system :with_connectors do
|
|
154
179
|
# end
|
155
180
|
# end
|
156
181
|
# hif(ack_in) do
|
157
|
-
#
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
182
|
+
# mid_qu0.read(res_0)
|
183
|
+
# mid_qu1.read(res_1)
|
184
|
+
# mid_qu2.read(res_2)
|
185
|
+
# mid_qu3.read(res_3) { ack_out <= 1 }
|
161
186
|
# end
|
162
187
|
# end
|
163
188
|
# end
|
@@ -165,17 +190,31 @@ system :with_connectors do
|
|
165
190
|
# Fast version but assumes connected channels are blocking
|
166
191
|
par(clk.posedge) do
|
167
192
|
ack_in <= 0
|
168
|
-
|
193
|
+
ack_inb0 <= 0
|
194
|
+
ack_inb1 <= 0
|
195
|
+
hif(rst) { counter <= 0; counterb <= 0 }
|
169
196
|
helse do
|
170
197
|
in_qu.write(counter) do
|
171
198
|
ack_in <= 1
|
172
199
|
counter <= counter + 1
|
173
200
|
end
|
174
201
|
hif(ack_in) do
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
202
|
+
out_qu.read(res)
|
203
|
+
end
|
204
|
+
hif(~ack_inb0) do
|
205
|
+
in_qub0.write(counterb) do
|
206
|
+
ack_inb0 <= 1
|
207
|
+
counterb <= counterb + 1
|
208
|
+
end
|
209
|
+
end
|
210
|
+
helse do
|
211
|
+
in_qub1.write(counterb) do
|
212
|
+
ack_inb1 <= 1
|
213
|
+
counterb <= counterb + 1
|
214
|
+
end
|
215
|
+
end
|
216
|
+
hif(ack_inb0 | ack_inb1) do
|
217
|
+
out_qub.read(resb)
|
179
218
|
end
|
180
219
|
end
|
181
220
|
end
|
@@ -183,6 +222,7 @@ system :with_connectors do
|
|
183
222
|
timed do
|
184
223
|
clk <= 0
|
185
224
|
rst <= 0
|
225
|
+
dup_req <= 0
|
186
226
|
!10.ns
|
187
227
|
clk <= 1
|
188
228
|
!10.ns
|
@@ -197,6 +237,13 @@ system :with_connectors do
|
|
197
237
|
!10.ns
|
198
238
|
clk <= 0
|
199
239
|
rst <= 0
|
240
|
+
4.times do
|
241
|
+
!10.ns
|
242
|
+
clk <= 1
|
243
|
+
!10.ns
|
244
|
+
clk <= 0
|
245
|
+
end
|
246
|
+
dup_req <= 1
|
200
247
|
16.times do
|
201
248
|
!10.ns
|
202
249
|
clk <= 1
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'std/memory.rb'
|
2
|
+
require "std/fixpoint.rb"
|
3
|
+
require 'std/channel.rb'
|
4
|
+
require 'std/connector.rb'
|
5
|
+
|
6
|
+
include HDLRuby::High::Std
|
7
|
+
|
8
|
+
system :channel_connector do
|
9
|
+
# データ型の宣言
|
10
|
+
integer_width = 4 # 整数部のビット幅
|
11
|
+
decimal_width = 4 # 実数部のビット幅
|
12
|
+
address_width = 4 # lutのアドレスのビット幅
|
13
|
+
typ = signed[integer_width + decimal_width] # データ型
|
14
|
+
|
15
|
+
inputs_x = _00010011
|
16
|
+
inputs_h = _10100001
|
17
|
+
columns = [2, 2, 1]
|
18
|
+
|
19
|
+
inner :clk, # clock
|
20
|
+
:rst, # reset
|
21
|
+
:req, # request
|
22
|
+
:fill # 入力値のメモリへの書き込み
|
23
|
+
|
24
|
+
# inputs_x = quantize(inputs_x, typ, decimal_width)
|
25
|
+
# inputs_h = quantize(inputs_h, typ, decimal_width)
|
26
|
+
|
27
|
+
mem_rom(typ, columns[0], clk, rst, inputs_x, rinc: :rst, winc: :rst).(:rom_inputs_x) # 入力値を格納するrom(x)
|
28
|
+
|
29
|
+
mem_rom(typ, columns[0], clk, rst, inputs_h, rinc: :rst, winc: :rst).(:rom_inputs_h) # 入力値を格納するrom(h)
|
30
|
+
|
31
|
+
mem_dual(typ, columns[0], clk, rst, rinc: :rst, winc: :rst).(:ram_inputs_serializer) #
|
32
|
+
|
33
|
+
mem_dual(typ, columns[0]*2, clk, rst, rinc: :rst, winc: :rst).(:ram_inputs_merger) #
|
34
|
+
|
35
|
+
reader_inputs_x = rom_inputs_x.branch(:rinc) #入力値xの読みだし用branch
|
36
|
+
reader_inputs_h = rom_inputs_h.branch(:rinc) #入力値hの読みだし用branch
|
37
|
+
writer_inputs_serializer = ram_inputs_serializer.branch(:winc) #入力値を合成した値の書き込み用branch
|
38
|
+
writer_inputs_meger = ram_inputs_merger.branch(:winc) #入力値を合成した値の書き込み用branch
|
39
|
+
|
40
|
+
|
41
|
+
serializer(typ,clk.negedge,[reader_inputs_x,reader_inputs_h],writer_inputs_serializer)
|
42
|
+
|
43
|
+
# merger([typ]*2,clk.negedge,[reader_inputs_x,reader_inputs_h], writer_inputs_meger)
|
44
|
+
|
45
|
+
# duplicator(typ,clk.negedge,reader_inputs_r,[])
|
46
|
+
|
47
|
+
|
48
|
+
timed do
|
49
|
+
# リセット
|
50
|
+
clk <= 0
|
51
|
+
rst <= 0
|
52
|
+
req <= 0
|
53
|
+
fill <= 0
|
54
|
+
!10.ps
|
55
|
+
|
56
|
+
# メモリ読み出し位置の初期化
|
57
|
+
rst <= 1
|
58
|
+
!10.ps
|
59
|
+
clk <= 1
|
60
|
+
!10.ps
|
61
|
+
clk <= 0
|
62
|
+
!10.ps
|
63
|
+
clk <= 1
|
64
|
+
!10.ps
|
65
|
+
|
66
|
+
# パラメータのメモリへの書き込み
|
67
|
+
clk <= 0
|
68
|
+
rst <= 0
|
69
|
+
fill <= 1
|
70
|
+
|
71
|
+
!10.ps
|
72
|
+
10.times do |i|
|
73
|
+
clk <= 1
|
74
|
+
!10.ps
|
75
|
+
clk <= 0
|
76
|
+
!10.ps
|
77
|
+
end
|
78
|
+
|
79
|
+
fill <= 0
|
80
|
+
clk <= 1
|
81
|
+
!10.ps
|
82
|
+
|
83
|
+
# 計算の実行
|
84
|
+
clk <= 0
|
85
|
+
req <= 1
|
86
|
+
!10.ps
|
87
|
+
clk <= 1
|
88
|
+
!10.ps
|
89
|
+
clk <= 0
|
90
|
+
!10.ps
|
91
|
+
30.times do
|
92
|
+
clk <= 1
|
93
|
+
!10.ps
|
94
|
+
clk <= 0
|
95
|
+
!10.ps
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -23,12 +23,6 @@ channel(:queue) do |typ,depth,clk,rst|
|
|
23
23
|
par(clk.posedge) do
|
24
24
|
hif(rst) { rptr <= 0; wptr <= 0 }
|
25
25
|
helse do
|
26
|
-
# hif(rsync) do
|
27
|
-
# hif(rptr != wptr) do
|
28
|
-
# rdata <= buffer[rptr]
|
29
|
-
# end
|
30
|
-
# end
|
31
|
-
# helse do
|
32
26
|
hif(~rsync) do
|
33
27
|
hif (~rreq) { rack <= 0 }
|
34
28
|
hif(rreq & (~rack) & (rptr != wptr)) do
|
@@ -38,10 +32,6 @@ channel(:queue) do |typ,depth,clk,rst|
|
|
38
32
|
end
|
39
33
|
end
|
40
34
|
|
41
|
-
# hif(wsync) do
|
42
|
-
# buffer[wptr] <= wdata
|
43
|
-
# end
|
44
|
-
# helse do
|
45
35
|
hif(~wsync) do
|
46
36
|
hif (~wreq) { wack <= 0 }
|
47
37
|
hif(wreq & (~wack) & (((wptr+1) % depth) != rptr)) do
|
@@ -67,7 +57,6 @@ channel(:queue) do |typ,depth,clk,rst|
|
|
67
57
|
end
|
68
58
|
seq do
|
69
59
|
hif(rptr != wptr) do
|
70
|
-
# target <= rdata
|
71
60
|
target <= buffer[rptr]
|
72
61
|
rptr <= (rptr + 1) % depth
|
73
62
|
blk.call if blk
|
@@ -102,7 +91,6 @@ channel(:queue) do |typ,depth,clk,rst|
|
|
102
91
|
wreq <= 0
|
103
92
|
end
|
104
93
|
hif(((wptr+1) % depth) != rptr) do
|
105
|
-
# wdata <= target
|
106
94
|
buffer[wptr] <= target
|
107
95
|
wptr <= (wptr + 1) % depth
|
108
96
|
blk.call if blk
|
data/lib/HDLRuby/hruby_tools.rb
CHANGED
@@ -29,8 +29,14 @@ module HDLRuby
|
|
29
29
|
class ::Integer
|
30
30
|
|
31
31
|
# Gets the bit width
|
32
|
+
# NOTE: returns infinity if the number is negative.
|
32
33
|
def width
|
33
|
-
return Math.log2(self+1).ceil
|
34
|
+
return self >= 0 ? Math.log2(self+1).ceil : 1.0/0.0
|
35
|
+
end
|
36
|
+
|
37
|
+
# Tells if the value is a power of 2.
|
38
|
+
def pow2?
|
39
|
+
return self > 0 && (self & (self - 1) == 0)
|
34
40
|
end
|
35
41
|
end
|
36
42
|
|
@@ -1223,6 +1223,8 @@ static Value concat_value_bitstring_array(int num, int dir,
|
|
1223
1223
|
}
|
1224
1224
|
/* Resize the destination accordignly. */
|
1225
1225
|
resize_value(dst,width);
|
1226
|
+
/* Ensure it is not numeric. */
|
1227
|
+
dst->numeric = 0;
|
1226
1228
|
|
1227
1229
|
/* Access the data of the destination. */
|
1228
1230
|
char* dst_data = dst->data_str;
|
@@ -1233,7 +1235,7 @@ static Value concat_value_bitstring_array(int num, int dir,
|
|
1233
1235
|
unsigned int idx = dir ? (num-i-1) : i;
|
1234
1236
|
Value value = args[idx];
|
1235
1237
|
unsigned long long cw = type_width(value->type);
|
1236
|
-
// printf("value=%s cw=%llu\n",value->data_str,cw);
|
1238
|
+
// printf("value=%s cw=%llu pos=%llu\n",value->data_str,cw,pos);
|
1237
1239
|
memcpy(dst_data+pos,value->data_str,cw);
|
1238
1240
|
pos += cw;
|
1239
1241
|
}
|
@@ -6,37 +6,124 @@ module HDLRuby::High::Std
|
|
6
6
|
########################################################################
|
7
7
|
|
8
8
|
# Function for generating a connector that duplicates the output of
|
9
|
-
# channel +
|
9
|
+
# channel +in_ch+ and connect it to channels +out_chs+ with data of
|
10
10
|
# +typ+.
|
11
11
|
# The duplication is done according to event +ev+.
|
12
|
-
|
12
|
+
# The optional req and ack arguments are the signals for controlling the
|
13
|
+
# duplicator using a handshake protocol. If set to nil, the duplicator
|
14
|
+
# runs automatically.
|
15
|
+
function :duplicator do |typ, ev, in_ch, out_chs, req = nil, ack = nil|
|
13
16
|
ev = ev.poswedge unless ev.is_a?(Event)
|
14
|
-
inner :in_ack
|
15
|
-
|
16
|
-
|
17
|
-
end
|
17
|
+
inner :in_ack
|
18
|
+
inner :in_req
|
19
|
+
out_acks = out_chs.size.times.map { |i| inner(:"out_ack#{i}") }
|
18
20
|
typ.inner :data
|
19
21
|
par(ev) do
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
if (ack) then
|
23
|
+
# Output ack mode.
|
24
|
+
ack <= 0
|
25
|
+
end
|
26
|
+
if (req) then
|
27
|
+
# Input request mode.
|
28
|
+
in_req <= 0
|
29
|
+
hif(req) { in_req <= 1 }
|
30
|
+
else
|
31
|
+
# Automatic mode.
|
32
|
+
in_req <= 1
|
33
|
+
end
|
34
|
+
out_acks.each { |ack| ack <= 0 }
|
35
|
+
out_acks.each do |ack|
|
23
36
|
hif(ack == 1) { in_req <= 0 }
|
24
37
|
end
|
25
38
|
hif(in_req) do
|
26
39
|
in_ack <= 0
|
27
|
-
|
40
|
+
in_ch.read(data) { in_ack <= 1 }
|
28
41
|
end
|
29
42
|
hif(in_ack) do
|
30
|
-
|
43
|
+
out_chs.zip(out_acks).each do |ch,ack|
|
31
44
|
hif(ack == 0) { ch.write(data) { ack <= 1 } }
|
32
45
|
end
|
33
|
-
hif (
|
34
|
-
|
46
|
+
hif (out_acks.reduce(_1) { |sum,ack| ack & sum }) do
|
47
|
+
out_acks.each { |ack| ack <= 0 }
|
48
|
+
if (ack) then
|
49
|
+
# Output ack mode.
|
50
|
+
ack <= 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Function for generating a connector that merges the output of
|
58
|
+
# channels +in_chs+ and connects the result to channel +out_ch+ with
|
59
|
+
# data of types from +typs+.
|
60
|
+
# The merge is done according to event +ev+.
|
61
|
+
function :merger do |typs, ev, in_chs, out_ch|
|
62
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
63
|
+
inner :out_ack
|
64
|
+
in_reqs = in_chs.size.times.map { |i| inner(:"in_req#{i}") }
|
65
|
+
in_acks = in_chs.size.times.map { |i| inner(:"in_ack#{i}") }
|
66
|
+
datas = typs.map.with_index { |typ,i| typ.inner(:"data#{i}") }
|
67
|
+
par(ev) do
|
68
|
+
in_reqs.each { |req| req <= 1 }
|
69
|
+
out_ack <= 0
|
70
|
+
hif(out_ack == 1) { in_reqs.each { |req| req <= 0 } }
|
71
|
+
hif(in_reqs.reduce(_1) { |sum,req| req & sum }) do
|
72
|
+
in_chs.each_with_index do |ch,i|
|
73
|
+
in_acks[i] <= 0
|
74
|
+
ch.read(datas[i]) { in_acks[i] <= 1 }
|
35
75
|
end
|
36
76
|
end
|
77
|
+
hif(in_acks.reduce(_1) { |sum,req| req & sum }) do
|
78
|
+
hif(out_ack == 0) { out_ch.write(datas) { out_ack <= 1 } }
|
79
|
+
hif (out_ack == 1) { out_ack <= 0 }
|
80
|
+
end
|
37
81
|
end
|
38
82
|
end
|
39
83
|
|
40
84
|
|
85
|
+
# Function for generating a connector that serialize to the output of
|
86
|
+
# channels +in_chs+ and connects the result to channel +out_ch+ with
|
87
|
+
# data of +typ+.
|
88
|
+
# The merge is done according to event +ev+.
|
89
|
+
function :serializer do |typ, ev, in_chs, out_ch|
|
90
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
91
|
+
size = in_chs.size
|
92
|
+
inner :out_ack
|
93
|
+
# in_reqs = size.times.map { |i| inner(:"in_req#{i}") }
|
94
|
+
in_acks = size.times.map { |i| inner(:"in_ack#{i}") }
|
95
|
+
datas = size.times.map { |i| typ.inner(:"data#{i}") }
|
96
|
+
# The inpt channel selector
|
97
|
+
[size.width].inner :idx
|
98
|
+
inner :reading
|
99
|
+
par(ev) do
|
100
|
+
# in_reqs.each { |req| req <= 1 }
|
101
|
+
idx <= 0
|
102
|
+
reading <= 0
|
103
|
+
out_ack <= 0
|
104
|
+
hif(idx == size-1) { in_acks.each { |ack| ack <= 0 } }
|
105
|
+
# hif((idx == 0) & (in_reqs.reduce(_1) { |sum,req| req & sum })) do
|
106
|
+
hif(idx == 0) do
|
107
|
+
hif(~reading) do
|
108
|
+
size.times { |i| in_acks[i] <= 0 }
|
109
|
+
end
|
110
|
+
reading <= 1
|
111
|
+
in_chs.each_with_index do |ch,i|
|
112
|
+
hif(~in_acks[i]) do
|
113
|
+
ch.read(datas[i]) { in_acks[i] <= 1 }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
hif(in_acks.reduce(_1) { |sum,req| req & sum }) do
|
118
|
+
hcase(idx)
|
119
|
+
datas.each_with_index do |data,i|
|
120
|
+
hwhen(i) do
|
121
|
+
out_ch.write(data) { idx <= idx + 1; out_ack <= 1 }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
41
128
|
|
42
129
|
end
|