Class: Origen::Generator::PatternThread
- Defined in:
- lib/origen/generator/pattern_thread.rb
Overview
An instance of PatternThread is created for each parallel thread of execution in a pattern sequence. One instance of this class is also created to represent the original main thread in addition to those created by calling seq.in_parallel
Instance Attribute Summary collapse
-
#cycle_count_start ⇒ Object
readonly
Returns the value of attribute cycle_count_start.
-
#cycle_count_stop ⇒ Object
readonly
Returns the value of attribute cycle_count_stop.
-
#events ⇒ Object
readonly
A record of when the thread is active to construct the execution profile.
-
#id ⇒ Object
readonly
Returns the value of attribute id.
-
#pending_cycles ⇒ Object
readonly
Returns the value of attribute pending_cycles.
-
#reservations ⇒ Object
readonly
Returns the value of attribute reservations.
-
#sequence ⇒ Object
readonly
Returns the parent pattern sequence object.
Instance Method Summary collapse
-
#advance(completed_cycles = nil) ⇒ Object
This should be called only by the pattern sequence running in the main thread, it will un-block the pattern thread which is currently waiting, and it will block the main thread until the pattern thread reaches the next wait point (or completes).
- #completed? ⇒ Boolean
- #current_cycle_count ⇒ Object
-
#cycle(options) ⇒ Object
Will be called when the thread is ready for the next cycle.
- #executed_cycles(cycles) ⇒ Object private
- #execution_profile(start, stop, step) ⇒ Object
-
#initialize(id, sequence, block, primary = false, pre_block = nil) ⇒ PatternThread
constructor
A new instance of PatternThread.
-
#primary? ⇒ Boolean
Returns true if this is main thread (the one from which all in_parallel threads have been branched from).
- #record_active ⇒ Object
- #record_cycle_count_stop ⇒ Object
-
#start ⇒ Object
private
This method is called once by the pattern sequence to start a new thread.
-
#wait ⇒ Object
This should be called only by the pattern thread itself, and will block it until it is told to advance by the pattern sequence running in the main thread.
-
#waiting? ⇒ Boolean
Returns true if the thread is currently waiting for the pattern sequence to advance it.
-
#waiting_for_serialize(serialize_id, skip_event = false) ⇒ Object
Will be called when the thread can’t execute its next cycle because it is waiting to obtain a lock on a serialized block.
-
#waiting_for_thread(skip_event = false) ⇒ Object
Will be called when the thread can’t execute its next cycle because it is waiting for another thread to complete.
Constructor Details
#initialize(id, sequence, block, primary = false, pre_block = nil) ⇒ PatternThread
Returns a new instance of PatternThread.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/origen/generator/pattern_thread.rb', line 17 def initialize(id, sequence, block, primary = false, pre_block = nil) if primary @cycle_count_start = 0 else @cycle_count_start = current_cycle_count end @events = [[:active, cycle_count_start]] @id = id.to_sym @sequence = sequence @block = block @pre_block = pre_block @primary = primary @running = Concurrent::Event.new @waiting = Concurrent::Event.new @pending_cycles = nil @completed = false @reservations = {} end |
Instance Attribute Details
#cycle_count_start ⇒ Object (readonly)
Returns the value of attribute cycle_count_start.
12 13 14 |
# File 'lib/origen/generator/pattern_thread.rb', line 12 def cycle_count_start @cycle_count_start end |
#cycle_count_stop ⇒ Object (readonly)
Returns the value of attribute cycle_count_stop.
13 14 15 |
# File 'lib/origen/generator/pattern_thread.rb', line 13 def cycle_count_stop @cycle_count_stop end |
#events ⇒ Object (readonly)
A record of when the thread is active to construct the execution profile
15 16 17 |
# File 'lib/origen/generator/pattern_thread.rb', line 15 def events @events end |
#id ⇒ Object (readonly)
Returns the value of attribute id.
10 11 12 |
# File 'lib/origen/generator/pattern_thread.rb', line 10 def id @id end |
#pending_cycles ⇒ Object (readonly)
Returns the value of attribute pending_cycles.
9 10 11 |
# File 'lib/origen/generator/pattern_thread.rb', line 9 def pending_cycles @pending_cycles end |
#reservations ⇒ Object (readonly)
Returns the value of attribute reservations.
11 12 13 |
# File 'lib/origen/generator/pattern_thread.rb', line 11 def reservations @reservations end |
#sequence ⇒ Object (readonly)
Returns the parent pattern sequence object
8 9 10 |
# File 'lib/origen/generator/pattern_thread.rb', line 8 def sequence @sequence end |
Instance Method Details
#advance(completed_cycles = nil) ⇒ Object
This should be called only by the pattern sequence running in the main thread, it will un-block the pattern thread which is currently waiting, and it will block the main thread until the pattern thread reaches the next wait point (or completes)
170 171 172 173 174 |
# File 'lib/origen/generator/pattern_thread.rb', line 170 def advance(completed_cycles = nil) @waiting.reset @running.set # Release the pattern thread @waiting.wait # And wait for it to reach the next wait point end |
#completed? ⇒ Boolean
150 151 152 |
# File 'lib/origen/generator/pattern_thread.rb', line 150 def completed? @completed end |
#current_cycle_count ⇒ Object
70 71 72 |
# File 'lib/origen/generator/pattern_thread.rb', line 70 def current_cycle_count tester.try(:cycle_count) || 0 end |
#cycle(options) ⇒ Object
Will be called when the thread is ready for the next cycle
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/origen/generator/pattern_thread.rb', line 124 def cycle() @pending_cycles = [:repeat] || 1 # If there are threads pending start and we are about to enter a long delay, block for only # one cycle to give them a change to get underway and make use of this delay if @pending_cycles > 1 && sequence.send(:threads_waiting_to_start?) remainder = @pending_cycles - 1 @pending_cycles = 1 end wait @pending_cycles = remainder if remainder # If the sequence did not do enough cycles in that round to satisfy this thread, then go back # around to complete the remainder before continuing with the rest of the pattern if @pending_cycles == 0 @pending_cycles = nil elsif @pending_cycles > 0 @pending_cycles.cycles else fail "Something has gone wrong @pending_cycles is #{@pending_cycles}" end end |
#executed_cycles(cycles) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
146 147 148 |
# File 'lib/origen/generator/pattern_thread.rb', line 146 def executed_cycles(cycles) @pending_cycles -= cycles if @pending_cycles end |
#execution_profile(start, stop, step) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/origen/generator/pattern_thread.rb', line 74 def execution_profile(start, stop, step) events = @events.dup cycles = start state = :inactive line = '' ((stop - start) / step).times do |i| active_cycles = 0 while events.first && events.first[1] >= cycles && events.first[1] < cycles + step event = events.shift # Bring the current cycles up to this event point applying the current state if state == :active active_cycles += event[1] - cycles end state = event[0] == :active ? :active : :inactive cycles = event[1] end # Bring the current cycles up to the end of this profile tick if state == :active active_cycles += ((i + 1) * step) - cycles end cycles = ((i + 1) * step) if active_cycles == 0 line += '_' elsif active_cycles > (step * 0.5) line += '█' else line += '▄' end end line end |
#primary? ⇒ Boolean
Returns true if this is main thread (the one from which all in_parallel threads have been branched from)
38 39 40 |
# File 'lib/origen/generator/pattern_thread.rb', line 38 def primary? @primary end |
#record_active ⇒ Object
66 67 68 |
# File 'lib/origen/generator/pattern_thread.rb', line 66 def record_active events << [:active, current_cycle_count] end |
#record_cycle_count_stop ⇒ Object
60 61 62 63 64 |
# File 'lib/origen/generator/pattern_thread.rb', line 60 def record_cycle_count_stop @cycle_count_stop = current_cycle_count events << [:stopped, cycle_count_stop] events.freeze end |
#start ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method is called once by the pattern sequence to start a new thread. It will block until the thread is in the waiting state.
46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/origen/generator/pattern_thread.rb', line 46 def start @thread = Thread.new do PatSeq.send(:thread=, self) wait @pre_block.call if @pre_block @block.call(sequence) sequence.send(:thread_completed, self) record_cycle_count_stop @completed = true wait end @waiting.wait end |
#wait ⇒ Object
This should be called only by the pattern thread itself, and will block it until it is told to advance by the pattern sequence running in the main thread
161 162 163 164 165 |
# File 'lib/origen/generator/pattern_thread.rb', line 161 def wait @running.reset @waiting.set @running.wait end |
#waiting? ⇒ Boolean
Returns true if the thread is currently waiting for the pattern sequence to advance it
155 156 157 |
# File 'lib/origen/generator/pattern_thread.rb', line 155 def waiting? @waiting.set? end |
#waiting_for_serialize(serialize_id, skip_event = false) ⇒ Object
Will be called when the thread can’t execute its next cycle because it is waiting to obtain a lock on a serialized block
110 111 112 113 114 |
# File 'lib/origen/generator/pattern_thread.rb', line 110 def waiting_for_serialize(serialize_id, skip_event = false) # puts "Thread #{id} is blocked waiting for #{serialize_id}" events << [:waiting, current_cycle_count] unless skip_event wait end |
#waiting_for_thread(skip_event = false) ⇒ Object
Will be called when the thread can’t execute its next cycle because it is waiting for another thread to complete
118 119 120 121 |
# File 'lib/origen/generator/pattern_thread.rb', line 118 def waiting_for_thread(skip_event = false) events << [:waiting, current_cycle_count] unless skip_event wait end |