HDLRuby 2.4.14 → 2.4.20

Sign up to get free protection for your applications and to get access to all the features.
@@ -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