HDLRuby 2.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/HDLRuby.gemspec +36 -0
- data/LICENSE.txt +21 -0
- data/README.md +2774 -0
- data/README.pdf +0 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/hdrcc +3 -0
- data/lib/HDLRuby/alcc.rb +137 -0
- data/lib/HDLRuby/backend/hruby_allocator.rb +69 -0
- data/lib/HDLRuby/backend/hruby_c_allocator.rb +76 -0
- data/lib/HDLRuby/hdr_samples/adder.rb +7 -0
- data/lib/HDLRuby/hdr_samples/adder_assign_error.rb +11 -0
- data/lib/HDLRuby/hdr_samples/adder_bench.rb +27 -0
- data/lib/HDLRuby/hdr_samples/adder_gen.rb +7 -0
- data/lib/HDLRuby/hdr_samples/adder_nodef_error.rb +7 -0
- data/lib/HDLRuby/hdr_samples/addsub.rb +19 -0
- data/lib/HDLRuby/hdr_samples/addsubz.rb +22 -0
- data/lib/HDLRuby/hdr_samples/alu.rb +47 -0
- data/lib/HDLRuby/hdr_samples/calculator.rb +48 -0
- data/lib/HDLRuby/hdr_samples/counter_bench.rb +83 -0
- data/lib/HDLRuby/hdr_samples/dff.rb +9 -0
- data/lib/HDLRuby/hdr_samples/dff_bench.rb +66 -0
- data/lib/HDLRuby/hdr_samples/dff_counter.rb +20 -0
- data/lib/HDLRuby/hdr_samples/include.rb +14 -0
- data/lib/HDLRuby/hdr_samples/instance_open.rb +23 -0
- data/lib/HDLRuby/hdr_samples/mei8.rb +256 -0
- data/lib/HDLRuby/hdr_samples/mei8_bench.rb +309 -0
- data/lib/HDLRuby/hdr_samples/multer_gen.rb +8 -0
- data/lib/HDLRuby/hdr_samples/multer_seq.rb +29 -0
- data/lib/HDLRuby/hdr_samples/neural/a.rb +9 -0
- data/lib/HDLRuby/hdr_samples/neural/a_sub.rb +5 -0
- data/lib/HDLRuby/hdr_samples/neural/bw.rb +23 -0
- data/lib/HDLRuby/hdr_samples/neural/counter.rb +16 -0
- data/lib/HDLRuby/hdr_samples/neural/dadz.rb +9 -0
- data/lib/HDLRuby/hdr_samples/neural/dadz_sub.rb +4 -0
- data/lib/HDLRuby/hdr_samples/neural/forward.rb +153 -0
- data/lib/HDLRuby/hdr_samples/neural/forward_sub.rb +62 -0
- data/lib/HDLRuby/hdr_samples/neural/forward_sub_rand.rb +41 -0
- data/lib/HDLRuby/hdr_samples/neural/forward_sub_rand_typedef.rb +47 -0
- data/lib/HDLRuby/hdr_samples/neural/mem.rb +30 -0
- data/lib/HDLRuby/hdr_samples/neural/random.rb +23 -0
- data/lib/HDLRuby/hdr_samples/neural/selector.rb +29 -0
- data/lib/HDLRuby/hdr_samples/neural/sigmoid.rb +20 -0
- data/lib/HDLRuby/hdr_samples/neural/z.rb +33 -0
- data/lib/HDLRuby/hdr_samples/prog.obj +256 -0
- data/lib/HDLRuby/hdr_samples/ram.rb +18 -0
- data/lib/HDLRuby/hdr_samples/register_with_code_bench.rb +98 -0
- data/lib/HDLRuby/hdr_samples/rom.rb +10 -0
- data/lib/HDLRuby/hdr_samples/struct.rb +14 -0
- data/lib/HDLRuby/hdr_samples/sumprod.rb +29 -0
- data/lib/HDLRuby/hdr_samples/sw_encrypt_bench.rb +103 -0
- data/lib/HDLRuby/hdr_samples/sw_encrypt_cpu_bench.rb +261 -0
- data/lib/HDLRuby/hdr_samples/sw_encrypt_cpusim_bench.rb +302 -0
- data/lib/HDLRuby/hdr_samples/system_open.rb +11 -0
- data/lib/HDLRuby/hdr_samples/tuple.rb +16 -0
- data/lib/HDLRuby/hdr_samples/with_channel.rb +118 -0
- data/lib/HDLRuby/hdr_samples/with_class.rb +199 -0
- data/lib/HDLRuby/hdr_samples/with_decoder.rb +17 -0
- data/lib/HDLRuby/hdr_samples/with_fsm.rb +34 -0
- data/lib/HDLRuby/hdr_samples/with_reconf.rb +103 -0
- data/lib/HDLRuby/hdrcc.rb +623 -0
- data/lib/HDLRuby/high_samples/_adder_fault.rb +23 -0
- data/lib/HDLRuby/high_samples/_generic_transmission2.rb +146 -0
- data/lib/HDLRuby/high_samples/adder.rb +21 -0
- data/lib/HDLRuby/high_samples/adder_common_errors.rb +25 -0
- data/lib/HDLRuby/high_samples/addsub.rb +33 -0
- data/lib/HDLRuby/high_samples/addsubz.rb +37 -0
- data/lib/HDLRuby/high_samples/after.rb +28 -0
- data/lib/HDLRuby/high_samples/all_signals.rb +29 -0
- data/lib/HDLRuby/high_samples/alu.rb +61 -0
- data/lib/HDLRuby/high_samples/anonymous.rb +41 -0
- data/lib/HDLRuby/high_samples/before.rb +28 -0
- data/lib/HDLRuby/high_samples/blockblock.rb +26 -0
- data/lib/HDLRuby/high_samples/bugs/dadz.rb +22 -0
- data/lib/HDLRuby/high_samples/bugs/misample_instan.rb +20 -0
- data/lib/HDLRuby/high_samples/bugs/misample_updown.rb +22 -0
- data/lib/HDLRuby/high_samples/bugs/sample_add.rb +16 -0
- data/lib/HDLRuby/high_samples/bugs/sample_barrel.rb +13 -0
- data/lib/HDLRuby/high_samples/bugs/sample_daice.rb +57 -0
- data/lib/HDLRuby/high_samples/bugs/sample_kumiawase.rb +52 -0
- data/lib/HDLRuby/high_samples/bugs/sample_multi.rb +18 -0
- data/lib/HDLRuby/high_samples/bugs/sample_sub.rb +14 -0
- data/lib/HDLRuby/high_samples/bugs/z2.rb +32 -0
- data/lib/HDLRuby/high_samples/case.rb +32 -0
- data/lib/HDLRuby/high_samples/case2.rb +30 -0
- data/lib/HDLRuby/high_samples/change.rb +23 -0
- data/lib/HDLRuby/high_samples/clocks.rb +35 -0
- data/lib/HDLRuby/high_samples/comparer.rb +21 -0
- data/lib/HDLRuby/high_samples/conditionals.rb +29 -0
- data/lib/HDLRuby/high_samples/dff.rb +23 -0
- data/lib/HDLRuby/high_samples/each.rb +28 -0
- data/lib/HDLRuby/high_samples/exporter.rb +42 -0
- data/lib/HDLRuby/high_samples/functions.rb +60 -0
- data/lib/HDLRuby/high_samples/if_seq.rb +26 -0
- data/lib/HDLRuby/high_samples/inherit_as_dff.rb +32 -0
- data/lib/HDLRuby/high_samples/inherit_dff.rb +36 -0
- data/lib/HDLRuby/high_samples/instance.rb +37 -0
- data/lib/HDLRuby/high_samples/memory.rb +64 -0
- data/lib/HDLRuby/high_samples/multi_file.rb +27 -0
- data/lib/HDLRuby/high_samples/overload.rb +32 -0
- data/lib/HDLRuby/high_samples/paper_after.rb +49 -0
- data/lib/HDLRuby/high_samples/ram.rb +27 -0
- data/lib/HDLRuby/high_samples/registers.rb +139 -0
- data/lib/HDLRuby/high_samples/rom.rb +23 -0
- data/lib/HDLRuby/high_samples/scopeblockname.rb +37 -0
- data/lib/HDLRuby/high_samples/scopescope.rb +26 -0
- data/lib/HDLRuby/high_samples/shift.rb +31 -0
- data/lib/HDLRuby/high_samples/shift2.rb +40 -0
- data/lib/HDLRuby/high_samples/simple_instance.rb +31 -0
- data/lib/HDLRuby/high_samples/test_all.sh +10 -0
- data/lib/HDLRuby/high_samples/typedef.rb +24 -0
- data/lib/HDLRuby/high_samples/values.rb +70 -0
- data/lib/HDLRuby/high_samples/vector.rb +22 -0
- data/lib/HDLRuby/high_samples/with_decoder.rb +30 -0
- data/lib/HDLRuby/high_samples/with_fsm.rb +46 -0
- data/lib/HDLRuby/high_samples/with_pipe.rb +43 -0
- data/lib/HDLRuby/high_samples/with_seq.rb +25 -0
- data/lib/HDLRuby/hruby_bstr.rb +1085 -0
- data/lib/HDLRuby/hruby_check.rb +317 -0
- data/lib/HDLRuby/hruby_db.rb +432 -0
- data/lib/HDLRuby/hruby_error.rb +44 -0
- data/lib/HDLRuby/hruby_high.rb +4103 -0
- data/lib/HDLRuby/hruby_low.rb +4735 -0
- data/lib/HDLRuby/hruby_low2c.rb +1986 -0
- data/lib/HDLRuby/hruby_low2high.rb +738 -0
- data/lib/HDLRuby/hruby_low2seq.rb +248 -0
- data/lib/HDLRuby/hruby_low2sym.rb +126 -0
- data/lib/HDLRuby/hruby_low2vhd.rb +1437 -0
- data/lib/HDLRuby/hruby_low_bool2select.rb +295 -0
- data/lib/HDLRuby/hruby_low_cleanup.rb +193 -0
- data/lib/HDLRuby/hruby_low_fix_types.rb +437 -0
- data/lib/HDLRuby/hruby_low_mutable.rb +1803 -0
- data/lib/HDLRuby/hruby_low_resolve.rb +165 -0
- data/lib/HDLRuby/hruby_low_skeleton.rb +129 -0
- data/lib/HDLRuby/hruby_low_with_bool.rb +141 -0
- data/lib/HDLRuby/hruby_low_with_port.rb +167 -0
- data/lib/HDLRuby/hruby_low_with_var.rb +302 -0
- data/lib/HDLRuby/hruby_low_without_bit2vector.rb +88 -0
- data/lib/HDLRuby/hruby_low_without_concat.rb +162 -0
- data/lib/HDLRuby/hruby_low_without_connection.rb +113 -0
- data/lib/HDLRuby/hruby_low_without_namespace.rb +718 -0
- data/lib/HDLRuby/hruby_low_without_outread.rb +107 -0
- data/lib/HDLRuby/hruby_low_without_select.rb +206 -0
- data/lib/HDLRuby/hruby_serializer.rb +398 -0
- data/lib/HDLRuby/hruby_tools.rb +37 -0
- data/lib/HDLRuby/hruby_types.rb +239 -0
- data/lib/HDLRuby/hruby_values.rb +64 -0
- data/lib/HDLRuby/hruby_verilog.rb +1888 -0
- data/lib/HDLRuby/hruby_verilog_name.rb +52 -0
- data/lib/HDLRuby/low_samples/adder.yaml +97 -0
- data/lib/HDLRuby/low_samples/after.yaml +228 -0
- data/lib/HDLRuby/low_samples/before.yaml +223 -0
- data/lib/HDLRuby/low_samples/blockblock.yaml +48 -0
- data/lib/HDLRuby/low_samples/bugs/sample_add.yaml +97 -0
- data/lib/HDLRuby/low_samples/bugs/sample_daice.yaml +444 -0
- data/lib/HDLRuby/low_samples/bugs/sample_kumiawase.yaml +332 -0
- data/lib/HDLRuby/low_samples/bugs/sample_sub.yaml +97 -0
- data/lib/HDLRuby/low_samples/bugs/seqpar.yaml +184 -0
- data/lib/HDLRuby/low_samples/case.yaml +327 -0
- data/lib/HDLRuby/low_samples/change.yaml +135 -0
- data/lib/HDLRuby/low_samples/clocks.yaml +674 -0
- data/lib/HDLRuby/low_samples/cloner.rb +22 -0
- data/lib/HDLRuby/low_samples/comparer.yaml +85 -0
- data/lib/HDLRuby/low_samples/conditionals.yaml +133 -0
- data/lib/HDLRuby/low_samples/dff.yaml +107 -0
- data/lib/HDLRuby/low_samples/each.yaml +1328 -0
- data/lib/HDLRuby/low_samples/exporter.yaml +226 -0
- data/lib/HDLRuby/low_samples/functions.yaml +298 -0
- data/lib/HDLRuby/low_samples/generic_transmission.yaml +597 -0
- data/lib/HDLRuby/low_samples/inherit_as_dff.yaml +125 -0
- data/lib/HDLRuby/low_samples/inherit_dff.yaml +107 -0
- data/lib/HDLRuby/low_samples/load_yaml.rb +11 -0
- data/lib/HDLRuby/low_samples/memory.yaml +678 -0
- data/lib/HDLRuby/low_samples/namespace_extractor.rb +23 -0
- data/lib/HDLRuby/low_samples/overload.yaml +226 -0
- data/lib/HDLRuby/low_samples/paper_after.yaml +431 -0
- data/lib/HDLRuby/low_samples/port_maker.rb +14 -0
- data/lib/HDLRuby/low_samples/ram.yaml +207 -0
- data/lib/HDLRuby/low_samples/registers.yaml +228 -0
- data/lib/HDLRuby/low_samples/rom.yaml +2950 -0
- data/lib/HDLRuby/low_samples/shift.yaml +230 -0
- data/lib/HDLRuby/low_samples/shift2.yaml +2095 -0
- data/lib/HDLRuby/low_samples/simple_instance.yaml +102 -0
- data/lib/HDLRuby/low_samples/test_all.sh +43 -0
- data/lib/HDLRuby/low_samples/typedef.yaml +115 -0
- data/lib/HDLRuby/low_samples/values.yaml +577 -0
- data/lib/HDLRuby/low_samples/variable_maker.rb +14 -0
- data/lib/HDLRuby/low_samples/vector.yaml +56 -0
- data/lib/HDLRuby/low_samples/with_seq.yaml +188 -0
- data/lib/HDLRuby/low_samples/yaml2hdr.rb +10 -0
- data/lib/HDLRuby/low_samples/yaml2vhd.rb +19 -0
- data/lib/HDLRuby/sim/Makefile +19 -0
- data/lib/HDLRuby/sim/hruby_sim.h +590 -0
- data/lib/HDLRuby/sim/hruby_sim_calc.c +2362 -0
- data/lib/HDLRuby/sim/hruby_sim_core.c +589 -0
- data/lib/HDLRuby/sim/hruby_sim_list.c +93 -0
- data/lib/HDLRuby/sim/hruby_sim_vizualize.c +91 -0
- data/lib/HDLRuby/sim/hruby_value_pool.c +64 -0
- data/lib/HDLRuby/std/channel.rb +354 -0
- data/lib/HDLRuby/std/clocks.rb +165 -0
- data/lib/HDLRuby/std/counters.rb +82 -0
- data/lib/HDLRuby/std/decoder.rb +214 -0
- data/lib/HDLRuby/std/fsm.rb +516 -0
- data/lib/HDLRuby/std/pipeline.rb +220 -0
- data/lib/HDLRuby/std/reconf.rb +309 -0
- data/lib/HDLRuby/test_hruby_bstr.rb +2259 -0
- data/lib/HDLRuby/test_hruby_high.rb +594 -0
- data/lib/HDLRuby/test_hruby_high_low.rb +99 -0
- data/lib/HDLRuby/test_hruby_low.rb +934 -0
- data/lib/HDLRuby/v_samples/adder.v +10 -0
- data/lib/HDLRuby/v_samples/dff.v +12 -0
- data/lib/HDLRuby/v_samples/ram.v +20 -0
- data/lib/HDLRuby/v_samples/rom.v +270 -0
- data/lib/HDLRuby/version.rb +3 -0
- data/lib/HDLRuby.rb +11 -0
- data/makedoc +1 -0
- data/metadata.yaml +4 -0
- metadata +299 -0
@@ -0,0 +1,516 @@
|
|
1
|
+
module HDLRuby::High::Std
|
2
|
+
|
3
|
+
##
|
4
|
+
# Standard HDLRuby::High library: fsm generator.
|
5
|
+
#
|
6
|
+
########################################################################
|
7
|
+
|
8
|
+
|
9
|
+
##
|
10
|
+
# Describes a high-level fsm type.
|
11
|
+
class FsmT
|
12
|
+
include HDLRuby::High::HScope_missing
|
13
|
+
|
14
|
+
# The state class
|
15
|
+
class State
|
16
|
+
attr_accessor :value, :name, :code, :gotos
|
17
|
+
end
|
18
|
+
|
19
|
+
# The name of the FSM type.
|
20
|
+
attr_reader :name
|
21
|
+
|
22
|
+
# The namespace associated with the FSM
|
23
|
+
attr_reader :namespace
|
24
|
+
|
25
|
+
# The reset codes for the synchronous and the asynchronous operative
|
26
|
+
# parts of the fsm
|
27
|
+
attr_reader :reset_sync, :reset_async
|
28
|
+
|
29
|
+
# The current and next state signals.
|
30
|
+
attr_accessor :cur_state_sig, :next_state_sig, :work_state
|
31
|
+
|
32
|
+
# Creates a new fsm type with +name+.
|
33
|
+
# +options+ allows to specify the type of fsm:
|
34
|
+
# synchronous (default) / asynchronous and
|
35
|
+
# mono-front(default) / dual front
|
36
|
+
def initialize(name,*options)
|
37
|
+
# Check and set the name
|
38
|
+
@name = name.to_sym
|
39
|
+
# Check and set the type of fsm depending of the options.
|
40
|
+
@dual = false
|
41
|
+
@type = :sync
|
42
|
+
options.each do |opt|
|
43
|
+
case opt
|
44
|
+
when :sync,:synchronous then
|
45
|
+
@type = :sync
|
46
|
+
when :async, :asynchronous then
|
47
|
+
@type = :async
|
48
|
+
when :dual then
|
49
|
+
@dual = true
|
50
|
+
else
|
51
|
+
raise AnyError, "Invalid option for a fsm: :#{type}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Initialize the internals of the FSM.
|
56
|
+
|
57
|
+
|
58
|
+
# Initialize the environment for building the FSM
|
59
|
+
|
60
|
+
# The main states.
|
61
|
+
@states = []
|
62
|
+
|
63
|
+
# The extra synchronous states.
|
64
|
+
@extra_syncs = []
|
65
|
+
# The extra asynchronous states.
|
66
|
+
@extra_asyncs = []
|
67
|
+
|
68
|
+
# The default code of the operative part.
|
69
|
+
@default_codes = []
|
70
|
+
|
71
|
+
# The current and next state signals
|
72
|
+
@cur_state_sig = nil
|
73
|
+
@next_state_sig = nil
|
74
|
+
|
75
|
+
# The event synchronizing the fsm
|
76
|
+
@mk_ev = proc { $clk.posedge }
|
77
|
+
|
78
|
+
# The reset check.
|
79
|
+
@mk_rst = proc { $rst }
|
80
|
+
|
81
|
+
# The code executed in case of reset.
|
82
|
+
# (By default, nothing).
|
83
|
+
@reset_sync = nil
|
84
|
+
@reset_async = nil
|
85
|
+
|
86
|
+
# Creates the namespace to execute the fsm block in.
|
87
|
+
@namespace = Namespace.new(self)
|
88
|
+
|
89
|
+
# Generates the function for setting up the fsm
|
90
|
+
# provided there is a name.
|
91
|
+
obj = self # For using the right self within the proc
|
92
|
+
HDLRuby::High.space_reg(@name) do |&ruby_block|
|
93
|
+
if ruby_block then
|
94
|
+
# Builds the fsm.
|
95
|
+
obj.build(&ruby_block)
|
96
|
+
else
|
97
|
+
# Return the fsm as is.
|
98
|
+
return obj
|
99
|
+
end
|
100
|
+
end unless name.empty?
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
## builds the fsm by executing +ruby_block+.
|
105
|
+
def build(&ruby_block)
|
106
|
+
# Use local variable for accessing the attribute since they will
|
107
|
+
# be hidden when opening the sytem.
|
108
|
+
states = @states
|
109
|
+
namespace = @namespace
|
110
|
+
this = self
|
111
|
+
mk_ev = @mk_ev
|
112
|
+
mk_rst = @mk_rst
|
113
|
+
type = @type
|
114
|
+
dual = @dual
|
115
|
+
extra_syncs = @extra_syncs
|
116
|
+
extra_asyncs = @extra_asyncs
|
117
|
+
default_codes = @default_codes
|
118
|
+
|
119
|
+
return_value = nil
|
120
|
+
|
121
|
+
# Enters the current system
|
122
|
+
HDLRuby::High.cur_system.open do
|
123
|
+
sub do
|
124
|
+
HDLRuby::High.space_push(namespace)
|
125
|
+
# Execute the instantiation block
|
126
|
+
return_value =HDLRuby::High.top_user.instance_exec(&ruby_block)
|
127
|
+
|
128
|
+
# Expands the extra state processing so that al all the
|
129
|
+
# parts of the state machine are in par (clear synthesis).
|
130
|
+
[extra_syncs,extra_asyncs].each do |extras|
|
131
|
+
# Set the values of the extra states from their name.
|
132
|
+
extras.each do |extra|
|
133
|
+
st = states.find {|st| st.name == extra.name }
|
134
|
+
unless st then
|
135
|
+
raise "Unknown state name: #{extra.name}"
|
136
|
+
end
|
137
|
+
extra.value = st.value
|
138
|
+
end
|
139
|
+
# Fills the holes in the extra syncs and asyncs.
|
140
|
+
if extras.any? then
|
141
|
+
# Sort by value in a new array using counter sort.
|
142
|
+
results = [ nil ] * states.size
|
143
|
+
extras.each {|st| results[st.value] = st }
|
144
|
+
# Fill the whole with empty states.
|
145
|
+
results.map!.with_index do |st,i|
|
146
|
+
unless st then
|
147
|
+
st = State.new
|
148
|
+
st.value = i
|
149
|
+
st.code = proc {}
|
150
|
+
end
|
151
|
+
st
|
152
|
+
end
|
153
|
+
# Replace the content of extras
|
154
|
+
extras.clear
|
155
|
+
results.each {|st| extras << st }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Create the state register.
|
160
|
+
name = HDLRuby.uniq_name
|
161
|
+
# Declare the state register.
|
162
|
+
this.cur_state_sig = [states.size.width].inner(name)
|
163
|
+
# Declare the next state wire.
|
164
|
+
name = HDLRuby.uniq_name
|
165
|
+
this.next_state_sig = [states.size.width].inner(name)
|
166
|
+
|
167
|
+
# Create the fsm code
|
168
|
+
|
169
|
+
# Control part: update of the state.
|
170
|
+
par(mk_ev.call) do
|
171
|
+
hif(mk_rst.call) do
|
172
|
+
# Reset: current state is to put to 0.
|
173
|
+
this.cur_state_sig <= 0
|
174
|
+
end
|
175
|
+
helse do
|
176
|
+
# No reset: current state is updated with
|
177
|
+
# next state value.
|
178
|
+
this.cur_state_sig <= this.next_state_sig
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# Operative main-part: one case per state.
|
183
|
+
# (clock-dependent if synchronous mode).
|
184
|
+
if type == :sync then
|
185
|
+
# Synchronous case.
|
186
|
+
event = mk_ev.call
|
187
|
+
event = event.invert if dual
|
188
|
+
else
|
189
|
+
# Asynchronous case: no event required.
|
190
|
+
event = []
|
191
|
+
end
|
192
|
+
# The process
|
193
|
+
par(*event) do
|
194
|
+
# The operative code.
|
195
|
+
oper_code = proc do
|
196
|
+
# The default code.
|
197
|
+
default_codes.each(&:call)
|
198
|
+
# Depending on the state.
|
199
|
+
hcase(this.cur_state_sig)
|
200
|
+
states.each do |st|
|
201
|
+
# Register the working state (for the gotos)
|
202
|
+
this.work_state = st
|
203
|
+
hwhen(st.value) do
|
204
|
+
# Generate the content of the state.
|
205
|
+
st.code.call
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
# Is there reset code?
|
210
|
+
if type == :sync and this.reset_sync then
|
211
|
+
# Yes in case of synchronous fsm,
|
212
|
+
# use it before the operative code.
|
213
|
+
hif(mk_rst.call) do
|
214
|
+
this.reset_sync.call
|
215
|
+
end
|
216
|
+
helse(&oper_code)
|
217
|
+
elsif type == :async and this.reset_async then
|
218
|
+
# Yes in case of asynchronous fsm,
|
219
|
+
# use it before the operative code.
|
220
|
+
hif(mk_rst.call) do
|
221
|
+
this.reset_async.call
|
222
|
+
end
|
223
|
+
helse(&oper_code)
|
224
|
+
else
|
225
|
+
# Use only the operative code.
|
226
|
+
oper_code.call
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# Control part: computation of the next state.
|
231
|
+
# (clock-independent)
|
232
|
+
hcase(this.cur_state_sig)
|
233
|
+
states.each do |st|
|
234
|
+
hwhen(st.value) do
|
235
|
+
if st.gotos.any? then
|
236
|
+
# Gotos were present, use them.
|
237
|
+
st.gotos.each(&:call)
|
238
|
+
else
|
239
|
+
# No gotos, by default the next step is
|
240
|
+
# current + 1
|
241
|
+
# this.next_state_sig <= mux(mk_rst.call , 0, this.cur_state_sig + 1)
|
242
|
+
this.next_state_sig <= this.cur_state_sig + 1
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
# By default set the next state to 0.
|
247
|
+
helse do
|
248
|
+
this.next_state_sig <= 0
|
249
|
+
end
|
250
|
+
|
251
|
+
# Operative additional parts.
|
252
|
+
# Extra synchronous operative part.
|
253
|
+
if extra_syncs.any? then
|
254
|
+
event = mk_ev.call
|
255
|
+
event = event.invert if @dual
|
256
|
+
# The extra code.
|
257
|
+
par(*event) do
|
258
|
+
# Build the extra synchronous part.
|
259
|
+
sync_code = proc do
|
260
|
+
hcase(this.cur_state_sig)
|
261
|
+
extra_syncs.each do |st|
|
262
|
+
hwhen(st.value) do
|
263
|
+
# Generate the content of the state.
|
264
|
+
st.code.call
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
# Place it.
|
269
|
+
if this.reset_sync then
|
270
|
+
# There some synchronous reset code, use
|
271
|
+
# it.
|
272
|
+
hif(mk_rst.call) do
|
273
|
+
this.reset_sync.call
|
274
|
+
end
|
275
|
+
helse(&sync_code)
|
276
|
+
else
|
277
|
+
# No syncrhonous code, place the extra
|
278
|
+
# synchronous states as is.
|
279
|
+
sync_code.call
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
# Extra asynchronous operative part.
|
285
|
+
if extra_asyncs.any? then
|
286
|
+
par do
|
287
|
+
# Build the extra synchronous part.
|
288
|
+
async_code = proc do
|
289
|
+
hcase(this.cur_state_sig)
|
290
|
+
extra_asyncs.each do |st|
|
291
|
+
hwhen(st.value) do
|
292
|
+
# Generate the content of the state.
|
293
|
+
st.code.call
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
# Place it with possible reset.
|
298
|
+
if this.reset_async then
|
299
|
+
# There some synchronous reset code, use
|
300
|
+
# it.
|
301
|
+
hif(mk_rst.call) do
|
302
|
+
this.reset_async.call
|
303
|
+
end
|
304
|
+
helse(&sync_code)
|
305
|
+
else
|
306
|
+
# No syncrhonous code, place the extra
|
307
|
+
# synchronous states as is.
|
308
|
+
sync_code.call
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
HDLRuby::High.space_pop
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
return return_value
|
318
|
+
end
|
319
|
+
|
320
|
+
|
321
|
+
## The interface for building the fsm
|
322
|
+
|
323
|
+
# Sets the event synchronizing the fsm.
|
324
|
+
def for_event(event = nil,&ruby_block)
|
325
|
+
if event then
|
326
|
+
# An event is passed as argument, use it.
|
327
|
+
@mk_ev = proc { event.to_event }
|
328
|
+
else
|
329
|
+
# No event given, use the ruby_block as event generator.
|
330
|
+
@mk_ev = ruby_block
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
# Sets the reset.
|
335
|
+
def for_reset(reset = nil,&ruby_block)
|
336
|
+
if reset then
|
337
|
+
# An reset is passed as argument, use it.
|
338
|
+
@mk_rst = proc { reset.to_expr }
|
339
|
+
else
|
340
|
+
# No reset given, use the ruby_block as event generator.
|
341
|
+
@mk_rst = ruby_block
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
# Adds a code to be executed in case of reset.
|
346
|
+
# +type+ indicates if it is the synchronous part or the
|
347
|
+
# asynchronous part that is to reset.
|
348
|
+
def reset(type = @type,&ruby_block)
|
349
|
+
if type == :sync or type == :synchronous then
|
350
|
+
# Reset of the synchronous part.
|
351
|
+
if @reset_sync then
|
352
|
+
raise AnyError.new("Reset of the synchronous part already declared.")
|
353
|
+
end
|
354
|
+
@reset_sync = ruby_block
|
355
|
+
elsif type == :async or type == :asynchronous then
|
356
|
+
# Reset if the asynchronous part.
|
357
|
+
if @reset_async then
|
358
|
+
raise AnyError.new("Reset of the asynchronosu part already declared.")
|
359
|
+
end
|
360
|
+
else
|
361
|
+
raise AnyError.new("Invalid fsm type for declaring a reset code: #{type}")
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
# Adds a default operative code.
|
366
|
+
def default(&ruby_block)
|
367
|
+
@default_codes << ruby_block
|
368
|
+
end
|
369
|
+
|
370
|
+
# Declares a new state with +name+ and executing +ruby_block+.
|
371
|
+
def state(name = :"", &ruby_block)
|
372
|
+
# Create the resulting state
|
373
|
+
result = State.new
|
374
|
+
# Its value is the current number of states
|
375
|
+
result.value = @states.size
|
376
|
+
result.name = name.to_sym
|
377
|
+
result.code = ruby_block
|
378
|
+
result.gotos = []
|
379
|
+
# Add it to the list of states.
|
380
|
+
@states << result
|
381
|
+
# Return it.
|
382
|
+
return result
|
383
|
+
end
|
384
|
+
|
385
|
+
# Declares an extra synchronous code to execute for state +name+.
|
386
|
+
def sync(name, &ruby_block)
|
387
|
+
# Create the resulting state.
|
388
|
+
result = State.new
|
389
|
+
result.name = name.to_sym
|
390
|
+
result.code = ruby_block
|
391
|
+
# Add it to the lis of extra synchronous states.
|
392
|
+
@extra_syncs << result
|
393
|
+
# Return it
|
394
|
+
return result
|
395
|
+
end
|
396
|
+
|
397
|
+
# Declares an extra asynchronous code to execute for state +name+.
|
398
|
+
def async(name, &ruby_block)
|
399
|
+
# Create the resulting state.
|
400
|
+
result = State.new
|
401
|
+
result.name = name.to_sym
|
402
|
+
result.code = ruby_block
|
403
|
+
# Add it to the lis of extra synchronous states.
|
404
|
+
@extra_asyncs << result
|
405
|
+
# Return it
|
406
|
+
return result
|
407
|
+
end
|
408
|
+
|
409
|
+
# Sets the next state. Arguments can be:
|
410
|
+
#
|
411
|
+
# +name+: the name of the next state.
|
412
|
+
# +expr+, +names+: an expression with the list of the next statements
|
413
|
+
# in order of the value of the expression, the last
|
414
|
+
# one being necesserily the default case.
|
415
|
+
def goto(*args)
|
416
|
+
# Make reference to the fsm attributes.
|
417
|
+
next_state_sig = @next_state_sig
|
418
|
+
states = @states
|
419
|
+
# Add the code of the goto to the working state.
|
420
|
+
@work_state.gotos << proc do
|
421
|
+
# Depending on the first argument type.
|
422
|
+
unless args[0].is_a?(Symbol) then
|
423
|
+
# expr + names arguments.
|
424
|
+
# Get the predicate
|
425
|
+
pred = args.shift
|
426
|
+
# hif or hcase?
|
427
|
+
if args.size <= 2 then
|
428
|
+
# 2 or less cases, generate an hif
|
429
|
+
arg = args.shift
|
430
|
+
hif(pred) do
|
431
|
+
next_state_sig <=
|
432
|
+
(states.detect { |st| st.name == arg }).value
|
433
|
+
end
|
434
|
+
arg = args.shift
|
435
|
+
if arg then
|
436
|
+
# There is an else.
|
437
|
+
helse do
|
438
|
+
next_state_sig <=
|
439
|
+
(states.detect { |st| st.name == arg }).value
|
440
|
+
end
|
441
|
+
end
|
442
|
+
else
|
443
|
+
# More than 2, generate a hcase
|
444
|
+
hcase (pred)
|
445
|
+
args[0..-2].each.with_index do |arg,i|
|
446
|
+
# Ensure the argument is a symbol.
|
447
|
+
arg = arg.to_sym
|
448
|
+
# Make the when statement.
|
449
|
+
hwhen(i) do
|
450
|
+
next_state_sig <=
|
451
|
+
(states.detect { |st| st.name == arg }).value
|
452
|
+
end
|
453
|
+
end
|
454
|
+
# The last name is the default case.
|
455
|
+
# Ensure it is a symbol.
|
456
|
+
arg = args[-1].to_sym
|
457
|
+
# Make the default statement.
|
458
|
+
helse do
|
459
|
+
next_state_sig <=
|
460
|
+
(states.detect { |st| st.name == arg }).value
|
461
|
+
end
|
462
|
+
end
|
463
|
+
else
|
464
|
+
# single name argument, check it.
|
465
|
+
raise AnyError, "Invalid argument for a goto: if no expression is given only a single name can be used." if args.size > 1
|
466
|
+
# Ensure the name is a symbol.
|
467
|
+
name = args[0].to_sym
|
468
|
+
# Get the state with name.
|
469
|
+
next_state_sig <= (states.detect { |st| st.name == name }).value
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
end
|
475
|
+
|
476
|
+
|
477
|
+
## Declare a new fsm.
|
478
|
+
# The arguments can be any of (but in this order):
|
479
|
+
#
|
480
|
+
# - +name+:: name.
|
481
|
+
# - +clk+:: clock.
|
482
|
+
# - +event+:: clock event.
|
483
|
+
# - +rst+:: reset. (must be declared AFTER clock or clock event).
|
484
|
+
#
|
485
|
+
# If provided, +ruby_block+ the fsm is directly instantiated with it.
|
486
|
+
def fsm(*args, &ruby_block)
|
487
|
+
# Sets the name if any
|
488
|
+
unless args[0].respond_to?(:to_event) then
|
489
|
+
name = args.shift.to_sym
|
490
|
+
else
|
491
|
+
name = :""
|
492
|
+
end
|
493
|
+
# Get the options from the arguments.
|
494
|
+
options, args = args.partition {|arg| arg.is_a?(Symbol) }
|
495
|
+
# Create the fsm.
|
496
|
+
fsmI = FsmT.new(name,*options)
|
497
|
+
|
498
|
+
# Process the clock event if any.
|
499
|
+
unless args.empty? then
|
500
|
+
fsmI.for_event(args.shift)
|
501
|
+
end
|
502
|
+
# Process the reset if any.
|
503
|
+
unless args.empty? then
|
504
|
+
fsmI.for_reset(args.shift)
|
505
|
+
end
|
506
|
+
# Is there a ruby block?
|
507
|
+
if ruby_block then
|
508
|
+
# Yes, generate the fsm.
|
509
|
+
fsmI.build(&ruby_block)
|
510
|
+
else
|
511
|
+
# No return the fsm structure for later generation.
|
512
|
+
return fsmI
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
end
|