HDLRuby 2.2.14 → 2.2.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a6a6e334b6e55bdc8f7947f92f4dd8a9de83fc0f90725bad5bfafedc27a8ca2e
4
- data.tar.gz: a6f43c383176d02af9e8491c6b2425b5e1e8ca3c339464842dbf288fbe91dc26
3
+ metadata.gz: cac7290729b07ecdbbd73528b0807e601c8ba0f04e6d2476bbd075d5c4dbb648
4
+ data.tar.gz: b2d244a59dcff8b363e6d1cdd66ff22cca81ffa24b666b97eb46b7b142047787
5
5
  SHA512:
6
- metadata.gz: 50a46ad334407428425912ec7b1fbd745d1de686e8792548524f23d4ca10f6252368b589f5fc77b201b07f1becf86aa7c234c77443b1014caad341c1fa0fa966
7
- data.tar.gz: c8defb6937e32d43ddd0c56f49a2a608a8444a8ca0eef10f387fb1fc89597dc13871ce086223e8d1892799d1518d9a5cf915142e500cf4c74937bdfbfff68514
6
+ metadata.gz: '093bfbd1c000b0d7a4e039d51a8a27da09483ac1b61f0d19d78a3999d9231abe6df0611b720e4d47409b8c9769a31e7f3770f8bd6fa0246b8854ea15f56d1648'
7
+ data.tar.gz: fb97205d4d7f542efb02e4951c696783c8d3f99b7f6def0f3a2cfbae27c7ff3d5e72459ba8aa899c6e93241d92302958177be0ee47472f329272f0c5fa2afd09
@@ -0,0 +1,207 @@
1
+ require 'std/memory.rb'
2
+ require 'std/linear.rb'
3
+
4
+ include HDLRuby::High::Std
5
+
6
+ # Tries for matrix-vector product.
7
+
8
+
9
+
10
+
11
+
12
+ # Sample code for testing the linear library.
13
+
14
+ system :linear_test do
15
+
16
+ # Clock and reset.
17
+ inner :clk,:rst
18
+
19
+ # Request and acknoledge signals.
20
+ inner :req
21
+ [8].inner :ack
22
+
23
+
24
+ # Circuit for testing the scaling.
25
+
26
+ # Input memory
27
+ mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_scale_in)
28
+ # Output memory
29
+ mem_file([8],8,clk,rst, winc: :rst).(:mem_scale_out)
30
+ # Access ports.
31
+ mem_scale_in.branch(:anum).inner :mem_scale_inP
32
+ mem_scale_inPs = 8.times.map { |i| mem_scale_inP.wrap(i) }
33
+ mem_scale_out.branch(:anum).inner :mem_scale_outP
34
+ mem_scale_outPs = 8.times.map { |i| mem_scale_outP.wrap(i) }
35
+
36
+ # Build the scaler.
37
+ scale([8],clk.posedge,req,ack[0],channel_port(3),
38
+ mem_scale_inPs,mem_scale_outPs)
39
+
40
+
41
+ # Circuit for testing the parallel addition.
42
+
43
+ # Input memories
44
+ mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_addn_left_in)
45
+ mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_addn_right_in)
46
+ # Output memory
47
+ mem_file([8],8,clk,rst, winc: :rst).(:mem_addn_out)
48
+ # Access ports.
49
+ mem_addn_left_in.branch(:anum).inner :mem_addn_left_inP
50
+ mem_addn_left_inPs = 8.times.map { |i| mem_addn_left_inP.wrap(i) }
51
+ mem_addn_right_in.branch(:anum).inner :mem_addn_right_inP
52
+ mem_addn_right_inPs = 8.times.map { |i| mem_addn_right_inP.wrap(i) }
53
+ mem_addn_out.branch(:anum).inner :mem_addn_outP
54
+ mem_addn_outPs = 8.times.map { |i| mem_addn_outP.wrap(i) }
55
+
56
+ # Build the adder.
57
+ add_n([8],clk.posedge,ack[0],ack[1],mem_addn_left_inPs,
58
+ mem_addn_right_inPs,mem_addn_outPs)
59
+
60
+
61
+ # Circuit for testing the parallel multiplication.
62
+
63
+ # Input memories
64
+ mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_muln_left_in)
65
+ mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_muln_right_in)
66
+ # Output memory
67
+ mem_file([8],8,clk,rst, winc: :rst).(:mem_muln_out)
68
+ # Access ports.
69
+ mem_muln_left_in.branch(:anum).inner :mem_muln_left_inP
70
+ mem_muln_left_inPs = 8.times.map { |i| mem_muln_left_inP.wrap(i) }
71
+ mem_muln_right_in.branch(:anum).inner :mem_muln_right_inP
72
+ mem_muln_right_inPs = 8.times.map { |i| mem_muln_right_inP.wrap(i) }
73
+ mem_muln_out.branch(:anum).inner :mem_muln_outP
74
+ mem_muln_outPs = 8.times.map { |i| mem_muln_outP.wrap(i) }
75
+
76
+ # Build the multer.
77
+ mul_n([8],clk.posedge,ack[1],ack[2],mem_muln_left_inPs,
78
+ mem_muln_right_inPs,mem_muln_outPs)
79
+
80
+
81
+ # Circuit for testing the mac
82
+ # Output signal.
83
+ [8].inner :acc
84
+
85
+ # Build the mac.
86
+ mac([8],clk.posedge,ack[2],ack[3],channel_port(5), channel_port(6),
87
+ channel_port(acc))
88
+
89
+
90
+ # Circuit for testing the parallel mac.
91
+ # Input memory
92
+ mem_file([8],8,clk,rst, winc: :rst).(:mem_macn1_left_in)
93
+ # Output memory
94
+ mem_file([8],8,clk,rst, winc: :rst).(:mem_macn1_out)
95
+ # Access ports.
96
+ mem_macn1_left_in.branch(:anum).inner :mem_macn1_left_inP
97
+ mem_macn1_left_inPs = 8.times.map { |i| mem_macn1_left_inP.wrap(i) }
98
+ mem_macn1_out.branch(:anum).inner :mem_macn1_outP
99
+ mem_macn1_outPs = 8.times.map { |i| mem_macn1_outP.wrap(i) }
100
+
101
+ # Build the mac.
102
+ mac_n1([8],clk.posedge,ack[3],ack[4], mem_macn1_left_inPs,
103
+ channel_port(5), mem_macn1_outPs)
104
+
105
+
106
+ # The memory initializer.
107
+ # Writing ports
108
+ mem_scale_in.branch(:winc).inner :mem_scale_in_writeP
109
+ mem_addn_left_in.branch(:winc).inner :mem_addn_left_in_writeP
110
+ mem_addn_right_in.branch(:winc).inner :mem_addn_right_in_writeP
111
+ mem_muln_left_in.branch(:winc).inner :mem_muln_left_in_writeP
112
+ mem_muln_right_in.branch(:winc).inner :mem_muln_right_in_writeP
113
+ mem_macn1_left_in.branch(:winc).inner :mem_macn1_left_in_writeP
114
+ # Filling index
115
+ [8].inner :idx
116
+ # Filling counter
117
+ [3].inner :cnt
118
+ # Filling value
119
+ [8].inner :val
120
+
121
+ # Start flag
122
+ inner :start
123
+
124
+ # The execution process
125
+ par(clk.posedge) do
126
+ hif(rst) { cnt <= 0; val <= 0 }
127
+ helse do
128
+ # Step index processing.
129
+ hif(cnt == 7) do
130
+ hif(idx < 6) { idx <= idx + 1 }
131
+ end
132
+ # Memory filling steps.
133
+ hcase(idx)
134
+ hwhen(0) do
135
+ mem_scale_in_writeP.write(val) do
136
+ cnt <= cnt + 1; val <= val + 1
137
+ end
138
+ end
139
+ hwhen(1) do
140
+ mem_addn_left_in_writeP.write(val) do
141
+ cnt <= cnt + 1; val <= val + 1
142
+ end
143
+ end
144
+ hwhen(2) do
145
+ mem_addn_right_in_writeP.write(val) do
146
+ cnt <= cnt + 1; val <= val + 1
147
+ end
148
+ end
149
+ hwhen(3) do
150
+ mem_muln_left_in_writeP.write(val-24) do
151
+ cnt <= cnt + 1; val <= val + 1
152
+ end
153
+ end
154
+ hwhen(4) do
155
+ mem_muln_right_in_writeP.write(val-24) do
156
+ cnt <= cnt + 1; val <= val + 1
157
+ end
158
+ end
159
+ hwhen(5) do
160
+ mem_macn1_left_in_writeP.write(val-32) do
161
+ cnt <= cnt + 1; val <= val + 1
162
+ end
163
+ end
164
+ # Computation steps.
165
+ helse do
166
+ hif(start) do
167
+ req <= 1
168
+ start <= 0
169
+ end
170
+ helse { req <= 0 }
171
+ end
172
+ end
173
+ end
174
+
175
+
176
+ # The test bench.
177
+ timed do
178
+ req <= 0
179
+ ack <= 0
180
+ clk <= 0
181
+ rst <= 0
182
+ cnt <= 0
183
+ idx <= 0
184
+ val <= 0
185
+ start <= 0
186
+ !10.ns
187
+ clk <= 1
188
+ !10.ns
189
+ # Reset
190
+ clk <= 0
191
+ rst <= 1
192
+ !10.ns
193
+ clk <= 1
194
+ !10.ns
195
+ clk <= 0
196
+ rst <= 0
197
+ start <= 1
198
+ !10.ns
199
+ # Run
200
+ 64.times do
201
+ clk <= 1
202
+ !10.ns
203
+ clk <= 0
204
+ !10.ns
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,163 @@
1
+ require 'std/memory.rb'
2
+ require 'std/linear.rb'
3
+
4
+ include HDLRuby::High::Std
5
+
6
+ # Tries for matrix-vector product.
7
+
8
+
9
+
10
+
11
+
12
+ # Testing.
13
+ system :testmat do
14
+
15
+ inner :clk,:rst, :req
16
+
17
+ # Input memories
18
+ mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memL0)
19
+ mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memL1)
20
+ mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memR)
21
+ # Access ports.
22
+ memL0.branch(:rinc).inner :readL0
23
+ memL1.branch(:rinc).inner :readL1
24
+ memR.branch(:rinc).inner :readR
25
+
26
+ # Prepares the left and acc arrays.
27
+ lefts = [readL0, readL1]
28
+
29
+ # Accumulators memory.
30
+ mem_file([8],2,clk,rst,rinc: :rst).(:memAcc)
31
+ memAcc.branch(:anum).inner :accs
32
+ accs_out = [accs.wrap(0), accs.wrap(1)]
33
+
34
+ # Layer 0 ack.
35
+ inner :ack0
36
+
37
+ # Instantiate the matrix product.
38
+ mac_n1([8],clk,req,ack0,lefts,readR,accs_out)
39
+
40
+ # Translation.
41
+ # Translation memory.
42
+ mem_file([8],2,clk,rst,winc: :rst).(:memT)
43
+ # Tarnslation result
44
+ mem_file([8],2,clk,rst,rinc: :rst).(:memF)
45
+ # Access ports.
46
+ memT.branch(:anum).inner :readT
47
+ memF.branch(:anum).inner :writeF
48
+ regRs = [ readT.wrap(0), readT.wrap(1) ]
49
+ regLs = [ accs.wrap(0), accs.wrap(1) ]
50
+ regs = [ writeF.wrap(0), writeF.wrap(1) ]
51
+
52
+ # Translater ack.
53
+ inner :ackT
54
+
55
+ # Instantiate the translater.
56
+ add_n([8],clk,ack0,ackT,regLs,regRs,regs)
57
+
58
+
59
+
60
+ # Second layer.
61
+ # Input memories.
62
+ mem_dual([8],2,clk,rst, rinc: :rst,winc: :rst).(:mem2L0)
63
+ # Access ports.
64
+ mem2L0.branch(:rinc).inner :read2L0
65
+ # memAcc.branch(:rinc).inner :accsR
66
+ memF.branch(:rinc).inner :readF
67
+
68
+ # Second layer ack.
69
+ inner :ack1
70
+
71
+ # Result.
72
+ [8].inner :res
73
+
74
+ sub do
75
+ # Instantiate the second matrix product.
76
+ # mac([8],clk,req,read2L0,accsR,res)
77
+ mac([8],clk,ackT,ack1,read2L0,readF,channel_port(res))
78
+ end
79
+
80
+
81
+
82
+ # The memory initializer.
83
+ memL0.branch(:winc).inner :writeL0
84
+ memL1.branch(:winc).inner :writeL1
85
+ memR.branch(:winc).inner :writeR
86
+ memT.branch(:winc).inner :writeT
87
+ mem2L0.branch(:winc).inner :write2L0
88
+ inner :fill, :fill2
89
+ [8].inner :val
90
+ par(clk.posedge) do
91
+ hif(fill) do
92
+ writeL0.write(val)
93
+ writeL1.write(val+1)
94
+ writeR.write(val+1)
95
+ end
96
+ hif(fill2) do
97
+ write2L0.write(val+2)
98
+ writeT.write(val+2)
99
+ end
100
+ end
101
+
102
+ timed do
103
+ req <= 0
104
+ clk <= 0
105
+ rst <= 0
106
+ fill <= 0
107
+ fill2 <= 0
108
+ val <= 0
109
+ !10.ns
110
+ # Reset the memories.
111
+ rst <= 1
112
+ !10.ns
113
+ clk <= 1
114
+ !10.ns
115
+ # Fill the memories.
116
+ # First layer
117
+ clk <= 0
118
+ rst <= 0
119
+ fill <= 1
120
+ !10.ns
121
+ 256.times do |i|
122
+ clk <= 1
123
+ !10.ns
124
+ clk <= 0
125
+ val <= val + 1
126
+ !10.ns
127
+ end
128
+ fill <= 0
129
+ clk <= 1
130
+ !10.ns
131
+ # Second layer
132
+ clk <= 0
133
+ rst <= 0
134
+ fill2 <= 1
135
+ !10.ns
136
+ 2.times do |i|
137
+ clk <= 1
138
+ !10.ns
139
+ clk <= 0
140
+ val <= val + 1
141
+ !10.ns
142
+ end
143
+ fill2 <= 0
144
+ clk <= 1
145
+ !10.ns
146
+ clk <= 0
147
+ !10.ns
148
+ clk <= 1
149
+ !10.ns
150
+ clk <= 0
151
+ !10.ns
152
+ # Launch the computation
153
+ clk <= 0
154
+ req <= 1
155
+ !10.ns
156
+ 300.times do
157
+ clk <= 1
158
+ !10.ns
159
+ clk <= 0
160
+ !10.ns
161
+ end
162
+ end
163
+ end
@@ -3059,24 +3059,6 @@ module HDLRuby::Low
3059
3059
  return [@value,@whens,@default].hash
