HDLRuby 2.2.17 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -157,6 +157,13 @@ extern Value mul_value(Value src0, Value src1, Value dst);
157
157
  * @return dst */
158
158
  extern Value div_value(Value src0, Value src1, Value dst);
159
159
 
160
+ /** Computes the modulo of two general values.
161
+ * @param src0 the first source value of the addition
162
+ * @param src1 the second source value of the addition
163
+ * @param dst the destination value
164
+ * @return dst */
165
+ extern Value mod_value(Value src0, Value src1, Value dst);
166
+
160
167
  /** Computes the not of a value.
161
168
  * @param src the source value of the not
162
169
  * @param dst the destination value
@@ -397,6 +397,9 @@ static Value set_undefined_bitstring(Value dst) {
397
397
 
398
398
  /* set the type and size of the destination. */
399
399
  dst->numeric = 0;
400
+ /* Ensures the buffer of dst has the write size (in cas it was a fromer
401
+ * numeric for example). */
402
+ resize_value(dst,width);
400
403
 
401
404
  /* Get access to the destination data. */
402
405
  char* dst_data = dst->data_str;
@@ -604,7 +607,7 @@ static Value mul_value_defined_bitstring(Value src0, Value src1, Value dst) {
604
607
  dst->type = src0->type;
605
608
  dst->numeric = 1;
606
609
 
607
- /* Perform the addition. */
610
+ /* Perform the multiplication. */
608
611
  dst->data_int = value2integer(src0) * value2integer(src1);
609
612
  return dst;
610
613
  }
@@ -620,12 +623,29 @@ static Value div_value_defined_bitstring(Value src0, Value src1, Value dst) {
620
623
  dst->type = src0->type;
621
624
  dst->numeric = 1;
622
625
 
623
- /* Perform the addition. */
626
+ /* Perform the division. */
624
627
  dst->data_int = value2integer(src0) / value2integer(src1);
625
628
  return dst;
626
629
  }
627
630
 
628
631
 
632
+ /** Computes the modulo of two defined bitstring values.
633
+ * @param src0 the first source value of the addition
634
+ * @param src1 the second source value of the addition
635
+ * @param dst the destination value
636
+ * @return dst */
637
+ static Value mod_value_defined_bitstring(Value src0, Value src1, Value dst) {
638
+ /* Sets state of the destination using the first source. */
639
+ dst->type = src0->type;
640
+ dst->numeric = 1;
641
+
642
+ /* Perform the modulo. */
643
+ // printf("modulo with src0=%lld src1=%lld, result=%lld\n",value2integer(src0),value2integer(src1),value2integer(src0) % value2integer(src1));
644
+ dst->data_int = value2integer(src0) % value2integer(src1);
645
+ return dst;
646
+ }
647
+
648
+
629
649
  /** Computes the lesser comparision of two defined bitstring values.
630
650
  * @param src0 the first source value of the addition
631
651
  * @param src1 the second source value of the addition
@@ -1415,7 +1435,10 @@ fix_numeric_type(Type type, unsigned long long val) {
1415
1435
  /* Get the width of the type. */
1416
1436
  int width = type_width(type);
1417
1437
  /* Compute the base mask. */
1418
- unsigned long long mask = ((unsigned long long)(-1)) << width;
1438
+ // unsigned long long mask = ((unsigned long long)(-1)) << width;
1439
+ /* NOTE: (ull)-1 << 64 becomes (ull)-1 on Intel processors, this is
1440
+ * totally not what I expected (I expected 0). */
1441
+ unsigned long long mask = width == 64 ? 0 : ((unsigned long long)(-1)) << width;
1419
1442
  // printf("width=%i val=%llu mask=%llx\n",width,val,mask);
1420
1443
 
1421
1444
  /* Is the type signed? */
@@ -1516,6 +1539,23 @@ static Value div_value_numeric(Value src0, Value src1, Value dst) {
1516
1539
  }
1517
1540
 
1518
1541
 
