HDLRuby 2.2.17 → 2.3.0
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 +4 -4
- data/lib/HDLRuby/hdr_samples/ruby_fir_hw.rb +96 -0
- data/lib/HDLRuby/hdr_samples/with_linear.rb +4 -1
- data/lib/HDLRuby/hdr_samples/with_loop.rb +69 -0
- data/lib/HDLRuby/hdr_samples/with_memory.rb +13 -3
- data/lib/HDLRuby/hruby_high.rb +6 -0
- data/lib/HDLRuby/hruby_low.rb +24 -9
- data/lib/HDLRuby/hruby_low2c.rb +9 -5
- data/lib/HDLRuby/hruby_low_fix_types.rb +4 -2
- data/lib/HDLRuby/hruby_low_resolve.rb +5 -3
- data/lib/HDLRuby/hruby_low_without_concat.rb +8 -4
- data/lib/HDLRuby/hruby_types.rb +82 -72
- data/lib/HDLRuby/sim/hruby_sim.h +7 -0
- data/lib/HDLRuby/sim/hruby_sim_calc.c +79 -6
- data/lib/HDLRuby/std/channel.rb +39 -16
- data/lib/HDLRuby/std/fixpoint.rb +7 -6
- data/lib/HDLRuby/std/linear.rb +68 -0
- data/lib/HDLRuby/std/loop.rb +101 -0
- data/lib/HDLRuby/std/memory.rb +1000 -30
- data/lib/HDLRuby/std/task.rb +850 -0
- data/lib/HDLRuby/version.rb +1 -1
- metadata +6 -2
data/lib/HDLRuby/sim/hruby_sim.h
CHANGED
@@ -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
|
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
|
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
|
-
|
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
|
data/lib/HDLRuby/std/channel.rb
CHANGED
@@ -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
|
-
|
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
|
-
#
|
608
|
-
channelI
|
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
|
|
data/lib/HDLRuby/std/fixpoint.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
data/lib/HDLRuby/std/linear.rb
CHANGED
@@ -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
|