3060
3060
  end
3061
3061
 
3062
- # # Adds a possible +match+ for the case's value that lead to the
3063
- # # execution of +statement+.
3064
- # def add_when(match,statement)
3065
- # # Checks the match.
3066
- # unless match.is_a?(Expression)
3067
- # raise AnyError, "Invalid class for a case match: #{match.class}"
3068
- # end
3069
- # # Checks statement.
3070
- # unless statement.is_a?(Statement)
3071
- # raise AnyError, "Invalid class for a statement: #{statement.class}"
3072
- # end
3073
- # # Add the case.
3074
- # @whens << [match,statement]
3075
- # # And set their parents.
3076
- # match.parent = statement.parent = self
3077
- # [match,statement]
3078
- # end
3079
-
3080
3062
  # Adds possible when case +w+.
3081
3063
  def add_when(w)
3082
3064
  # Check +w+.
@@ -3178,7 +3160,7 @@ module HDLRuby::Low
3178
3160
  # Clones the Case (deeply)
3179
3161
  def clone
3180
3162
  # Clone the default if any.
3181
- defaut = @default ? @default.clone : nil
3163
+ default = @default ? @default.clone : nil
3182
3164
  # Clone the case.
3183
3165
  return Case.new(@value.clone,default,(@whens.map do |w|
3184
3166
  w.clone
@@ -1069,7 +1069,8 @@ module HDLRuby::Low
1069
1069
  node2rep = node2reassign.map {|n,r| [n,r[0]] }.to_h
1070
1070
 
1071
1071
  # First recurse on the sub blocks.
1072
- self.each_block { |block| block.reassign_expressions!(node2rep) }
1072
+ # self.each_block { |block| block.reassign_expressions!(node2rep) }
1073
+ self.each_block { |block| block.reassign_expressions!(node2reassign) }
1073
1074
 
1074
1075
  # Now work on the block.
1075
1076
  # Replace on the statements.
@@ -205,6 +205,20 @@ Value shift_right_value(Value src0, Value src1, Value dst);
205
205
  * @return dst */
206
206
  extern Value equal_value(Value src0, Value src1, Value dst);
207
207
 
208
+ /** Computes the lesser comparision of two values.
209
+ * @param src0 the first source value of the addition
210
+ * @param src1 the second source value of the addition
211
+ * @param dst the destination value
212
+ * @return dst */
213
+ extern Value lesser_value(Value src0, Value src1, Value dst);
214
+
215
+ /** Computes the greater comparision of two values.
216
+ * @param src0 the first source value of the addition
217
+ * @param src1 the second source value of the addition
218
+ * @param dst the destination value
219
+ * @return dst */
220
+ extern Value greater_value(Value src0, Value src1, Value dst);
221
+
208
222
  /** Selects a value depending on a condition.
209
223
  * @param cond the condition to use for selecting a value
210
224
  * @param dst the destination value
@@ -284,6 +284,11 @@ Value make_set_value(Type type, int numeric, void* data) {
284
284
  // }
285
285
  // }
286
286
 
287
+ /* Defined after.*/
288
+ static unsigned long long
289
+ fix_numeric_type(Type type, unsigned long long val);
290
+
291
+
287
292
  /** Copies a value to another, the type of the destination is preserved.
288
293
  * @param src the source value
289
294
  * @param dst the destination value
@@ -296,7 +301,7 @@ Value copy_value(Value src, Value dst) {
296
301
  /* Copy the data. */
297
302
  if (src->numeric) {
298
303
  /* Numeric copy. */
299
- dst->data_int = src->data_int;
304
+ dst->data_int = fix_numeric_type(dst->type,src->data_int);
300
305
  } else {
301
306
  /* Resize the destination if required. */
302
307
  resize_value(dst,type_width(dst->type));
@@ -617,6 +622,38 @@ static Value div_value_defined_bitstring(Value src0, Value src1, Value dst) {
617
622
  }
618
623
 
619
624
 
625
+ /** Computes the lesser comparision of two defined bitstring values.
626
+ * @param src0 the first source value of the addition
627
+ * @param src1 the second source value of the addition
628
+ * @param dst the destination value
629
+ * @return dst */
630
+ static Value lesser_value_defined_bitstring(Value src0, Value src1, Value dst) {
631
+ /* Sets state of the destination using the first source. */
632
+ dst->type = src0->type;
633
+ dst->numeric = 1;
634
+
635
+ /* Perform the comparison. */
636
+ dst->data_int = (value2integer(src0) < value2integer(src1));
637
+ return dst;
638
+ }
639
+
640
+
641
+ /** Computes the greater comparision of two defined bitstring values.
642
+ * @param src0 the first source value of the addition
643
+ * @param src1 the second source value of the addition
644
+ * @param dst the destination value
645
+ * @return dst */
646
+ static Value greater_value_defined_bitstring(Value src0, Value src1, Value dst) {
647
+ /* Sets state of the destination using the first source. */
648
+ dst->type = src0->type;
649
+ dst->numeric = 1;
650
+
651
+ /* Perform the comparison. */
652
+ dst->data_int = (value2integer(src0) > value2integer(src1));
653
+ return dst;
654
+ }
655
+
656
+
620
657
  /** Computes the NOT of a bitstring value.
621
658
  * @param src the source value of the not
622
659
  * @param dst the destination value
@@ -1364,6 +1401,37 @@ Value write_range_bitstring_no_z(Value src, long long first, long long last,
1364
1401
 
1365
1402
  /* ############# Start of the computation of numeric values. ############## */
1366
1403
 
1404
+ /** Fix the content of a numeric value according to its type so that
1405
+ * it can be used for C numeric computation.
1406
+ * @param type the type to fix the value to
1407
+ * @param val the value to fix
1408
+ * @return the rsulting value */
1409
+ static unsigned long long
1410
+ fix_numeric_type(Type type, unsigned long long val) {
1411
+ /* Get the width of the type. */
1412
+ int width = type_width(type);
1413
+ /* Compute the base mask. */
1414
+ unsigned long long mask = ((unsigned long long)(-1)) << width;
1415
+ // printf("width=%i val=%llu mask=%llx\n",width,val,mask);
1416
+
1417
+ /* Is the type signed? */
1418
+ if (type->flags.sign) {
1419
+ /* Yes, perform sign extension. */
1420
+ int is_neg = (val >> (width-1)) & 1;
1421
+ // printf("is_neg=%i\n",is_neg);
1422
+ if (is_neg) {
1423
+ /* Negative sign extension. */
1424
+ return val | mask;
1425
+ } else {
1426
+ /* Positive sign extension. */
1427
+ return val & ~mask;
1428
+ }
1429
+ } else {
1430
+ /* No, perform a zero extension. */
1431
+ return val & ~mask;
1432
+ }
1433
+ }
1434
+
1367
1435
 
1368
1436
  /** Computes the neg of a numeric value.
1369
1437
  * @param src the source value of the not
@@ -1375,7 +1443,7 @@ static Value neg_value_numeric(Value src, Value dst) {
1375
1443
  dst->numeric = 1;
1376
1444
 
1377
1445
  /* Perform the negation. */
1378
- dst->data_int = -src->data_int;
1446
+ dst->data_int = fix_numeric_type(dst->type,-src->data_int);
1379
1447
  return dst;
1380
1448
  }
1381
1449
 
@@ -1391,7 +1459,7 @@ static Value add_value_numeric(Value src0, Value src1, Value dst) {
1391
1459
  dst->numeric = 1;
1392
1460
 
1393
1461
  /* Perform the addition. */
1394
- dst->data_int = src0->data_int + src1->data_int;
1462
+ dst->data_int = fix_numeric_type(dst->type,src0->data_int + src1->data_int);
1395
1463
  return dst;
1396
1464
  }
1397
1465
 
@@ -1407,7 +1475,7 @@ static Value sub_value_numeric(Value src0, Value src1, Value dst) {
1407
1475
  dst->numeric = 1;
1408
1476
 
1409
1477
  /* Perform the subtraction. */
1410
- dst->data_int = src0->data_int - src1->data_int;
1478
+ dst->data_int = fix_numeric_type(dst->type,src0->data_int - src1->data_int);
1411
1479
  return dst;
1412
1480
  }
1413
1481
 
@@ -1422,8 +1490,8 @@ static Value mul_value_numeric(Value src0, Value src1, Value dst) {
1422
1490
  dst->type = src0->type;
1423
1491
  dst->numeric = 1;
1424
1492
 
1425
- /* Perform the addition. */
1426
- dst->data_int = src0->data_int * src1->data_int;
1493
+ /* Perform the multiplication. */
1494
+ dst->data_int = fix_numeric_type(dst->type, src0->data_int * src1->data_int);
1427
1495
  return dst;
1428
1496
  }
1429
1497
 
@@ -1438,8 +1506,8 @@ static Value div_value_numeric(Value src0, Value src1, Value dst) {
1438
1506
  dst->type = src0->type;
1439
1507
  dst->numeric = 1;
1440
1508
 
1441
- /* Perform the addition. */
1442
- dst->data_int = src0->data_int / src1->data_int;
1509
+ /* Perform the division. */
1510
+ dst->data_int = fix_numeric_type(dst->type, src0->data_int / src1->data_int);
1443
1511
  return dst;
1444
1512
  }
1445
1513
 
@@ -1454,7 +1522,7 @@ static Value not_value_numeric(Value src, Value dst) {
1454
1522
  dst->numeric = 1;
1455
1523
 
1456
1524
  /* Perform the not. */
1457
- dst->data_int = !src->data_int;
1525
+ dst->data_int = fix_numeric_type(dst->type,!src->data_int);
1458
1526
  return dst;
1459
1527
  }
1460
1528
 
@@ -1518,7 +1586,7 @@ static Value shift_left_value_numeric(Value src0, Value src1, Value dst) {
1518
1586
  dst->numeric = 1;
1519
1587
 
1520
1588
  /* Perform the left shift. */
1521
- dst->data_int = src0->data_int << src1->data_int;
1589
+ dst->data_int = fix_numeric_type(dst->type,src0->data_int << src1->data_int);
1522
1590
  return dst;
1523
1591
  }
1524
1592
 
@@ -1534,7 +1602,7 @@ static Value shift_right_value_numeric(Value src0, Value src1, Value dst) {
1534
1602
  dst->numeric = 1;
1535
1603
 
1536
1604
  /* Perform the right shift. */
1537
- dst->data_int = src0->data_int >> src1->data_int;
1605
+ dst->data_int = fix_numeric_type(dst->type,src0->data_int >> src1->data_int);
1538
1606
  return dst;
1539
1607
  }
1540
1608
 
@@ -1555,6 +1623,37 @@ static Value equal_value_numeric(Value src0, Value src1, Value dst) {
1555
1623
  }
1556
1624
 
1557
1625
 
1626
+ /** Computes the lesser comparision of two numeric values.
1627
+ * @param src0 the first source value of the addition
1628
+ * @param src1 the second source value of the addition
1629
+ * @param dst the destination value
1630
+ * @return the destination value */
1631
+ static Value lesser_value_numeric(Value src0, Value src1, Value dst) {
1632
+ /* Sets state of the destination using the first source. */
1633
+ dst->type = src0->type;
1634
+ dst->numeric = 1;
1635
+
1636
+ /* Perform the lesser. */
1637
+ dst->data_int = (src0->data_int < src1->data_int);
1638
+ return dst;
1639
+ }
1640
+
1641
+ /** Computes the greater comparision of two numeric values.
1642
+ * @param src0 the first source value of the addition
1643
+ * @param src1 the second source value of the addition
1644
+ * @param dst the destination value
1645
+ * @return the destination value */
1646
+ static Value greater_value_numeric(Value src0, Value src1, Value dst) {
1647
+ /* Sets state of the destination using the first source. */
1648
+ dst->type = src0->type;
1649
+ dst->numeric = 1;
1650
+
1651
+ /* Perform the lesser. */
1652
+ dst->data_int = (src0->data_int > src1->data_int);
1653
+ return dst;
1654
+ }
1655
+
1656
+
1558
1657
  /** Selects a value depending on a numeric condition.
1559
1658
  * @param cond the condition to use for selecting a value
1560
1659
  * @param dst the destination value (used only if new value is created).
@@ -1719,6 +1818,7 @@ Value read_range_numeric(Value value, long long first, long long last,
1719
1818
  * @return dst */
1720
1819
  Value write_range_numeric(Value src, long long first, long long last,
1721
1820
  Value dst) {
1821
+ // printf("write_range_numeric\n");
1722
1822
  /* Ensure first is the smaller. */
1723
1823
  if (first > last) {
1724
1824
  long long tmp = last;
@@ -1730,6 +1830,7 @@ Value write_range_numeric(Value src, long long first, long long last,
1730
1830
  unsigned long long dst_width = type_width(dst->type);
1731
1831
  /* scale the range according to the base type of the destination. */
1732
1832
  unsigned long long bw = dst->type->base;
1833
+ // printf("src_width=%llu dst_wdith=%llu bw=%llu\n",src_width,dst_width,bw);
1733
1834
  first *= bw;
1734
1835
  last *= bw;
1735
1836
  /* If first is too large, end here. */
@@ -1737,11 +1838,13 @@ Value write_range_numeric(Value src, long long first, long long last,
1737
1838
  /* Adjust the last to fit the source and destination range. */
1738
1839
  if (last >= dst_width) last = dst_width-1;
1739
1840
  if (last-first >= src_width) last = src_width + first - 1;
1841
+ // printf("first=%lld last=%lld\n",first,last);
1740
1842
  /* Copy from the source. */
1741
- unsigned long long src_data = src->data_int & ~((-1LL) << (last-first));
1843
+ unsigned long long src_data = src->data_int & ~((-1LL) << (last-first+1));
1742
1844
  /* Cleans the destination where to place the data. */
1743
- unsigned long long mask = ((-1LL) << first) & ~((-1LL) << last);
1845
+ unsigned long long mask = ~(((-1LL) << first) & ~((-1LL) << (last+1)));
1744
1846
  unsigned long long dst_data = dst->data_int & mask;
1847
+ // printf("src_data=%llx mask=%llx dst_data=%llx\n",src_data,mask,dst_data);
1745
1848
  /* Write the data. */
1746
1849
  dst_data |= src_data << first;
1747
1850
  dst->data_int = dst_data;
@@ -2111,6 +2214,60 @@ Value equal_value(Value src0, Value src1, Value dst) {
2111
2214
  }
2112
2215
 
2113
2216
 
2217
+ /** Computes the lesser comparision of two general values.
2218
+ * @param src0 the first source value of the addition
2219
+ * @param src1 the second source value of the addition
2220
+ * @param dst the destination value
2221
+ * @return dst */
2222
+ Value lesser_value(Value src0, Value src1, Value dst) {
2223
+ /* Might allocate a new value so save the current pool state. */
2224
+ unsigned int pos = get_value_pos();
2225
+ /* Do a numeric computation if possible, otherwise fallback to bitstring
2226
+ * computation. */
2227
+ if (src0->numeric && src1->numeric) {
2228
+ /* Both sources are numeric. */
2229
+ return lesser_value_numeric(src0,src1,dst);
2230
+ } else if (is_defined_value(src0) && is_defined_value(src1)) {
2231
+ /* Both sources can be converted to numeric values. */
2232
+ return lesser_value_defined_bitstring(src0,src1,dst);
2233
+ } else {
2234
+ /* Cannot compute (for now), simply undefines the destination. */
2235
+ /* First ensure dst has the right shape. */
2236
+ copy_value(src0,dst);
2237
+ /* Then make it undefined. */
2238
+ set_undefined_bitstring(dst);
2239
+ }
2240
+ return dst;
2241
+ }
2242
+
2243
+
2244
+ /** Computes the greater comparision of two general values.
2245
+ * @param src0 the first source value of the addition
2246
+ * @param src1 the second source value of the addition
2247
+ * @param dst the destination value
2248
+ * @return dst */
2249
+ Value greater_value(Value src0, Value src1, Value dst) {
2250
+ /* Might allocate a new value so save the current pool state. */
2251
+ unsigned int pos = get_value_pos();
2252
+ /* Do a numeric computation if possible, otherwise fallback to bitstring
2253
+ * computation. */
2254
+ if (src0->numeric && src1->numeric) {
2255
+ /* Both sources are numeric. */
2256
+ return greater_value_numeric(src0,src1,dst);
2257
+ } else if (is_defined_value(src0) && is_defined_value(src1)) {
2258
+ /* Both sources can be converted to numeric values. */
2259
+ return greater_value_defined_bitstring(src0,src1,dst);
2260
+ } else {
2261
+ /* Cannot compute (for now), simply undefines the destination. */
2262
+ /* First ensure dst has the right shape. */
2263
+ copy_value(src0,dst);
2264
+ /* Then make it undefined. */
2265
+ set_undefined_bitstring(dst);
2266
+ }
2267
+ return dst;
2268
+ }
2269
+
2270
+
2114
2271
  /** Selects a value depending on a general condition.
2115
2272
  * @param cond the condition to use for selecting a value
2116
2273
  * @param dst the destination value (used only if new value is created).
@@ -2460,6 +2617,7 @@ Value read_range(Value value, long long first, long long last, Type base,
2460
2617
  * @param dst the destination value
2461
2618
  * @return dst */
2462
2619
  Value write_range(Value src, long long first, long long last, Value dst) {
2620
+ // printf("write_range\n");
2463
2621
  /* Is the value numeric? */
2464
2622
  if ((src->numeric) && (dst->numeric)) {
2465
2623
  /* Yes, do a numeric range read. */
@@ -2485,6 +2643,7 @@ Value write_range(Value src, long long first, long long last, Value dst) {
2485
2643
  * @param dst the destination value
2486
2644
  * @return dst */
2487
2645
  Value write_range_no_z(Value src, long long first, long long last, Value dst) {
2646
+ // printf("write_range_no_z\n");
2488
2647
  /* Is the value numeric? */
2489
2648
  if ((src->numeric) && (dst->numeric)) {
2490
2649
  /* Yes, do a numeric range read. */
@@ -901,29 +901,77 @@ module HDLRuby::High::Std
901
901
  end
902
902
 
903
903
 
904
- end
905
-
904
+ # Wrapper to make an object run like a channel port.
905
+ class ChannelPortObject
906
+ # Create a new object wrapper for +obj+.
907
+ def initialize(obj)
908
+ @obj = obj
909
+ end
906
910
 
907
- module HDLRuby::High
911
+ # Port read with arguments +args+ executing +ruby_block+ in
912
+ # case of success.
913
+ def read(*args,&ruby_block)
914
+ # Get the target from the arguments.
915
+ target = args.pop
916
+ # Is there any argument left?
917
+ unless (args.empty?) then
918
+ # There are arguments left, perform an array access.
919
+ target <= @obj[*args]
920
+ else
921
+ # There are no argument left, perform a direct access.
922
+ target <= @obj
923
+ end
924
+ # Execute the ruby_block if any.
925
+ ruby_block.call if ruby_block
926
+ end
908
927
 
909
- ## Enhance expressions with possibility to act like a reading branch.
910
- module HExpression
911
- ## Transmits the expression to +target+ and execute +ruby_block+ if
912
- # any.
913
- def read(target,&ruby_block)
914
- target <= self
915
- ruby_block.call if ruby_block
928
+ # Port write with argumnet +Args+ executing +ruby_block+ in
929
+ # case of success.
930
+ def write(*args,&ruby_block)
931
+ # Get the value to write from the arguments.
932
+ value = args.pop
933
+ # Is there any argument left?
934
+ unless (args.empty?) then
935
+ # There are arguments left, perform an array access.
936
+ @obj[*args] <= value
937
+ else
938
+ # There are no argument left, perform a direct access.
939
+ @obj <= value
940
+ end
941
+ # Execute the ruby_block if any.
942
+ ruby_block.call if ruby_block
916
943
  end
944
+
917
945
  end
918
946
 
919
947
 
920
- ## Enhance references with possibility to act like a writing branch.
921
- module HRef
922
- ## Transmits +target+ to the reference and execute +ruby_block+ if
923
- # any.
924
- def write(target,&ruby_block)
925
- self <= target
926
- ruby_block.call if ruby_block
927
- end
948
+ # Wrap object +obj+ to act like a channel port.
949
+ def channel_port(obj)
950
+ return ChannelPortObject.new(obj)
928
951
  end
929
952
  end
953
+
954
+
955
+ # module HDLRuby::High
956
+ #
957
+ # ## Enhance expressions with possibility to act like a reading branch.
958
+ # module HExpression
959
+ # ## Transmits the expression to +target+ and execute +ruby_block+ if
960
+ # # any.
961
+ # def read(target,&ruby_block)
962
+ # target <= self
963
+ # ruby_block.call if ruby_block
964
+ # end
965
+ # end
966
+ #
967
+ #
968
+ # ## Enhance references with possibility to act like a writing branch.
969
+ # module HRef
970
+ # ## Transmits +target+ to the reference and execute +ruby_block+ if
971
+ # # any.
972
+ # def write(target,&ruby_block)
973
+ # self <= target
974
+ # ruby_block.call if ruby_block
975
+ # end
976
+ # end
977
+ # end
@@ -0,0 +1,197 @@
1
+ module HDLRuby::High::Std
2
+
3
+
4
+ ##
5
+ # Standard HDLRuby::High library: linear algebra functions.
6
+ #
7
+ # NOTE: require channel-like interface.
8
+ #
9
+ ########################################################################
10
+
11
+
12
+ # Delcares a vector product by a scalar value.
13
+ #
14
+ # Can be used for scaling a vector.
15
+ function :scale do |typ,ev,req,ack,left,rights,prods,
16
+ mul = proc { |x,y| x*y }|
17
+ # Ensure ev is really an event.
18
+ ev = ev.posedge unless ev.is_a?(Event)
19
+ # Ensures rights and prods are arrays.
20
+ rights = rights.to_a
21
+ prods = prods.to_a
22
+ # Left value (the scale) and right value.
23
+ typ.inner :lv
24
+ rvs = rights.each_with_index.map { |left,i| typ.inner :"rv#{i}" }
25
+ # lv and rv are valid.
26
+ inner :lvok
27
+ rvoks = rights.each_with_index.map { |left,i| inner :"rvok#{i}" }
28
+ # Run flag
29
+ inner :run
30
+ par(ev) do
31
+ ack <= 0
32
+ run <= 0
33
+ hif(req | run) do
34
+ run <= 1
35
+ # Computation request.
36
+ left.read(lv) { lvok <= 1 }
37
+ rights.each_with_index do |right,i|
38
+ right.read(rvs[i]) { rvoks[i] <= 1 }
39
+ hif(lvok & rvoks[i]) do
40
+ ack <= 1
41
+ run <= 0
42
+ prods[i].write(mul.(lv,rvs[i]))
43
+ end
44
+ end
45
+ end
46
+ helse do
47
+ lvok <= 0
48
+ rights.each_with_index do |right,i|
49
+ rvoks[i] <= 0
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+
56
+ # Declares a 1-dimension vector adder.
57
+ #
58
+ # Can be used for the sum of two vectors.
59
+ function :add_n do |typ,ev,req,ack,lefts, rights, sums,
60
+ add = proc { |x,y| x+y }|
61
+ # Ensure ev is really an event.
62
+ ev = ev.posedge unless ev.is_a?(Event)
63
+ # Ensures lefts and rights and sums are arrays.
64
+ lefts = lefts.to_a
65
+ rights = rights.to_a
66
+ sums = sums.to_a
67
+ # Left value and right value.
68
+ lvs = lefts.each_with_index.map { |left,i| typ.inner :"lv#{i}" }
69
+ rvs = lefts.each_with_index.map { |left,i| typ.inner :"rv#{i}" }
70
+ # lv and rv are valid.
71
+ lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
72
+ rvoks = lefts.each_with_index.map { |left,i| inner :"rvok#{i}" }
73
+ # Run flag.
74
+ inner :run
75
+ par(ev) do
76
+ ack <= 0
77
+ run <= 0
78
+ hif(req | run) do
79
+ run <= 1
80
+ # Computation request.
81
+ lefts.zip(rights).each_with_index do |(left,right),i|
82
+ left.read(lvs[i]) { lvoks[i] <= 1 }
83
+ right.read(rvs[i]) { rvoks[i] <= 1 }
84
+ hif(lvoks[i] & rvoks[i]) do
85
+ run <= 0
86
+ ack <= 1
87
+ sums[i].write(add.(lvs[i],rvs[i]))
88
+ end
89
+ end
90
+ end
91
+ helse do
92
+ lefts.each_with_index do |left,i|
93
+ lvoks[i] <= 0
94
+ rvoks[i] <= 0
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ # Declares a 1-dimension vector element-wise multiplier.
101
+ function :mul_n do |typ,ev,req,ack,lefts, rights, prods,
102
+ mul = proc { |x,y| x*y }|
103
+ add_n(typ,ev,req,ack,lefts,rights,prods,mul)
104
+ end
105
+
106
+
107
+ # Declares a simple multiplier accumulator.
108
+ #
109
+ # Can be used for the scalar product of two vectors.
110
+ function :mac do |typ,ev,req,ack,left, right, acc,
111
+ mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
112
+ # Ensure ev is really an event.
113
+ ev = ev.posedge unless ev.is_a?(Event)
114
+ # Left value and right value.
115
+ typ.inner :lv, :rv, :av
116
+ # lv and rv are valid.
117
+ inner :lvok, :rvok
118
+ # Run flag
119
+ inner :run
120
+ par(ev) do
121
+ ack <= 0
122
+ run <= 0
123
+ hif(req | run) do
124
+ run <= 1
125
+ # Computation request.
126
+ left.read(lv) { lvok <= 1 }
127
+ right.read(rv) { rvok <= 1 }
128
+ # ( acc <= add.(acc,mul.(lv,rv)) ).hif(lvok & rvok)
129
+ acc.read(av)
130
+ hif(lvok & rvok) do
131
+ ack <= 1
132
+ run <= 0
133
+ acc.write(add.(av,mul.(lv,rv)))
134
+ end
135
+ end
136
+ helse do
137
+ lvok <= 0
138
+ rvok <= 0
139
+ acc.write(0)
140
+ end
141
+ end
142
+ end
143
+
144
+
145
+ # Declares a simple multiple mac with single right data.
146
+ #
147
+ # Can be used for the product of a martix-vector product.
148
+ function :mac_n1 do |typ,ev,req,ack,lefts, right, accs,
149
+ mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
150
+ # Ensure ev is really an event.
151
+ ev = ev.posedge unless ev.is_a?(Event)
152
+ # Ensures lefts is an array.
153
+ lefts = lefts.to_a
154
+ # Ensures accs is an array.
155
+ accs = accs.to_a
156
+ # Left value and right value.
157
+ lvs = lefts.each_with_index.map { |left,i| typ.inner :"lv#{i}" }
158
+ # Accumutated values.
159
+ avs = lefts.each_with_index.map { |left,i| typ.inner :"av#{i}" }
160
+ typ.inner :rv
161
+ # lv and rv are valid.
162
+ lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
163
+ inner :rvok
164
+ # Run flag
165
+ inner :run
166
+ par(ev) do
167
+ ack <= 0
168
+ run <= 0
169
+ hif(req | run) do
170
+ run <= 1
171
+ # Computation request.
172
+ right.read(rv) { rvok <= 1 }
173
+ lefts.each_with_index do |left,i|
174
+ left.read(lvs[i]) { lvoks[i] <= 1 }
175
+ # accs.read(i,avs[i])
176
+ accs[i].read(avs[i])
177
+ hif(lvoks[i] & rvok) do
178
+ ack <= 1
179
+ run <= 0
180
+ # accs.write(i,add.(avs[i],mul.(lvs[i],rv)))
181
+ accs[i].write(add.(avs[i],mul.(lvs[i],rv)))
182
+ end
183
+ end
184
+ end
185
+ helse do
186
+ rvok <= 0
187
+ lefts.each_with_index do |left,i|
188
+ lvoks[i] <= 0
189
+ # accs.write(i,0)
190
+ accs[i].write(0)
191
+ end
192
+ end
193
+ end
194
+ end
195
+
196
+
197
+ end
@@ -1,3 +1,3 @@
1
1
  module HDLRuby
2
- VERSION = "2.2.14"
2
+ VERSION = "2.2.15"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: HDLRuby
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.14
4
+ version: 2.2.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lovic Gauthier
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-26 00:00:00.000000000 Z
11
+ date: 2020-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -82,6 +82,7 @@ files:
82
82
  - lib/HDLRuby/hdr_samples/dff_counter.rb
83
83
  - lib/HDLRuby/hdr_samples/include.rb
84
84
  - lib/HDLRuby/hdr_samples/instance_open.rb
85
+ - lib/HDLRuby/hdr_samples/linear_test.rb
85
86
  - lib/HDLRuby/hdr_samples/mei8.rb
86
87
  - lib/HDLRuby/hdr_samples/mei8_bench.rb
87
88
  - lib/HDLRuby/hdr_samples/memory_test.rb
@@ -118,6 +119,7 @@ files:
118
119
  - lib/HDLRuby/hdr_samples/with_decoder.rb
119
120
  - lib/HDLRuby/hdr_samples/with_fixpoint.rb
120
121
  - lib/HDLRuby/hdr_samples/with_fsm.rb
122
+ - lib/HDLRuby/hdr_samples/with_linear.rb
121
123
  - lib/HDLRuby/hdr_samples/with_memory.rb
122
124
  - lib/HDLRuby/hdr_samples/with_reconf.rb
123
125
  - lib/HDLRuby/hdrcc.rb
@@ -266,6 +268,7 @@ files:
266
268
  - lib/HDLRuby/std/decoder.rb
267
269
  - lib/HDLRuby/std/fixpoint.rb
268
270
  - lib/HDLRuby/std/fsm.rb
271
+ - lib/HDLRuby/std/linear.rb
269
272
  - lib/HDLRuby/std/memory.rb
270
273
  - lib/HDLRuby/std/pipeline.rb
271
274
  - lib/HDLRuby/std/reconf.rb