1542
+ /** Computes the modulo of two numeric values.
1543
+ * @param src0 the first source value of the addition
1544
+ * @param src1 the second source value of the addition
1545
+ * @param dst the destination value
1546
+ * @return dst */
1547
+ static Value mod_value_numeric(Value src0, Value src1, Value dst) {
1548
+ /* Sets state of the destination using the first source. */
1549
+ dst->type = src0->type;
1550
+ dst->numeric = 1;
1551
+
1552
+ /* Perform the division. */
1553
+ // printf("modulo numeric with src0=%lld src1=%lld, result=%lld\n",src0->data_int, src1->data_int,src0->data_int % src1->data_int);
1554
+ dst->data_int = fix_numeric_type(dst->type, src0->data_int % src1->data_int);
1555
+ return dst;
1556
+ }
1557
+
1558
+
1519
1559
  /** Computes the NOT of a numeric value.
1520
1560
  * @param src the source value of the not
1521
1561
  * @param dst the destination value
@@ -1690,7 +1730,7 @@ static Value concat_value_numeric_array(int num, int dir,
1690
1730
  unsigned int i,pos;
1691
1731
  /* Compute the bit width of the destination. */
1692
1732
  unsigned int width = 0;
1693
- // printf("concat_value_numeric with dir=%d\n",dir);
1733
+ // printf("concat_value_numeric with dir=%d and width=%llu\n",dir,type_width(args[0]->type));
1694
1734
  for(i=0; i<num; ++i) width += type_width(args[i]->type);
1695
1735
 
1696
1736
  /* Sets state of the destination using the bit width. */
@@ -1714,6 +1754,7 @@ static Value concat_value_numeric_array(int num, int dir,
1714
1754
  pos += arg_width;
1715
1755
  }
1716
1756
  /* Return the destination. */
1757
+ // printf("Result is dst=%llx\n",dst->data_int);
1717
1758
  return dst;
1718
1759
  }
1719
1760
 
