Class: Origen::Application::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/origen/application/runner.rb

Overview

The Runner is responsible for co-ordinating all compile and generate requests from the command line

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#optionsObject

Returns the value of attribute options


9
10
11
# File 'lib/origen/application/runner.rb', line 9

def options
  @options
end

Instance Method Details

#confirm_production_ready(_options = {}) ⇒ Object


252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/origen/application/runner.rb', line 252

def confirm_production_ready(_options = {})
  # The caller would have already verified the status before submission
  if Origen.running_locally?
    if Origen.mode.production? && Origen.app.rc
      unless Origen.app.rc.local_modifications.empty?
        puts <<-EOT
    Your workspace has local modifications that are preventing the requested action
- run 'origen rc mods' to see them.
        EOT
        exit 1
      end
    end
  end
end

#expand_lists_and_directories(files, options = {}) ⇒ Object

Expands any list references in the supplied pattern array and returns an array of pattern names. No guarantee is made to whether the pattern names are valid at this stage. Any duplicates will be removed.


190
191
192
# File 'lib/origen/application/runner.rb', line 190

def expand_lists_and_directories(files, options = {})
  Origen.file_handler.expand_list(files, options)
end

#extract_action(options) ⇒ Object

The action to take should be set by the action option, but legacy code will pass things like :compile => true, the extract_action method handles the old code


157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/origen/application/runner.rb', line 157

def extract_action(options)
  return options[:action] if options[:action]
  if options[:compile]
    :compile
  elsif options[:program]
    :program
  elsif options[:job_type] == :merge
    :merge
  else
    :pattern
  end
end

#extract_files(options) ⇒ Object

Legacy file references can be input via :pattern, :patterns, etc. this cleans it up and forces them all to be in an array assigned to options


172
173
174
175
176
177
# File 'lib/origen/application/runner.rb', line 172

def extract_files(options)
  files = [options[:pattern]] + [options[:patterns]] + [options[:file]] + [options[:files]]
  files.flatten!
  files.compact!
  files
end

#launch(options = {}) ⇒ Object Also known as: generate

Launch Origen, any command which generates an output file should launch from here as it gives a common point for listeners to hook in and to establish output directories and so on.

Originally this method was called generate but that is now deprecated in favour of the more generic 'launch' as the Origen feature set has expanded.


17
18
19
20
21
22
23
24
25
26
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/origen/application/runner.rb', line 17

def launch(options = {})
  Origen.file_handler.preserve_state do
    # Clean up the input from legacy code
    options[:action] = extract_action(options)
    options[:files] = extract_files(options)
    @options = options
    prepare_and_validate_workspace(options)
    if options[:lsf]
      record_invocation(options) do
        prepare_for_lsf
        Origen.app.listeners_for(:before_lsf_submission).each(&:before_lsf_submission)
        batch = []
        expand_lists_and_directories(options[:files], options).each do |file|
          if options[:batch]
            # Batch jobs into groups of 10
            batch << file
            if batch.size == options[:batch]
              Origen.app.lsf_manager.submit_origen_job(batch.join(' '), options)
              batch = []
            end
          else
            Origen.app.lsf_manager.submit_origen_job(file, options)
          end
        end
        if options[:batch]
          Origen.app.lsf_manager.submit_origen_job(batch.join(' '), options) unless batch.empty?
        end
      end
      Origen.log.info ''
      Origen.log.info 'Monitor status of remote jobs via:'
      Origen.log.info '  origen l'
    else
      Origen.log.info '*' * 70 unless options[:quiet]
      Origen.app.listeners_for(:before_generate).each do |listener|
        if listener.class.instance_method(:before_generate).arity == 0
          listener.before_generate
        else
          listener.before_generate(options)
        end
      end
      if Origen.running_remotely?
        Origen.app.listeners_for(:before_generate_remote).each do |listener|
          if listener.class.instance_method(:before_generate_remote).arity == 0
            listener.before_generate_remote
          else
            listener.before_generate_remote(options)
          end
        end
      else
        Origen.app.listeners_for(:before_generate_local).each do |listener|
          if listener.class.instance_method(:before_generate_local).arity == 0
            listener.before_generate_local
          else
            listener.before_generate_local(options)
          end
        end
      end

      record_invocation(options) do
        case options[:action]
        when :forecast_test_time
          Origen.time.forecast_test_time(options)
        else
          if options[:action] == :program
            Origen.generator.generate_program(expand_lists_and_directories(options[:files], options), options)
            Origen.app.listeners_for(:program_generated).each(&:program_generated)
          else
            temporary_plugin_from_options = options[:current_plugin]
            expand_lists_and_directories(options[:files], options).each do |file|
              if temporary_plugin_from_options
                Origen.app.plugins.temporary = temporary_plugin_from_options
              end
              case options[:action]
              when :compile
                Origen.generator.compile_file_or_directory(file, options)
              when :merge
                Origen.generator.merge_file_or_directory(file, options)
              when :import_test_time
                Origen.time.import_test_time(file, options)
              when :import_test_flow
                Origen.time.import_test_flow(file, options)
              else
                Origen.generator.generate_pattern(file, options)
              end
              Origen.app.plugins.temporary = nil if temporary_plugin_from_options
            end
          end
        end
      end

      unless options[:quiet]
        Origen.log.info '*' * 70
        stats.print_summary unless options[:action] == :merge
      end
    end
  end
