Class: Origen::Application::Target

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

Overview

Class to handle the target.

The target is a Ruby file that is run prior to generating each pattern, and it should be used to instantiate the top-level models used by the application. It can also be used to override and settings within these classes after they have been instantiated and before they are run.

All target files must live in Origen.root/target.

An instance of this class is automatically instantiated and available globally as Origen.app.target

Constant Summary collapse

DIR =

:nodoc:

"#{Origen.root}/target"
SAVE_FILE =

:nodoc:

"#{DIR}/.default"
DEFAULT_FILE =

:nodoc:

"#{DIR}/default.rb"

Instance Method Summary collapse

Instance Method Details

#all_targetsObject

Returns Array of all targets available


127
128
129
130
131
132
133
# File 'lib/origen/application/target.rb', line 127

def all_targets
  targets = []
  find('').sort.each do |file|
    targets << File.basename(file)
  end
  targets # return
end

#default=(name) ⇒ Object

As #temporary= except that the given target will be set to the workspace default


227
228
229
230
231
232
233
234
# File 'lib/origen/application/target.rb', line 227

def default=(name)
  if name
    self.temporary = name
  else
    @file = nil
  end
  save
end

#default_fileObject

Load the default file from the workspace default if it exists and return it, otherwise returns nil


280
281
282
283
284
285
286
287
288
289
290
# File 'lib/origen/application/target.rb', line 280

def default_file
  return @default_file if @default_file
  if File.exist?(SAVE_FILE)
    File.open(SAVE_FILE) do |f|
      @default_file = Marshal.load(f)
    end
  elsif File.exist?(DEFAULT_FILE)
    @default_file = Pathname.new(DEFAULT_FILE)
  end
  @default_file
end

#describeObject

Prints out the current target details to the command line


237
238
239
240
241
242
243
244
245
# File 'lib/origen/application/target.rb', line 237

def describe
  f = self.file!
  puts "Current target: #{f.basename}"
  puts '*' * 70
  File.open(f).each do |line|
    puts "  #{line}"
  end
  puts '*' * 70
end

#each_production(options = {}) ⇒ Object

Use this to implement a loop for each production target, it will automatically load each target before yielding to the block.

The production targets are defined by the production_targets configuration option.

Example

Origen.app.target.each_production do
  Run something within the context of each target
end

58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/origen/application/target.rb', line 58

def each_production(options = {})
  options = {
    force_debug: false,  # Set true to force debug mode for all targets
  }.merge(options)
  prod_targets.each do |moo, targets|
    [targets].flatten.each do |target|
      self.temporary = target
      Origen.app.load_target!(options)
      yield moo
    end
  end
end

#each_unique_production(options = {}) ⇒ Object

As each_production except it only yields unique targets. i.e. if you have two MOOs that use the same target file defined in the production_targets then this method will only yield once.

An array of MOOs that use each target is returned each time.

Example

Origen.app.target.each_unique_production do |moos|
  Run something within the context of each unique target
end

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/origen/application/target.rb', line 80

def each_unique_production(options = {})
  options = {
    force_debug: false,  # Set true to force debug mode for all targets
  }.merge(options)
  targets = {}
  prod_targets.each do |moo, moos_targets|
    [moos_targets].flatten.each do |target|
      if targets[target]
        targets[target] << moo
      else
        targets[target] = [moo]
      end
    end
  end
  targets.each do |target, moos|
    self.temporary = target
    Origen.app.load_target!(options)
    yield moos
  end
end

#exists?(name) ⇒ Boolean Also known as: exist?

Returns true if the target exists, this can be used to test for the presence of a target before calling one of the other methods to actually apply it.

It will return true if one or more targets are found matching the given name, use the unique? method to test if the given name uniquely identifies a valid target.

Returns:

  • (Boolean)

146
147
148
149
150
# File 'lib/origen/application/target.rb', line 146

def exists?(name)
  tgts = resolve_mapping(name)
  targets = tgts.is_a?(Array) ? tgts : find(tgts)
  targets.size > 0
end

#fileObject

Returns the target file (a Pathname object) if it has been defined, otherwise nil


293
294
295
296
297
298
# File 'lib/origen/application/target.rb', line 293