@@ -1724,6 +1765,7 @@ static Value concat_value_numeric_array(int num, int dir,
1724
1765
  * @param dst the destination value
1725
1766
  * @return dst */
1726
1767
  static Value cast_value_numeric(Value src, Type type, Value dst) {
1768
+ // printf("cast_value_numeric with src=%llx",src->data_int);
1727
1769
  /* Copy the source to the destination. */
1728
1770
  dst->data_int = src->data_int;
1729
1771
  /* Update the destination type to the cast. */
@@ -1783,6 +1825,7 @@ static int same_content_value_range_numeric(Value value0,
1783
1825
  * @return dst */
1784
1826
  Value read_range_numeric(Value value, long long first, long long last,
1785
1827
  Type base, Value dst) {
1828
+ /* printf("read_range_numeric with value=%llx and first=%llu and last=%llu\n",value->data_int,first,last); */
1786
1829
  /* Ensure first is the smaller. */
1787
1830
  if (first > last) {
1788
1831
  long long tmp = last;
@@ -1795,15 +1838,18 @@ Value read_range_numeric(Value value, long long first, long long last,
1795
1838
  unsigned long long bw = type_width(base);
1796
1839
  /* Scale the range according to the base type. */
1797
1840
  first *= bw;
1841
+ last *= bw;
1798
1842
  length *= bw;
1799
- // printf("first=%lld last=%lld bw=%llu length=%lld\n",first,last,bw,length);
1843
+ /* printf("first=%lld last=%lld bw=%llu length=%lld\n",first,last,bw,length); */
1800
1844
 
1801
1845
  /* Set the type and size of the destination from the type of the source.*/
1802
1846
  dst->type = make_type_vector(get_type_bit(),length);
1803
1847
  dst->numeric = 1;
1804
1848
 
1805
1849
  /* Compute the read mask. */
1806
- unsigned long long mask = ((-1LL) << first) & (~((-1LL) << (last+1)));
1850
+ // unsigned long long mask = ((-1LL) << first) & (~((-1LL) << (last+1)));
1851
+ /* NOTE: once again, << 64 does not work like expected. */
1852
+ unsigned long long mask = mask+bw < 64 ? (~((-1LL) << (last+bw))) : -1LL;
1807
1853
  /* Performs the read. */
1808
1854
  unsigned long long data = (value->data_int & mask) >> first;
1809
1855
  /* Write it to the destination. */
@@ -1999,6 +2045,33 @@ Value div_value(Value src0, Value src1, Value dst) {
1999
2045
  }
2000
2046
 
2001
2047
 
2048
+ /** Computes the modulo of two general values.
2049
+ * @param src0 the first source value of the addition
2050
+ * @param src1 the second source value of the addition
2051
+ * @param dst the destination value
2052
+ * @return dst */
2053
+ Value mod_value(Value src0, Value src1, Value dst) {
2054
+ /* Might allocate a new value so save the current pool state. */
2055
+ unsigned int pos = get_value_pos();
2056
+ /* Do a numeric computation if possible, otherwise fallback to bitstring
2057
+ * computation. */
2058
+ if (src0->numeric && src1->numeric) {
2059
+ /* Both sources are numeric. */
2060
+ return mod_value_numeric(src0,src1,dst);
2061
+ } else if (is_defined_value(src0) && is_defined_value(src1)) {
2062
+ /* Both sources can be converted to numeric values. */
2063
+ return mod_value_defined_bitstring(src0,src1,dst);
2064
+ } else {
2065
+ /* Cannot compute (for now), simply undefines the destination. */
2066
+ /* First ensure dst has the right shape. */
2067
+ copy_value(src0,dst);
2068
+ /* Then make it undefined. */
2069
+ set_undefined_bitstring(dst);
2070
+ }
2071
+ return dst;
2072
+ }
2073
+
2074
+
2002
2075
  /** Computes the NOT of a general value.
2003
2076
  * @param src the source value of the not
2004
2077
  * @param dst the destination value
@@ -81,9 +81,17 @@ module HDLRuby::High::Std
81
81
  end
82
82
 
83
83
 
84
- ##
85
- # Module for wrapping channel ports.
86
- module ChannelPortWrapping
84
+ # ##
85
+ # # Module for wrapping channel ports.
86
+ # module ChannelPortWrapping
87
+ # # Wrap with +args+ arguments.
88
+ # def wrap(*args)
89
+ # return ChannelPortB.new(self,*args)
90
+ # end
91
+ # end
92
+
93
+ ## Describes a channel port.
94
+ class ChannelPort
87
95
  # Wrap with +args+ arguments.
88
96
  def wrap(*args)
89
97
  return ChannelPortB.new(self,*args)
@@ -93,8 +101,8 @@ module HDLRuby::High::Std
93
101
 
94
102
  ##
95
103
  # Describes a read port to a channel.
96
- class ChannelPortR
97
- include ChannelPortWrapping
104
+ class ChannelPortR < ChannelPort
105
+ # include ChannelPortWrapping
98
106
 
99
107
  # Creates a new channel reader running in +namespace+ and
100
108
  # reading using +reader_proc+ and reseting using +reseter_proc+.
@@ -137,8 +145,8 @@ module HDLRuby::High::Std
137
145
 
138
146
  ##
139
147
  # Describes a writer port to a channel.
140
- class ChannelPortW
141
- include ChannelPortWrapping
148
+ class ChannelPortW < ChannelPort
149
+ # include ChannelPortWrapping
142
150
 
143
151
  # Creates a new channel writer running in +namespace+ and
144
152
  # writing using +writer_proc+ and reseting using +reseter_proc+.
@@ -181,8 +189,8 @@ module HDLRuby::High::Std
181
189
 
182
190
  ##
183
191
  # Describes an access port to a channel.
184
- class ChannelPortA
185
- include ChannelPortWrapping
192
+ class ChannelPortA < ChannelPort
193
+ # include ChannelPortWrapping
186
194
 
187
195
  # Creates a new channel accesser running in +namespace+
188
196
  # and reading using +reader_proc+, writing using +writer_proc+,
@@ -243,8 +251,8 @@ module HDLRuby::High::Std
243
251
 
244
252
  ##
245
253
  # Describes port wrapper (Box) for fixing arugments.
246
- class ChannelPortB
247
- include ChannelPortWrapping
254
+ class ChannelPortB < ChannelPort
255
+ # include ChannelPortWrapping
248
256
 
249
257
  # Creates a new channel box over channel port +port+ fixing +args+
250
258
  # as arguments.
@@ -600,13 +608,23 @@ module HDLRuby::High::Std
600
608
 
601
609
  # Defines a branch in the channel named +name+ built executing
602
610
  # +ruby_block+.
603
- def brancher(name,&ruby_block)
611
+ # Alternatively, a ready channel instance can be passed as argument
612
+ # as +channelI+.
613
+ def brancher(name,channelI = nil,&ruby_block)
604
614
  # Ensure name is a symbol.
605
615
  name = name.to_s unless name.respond_to?(:to_sym)
606
616
  name = name.to_sym
607
- # Create the branch.
608
- channelI = HDLRuby::High.channel_instance(name, &ruby_block)
617
+ # Is there a ready channel instance.
618
+ if channelI then
619
+ # Yes, use it directly.
620
+ @branches[name] = channelI
621
+ return self
622
+ end
623
+ # No, create the branch.
624
+ # channelI = HDLRuby::High.channel_instance(name, &ruby_block)
625
+ channelI = HDLRuby::High::Std.channel_instance(name, &ruby_block)
609
626
  @branches[name] = channelI
627
+ return self
610
628
  end
611
629
 
612
630
 
@@ -619,6 +637,7 @@ module HDLRuby::High::Std
619
637
  name = name.to_s unless name.respond_to?(:to_sym)
620
638
  name = name.to_sym
621
639
  # Get the branch.
640
+ channelI = @branches[name]
622
641
  return @branches[name]
623
642
  end
624
643
 
@@ -902,7 +921,7 @@ module HDLRuby::High::Std
902
921
 
903
922
 
904
923
  # Wrapper to make an object run like a channel port.
905
- class ChannelPortObject
924
+ class ChannelPortObject < ChannelPort
906
925
  # Create a new object wrapper for +obj+.
907
926
  def initialize(obj)
908
927
  @obj = obj
@@ -946,9 +965,13 @@ module HDLRuby::High::Std
946
965
 
947
966
 
948
967
  # Wrap object +obj+ to act like a channel port.
949
- def channel_port(obj)
968
+ def self.channel_port(obj)
969
+ return obj if obj.is_a?(ChannelPort) # No need to wrap.
950
970
  return ChannelPortObject.new(obj)
951
971
  end
972
+ def channel_port(obj)
973
+ return HDLRuby::High::Std.channel_port(obj)
974
+ end
952
975
  end
953
976
 
954
977
 
@@ -26,17 +26,18 @@ module HDLRuby::High::Std
26
26
  if args.size == 1 then
27
27
  return self.send(:"_[]_fixpoint",*args)
28
28
  else
29
- # Handle the arguments.
29
+ # Handle the arguments and compute the fix point sizes.
30
30
  arg0,arg1 = *args
31
31
  if arg0.respond_to?(:to_i) then
32
- arg0 = (arg0.to_i.abs-1)..0
32
+ isize = arg0
33
+ else
34
+ isize = (arg0.first-arg0.last).abs+1
33
35
  end
34
36
  if arg1.respond_to?(:to_i) then
35
- arg1 = (arg1.to_i.abs-1)..0
37
+ fsize = arg1
38
+ else
39
+ fsize = (arg1.first-arg1.last).abs+1
36
40
  end
37
- # Compute the fix point sizes.
38
- isize = (arg0.first-arg0.last).abs+1
39
- fsize = (arg1.first-arg1.last).abs+1
40
41
  # Build the type.
41
42
  case(self.name)
42
43
  when :bit
@@ -244,6 +244,74 @@ module HDLRuby::High::Std
244
244
  end
245
245
 
246
246
 
247
+ # Declares a simple pipelined multiple mac with single right data.
248
+ #
249
+ # Can be used for the product of a martix-vector product.
250
+ function :mac_np do |typ,ev,req,ack,lefts, rights, last,
251
+ mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
252
+ # Ensure ev is really an event.
253
+ ev = ev.posedge unless ev.is_a?(Event)
254
+ # Ensures lefts is an array.
255
+ lefts = lefts.to_a
256
+ # Ensures rights is an array.
257
+ rights = rights.to_a
258
+ # Get the size of the pipeline and ensure lefts and rights have the
259
+ # same.
260
+ size = lefts.size
261
+ if (rights.size != size) then
262
+ raise "Incompatible lefts and rights sizes: lefts size is #{size} and rights size is #{rights.size}"
263
+ end
264
+ # Declares the accumulators.
265
+ accs = size.times.map { |i| typ.inner :"acc#{i}" }
266
+ # Left value and right value.
267
+ lvs = lefts.each_with_index.map { |left,i| typ.inner :"lv#{i}" }
268
+ rvs = rights.each_with_index.map { |right,i| typ.inner :"rv#{i}" }
269
+ # typ.inner :rv
270
+ # lv and rv are valid.
271
+ lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
272
+ # inner :rvok
273
+ rvoks = rights.each_with_index.map { |right,i| inner :"rvok#{i}" }
274
+ # Run flag
275
+ inner :run
276
+ par(ev) do
277
+ ack <= 0
278
+ run <= 0
279
+ hif(req | run) do
280
+ run <= 1
281
+ # Computation request.
282
+ lefts.zip(rights).each_with_index do |(left,right),i|
283
+ left.read(lvs[i]) { lvoks[i] <= 1 }
284
+ right.read(rvs[i]) { rvoks[i] <= 1 }
285
+ hif(lvoks[i] & rvoks[i]) do
286
+ ack <= 1
287
+ run <= 0
288
+ if (i < lefts.size-1) then
289
+ if (i>0) then
290
+ accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i])) +
291
+ accs[i-1]
292
+ else
293
+ accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i]))
294
+ end
295
+ else
296
+ # The last is reached
297
+ seq do
298
+ accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i]))
299
+ last.write(accs[i])
300
+ end
301
+ end
302
+ end
303
+ end
304
+ end
305
+ helse do
306
+ lefts.each_with_index do |left,i|
307
+ lvoks[i] <= 0
308
+ rvoks[i] <= 0
309
+ accs[i] <= 0
310
+ end
311
+ end
312
+ end
313
+ end
314
+
247
315
 
248
316
 
249
317
  end
@@ -0,0 +1,101 @@
1
+ require 'std/task.rb'
2
+
3
+
4
+
5
+ ##
6
+ # Standard HDLRuby::High library: loops encapsulated in tasks.
7
+ #
8
+ ########################################################################
9
+
10
+ ## While loop: loops until +condition+ is met execution +ruby_block+.
11
+ # The loop is synchronized on +clk_e+ and initialized by +init+.
12
+ # If +condition+ is nil, then +init+ is used as +condition+.
13
+ HDLRuby::High::Std.task(:while_task) do |clk_e, init, condition, ruby_block|
14
+ # Ensure clk_e is an event, if not set it to a positive edge.
15
+ clk_e = clk_e.posedge unless clk_e.is_a?(Event)
16
+
17
+ # Ensures there is a condition.
18
+ unless condition then
19
+ condition = init
20
+ init = nil
21
+ end
22
+
23
+ # Transform condition into a proc if it is not the case.
24
+ unless condition.is_a?(Proc) then
25
+ condition_expr = condition
26
+ condition = proc { condition_expr }
27
+ end
28
+
29
+ # Ensures init to be a proc if not nil
30
+ init = init.to_proc unless init == nil
31
+
32
+ # Declares the signals for controlling the loop.
33
+ inner :req # Signal to set to 1 for running the loop.
34
+
35
+ # Declares the runner signals.
36
+ runner_output :req
37
+
38
+ par(clk_e) do
39
+ # Performs the loop.
40
+ hif(req) do
41
+ # By default the loop is not finished.
42
+ # If the condition is still met go on looping.
43
+ hif(condition.call,&ruby_block)
44
+ end
45
+ # # if (init) then
46
+ # # # There is an initialization, do it when there is no req.
47
+ # # helse do
48
+ # # init.call
49
+ # # end
50
+ # # end
51
+ end
52
+
53
+ # The code for reseting the task.
54
+ if (init) then
55
+ # reseter(&init)
56
+ reseter do
57
+ req <= 0
58
+ init.call
59
+ end
60
+ end
61
+
62
+ # The code for running the task.
63
+ runner do
64
+ # top_block.unshift { req <= 0 }
65
+ req <= 1
66
+ end
67
+
68
+ # The code for checking the end of execution.
69
+ finisher do |blk|
70
+ hif(~condition.call,&blk)
71
+ end
72
+
73
+ end
74
+
75
+
76
+
77
+ ## A simplified loop: loops until +condition+ is met execution +ruby_block+.
78
+ # The loop is synchronized on +clk_e+ and initialized by +init+.
79
+ # If +condition+ is nil, then +init+ is used as +condition+.
80
+ def while_loop(clk_e, init, condition = nil, &ruby_block)
81
+ # Create the loop task.
82
+ tsk = while_task(clk_e,init,condition,ruby_block).(HDLRuby.uniq_name)
83
+ # Create the inner access port.
84
+ prt = tsk.inner HDLRuby.uniq_name
85
+ # Return the access port.
86
+ return prt
87
+ end
88
+
89
+ ## Loop +num+ times executing +ruby_block+.
90
+ # The loop is synchronized on +clk_e+.
91
+ def times_loop(clk_e, num, &ruby_block)
92
+ # Compute the width of the counter.
93
+ width = num.respond_to?(:width) ? num.width : num.type.width
94
+ # Declares the counter.
95
+ cnt = [width].inner(HDLRuby.uniq_name)
96
+ # Create the loop.
97
+ return while_loop(clk_e, proc{cnt<=0}, cnt<num) do
98
+ cnt <= cnt + 1
99
+ ruby_block.call
100
+ end
101
+ end