HDLRuby 2.2.14 → 2.2.15

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 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