def file # :nodoc:
  return @file if @file
  if default_file && File.exist?(default_file)
    @file = default_file
  end
end

#file!Object

As file except will raise an exception if it hasn't been defined yet


301
302
303
304
305
306
307
308
309
# File 'lib/origen/application/target.rb', line 301

def file! # :nodoc:
  unless file
    puts 'No target has been specified!'
    puts 'To specify a target use the -t switch.'
    puts 'Look in the target directory for a list of available target names.'
    exit 1
  end
  file
end

#file=(path) ⇒ Object

:nodoc:


311
312
313
314
315
316
317
# File 'lib/origen/application/target.rb', line 311

def file=(path) # :nodoc:
  if path
    @file = Pathname.new(path)
  else
    @file = nil
  end
end

#find(name) ⇒ Object

Returns an array of matching target file paths


248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/origen/application/target.rb', line 248

def find(name)
  if name
    name = name.gsub('*', '')
    if File.exist?(name)
      [name]
    elsif File.exist?("#{Origen.root}/target/#{name}") && name != ''
      ["#{Origen.root}/target/#{name}"]
    else
      # The below weirdness is to make it recurse into symlinked directories
      Dir.glob("#{DIR}/**{,/*/**}/*").sort.uniq.select do |file|
        File.basename(file) =~ /#{name}/ && file !~ /.*\.rb.+$/
      end
    end
  else
    [nil]
  end
end

#forgetObject

Remove the workspace default target


320
321
322
323
# File 'lib/origen/application/target.rb', line 320

def forget
  File.delete(SAVE_FILE) if File.exist?(SAVE_FILE)
  @default_file = nil
end

#is_a_moo_number?(name) ⇒ Boolean

Returns true if the supplied target name is a moo number format

Returns:

  • (Boolean)

385
386
387
# File 'lib/origen/application/target.rb', line 385

def is_a_moo_number?(name) # :nodoc:
  !!(name.to_s.upcase =~ /^\d?\d?\*?[A-Z]\d\d[A-Z]$/)
end

#load!(options = {}) ⇒ Object

Load the target, calling this will re-instantiate all top-level objects defined there.


119
120
121
122
123
124
# File 'lib/origen/application/target.rb', line 119

def load!(options = {})
  options = {
    force_debug: false,  # Set true to force debug mode for all targets
  }.merge(options)
  Origen.app.load_target!(options)
end

#loop(options = {}) ⇒ Object

Implement a target loop based on the supplied options. The options can contain the keys :target or :targets or neither.

In the neither case the loop will run once for the current workspace default target.

In the case where one of the keys is present the loop will run for each target and the options will be passed into the block with the key :target set to the current target.


34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/origen/application/target.rb', line 34

def loop(options = {})
  options = {
    set_target:  true,
    force_debug: false,  # Set true to force debug mode for all targets
  }.merge(options)
  targets = [options.delete(:target), options.delete(:targets)].flatten.compact.uniq
  targets = [file!.basename.to_s] if targets.empty?
  set = options.delete(:set_target)
  targets.each do |target|
    Origen.load_target(target, options) if set
    options[:target] = target
    yield options
  end
end

#mooObject

If the production_targets moo number mapping inclues the current target then the MOO number will be returned, otherwise nil


103
104
105
106
107
108
109
110
# File 'lib/origen/application/target.rb', line 103

def moo
  prod_targets.each do |moo, targets|
    [targets].flatten.each do |target|
      return moo if File.basename(target, '.rb').to_s == file.basename('.rb').to_s
    end
  end
  nil
end

#moo_number_minus_revision(name) ⇒ Object

:nodoc:


389
390
391
392
# File 'lib/origen/application/target.rb', line 389

def moo_number_minus_revision(name) # :nodoc:
  name.to_s.upcase =~ /^\d?\d?([A-Z]\d\d[A-Z])$/
  Regexp.last_match[1]
end

#nameObject

Returns the name (the filename) of the current target


113
114
115
# File 'lib/origen/application/target.rb', line 113

def name
  file.basename('.rb').to_s if file
end

#procObject


209
210
211
# File 'lib/origen/application/target.rb', line 209

def proc
  @proc
end

#prod_targetsObject

Returns config.production_targets with all keys forced to upper case


