Class: HDLRuby::High::Std::SequencerT
- Inherits:
-
Object
- Object
- HDLRuby::High::Std::SequencerT
- Defined in:
- lib/HDLRuby/std/sequencer.rb
Overview
Describes a sequencer block.
Constant Summary collapse
- @@current =
The current sequencer.
nil
Instance Attribute Summary collapse
-
#end_state_value ⇒ Object
readonly
The start and end states values.
-
#start_state_value ⇒ Object
readonly
The start and end states values.
Class Method Summary collapse
-
.current ⇒ Object
Get the sequencer currently processing.
Instance Method Summary collapse
-
#fill_top_user(blk) ⇒ Object
Fills the top user with the content of block +blk+.
-
#initialize(ev, start, &ruby_block) ⇒ SequencerT
constructor
Create a new sequencer block synchronized on +ev+ and starting on +start+.
-
#loop_status ⇒ Object
Gets the closest loop status in the status stack.
-
#sbreak ⇒ Object
Breaks current iteration.
-
#scontinue ⇒ Object
Continues current iteration.
-
#selse(&ruby_block) ⇒ Object
Create a sequential else statement.
-
#sfor(expr, &ruby_block) ⇒ Object
Create a sequential for statement iterating over the elements of +expr+.
-
#sif(cond, &ruby_block) ⇒ Object
Create a sequential if statement on +cond+.
-
#size ⇒ Object
Gets the number of states of the underlining fsm.
-
#sloop(&ruby_block) ⇒ Object
Create a sequential infinite loop statement.
-
#step ⇒ Object
Mark a step.
-
#steps(num) ⇒ Object
Mark several steps.
-
#sterminate ⇒ Object
Terminates the sequencer.
-
#swait(cond) ⇒ Object
Wait a given condition.
-
#swhile(cond, &ruby_block) ⇒ Object
Create a sequential while statement on +cond+.
Constructor Details
#initialize(ev, start, &ruby_block) ⇒ SequencerT
Create a new sequencer block synchronized on +ev+ and starting on +start+
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/HDLRuby/std/sequencer.rb', line 27 def initialize(ev,start,&ruby_block) this = self # Process the arguments. ev = ev.posedge unless ev.is_a?(Event) if start.is_a?(Event) then start = start.type == :posedge ? start.ref : ~start.ref end # Create the fsm from the block. @fsm = fsm(ev,start,:seq) # On reset (start) tell to go to the first state. run = HDLRuby::High.cur_system.inner(HDLRuby.uniq_name(:run) => 0) @fsm.reset do # HDLRuby::High.top_user.instance_exec do # next_state_sig <= this.start_state_value # end run <= 1 end # The status stack of the sequencer. @status = [ {} ] # Creates the namespace to execute the sequencer deescription # block in. @namespace = Namespace.new(self) # The end state is actually 0, allows to sequencer to be stable # by default. @fsm.default { run <= 0 } @end_state = @fsm.state { } @end_state.gotos << proc do HDLRuby::High.top_user.instance_exec do hif(run) { next_state_sig <= this.start_state_value } helse { next_state_sig <= this.end_state_value } end end # Record the start and end state values. # For now, the start state is the one just following the end state. @end_state_value = @end_state.value @start_state_value = @end_state_value + 1 # puts "end_state_value=#{@end_state_value}" # Process the ruby_block. @@current = self HDLRuby::High.space_push(@namespace) blk = HDLRuby::High::Block.new(:seq,&ruby_block) HDLRuby::High.space_pop # If the block is not empty, add it as last state. this = self if blk.each_statement.any? then st = @fsm.state do this.fill_top_user(blk) end end # Build the fsm. @fsm.build end |
Instance Attribute Details
#end_state_value ⇒ Object (readonly)
The start and end states values.
23 24 25 |
# File 'lib/HDLRuby/std/sequencer.rb', line 23 def end_state_value @end_state_value end |
#start_state_value ⇒ Object (readonly)
The start and end states values.
23 24 25 |
# File 'lib/HDLRuby/std/sequencer.rb', line 23 def start_state_value @start_state_value end |
Class Method Details
.current ⇒ Object
Get the sequencer currently processing.
18 19 20 |
# File 'lib/HDLRuby/std/sequencer.rb', line 18 def self.current @@current end |
Instance Method Details
#fill_top_user(blk) ⇒ Object
Fills the top user with the content of block +blk+.
320 321 322 323 324 325 326 |
# File 'lib/HDLRuby/std/sequencer.rb', line 320 def fill_top_user(blk) # Fill the current block with blk content. blk.each_statement do |stmnt| stmnt.parent = nil HDLRuby::High.top_user.add_statement(stmnt) end end |
#loop_status ⇒ Object
Gets the closest loop status in the status stack. NOTE: raises an exception if there are not swhile state.
92 93 94 95 96 97 98 99 |
# File 'lib/HDLRuby/std/sequencer.rb', line 92 def loop_status i = @status.size-1 begin status = @status[i -= 1] raise "No loop for sbreak." unless status end while(!status[:loop]) return status end |
#sbreak ⇒ Object
Breaks current iteration.
142 143 144 145 146 147 148 149 150 151 |
# File 'lib/HDLRuby/std/sequencer.rb', line 142 def sbreak # Mark a step. st = self.step # Tell there is a break to process. # Do that in the first loop status met. status = self.loop_status status[:sbreaks] ||= [] status[:sbreaks] << st return st end |
#scontinue ⇒ Object
Continues current iteration.
154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/HDLRuby/std/sequencer.rb', line 154 def scontinue # Mark a step. st = self.step # Go to the begining of the iteration, i.e., the first loop # status met. status = self.loop_status st.gotos << proc do HDLRuby::High.top_user.instance_exec do next_state_sig <= status[:loop] end end return st end |
#selse(&ruby_block) ⇒ Object
Create a sequential else statement.
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/HDLRuby/std/sequencer.rb', line 208 def selse(&ruby_block) # Create a state to be executed if the previous condition is # not met. @status.push({}) no_name = HDLRuby.uniq_name("no") no_blk = HDLRuby::High::Block.new(:seq,&ruby_block) @status.pop this = self no = @fsm.state(no_name) { this.fill_top_user(no_blk) } # Adds a goto to the previous if yes state for jumping the no state. yes = @status.last[:sif_yes] raise "Cannot use selse here." unless yes cond = @status.last[:condition] yes.gotos << proc do HDLRuby::High.top_user.instance_exec do next_state_sig <= no.value + 1 end end return no end |
#sfor(expr, &ruby_block) ⇒ Object
Create a sequential for statement iterating over the elements of +expr+.
311 312 313 314 315 316 |
# File 'lib/HDLRuby/std/sequencer.rb', line 311 def sfor(expr,&ruby_block) # Ensures there is a ruby block to avoid returning an enumerator # (returning an enumerator would be confusing for a for statement). ruby_block = proc {} unless ruby_block expr.seach.with_index(&ruby_block) end |
#sif(cond, &ruby_block) ⇒ Object
Create a sequential if statement on +cond+.
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/HDLRuby/std/sequencer.rb', line 183 def sif(cond, &ruby_block) # Mark a step. st = self.step # Remember the condition. @status.last[:condition] = cond # Create a state to be executed if the condition is met. @status.push({}) yes_name = HDLRuby.uniq_name("yes") yes_blk = HDLRuby::High::Block.new(:seq,&ruby_block) @status.pop this = self yes = @fsm.state(yes_name) { this.fill_top_user(yes_blk) } # Add a goto to the previous state. st.gotos << proc do HDLRuby::High.top_user.instance_exec do hif(cond) { next_state_sig <= st.value + 1 } helse { next_state_sig <= yes.value + 1 } end end # Remeber the if yes state for being able to add else afterward. @status.last[:sif_yes] = yes return st end |
#size ⇒ Object
Gets the number of states of the underlining fsm.
86 87 88 |
# File 'lib/HDLRuby/std/sequencer.rb', line 86 def size return @fsm.size end |
#sloop(&ruby_block) ⇒ Object
Create a sequential infinite loop statement.
305 306 307 |
# File 'lib/HDLRuby/std/sequencer.rb', line 305 def sloop(&ruby_block) self.swhile(nil,&ruby_block) end |
#step ⇒ Object
Mark a step.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/HDLRuby/std/sequencer.rb', line 104 def step # Create a new block from all the statements in the previous block. blk = HDLRuby::High::Block.new(:seq) {} # Get all the statements of the builder block. stmnts = HDLRuby::High.cur_block.instance_variable_get(:@statements) # Add all the statements to blk. stmnts.each { |stmnt| stmnt.parent = nil; blk.add_statement(stmnt) } # Remove them from the builder block. stmnts.clear # Create a state for this block. this = self st = @fsm.state { this.fill_top_user(blk) } # # Set the previous step in sequence. # @status.last[:state] = st return st end |
#steps(num) ⇒ Object
Mark several steps.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/HDLRuby/std/sequencer.rb', line 123 def steps(num) # Create a counter. count = nil zero = nil one = nil HDLRuby::High.cur_system.open do if num.respond_to?(:width) then count = [num.width].inner(HDLRuby.uniq_name(:"steps_count")) else count = num.to_expr.type.inner(HDLRuby.uniq_name(:"steps_count")) end zero = _b0 one = _b1 end count <= num swhile(count > zero) { count <= count - one } end |
#sterminate ⇒ Object
Terminates the sequencer.
169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/HDLRuby/std/sequencer.rb', line 169 def sterminate # Mark a step. st = self.step # Adds a goto the ending state. this = self st.gotos << proc do HDLRuby::High.top_user.instance_exec do next_state_sig <= this.end_state_value end end return st end |
#swait(cond) ⇒ Object
Wait a given condition.
230 231 232 |
# File 'lib/HDLRuby/std/sequencer.rb', line 230 def swait(cond) return self.swhile(~cond) end |
#swhile(cond, &ruby_block) ⇒ Object
Create a sequential while statement on +cond+.
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/HDLRuby/std/sequencer.rb', line 235 def swhile(cond,&ruby_block) # Ensures there is a ruby block. This allows to use empty while # statement. ruby_block = proc { } unless ruby_block # Mark a step. st = self.step # Tell we are building a while and remember the state number. @status.last[:loop] = st.value + 1 # Create a state to be executed if the condition is met. @status.push({}) # Build the loop sub sequence. yes_name = HDLRuby.uniq_name("yes") yes_blk = HDLRuby::High::Block.new(:seq,&ruby_block) @status.pop this = self yes = @fsm.state(yes_name) { this.fill_top_user(yes_blk) } # Add a goto to the previous state. st.gotos << proc do HDLRuby::High.top_user.instance_exec do if cond then # There is a condition, it is a real while loop. hif(cond) { next_state_sig <= st.value + 1 } helse { next_state_sig <= yes.value + 1 } # puts("Here st: st.value+1=#{st.value+1} yes.value+1=#{yes.value+1}\n") else # There is no ending condition, this is an infinite loop. next_state_sig <= st.value + 1 # puts("There st: st.value+1=#{st.value+1}\n") end end end # And to the yes state. yes.gotos << proc do HDLRuby::High.top_user.instance_exec do if cond then # There is a condition, it is a real while loop hif(cond) { next_state_sig <= st.value + 1 } helse { next_state_sig <= yes.value + 1 } # puts("Here yes: st.value+1=#{st.value+1} yes.value+1=#{yes.value+1}\n") else # There is no ending condition, this is an infinite loop. next_state_sig <= st.value + 1 # puts("There yes: st.value+1=#{st.value+1}\n") end end end # puts "st_value=#{st.value} yes_value=#{yes.value}" # Where there any break? if @status.last[:sbreaks] then # Yes, adds them the right goto since the end of loop state # is now defined. @status.last[:sbreaks].each do |st_brk| st_brk.gotos << proc do HDLRuby::High.top_user.instance_exec do next_state_sig <= yes.value + 1 end end end # And remove them from the status to avoid reprocessing them, @status.last.clear end return st end |