HDLRuby 3.1.0 → 3.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/HDLRuby.gemspec +1 -0
- data/README.html +2330 -2670
- data/README.md +400 -100
- data/ext/hruby_sim/hruby_rcsim_build.c +402 -3
- data/ext/hruby_sim/hruby_sim.h +2 -1
- data/ext/hruby_sim/hruby_sim_calc.c +34 -7
- data/ext/hruby_sim/hruby_sim_core.c +15 -5
- data/ext/hruby_sim/hruby_sim_tree_calc.c +112 -23
- data/lib/HDLRuby/hdr_samples/c_program/echo.c +33 -0
- data/lib/HDLRuby/hdr_samples/comparison_bench.rb +2 -2
- data/lib/HDLRuby/hdr_samples/counter_bench.rb +1 -1
- data/lib/HDLRuby/hdr_samples/counter_dff_bench.rb +8 -7
- data/lib/HDLRuby/hdr_samples/dff_properties.rb +2 -0
- data/lib/HDLRuby/hdr_samples/enum_as_param.rb +52 -0
- data/lib/HDLRuby/hdr_samples/linear_test.rb +2 -0
- data/lib/HDLRuby/hdr_samples/logic_bench.rb +6 -0
- data/lib/HDLRuby/hdr_samples/mei8.rb +6 -6
- data/lib/HDLRuby/hdr_samples/mei8_bench.rb +6 -6
- data/lib/HDLRuby/hdr_samples/memory_test.rb +2 -0
- data/lib/HDLRuby/hdr_samples/named_sub.rb +9 -5
- data/lib/HDLRuby/hdr_samples/ram.rb +7 -6
- data/lib/HDLRuby/hdr_samples/ruby_fir_hw.rb +2 -0
- data/lib/HDLRuby/hdr_samples/ruby_program/echo.rb +9 -0
- data/lib/HDLRuby/hdr_samples/ruby_program/stdrw.rb +6 -0
- data/lib/HDLRuby/hdr_samples/ruby_program/sw_cpu_terminal.rb +614 -0
- data/lib/HDLRuby/hdr_samples/ruby_program/sw_inc_mem.rb +32 -0
- data/lib/HDLRuby/hdr_samples/ruby_program/sw_log.rb +33 -0
- data/lib/HDLRuby/hdr_samples/struct.rb +15 -3
- data/lib/HDLRuby/hdr_samples/with_board.rb +63 -0
- data/lib/HDLRuby/hdr_samples/with_bram.rb +1 -1
- data/lib/HDLRuby/hdr_samples/with_bram_frame_stack.rb +1 -1
- data/lib/HDLRuby/hdr_samples/with_bram_stack.rb +1 -1
- data/lib/HDLRuby/hdr_samples/with_channel.rb +2 -0
- data/lib/HDLRuby/hdr_samples/with_channel_other.rb +2 -0
- data/lib/HDLRuby/hdr_samples/with_class.rb +3 -1
- data/lib/HDLRuby/hdr_samples/with_clocks.rb +42 -0
- data/lib/HDLRuby/hdr_samples/with_connector.rb +2 -0
- data/lib/HDLRuby/hdr_samples/with_connector_memory.rb +2 -0
- data/lib/HDLRuby/hdr_samples/with_fixpoint.rb +6 -0
- data/lib/HDLRuby/hdr_samples/with_fixpoint_adv.rb +73 -0
- data/lib/HDLRuby/hdr_samples/with_leftright.rb +1 -1
- data/lib/HDLRuby/hdr_samples/with_of.rb +1 -1
- data/lib/HDLRuby/hdr_samples/with_program_c.rb +28 -0
- data/lib/HDLRuby/hdr_samples/with_program_ruby.rb +28 -0
- data/lib/HDLRuby/hdr_samples/with_program_ruby_cpu.rb +234 -0
- data/lib/HDLRuby/hdr_samples/with_program_ruby_io.rb +23 -0
- data/lib/HDLRuby/hdr_samples/with_program_ruby_mem.rb +58 -0
- data/lib/HDLRuby/hdr_samples/with_program_ruby_threads.rb +56 -0
- data/lib/HDLRuby/hdr_samples/with_sequencer.rb +17 -0
- data/lib/HDLRuby/hdr_samples/with_sequencer_channel.rb +58 -0
- data/lib/HDLRuby/hdr_samples/with_sequencer_enumerable.rb +10 -0
- data/lib/HDLRuby/hdr_samples/with_sequencer_enumerator.rb +18 -4
- data/lib/HDLRuby/hdr_samples/with_sequencer_func.rb +2 -4
- data/lib/HDLRuby/hdr_samples/with_sequencer_sync.rb +2 -1
- data/lib/HDLRuby/hdrcc.rb +72 -21
- data/lib/HDLRuby/hruby_error.rb +13 -0
- data/lib/HDLRuby/hruby_high.rb +125 -26
- data/lib/HDLRuby/hruby_low.rb +171 -3
- data/lib/HDLRuby/hruby_low2programs.rb +47 -0
- data/lib/HDLRuby/hruby_low_resolve.rb +3 -2
- data/lib/HDLRuby/hruby_low_without_namespace.rb +133 -5
- data/lib/HDLRuby/hruby_low_without_subsignals.rb +1 -1
- data/lib/HDLRuby/hruby_rcsim.rb +113 -6
- data/lib/HDLRuby/hruby_serializer.rb +2 -1
- data/lib/HDLRuby/hruby_verilog.rb +94 -20
- data/lib/HDLRuby/hruby_verilog_name.rb +3 -17
- data/lib/HDLRuby/std/clocks.rb +118 -50
- data/lib/HDLRuby/std/fixpoint.rb +2 -2
- data/lib/HDLRuby/std/function_generator.rb +1 -1
- data/lib/HDLRuby/std/linear.rb +7 -7
- data/lib/HDLRuby/std/sequencer.rb +263 -13
- data/lib/HDLRuby/std/sequencer_channel.rb +90 -0
- data/lib/HDLRuby/std/sequencer_func.rb +28 -15
- data/lib/HDLRuby/std/std.rb +6 -0
- data/lib/HDLRuby/ui/hruby_board.rb +1079 -0
- data/lib/HDLRuby/version.rb +1 -1
- data/lib/c/Rakefile +8 -0
- data/lib/c/cHDL.h +12 -0
- data/lib/c/extconf.rb +7 -0
- data/lib/rubyHDL.rb +33 -0
- data/tuto/gui_accum.png +0 -0
- data/tuto/gui_board.png +0 -0
- data/tuto/tutorial_sw.html +2263 -1890
- data/tuto/tutorial_sw.md +957 -62
- metadata +43 -5
- data/README.pdf +0 -0
- data/tuto/tutorial_sw.pdf +0 -0
|
@@ -338,17 +338,19 @@ module HDLRuby::High::Std
|
|
|
338
338
|
@@old_make_inners_proc = self.instance_method(:make_inners)
|
|
339
339
|
|
|
340
340
|
def make_inners(typ,*names)
|
|
341
|
+
res = nil
|
|
341
342
|
if SequencerT.current then
|
|
342
343
|
unames = names.map {|name| HDLRuby.uniq_name(name) }
|
|
343
|
-
HDLRuby::High.cur_scope.make_inners(typ, *unames)
|
|
344
|
+
res = HDLRuby::High.cur_scope.make_inners(typ, *unames)
|
|
344
345
|
names.zip(unames).each do |name,uname|
|
|
345
346
|
HDLRuby::High.space_reg(name) { send(uname) }
|
|
346
347
|
end
|
|
347
348
|
else
|
|
348
349
|
# self.old_make_inners(typ,*names)
|
|
349
350
|
# Call the old make_inners.
|
|
350
|
-
@@old_make_inners_proc.bind(self).call(typ,*names)
|
|
351
|
+
res = @@old_make_inners_proc.bind(self).call(typ,*names)
|
|
351
352
|
end
|
|
353
|
+
return res
|
|
352
354
|
end
|
|
353
355
|
end
|
|
354
356
|
|
|
@@ -357,7 +359,17 @@ module HDLRuby::High::Std
|
|
|
357
359
|
|
|
358
360
|
# Module adding functionalities to object including the +seach+ method.
|
|
359
361
|
module SEnumerable
|
|
360
|
-
|
|
362
|
+
|
|
363
|
+
# Iterator on each of the elements in range +rng+.
|
|
364
|
+
# *NOTE*:
|
|
365
|
+
# - Stop iteration when the end of the range is reached or when there
|
|
366
|
+
# are no elements left
|
|
367
|
+
# - This is not a method from Ruby but one specific for hardware where
|
|
368
|
+
# creating a array is very expensive.
|
|
369
|
+
def seach_range(rng,&ruby_block)
|
|
370
|
+
return self.seach.seach_range(rng,&ruby_block)
|
|
371
|
+
end
|
|
372
|
+
|
|
361
373
|
# Tell if all the elements respect a given criterion given either
|
|
362
374
|
# as +arg+ or as block.
|
|
363
375
|
def sall?(arg = nil,&ruby_block)
|
|
@@ -1659,6 +1671,55 @@ module HDLRuby::High::Std
|
|
|
1659
1671
|
end
|
|
1660
1672
|
end
|
|
1661
1673
|
|
|
1674
|
+
# Iterator on the +num+ next elements.
|
|
1675
|
+
# *NOTE*:
|
|
1676
|
+
# - Stop iteration when the end of the range is reached or when there
|
|
1677
|
+
# are no elements left
|
|
1678
|
+
# - This is not a method from Ruby but one specific for hardware where
|
|
1679
|
+
# creating a array is very expensive.
|
|
1680
|
+
def seach_nexts(num,&ruby_block)
|
|
1681
|
+
# # No block given, returns a new enumerator.
|
|
1682
|
+
# unless ruby_block then
|
|
1683
|
+
# res = SEnumeratorWrapper.new(self,:seach_nexts,num)
|
|
1684
|
+
# res.size = num
|
|
1685
|
+
# return res
|
|
1686
|
+
# end
|
|
1687
|
+
# # A block is given, iterate.
|
|
1688
|
+
# enum = self.seach
|
|
1689
|
+
# # Create a counter.
|
|
1690
|
+
# count = nil
|
|
1691
|
+
# zero = nil
|
|
1692
|
+
# one = nil
|
|
1693
|
+
# HDLRuby::High.cur_system.open do
|
|
1694
|
+
# if num.respond_to?(:width) then
|
|
1695
|
+
# count = [num.width].inner(HDLRuby.uniq_name(:"snexts_count"))
|
|
1696
|
+
# else
|
|
1697
|
+
# count = num.to_expr.type.inner(HDLRuby.uniq_name(:"snexts_count"))
|
|
1698
|
+
# end
|
|
1699
|
+
# zero = _b0
|
|
1700
|
+
# one = _b1
|
|
1701
|
+
# end
|
|
1702
|
+
# count <= num
|
|
1703
|
+
# SequencerT.current.swhile(count > zero) do
|
|
1704
|
+
# ruby_block.call(enum.snext)
|
|
1705
|
+
# count <= count - one
|
|
1706
|
+
# end
|
|
1707
|
+
zero = nil
|
|
1708
|
+
one = nil
|
|
1709
|
+
HDLRuby::High.cur_system.open do
|
|
1710
|
+
zero = _b0.as(num.to_expr.type)
|
|
1711
|
+
one = _b1.as(num.to_expr.type)
|
|
1712
|
+
end
|
|
1713
|
+
subE = SEnumeratorSub.new(self,zero..num-one)
|
|
1714
|
+
if ruby_block then
|
|
1715
|
+
# A block is given, iterate immediatly.
|
|
1716
|
+
subE.seach(&ruby_block)
|
|
1717
|
+
else
|
|
1718
|
+
# No block given, return the new sub iterator.
|
|
1719
|
+
return subE
|
|
1720
|
+
end
|
|
1721
|
+
end
|
|
1722
|
+
|
|
1662
1723
|
end
|
|
1663
1724
|
|
|
1664
1725
|
|
|
@@ -1682,10 +1743,30 @@ module HDLRuby::High::Std
|
|
|
1682
1743
|
return self unless ruby_block
|
|
1683
1744
|
# A block is given, iterate.
|
|
1684
1745
|
this = self
|
|
1685
|
-
#
|
|
1746
|
+
# Reinitialize the iteration.
|
|
1686
1747
|
this.srewind
|
|
1687
|
-
#
|
|
1748
|
+
# Perform the iteration.
|
|
1688
1749
|
SequencerT.current.swhile(self.index < self.size) do
|
|
1750
|
+
# ruby_block.call(this.snext)
|
|
1751
|
+
HDLRuby::High.top_user.instance_exec(this.snext,&ruby_block)
|
|
1752
|
+
end
|
|
1753
|
+
end
|
|
1754
|
+
|
|
1755
|
+
# Iterator on each of the elements in range +rng+.
|
|
1756
|
+
# *NOTE*:
|
|
1757
|
+
# - Stop iteration when the end of the range is reached or when there
|
|
1758
|
+
# are no elements left
|
|
1759
|
+
# - This is not a method from Ruby but one specific for hardware where
|
|
1760
|
+
# creating a array is very expensive.
|
|
1761
|
+
def seach_range(rng,&ruby_block)
|
|
1762
|
+
# No block given, returns a new enumerator.
|
|
1763
|
+
return SEnumeratorWrapper.new(self,:seach_range) unless ruby_block
|
|
1764
|
+
# A block is given, iterate.
|
|
1765
|
+
this = self
|
|
1766
|
+
# Perform the iteration.
|
|
1767
|
+
self.index <= rng.first
|
|
1768
|
+
SequencerT.current.swhile((self.index < self.size) &
|
|
1769
|
+
(self.index <= rng.last) ) do
|
|
1689
1770
|
ruby_block.call(this.snext)
|
|
1690
1771
|
end
|
|
1691
1772
|
end
|
|
@@ -1770,7 +1851,7 @@ module HDLRuby::High::Std
|
|
|
1770
1851
|
|
|
1771
1852
|
# The directly delegate methods.
|
|
1772
1853
|
def size
|
|
1773
|
-
return @
|
|
1854
|
+
return @enumertor.size
|
|
1774
1855
|
end
|
|
1775
1856
|
|
|
1776
1857
|
def type
|
|
@@ -1798,13 +1879,32 @@ module HDLRuby::High::Std
|
|
|
1798
1879
|
end
|
|
1799
1880
|
|
|
1800
1881
|
def snext?
|
|
1882
|
+
# if @size then
|
|
1883
|
+
# return @enumerator.index < @size
|
|
1884
|
+
# else
|
|
1885
|
+
# return @enumerator.snext?
|
|
1886
|
+
# end
|
|
1801
1887
|
return @enumerator.snext?
|
|
1802
1888
|
end
|
|
1803
1889
|
|
|
1890
|
+
def snext!(val)
|
|
1891
|
+
return @enumerator.snext!(val)
|
|
1892
|
+
end
|
|
1893
|
+
|
|
1804
1894
|
def srewind
|
|
1805
1895
|
return @enumerator.srewind
|
|
1806
1896
|
end
|
|
1807
1897
|
|
|
1898
|
+
# Iterator on each of the elements in range +rng+.
|
|
1899
|
+
# *NOTE*:
|
|
1900
|
+
# - Stop iteration when the end of the range is reached or when there
|
|
1901
|
+
# are no elements left
|
|
1902
|
+
# - This is not a method from Ruby but one specific for hardware where
|
|
1903
|
+
# creating a array is very expensive.
|
|
1904
|
+
def seach_range(rng,&ruby_block)
|
|
1905
|
+
return @enumerator.seach_range(rng,&ruby_block)
|
|
1906
|
+
end
|
|
1907
|
+
|
|
1808
1908
|
# Clones the enumerator.
|
|
1809
1909
|
def clone
|
|
1810
1910
|
return SEnumeratorWrapper.new(@enumerator,@iterator,*@arguments)
|
|
@@ -1820,6 +1920,92 @@ module HDLRuby::High::Std
|
|
|
1820
1920
|
end
|
|
1821
1921
|
|
|
1822
1922
|
|
|
1923
|
+
# Describes a sequencer enumerator class that allows to generate HW iterations
|
|
1924
|
+
# over HW or SW objects within sequencers.
|
|
1925
|
+
# This is the sub Enumerator over an other one for interating inside the
|
|
1926
|
+
# enumerator.
|
|
1927
|
+
# This is specific the HDLRuby for avoiding creation of array which are
|
|
1928
|
+
# expensive in HW. Used by seach_next for example.
|
|
1929
|
+
# Will change the index position of the initial iterator without reseting
|
|
1930
|
+
# it.
|
|
1931
|
+
class SEnumeratorSub < SEnumerator
|
|
1932
|
+
|
|
1933
|
+
# Create a new SEnumerator wrapper over +enum+ among +rng+ indexes.
|
|
1934
|
+
def initialize(enum,rng,*args)
|
|
1935
|
+
@enumerator = enum.seach
|
|
1936
|
+
@range = rng.first..rng.last
|
|
1937
|
+
# Declare the sub index.
|
|
1938
|
+
idx = nil
|
|
1939
|
+
siz = @range.last-@range.first+1
|
|
1940
|
+
HDLRuby::High.cur_system.open do
|
|
1941
|
+
idx = [siz.width].inner({
|
|
1942
|
+
HDLRuby.uniq_name("sub_idx") => 0 })
|
|
1943
|
+
end
|
|
1944
|
+
@index = idx
|
|
1945
|
+
@size = siz
|
|
1946
|
+
end
|
|
1947
|
+
|
|
1948
|
+
# The directly delegate methods.
|
|
1949
|
+
def size
|
|
1950
|
+
return @size
|
|
1951
|
+
end
|
|
1952
|
+
|
|
1953
|
+
def type
|
|
1954
|
+
return @enumerator.type
|
|
1955
|
+
end
|
|
1956
|
+
|
|
1957
|
+
def result
|
|
1958
|
+
return @enumerator.result
|
|
1959
|
+
end
|
|
1960
|
+
|
|
1961
|
+
def index
|
|
1962
|
+
return @index
|
|
1963
|
+
end
|
|
1964
|
+
|
|
1965
|
+
def access(idx)
|
|
1966
|
+
return @enumerator.access(@index+@range.first)
|
|
1967
|
+
end
|
|
1968
|
+
|
|
1969
|
+
def speek
|
|
1970
|
+
return @enumerator.speek
|
|
1971
|
+
end
|
|
1972
|
+
|
|
1973
|
+
def snext
|
|
1974
|
+
@index <= @index + 1
|
|
1975
|
+
return @enumerator.snext
|
|
1976
|
+
end
|
|
1977
|
+
|
|
1978
|
+
def snext?
|
|
1979
|
+
return @index < self.size
|
|
1980
|
+
end
|
|
1981
|
+
|
|
1982
|
+
def snext!(val)
|
|
1983
|
+
return @enumerator.snext!(val)
|
|
1984
|
+
end
|
|
1985
|
+
|
|
1986
|
+
def srewind
|
|
1987
|
+
@index <= 0
|
|
1988
|
+
end
|
|
1989
|
+
|
|
1990
|
+
# Clones the enumerator.
|
|
1991
|
+
def clone
|
|
1992
|
+
return SEnumeratorSub.new(@enumerator,@range)
|
|
1993
|
+
end
|
|
1994
|
+
|
|
1995
|
+
# Iterate over each element.
|
|
1996
|
+
def seach(&ruby_block)
|
|
1997
|
+
# No block given, returns self.
|
|
1998
|
+
return self unless ruby_block
|
|
1999
|
+
# A block is given, iterate.
|
|
2000
|
+
this = self
|
|
2001
|
+
SequencerT.current.swhile(this.snext?) do
|
|
2002
|
+
ruby_block.call(this.snext)
|
|
2003
|
+
end
|
|
2004
|
+
end
|
|
2005
|
+
end
|
|
2006
|
+
|
|
2007
|
+
|
|
2008
|
+
|
|
1823
2009
|
# Describes a sequencer enumerator class that allows to generate HW
|
|
1824
2010
|
# iterations over HW or SW objects within sequencers.
|
|
1825
2011
|
# This is the base Enumerator that directly iterates.
|
|
@@ -1880,9 +2066,17 @@ module HDLRuby::High::Std
|
|
|
1880
2066
|
|
|
1881
2067
|
# Tell if there is a next element.
|
|
1882
2068
|
def snext?
|
|
2069
|
+
# puts "@index=#{index}, @size=#{@size}"
|
|
1883
2070
|
return @index < @size
|
|
1884
2071
|
end
|
|
1885
2072
|
|
|
2073
|
+
# Set the next element.
|
|
2074
|
+
def snext!(val)
|
|
2075
|
+
@access.call(@index,val)
|
|
2076
|
+
@index <= @index + 1
|
|
2077
|
+
return val
|
|
2078
|
+
end
|
|
2079
|
+
|
|
1886
2080
|
# Restart the iteration.
|
|
1887
2081
|
def srewind
|
|
1888
2082
|
@index <= 0
|
|
@@ -1890,6 +2084,8 @@ module HDLRuby::High::Std
|
|
|
1890
2084
|
end
|
|
1891
2085
|
|
|
1892
2086
|
|
|
2087
|
+
|
|
2088
|
+
|
|
1893
2089
|
module HDLRuby::High::HExpression
|
|
1894
2090
|
# Enhance the HExpression module with sequencer iteration.
|
|
1895
2091
|
|
|
@@ -1897,8 +2093,14 @@ module HDLRuby::High::Std
|
|
|
1897
2093
|
def seach(&ruby_block)
|
|
1898
2094
|
# Create the hardware iterator.
|
|
1899
2095
|
this = self
|
|
1900
|
-
hw_enum = SEnumeratorBase.new(this.type.base,this.type.size) do |idx|
|
|
1901
|
-
|
|
2096
|
+
hw_enum = SEnumeratorBase.new(this.type.base,this.type.size) do |idx,val = nil|
|
|
2097
|
+
if val then
|
|
2098
|
+
# Write access
|
|
2099
|
+
this[idx] <= val
|
|
2100
|
+
else
|
|
2101
|
+
# Read access
|
|
2102
|
+
this[idx]
|
|
2103
|
+
end
|
|
1902
2104
|
end
|
|
1903
2105
|
# Is there a ruby block?
|
|
1904
2106
|
if(ruby_block) then
|
|
@@ -1917,23 +2119,27 @@ module HDLRuby::High::Std
|
|
|
1917
2119
|
end
|
|
1918
2120
|
|
|
1919
2121
|
|
|
1920
|
-
class HDLRuby::High::Value
|
|
2122
|
+
# class HDLRuby::High::Value
|
|
2123
|
+
module HDLRuby::High::HExpression
|
|
1921
2124
|
# Enhance the Value class with sequencer iterations.
|
|
1922
2125
|
|
|
1923
2126
|
# HW times iteration.
|
|
1924
2127
|
def stimes(&ruby_block)
|
|
1925
|
-
return (0..self-1).seach(&ruby_block)
|
|
2128
|
+
# return (0..self-1).seach(&ruby_block)
|
|
2129
|
+
return AnyRange.new(0,self-1).seach(&ruby_block)
|
|
1926
2130
|
end
|
|
1927
2131
|
|
|
1928
2132
|
# HW upto iteration.
|
|
1929
2133
|
def supto(val,&ruby_block)
|
|
1930
|
-
return (self..val).seach(&ruby_block)
|
|
2134
|
+
# return (self..val).seach(&ruby_block)
|
|
2135
|
+
return AnyRange.new(self,val).seach(&ruby_block)
|
|
1931
2136
|
end
|
|
1932
2137
|
|
|
1933
2138
|
# HW downto iteration.
|
|
1934
2139
|
def sdownto(val,&ruby_block)
|
|
1935
2140
|
# Create the hardware iterator.
|
|
1936
|
-
range = val..(self.to_i)
|
|
2141
|
+
# range = val..(self.to_i)
|
|
2142
|
+
range = AnyRange.new(val,self)
|
|
1937
2143
|
hw_enum = SEnumeratorBase.new(signed[32],range.size) do |idx|
|
|
1938
2144
|
range.last - idx
|
|
1939
2145
|
end
|
|
@@ -2034,6 +2240,51 @@ module HDLRuby::High::Std
|
|
|
2034
2240
|
end
|
|
2035
2241
|
|
|
2036
2242
|
|
|
2243
|
+
# Range substitute class for sequencers that supports any kind of bounds.
|
|
2244
|
+
class AnyRange
|
|
2245
|
+
# Enhance the AnyRange class with sequencer iteration.
|
|
2246
|
+
include SEnumerable
|
|
2247
|
+
|
|
2248
|
+
attr_reader :first, :last
|
|
2249
|
+
|
|
2250
|
+
def initialize(first,last)
|
|
2251
|
+
@first = first
|
|
2252
|
+
@last = last
|
|
2253
|
+
end
|
|
2254
|
+
|
|
2255
|
+
# HW iteration on each element.
|
|
2256
|
+
def seach(&ruby_block)
|
|
2257
|
+
# Create the iteration type: selection of the larger HDLRuby type
|
|
2258
|
+
# between first and last. If one of first and last is a Numeric,
|
|
2259
|
+
# priority to the non Numeric one.
|
|
2260
|
+
if (self.last.is_a?(Numeric)) then
|
|
2261
|
+
typ = self.first.to_expr.type
|
|
2262
|
+
elsif (self.first.is_a?(Numeric)) then
|
|
2263
|
+
typ = self.last.to_expr.type
|
|
2264
|
+
else
|
|
2265
|
+
typ = self.first.type.width > self.last.type.width ?
|
|
2266
|
+
self.first.type : self.last.type
|
|
2267
|
+
end
|
|
2268
|
+
# Create the hardware iterator.
|
|
2269
|
+
this = self
|
|
2270
|
+
# size = this.size ? this.size : this.last - this.first + 1
|
|
2271
|
+
size = this.last - this.first + 1
|
|
2272
|
+
size = size.to_expr.as(typ)
|
|
2273
|
+
hw_enum = SEnumeratorBase.new(typ,size) do |idx|
|
|
2274
|
+
idx.as(typ) + this.first.to_expr.as(typ)
|
|
2275
|
+
end
|
|
2276
|
+
# Is there a ruby block?
|
|
2277
|
+
if(ruby_block) then
|
|
2278
|
+
# Yes, apply it.
|
|
2279
|
+
return hw_enum.seach(&ruby_block)
|
|
2280
|
+
else
|
|
2281
|
+
# No, return the resulting enumerator.
|
|
2282
|
+
return hw_enum
|
|
2283
|
+
end
|
|
2284
|
+
end
|
|
2285
|
+
end
|
|
2286
|
+
|
|
2287
|
+
|
|
2037
2288
|
class ::Integer
|
|
2038
2289
|
# Enhance the Integer class with sequencer iterations.
|
|
2039
2290
|
|
|
@@ -2081,5 +2332,4 @@ module HDLRuby::High::Std
|
|
|
2081
2332
|
end
|
|
2082
2333
|
|
|
2083
2334
|
|
|
2084
|
-
|
|
2085
2335
|
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require 'std/sequencer'
|
|
2
|
+
|
|
3
|
+
module HDLRuby::High::Std
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# Standard HDLRuby::High library: channel generator.
|
|
7
|
+
# The idea is to have abstract communication interface whose
|
|
8
|
+
# implementation can be seamlessly modified.
|
|
9
|
+
#
|
|
10
|
+
########################################################################
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# Creates an abstract channel over an accessing method.
|
|
17
|
+
# NOTE: Works like an enumerator, but can be passed as generic arguments and
|
|
18
|
+
# generates a different enumerator per sequencer.
|
|
19
|
+
# - +typ+ is the data type of the elements.
|
|
20
|
+
# - +size+ is the number of elements.
|
|
21
|
+
# - +access+ is the block implementing the access method.
|
|
22
|
+
class SequencerChannel < SEnumerator
|
|
23
|
+
|
|
24
|
+
# Create a new channel for +size+ elements of type +type+ with an JW
|
|
25
|
+
# array-like accesser +access+.
|
|
26
|
+
def initialize(typ,size,&access)
|
|
27
|
+
@type = typ
|
|
28
|
+
@size = size
|
|
29
|
+
@access = access
|
|
30
|
+
@enums = {} # The enumerator per sequencer.
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Get the enumerator for current sequencer.
|
|
34
|
+
# If does not exist create a new one.
|
|
35
|
+
def senumerator
|
|
36
|
+
unless SequencerT.current then
|
|
37
|
+
raise "Cannot get a channel enumerator from outside a sequencer."
|
|
38
|
+
end
|
|
39
|
+
enum = @enums[SequencerT.current]
|
|
40
|
+
unless enum then
|
|
41
|
+
enum = @enums[SequencerT.current] =
|
|
42
|
+
SEnumeratorBase.new(@type,@size,&@access)
|
|
43
|
+
end
|
|
44
|
+
return enum
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Clones is ambigous here, so deactivated.
|
|
48
|
+
def clone
|
|
49
|
+
raise "clone not supported for channels."
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# The array read accesses.
|
|
53
|
+
def [](addr)
|
|
54
|
+
return @access.call(addr)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# The array write access.
|
|
58
|
+
def []=(addr,val)
|
|
59
|
+
return @access.call(addr,val)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# The access to the already defined elements.
|
|
63
|
+
attr_reader :type
|
|
64
|
+
attr_reader :size
|
|
65
|
+
|
|
66
|
+
# Delegate the enumeration methods to the enumerator of the current
|
|
67
|
+
# system.
|
|
68
|
+
|
|
69
|
+
[:result,:index,:access,:speek,
|
|
70
|
+
:snext,:snext?,:snext!,:srewind].each do |sym|
|
|
71
|
+
define_method(sym) do |*args,&ruby_block|
|
|
72
|
+
senumerator.send(sym,*args,&ruby_block)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# Creates an abstract channel over an accessing method.
|
|
80
|
+
# NOTE: Works like an enumerator or a memory access, but can be passed as
|
|
81
|
+
# generic arguments and generates a different enumerator per sequencer
|
|
82
|
+
# (memory access is identical for now though).
|
|
83
|
+
# - +typ+ is the data type of the elements.
|
|
84
|
+
# - +size+ is the number of elements.
|
|
85
|
+
# - +access+ is the block implementing the access method.
|
|
86
|
+
def schannel(typ,size,&access)
|
|
87
|
+
return SequencerChannel.new(typ,size,&access)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
end
|
|
@@ -16,6 +16,12 @@ module HDLRuby::High::Std
|
|
|
16
16
|
# their are set when the function is called.
|
|
17
17
|
# This is handle by the eigen functions (see SequencerFunctionE).
|
|
18
18
|
class SequencerFunctionT
|
|
19
|
+
|
|
20
|
+
ZERO = :_b0.to_value
|
|
21
|
+
ONE = :_sb01.to_value
|
|
22
|
+
# ZERO = 0
|
|
23
|
+
# ONE = 1
|
|
24
|
+
|
|
19
25
|
# The name of the function.
|
|
20
26
|
attr_reader :name
|
|
21
27
|
|
|
@@ -69,7 +75,7 @@ module HDLRuby::High::Std
|
|
|
69
75
|
# hprint("returning with stack_ptr=",stack_ptr,"\n")
|
|
70
76
|
hif(stack_ptr <= depth) do
|
|
71
77
|
# hprint("poking recursive return value at idx=",funcI.returnIdx," with value=",st_call.value+1,"\n")
|
|
72
|
-
funcI.poke(funcI.returnIdx,st_call.value +
|
|
78
|
+
funcI.poke(funcI.returnIdx,st_call.value + ONE)
|
|
73
79
|
end
|
|
74
80
|
end
|
|
75
81
|
end
|
|
@@ -89,7 +95,7 @@ module HDLRuby::High::Std
|
|
|
89
95
|
old_code.call
|
|
90
96
|
HDLRuby::High.top_user.instance_exec do
|
|
91
97
|
# hprint("poking return value at idx=",funcI.returnIdx," with value=",st_func.value+1,"\n")
|
|
92
|
-
funcI.poke(funcI.returnIdx,st_func.value +
|
|
98
|
+
funcI.poke(funcI.returnIdx,st_func.value + ONE)
|
|
93
99
|
end
|
|
94
100
|
end
|
|
95
101
|
end
|
|
@@ -151,6 +157,11 @@ module HDLRuby::High::Std
|
|
|
151
157
|
|
|
152
158
|
# Describes a sequencer function instance.
|
|
153
159
|
class SequencerFunctionI
|
|
160
|
+
|
|
161
|
+
ZERO = SequencerFunctionT::ZERO
|
|
162
|
+
ONE = SequencerFunctionT::ONE
|
|
163
|
+
|
|
164
|
+
|
|
154
165
|
@@current_stack = [] # The stack of current function instance.
|
|
155
166
|
|
|
156
167
|
# Get the function instance currently processing.
|
|
@@ -194,7 +205,7 @@ module HDLRuby::High::Std
|
|
|
194
205
|
# Create the stacks for the arguments.
|
|
195
206
|
@funcE.each_argT { |argT| self.make_stack(argT) }
|
|
196
207
|
# @argsIdx = @returnIdx + 2
|
|
197
|
-
@argsIdx = @returnIdx +
|
|
208
|
+
@argsIdx = @returnIdx + ONE
|
|
198
209
|
|
|
199
210
|
# Create the return value, however, at first their type is unknown
|
|
200
211
|
# to set it as a simple bit.
|
|
@@ -296,7 +307,7 @@ module HDLRuby::High::Std
|
|
|
296
307
|
|
|
297
308
|
# Get the state value of the function: it is the state
|
|
298
309
|
# following the first function call.
|
|
299
|
-
func_state_value = call_state.value +
|
|
310
|
+
func_state_value = call_state.value + ONE
|
|
300
311
|
# Do the call.
|
|
301
312
|
call_state.gotos << proc do
|
|
302
313
|
HDLRuby::High.top_user.instance_exec do
|
|
@@ -329,7 +340,7 @@ module HDLRuby::High::Std
|
|
|
329
340
|
# Since not pushed the stack yet for not loosing the previous
|
|
330
341
|
# arguments, add +1 to the offset when poking the new arguments.
|
|
331
342
|
# args.each_with_index { |arg,i| self.poke(@argsIdx + i,arg,1) }
|
|
332
|
-
args.each_with_index { |arg,i| this.poke(argsIdx + i,arg,
|
|
343
|
+
args.each_with_index { |arg,i| this.poke(argsIdx + i,arg,ONE) }
|
|
333
344
|
end
|
|
334
345
|
|
|
335
346
|
# Push a new frame.
|
|
@@ -349,7 +360,7 @@ module HDLRuby::High::Std
|
|
|
349
360
|
|
|
350
361
|
# Get the state value of the function: it is the state
|
|
351
362
|
# following the first function call.
|
|
352
|
-
func_state_value = @state.value +
|
|
363
|
+
func_state_value = @state.value + ONE
|
|
353
364
|
# Do the call.
|
|
354
365
|
call_state.gotos << proc do
|
|
355
366
|
HDLRuby::High.top_user.instance_exec do
|
|
@@ -358,7 +369,7 @@ module HDLRuby::High::Std
|
|
|
358
369
|
end
|
|
359
370
|
helse do
|
|
360
371
|
# Overflow! Skip the call.
|
|
361
|
-
next_state_sig <= call_state_value +
|
|
372
|
+
next_state_sig <= call_state_value + ONE
|
|
362
373
|
# if overflow then
|
|
363
374
|
# # There is some overflow code to execute.
|
|
364
375
|
# HDLRuby::High.top_user.instance_exec(&overflow)
|
|
@@ -395,32 +406,32 @@ module HDLRuby::High::Std
|
|
|
395
406
|
@stack_sigs << stack_sig
|
|
396
407
|
|
|
397
408
|
# Returns the index of the newly created stack.
|
|
398
|
-
return @stack_sigs.size-
|
|
409
|
+
return @stack_sigs.size - ONE
|
|
399
410
|
end
|
|
400
411
|
|
|
401
412
|
## Pushes a new frame to the top of the stacks.
|
|
402
413
|
def push_all
|
|
403
414
|
# HDLRuby::High.cur_system.hprint("push_all\n")
|
|
404
|
-
@stack_ptr <= @stack_ptr +
|
|
415
|
+
@stack_ptr <= @stack_ptr + ONE
|
|
405
416
|
end
|
|
406
417
|
|
|
407
418
|
## Remove the top frame from the stacks.
|
|
408
419
|
def pop_all
|
|
409
420
|
# HDLRuby::High.cur_system.hprint("pop_all\n")
|
|
410
|
-
@stack_ptr <= @stack_ptr -
|
|
421
|
+
@stack_ptr <= @stack_ptr - ONE
|
|
411
422
|
end
|
|
412
423
|
|
|
413
424
|
## Get a value from the top of stack number +idx+
|
|
414
425
|
# If +off+ is the offeset in the stack.
|
|
415
426
|
def peek(idx, off = 0)
|
|
416
|
-
return @stack_sigs[idx][@stack_ptr-
|
|
427
|
+
return @stack_sigs[idx][(@stack_ptr-ONE)+off]
|
|
417
428
|
end
|
|
418
429
|
|
|
419
430
|
## Sets value +val+ to the top of stack number +idx+.
|
|
420
431
|
# If +off+ is the offeset in the stack.
|
|
421
432
|
def poke(idx,val, off = 0)
|
|
422
433
|
# puts "idx=#{idx} val=#{val} sig=#{@stack_sigs[idx].name}"
|
|
423
|
-
@stack_sigs[idx][@stack_ptr-
|
|
434
|
+
@stack_sigs[idx][@stack_ptr-ONE+off] <= val
|
|
424
435
|
end
|
|
425
436
|
|
|
426
437
|
## Access the return value signal.
|
|
@@ -449,7 +460,7 @@ module HDLRuby::High::Std
|
|
|
449
460
|
# ret_state_value = self.peek(@returnIdx, HDLRuby::High.top_user.mux(@stack_ptr < @depth,-1,0))
|
|
450
461
|
# Peek before the stack pointer value to account from the fact that
|
|
451
462
|
# the pop is performed beforehand.
|
|
452
|
-
ret_state_value = self.peek(@returnIdx, HDLRuby::High.top_user.mux(@stack_ptr < @depth,
|
|
463
|
+
ret_state_value = self.peek(@returnIdx, HDLRuby::High.top_user.mux(@stack_ptr < @depth,ZERO,ONE))
|
|
453
464
|
# Return.
|
|
454
465
|
this = self
|
|
455
466
|
state.gotos << proc do
|
|
@@ -483,15 +494,17 @@ module HDLRuby::High::Std
|
|
|
483
494
|
alias_method :old_make_inners, :make_inners
|
|
484
495
|
|
|
485
496
|
def make_inners(typ,*names)
|
|
497
|
+
res = nil
|
|
486
498
|
if SequencerFunctionI.current then
|
|
487
499
|
unames = names.map {|name| HDLRuby.uniq_name(name) }
|
|
488
|
-
HDLRuby::High.cur_scope.make_inners(typ, *unames)
|
|
500
|
+
res = HDLRuby::High.cur_scope.make_inners(typ, *unames)
|
|
489
501
|
names.zip(unames).each do |name,uname|
|
|
490
502
|
HDLRuby::High.space_reg(name) { send(uname) }
|
|
491
503
|
end
|
|
492
504
|
else
|
|
493
|
-
self.old_make_inners(typ,*names)
|
|
505
|
+
res = self.old_make_inners(typ,*names)
|
|
494
506
|
end
|
|
507
|
+
return res
|
|
495
508
|
end
|
|
496
509
|
end
|
|
497
510
|
|
data/lib/HDLRuby/std/std.rb
CHANGED
|
@@ -4,10 +4,16 @@
|
|
|
4
4
|
#
|
|
5
5
|
########################################################################
|
|
6
6
|
|
|
7
|
+
# Hardware libraries.
|
|
8
|
+
|
|
7
9
|
require 'std/clocks.rb'
|
|
8
10
|
require 'std/fixpoint.rb'
|
|
9
11
|
require 'std/decoder.rb'
|
|
10
12
|
require 'std/fsm.rb'
|
|
11
13
|
require 'std/sequencer.rb'
|
|
14
|
+
require 'std/sequencer_channel.rb'
|
|
12
15
|
require 'std/sequencer_sync.rb'
|
|
13
16
|
require 'std/sequencer_func.rb'
|
|
17
|
+
|
|
18
|
+
# User interface libraries.
|
|
19
|
+
require 'ui/hruby_board.rb'
|