end

#mkdir(dir) ⇒ Object

Make the given directory if it doesn't exist, must be a full path


246
247
248
249
250
# File 'lib/origen/application/runner.rb', line 246

def mkdir(dir)
  unless File.exist?(dir)
    FileUtils.mkdir_p(dir)
  end
end

#prepare_and_validate_workspace(options = {}) ⇒ Object


116
117
118
119
# File 'lib/origen/application/runner.rb', line 116

def prepare_and_validate_workspace(options = {})
  confirm_production_ready(options)
  prepare_directories(options)
end

#prepare_directories(options = {}) ⇒ Object


225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/origen/application/runner.rb', line 225

def prepare_directories(options = {})
  # When running remotely on the LSF never create directories to
  # prevent race conditions as multiple processes run concurrently,
  # instead assume they were already created by the runner who
  # submitted the job.
  Origen.file_handler.set_output_directory(options.merge(create: Origen.running_locally?))
  Origen.file_handler.set_reference_directory(options.merge(create: Origen.running_locally?))
  unless Origen.running_globally?
    tmp = "#{Origen.root}/tmp"
    FileUtils.mkdir(tmp) unless File.exist?(tmp)
    if Origen.running_locally?
      mkdir Origen::Log.log_file_directory
      mkdir "#{Origen.root}/.lsf"
    end
    if options[:lsf]
      mkdir Origen.app.lsf_manager.log_file_directory
    end
  end
end

#prepare_for_lsfObject


199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/origen/application/runner.rb', line 199

def prepare_for_lsf
  if options[:lsf]
    # Build an options string for saving with the LSF job that represents this runtime environment
    str = "-t #{Origen.target.file.basename}"
    if Origen.environment.file
      str += " --environment #{Origen.environment.file.basename}"
    end
    if options[:output]
      str += " -o #{options[:output]}"
    end
    if options[:reference]
      str += " -r #{options[:reference]}"
    end
    options[:lsf_option_string] = str
    # Clear the LSF manager job list if specifically requested or if that is the default action and
    # no specific action has been requested
    if options[:lsf_action]
      if options[:lsf_action] == :clear
        Origen.app.lsf_manager.clear_all
      end
    elsif Origen.config.default_lsf_action == :clear
      Origen.app.lsf_manager.clear_all
    end
  end
end

#record_invocation(options) ⇒ 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.

Post an invocation to the Origen server for usage statistics tracking.

Posting an invocation was found to add ~0.5s to all command times, so here we run it in a separate thread to try and hide it behind the user's command.


128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/origen/application/runner.rb', line 128

def record_invocation(options)
  # record_invocation = false
  # begin
  #  # Only record user invocations at this time, also bypass windows since it seems
  #  # that threads can't be trusted not to block
  #  unless Origen.running_remotely? # || Origen.running_on_windows?
  #    record_invocation = Thread.new do
  #      Origen.client.record_invocation(options[:action]) if options[:action]
  #    end
  #  end
  # rescue
  #  # Don't allow this to kill an origen command
  # end
  yield
  # begin
  #  unless Origen.running_remotely?
  #    # Wait for a server response, ideally would like to not wait here, but it seems if not
  #    # then invocation postings can be dropped, especially on windows
  #    Origen.profile 'waiting for recording invocation' do
  #      record_invocation.value
  #    end
  #  end
  # rescue
  #  # Don't allow this to kill an origen command
  # end
end

#shutdownObject


179
180
181
182
183
184
# File 'lib/origen/application/runner.rb', line 179

def shutdown
  if Origen.app.stats.failed_files > 0 ||
     Origen.app.stats.failed_patterns > 0
    exit 1
  end
end

#statisticsObject Also known as: stats


194
195
196
# File 'lib/origen/application/runner.rb', line 194

def statistics
  @statistics ||= Statistics.new(options)
end