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



269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/origen/application/runner.rb', line 269

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 is running in production mode and it has local modifications which are preventing
    the requested action, run the following command to see what files have been modified:

origen rc mods

    If you are currently developing this application and are not ready to check everything in yet,
    then run the following command to switch your workspace to debug/development mode:

origen m debug
        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.



207
208
209
# File 'lib/origen/application/runner.rb', line 207

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



173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/origen/application/runner.rb', line 173

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



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

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
114
115
116
117
118
119
120
121
# 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
      unless tester && tester.try(:sim?)
        Origen.log.info '*' * 70 unless options[:quiet]
      end
      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]
            if options[:action] == :pattern && options[:sequence]
              patterns = expand_lists_and_directories(options[:files], options.merge(preserve_duplicates: true))
              Origen.generator.generate_pattern(patterns, options)
              Origen.app.plugins.temporary = nil if temporary_plugin_from_options
            else
              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
      end

      unless options[:quiet] || (tester && tester.try(:sim?))
        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



263
264
265
266
267
# File 'lib/origen/application/runner.rb', line 263

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

#prepare_and_validate_workspace(options = {}) ⇒ Object



124
125
126
127
# File 'lib/origen/application/runner.rb', line 124

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

#prepare_directories(options = {}) ⇒ Object



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/origen/application/runner.rb', line 242

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



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/origen/application/runner.rb', line 216

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.



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/origen/application/runner.rb', line 136

def record_invocation(options)
  if Origen.site_config.record_invocation == true
    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]
        rescue
          # Dont allow server being down to flood the screen with the stacktrace
        end
      end
    rescue
      # Don't allow this to kill an origen command
    end
  end
  # yield here is really important for the callback tests!!
  yield

  if Origen.site_config.record_invocation == true
    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
end

#shutdownObject



196
197
198
199
200
201
# File 'lib/origen/application/runner.rb', line 196

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

#statisticsObject Also known as: stats



211
212
213
# File 'lib/origen/application/runner.rb', line 211

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