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.
@@ -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
- [4].inner :counter, :res_0,:res_1,:res_2,:res_3
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 first output queue.
135
- queue(bit[4],4,clk,rst).(:out_qu0)
136
- queue(bit[4],4,clk,rst).(:out_qu1)
137
- queue(bit[4],4,clk,rst).(:out_qu2)
138
- queue(bit[4],4,clk,rst).(:out_qu3)
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
- # Connect them
141
- duplicator([4],clk.negedge,in_qu,[out_qu0,out_qu1,out_qu2,out_qu3])
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
- # out_qu0.read(res_0)
158
- # out_qu1.read(res_1)
159
- # out_qu2.read(res_2)
160
- # out_qu3.read(res_3) { ack_out <= 1 }
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
- hif(rst) { counter <= 0 }
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
- out_qu0.read(res_0)
176
- out_qu1.read(res_1)
177
- out_qu2.read(res_2)
178
- out_qu3.read(res_3)
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
@@ -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 +inch+ and connect it to channels +outchs+ with data of
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
- function :duplicator do |typ, ev, inch, outchs|
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, :in_req
15
- out_chacks = outchs.map.with_index do |ch,i|
16
- [ ch, inner(:"out_ack#{i}") ]
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
- in_req <= 1
21
- out_chacks.each { |ch,ack| ack <= 0 }
22
- out_chacks.each do |ch,ack|
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
- inch.read(data) { in_ack <= 1 }
40
+ in_ch.read(data) { in_ack <= 1 }
28
41
  end
29
42
  hif(in_ack) do
30
- out_chacks.each do |ch,ack|
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 (out_chacks.reduce(_1) { |sum,(ch,ack)| ack & sum }) do
34
- out_chacks.each { |ch,ack| ack <= 0 }
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