Class: Origen::Generator::PatternThread

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

Constructor Details

#initialize(id, sequence, block, primary = false) ⇒ PatternThread

Returns a new instance of PatternThread



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/origen/generator/pattern_thread.rb', line 17

def initialize(id, sequence, block, primary = false)
  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
  @primary = primary
  @running = Concurrent::Event.new
  @waiting = Concurrent::Event.new
  @pending_cycles = nil
  @completed = false
  @reservations = {}
end

Instance Attribute Details

#cycle_count_startObject (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_stopObject (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

#eventsObject (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

#idObject (readonly)

Returns the value of attribute id



10
11
12
# File 'lib/origen/generator/pattern_thread.rb', line 10

def id
  @id
end

#pending_cyclesObject (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

#reservationsObject (readonly)

Returns the value of attribute reservations



11
12
13
# File 'lib/origen/generator/pattern_thread.rb', line 11

def reservations
  @reservations
end

#sequenceObject (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)



168
169
170
171
172
# File 'lib/origen/generator/pattern_thread.rb', line 168

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

Returns:

  • (Boolean)


148
149
150
# File 'lib/origen/generator/pattern_thread.rb', line 148

def completed?
  @completed
end

#current_cycle_countObject



68
69
70
# File 'lib/origen/generator/pattern_thread.rb', line 68

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



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/origen/generator/pattern_thread.rb', line 122

def cycle(options)
  @pending_cycles = options[: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.



144
145
146
# File 'lib/origen/generator/pattern_thread.rb', line 144

def executed_cycles(cycles)
  @pending_cycles -= cycles if @pending_cycles
end

#execution_profile(start, stop, step) ⇒ Object



72
73
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
# File 'lib/origen/generator/pattern_thread.rb', line 72

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)

Returns:

  • (Boolean)


37
38
39
# File 'lib/origen/generator/pattern_thread.rb', line 37

def primary?
  @primary
end

#record_activeObject



64
65
66
# File 'lib/origen/generator/pattern_thread.rb', line 64

def record_active
  events << [:active, current_cycle_count]
end

#record_cycle_count_stopObject



58
59
60
61
62
# File 'lib/origen/generator/pattern_thread.rb', line 58

def record_cycle_count_stop
  @cycle_count_stop = current_cycle_count
  events << [:stopped, cycle_count_stop]
  events.freeze
end

#startObject

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.



45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/origen/generator/pattern_thread.rb', line 45

def start
  @thread = Thread.new do
    PatSeq.send(:thread=, self)
    wait
    @block.call(sequence)
    sequence.send(:thread_completed, self)
    record_cycle_count_stop
    @completed = true
    wait
  end
  @waiting.wait
end

#waitObject

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



159
160
161
162
163
# File 'lib/origen/generator/pattern_thread.rb', line 159

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

Returns:

  • (Boolean)


153
154
155
# File 'lib/origen/generator/pattern_thread.rb', line 153

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



108
109
110
111
112
# File 'lib/origen/generator/pattern_thread.rb', line 108

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



116
117
118
119
# File 'lib/origen/generator/pattern_thread.rb', line 116

def waiting_for_thread(skip_event = false)
  events << [:waiting, current_cycle_count] unless skip_event
  wait
end