374
375
376
377
378
379
380
381
382
# File 'lib/origen/application/target.rb', line 374

def prod_targets # :nodoc:
  return {} unless Origen.config.production_targets
  return @prod_targets if @prod_targets
  @prod_targets = {}
  Origen.config.production_targets.each do |key, value|
    @prod_targets[key.upcase] = value
  end
  @prod_targets
end

#production_targetsObject

Returns an array containing all current production targets


136
137
138
# File 'lib/origen/application/target.rb', line 136

def production_targets
  prod_targets.map { |_moo, targets| targets }.uniq
end

#resolve_mapping(name) ⇒ Object

Resolves the target name to a target file if a MOO number is supplied and app.config.production_targets has been defined


356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'lib/origen/application/target.rb', line 356

def resolve_mapping(name) # :nodoc:
  if is_a_moo_number?(name) && prod_targets
    # If an exact match
    if prod_targets[name.upcase]
      prod_targets[name.upcase]
    # If a wildcard match
    elsif prod_targets["*#{moo_number_minus_revision(name)}"]
      prod_targets["*#{moo_number_minus_revision(name)}"]
    # Else just return the given name
    else
      name
    end
  else
    name
  end
end

#saveObject

Saves the current target as the workspace default, i.e. the current target will be used by Origen the next time if no other target is specified


268
269
270
271
272
273
274
275
276
# File 'lib/origen/application/target.rb', line 268

def save # :nodoc:
  if @file
    File.open(SAVE_FILE, 'w') do |f|
      Marshal.dump(file, f)
    end
  else
    forget
  end
end

#set_signature(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.


221
222
223
224
# File 'lib/origen/application/target.rb', line 221

def set_signature(options)
  options ||= {}
  @signature = options.merge(_tname: name).to_a.hash
end

#signatureObject

Returns a signature for the current target, can be used to track target changes in cases where the name is not unique - i.e. when using a configurable target


216
217
218
# File 'lib/origen/application/target.rb', line 216

def signature
  @signature ||= set_signature(nil)
end

#temporary=(name) ⇒ Object Also known as: switch, switch_to

Switch to the supplied target, name can be a fragment as long as it allows a unique target to be identified.

The name can also be a MOO number mapping from the config.production_targets attribute of the application.

Calling this method does not affect the default target setting in the workspace.

The target can also be set to a proc to be called instead, this is really intended to be used for testing purposes:

Origen.target.temporary = -> { $dut = SomeLocalClass.new }

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/origen/application/target.rb', line 172

def temporary=(name)
  if name.is_a?(Proc)
    self.file = nil
    @proc = name
    return
  else
    @proc = nil
  end
  tgts = resolve_mapping(name)
  targets = tgts.is_a?(Array) ? tgts : find(tgts)
  if targets.size == 0
    puts "Sorry no targets were found matching '#{name}'!"
    puts 'Here are the available options:'
    find('').sort.each do |file|
      puts File.basename(file)
    end
    exit 1
  elsif targets.size > 1
    if is_a_moo_number?(name) && prod_targets
      puts "Multiple production targets exist for #{name.upcase}, use one of the following instead of the MOO number:"
      targets.sort.each do |file|
        puts File.basename(file)
      end
    else
      puts 'Please try again with one of the following targets:'
      targets.sort.each do |file|
        puts File.basename(file)
      end
    end
    exit 1
  else
    self.file = targets[0]
  end
end

#temporary?Boolean

Returns true if running with a temporary target, i.e. if the current target is not the same as the default target

Returns:

  • (Boolean)

350
351
352
# File 'lib/origen/application/target.rb', line 350

def temporary?
  @file == @default_file
end

#unique?(name) ⇒ Boolean

Similar to the exists? method, this will return true only if the given name resolves to a single valid target.

Returns:

  • (Boolean)

155
156
157
158
159
# File 'lib/origen/application/target.rb', line 155

def unique?(name)
  tgts = resolve_mapping(name)
  targets = tgts.is_a?(Array) ? tgts : find(tgts)
  targets.size == 1
end

#unload!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.

Not a clean unload, but allows objects to be re-instantiated for testing


21
22
23
# File 'lib/origen/application/target.rb', line 21

def unload!
  Origen.app.unload_target!
end