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



260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/origen/application/runner.rb', line 260

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.



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

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



165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/origen/application/runner.rb', line 165

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



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

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



254
255
256
257
258
# File 'lib/origen/application/runner.rb', line 254

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



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/origen/application/runner.rb', line 233

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



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/origen/application/runner.rb', line 207

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
# File 'lib/origen/application/runner.rb', line 136

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



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

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

#statisticsObject Also known as: stats



202
203
204
# File 'lib/origen/application/runner.rb', line 202

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