Module: OrigenTesters::API

Included in:
Decompiler
Defined in:
lib/origen_testers/api.rb

Overview

This module implements the basic set of methods that a tester must have in order for Origen to talk to it.

They can be overridden by tester specific classes and who may go on to add additional methods of their own.

Essentially this API means that any class that includes Origen::Tester will function as a tester, although it might not do very much!

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#capture_styleObject

Get/Set the capture style

This method changes the way tester.store() implements the store The default value and possible settings is dependent on the individual tester.

Examples:

tester.capture_style = :hram


29
30
31
# File 'lib/origen_testers/api.rb', line 29

def capture_style
  @capture_style
end

#comment_levelObject

Returns the value of attribute comment_level.



12
13
14
# File 'lib/origen_testers/api.rb', line 12

def comment_level
  @comment_level
end

#generatingObject

Returns the value of attribute generating.



13
14
15
# File 'lib/origen_testers/api.rb', line 13

def generating
  @generating
end

#includesObject

Returns the value of attribute includes.



11
12
13
# File 'lib/origen_testers/api.rb', line 11

def includes
  @includes
end

#overlay_styleObject

Get/Set the overlay style

This method changes the way overlay is handled. The default value and possible settings is dependent on the individual tester.

Examples:

tester.overlay_style = :label


21
22
23
# File 'lib/origen_testers/api.rb', line 21

def overlay_style
  @overlay_style
end

Instance Method Details

#annotate(msg, options = {}) ⇒ Object



128
129
# File 'lib/origen_testers/api.rb', line 128

def annotate(msg, options = {})
end

#any_clocks_running?Boolean

Returns:

  • (Boolean)


281
282
283
# File 'lib/origen_testers/api.rb', line 281

def any_clocks_running?
  @clocks_running.nil? ? false : @clocks_running.count > 0
end

#c1(msg, options = {}) ⇒ Object

Output a comment in the pattern, normally you would not call this directly and instead use these shorthand methods:

cc "Some comment"
ss "A single line step comment"
step_comment do
    cc "A multi line"
    cc "step comment"
end


157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/origen_testers/api.rb', line 157

def c1(msg, options = {})
  PatSeq.add_thread(msg) unless options[:no_thread_id]
  prefix = comment_char + ' '
  prefix += step_comment_prefix + ' ' if @step_comment_on
  if Origen.tester.generating == :program
    cc_coms = OrigenTesters::Flow.cc_comments
    # cc call must be on line directly before test method
    line_number = caller_locations(2, 1)[0].lineno + 1
    unless cc_coms[line_number]
      cc_coms[line_number] = []
    end
    cc_coms[line_number] << msg
  else
    push_comment(prefix + msg.to_s)
  end
end

#c2(msg, options = {}) ⇒ Object



174
175
176
# File 'lib/origen_testers/api.rb', line 174

def c2(msg, options = {})
  c1(msg, options)
end

#capture_memory(type = :default) ⇒ Object

Configure capture memory to a non-default setting

This method changes the way the instruments statement gets rendered if the tester’s capture memory is used.

If called without a block, this method will return the instance of type OrigenTesters::MemoryStyle for the corresponding memory type

Examples:

tester.capture_memory :default do |mem|
  mem.pin :tdo, size: 32, format: :long
end
mem_style = tester.capture_memory(:default)
if mem_style.contains_pin?(:tdo)
  attributes_hash = mem_style.accumulate_attributes(:tdo)

end


409
410
411
412
413
414
415
416
417
# File 'lib/origen_testers/api.rb', line 409

def capture_memory(type = :default)
  type = :hram if type == :default
  capture_memory_config[type] = OrigenTesters::MemoryStyle.new unless capture_memory_config.key?(type)
  if block_given?
    yield capture_memory_config[type]
  else
    capture_memory_config[type]
  end
end

#capture_memory_configObject



355
356
357
# File 'lib/origen_testers/api.rb', line 355

def capture_memory_config
  @capture_memory_config ||= {}
end

#clocks_runningObject Also known as: running_clocks



285
286
287
# File 'lib/origen_testers/api.rb', line 285

def clocks_running
  @clocks_running
end

#comment_charObject



52
53
54
# File 'lib/origen_testers/api.rb', line 52

def comment_char
  @comment_char || '//'
end

#cycle(options = {}) ⇒ Object

Generate a vector. Calling this method will generate a vector in the output pattern based on the current pin states and timeset.



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/origen_testers/api.rb', line 234

def cycle(options = {})
  options = {
    microcode: '',
    timeset:   current_timeset,
    pin_vals:  current_pin_vals,
    repeat:    nil
  }.merge(options)

  unless timeset.period_in_ns?
    fail "You must supply a period_in_ns to timeset '#{timeset.name}' before you can cycle the tester!"
  end
  timeset.cycled = true
  if PatSeq.thread
    PatSeq.thread.cycle(options)
  else
    if any_clocks_running?
      update_running_clocks
      if options[:repeat]
        slice_repeats(options).each do |slice|
          options[:repeat] = slice[0]
          delay(options.delete(:repeat), options) do |options|
            push_vector(options)
          end
          slice[1].each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
          options[:pin_vals] = current_pin_vals
        end
        pins_need_toggling.each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
      else
        push_vector(options)
        pins_need_toggling.each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
      end
    else
      if options[:repeat]
        delay(options.delete(:repeat), options) do |options|
          push_vector(options)
        end
      else
        push_vector(options)
      end
    end
  end
end

#d10?Boolean

Returns:

  • (Boolean)


104
105
106
# File 'lib/origen_testers/api.rb', line 104

def d10?
  is_a?(OrigenTesters::StilBasedTester::D10)
end

#diff_friendly_output=(value) ⇒ Object



131
132
133
# File 'lib/origen_testers/api.rb', line 131

def diff_friendly_output=(value)
  @diff_friendly_output = value
end

#diff_friendly_output?Boolean Also known as: diff_friendly_output

Returns:

  • (Boolean)


135
136
137
# File 'lib/origen_testers/api.rb', line 135

def diff_friendly_output?
  !!@diff_friendly_output
end

#doc?Boolean

Returns:

  • (Boolean)


116
117
118
# File 'lib/origen_testers/api.rb', line 116

def doc?
  false
end

#generate?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/origen_testers/api.rb', line 35

def generate?
  true
end

#generating_pattern?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/origen_testers/api.rb', line 39

def generating_pattern?
  @generating == :pattern
end

#generating_program?Boolean

Returns:

  • (Boolean)


43
44
45
# File 'lib/origen_testers/api.rb', line 43

def generating_program?
  @generating == :program
end

#ignore_fails(*pins) ⇒ Object

Ignore fails on the given pins for the duration of the given block, this has the effect of temporarily setting the states of the given pins to don’t care.



143
144
145
146
147
# File 'lib/origen_testers/api.rb', line 143

def ignore_fails(*pins)
  pins.each(&:suspend)
  yield
  pins.each(&:resume)
end

#igxl?Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/origen_testers/api.rb', line 96

def igxl?
  j750? || j750_hpt? || ultraflex?
end

#import_test_time(file, options = {}) ⇒ Object



277
278
279
# File 'lib/origen_testers/api.rb', line 277

def import_test_time(file, options = {})
  puts "Sorry but an importer doesn't exist for: #{Origen.tester.class}"
end

#inhibit_vectors_and_commentsObject

Allows a section to be run without actually generating any vectors. This can be useful to ensure the pin states end up as they otherwise would have if the section had been run. Classic example of this is a subroutine pattern, wrap this around a call to the startup routine to ensure the pin states are as they would have been immediately after the startup.

Example

# Setup state as if I had run startup without actually doing so
$tester.inhibit_vectors_and_comments do
    $soc.startup
    $top.startup
end


221
222
223
224
225
226
227
228
229
# File 'lib/origen_testers/api.rb', line 221

def inhibit_vectors_and_comments
  inhibit_vectors = @inhibit_vectors
  inhibit_comments = @inhibit_comments
  @inhibit_vectors = true
  @inhibit_comments = true
  yield
  @inhibit_vectors = inhibit_vectors      # Restore to their initial state
  @inhibit_comments = inhibit_comments
end

#is_command_based?Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/origen_testers/api.rb', line 75

def is_command_based?
  !is_vector_based?
end

#is_vector_based?Boolean

Returns:

  • (Boolean)


70
71
72
73
# File 'lib/origen_testers/api.rb', line 70

def is_vector_based?
  return @vector_based if defined?(@vector_based)
  true
end

#j750?Boolean

Returns:

  • (Boolean)


79
80
81
# File 'lib/origen_testers/api.rb', line 79

def j750?
  is_a?(OrigenTesters::IGXLBasedTester::J750)
end

#j750_hpt?Boolean

Returns:

  • (Boolean)


83
84
85
# File 'lib/origen_testers/api.rb', line 83

def j750_hpt?
  is_a?(OrigenTesters::IGXLBasedTester::J750_HPT)
end

#link?Boolean

Returns:

  • (Boolean)


108
109
110
# File 'lib/origen_testers/api.rb', line 108

def link?
  !!(self.class.to_s =~ /^OrigenLink::/)
end

#nameObject



31
32
33
# File 'lib/origen_testers/api.rb', line 31

def name
  @name || self.class
end

#pat_extensionObject Also known as: pattern_extension



47
48
49
# File 'lib/origen_testers/api.rb', line 47

def pat_extension
  @pat_extension || 'txt'
end


63
64
# File 'lib/origen_testers/api.rb', line 63

def pattern_footer(*args)
end

#pattern_header(*args) ⇒ Object



60
61
# File 'lib/origen_testers/api.rb', line 60

def pattern_header(*args)
end

#pattern_section(msg) ⇒ Object



178
179
180
181
182
183
184
185
# File 'lib/origen_testers/api.rb', line 178

def pattern_section(msg)
  if generating_program?
    yield
  else
    step_comment(msg)
    yield
  end
end

#pins_need_togglingObject



332
333
334
335
336
337
338
# File 'lib/origen_testers/api.rb', line 332

def pins_need_toggling
  toggle_ary = []
  clocks_running.each do |name, clock_pin|
    toggle_ary.push("#{name}") if clock_pin.next_edge == cycle_count
  end
  toggle_ary
end

#pop_running_clock(pin) ⇒ Object



294
295
296
297
# File 'lib/origen_testers/api.rb', line 294

def pop_running_clock(pin)
  fail "ERROR: No clocks running, doesn't make sense to pop one" unless any_clocks_running?
  @clocks_running.delete(pin.name.to_s)
end

#program_comment_charObject



56
57
58
# File 'lib/origen_testers/api.rb', line 56

def program_comment_char
  @program_comment_char || comment_char
end

#push_running_clock(pin) ⇒ Object



290
291
292
# File 'lib/origen_testers/api.rb', line 290

def push_running_clock(pin)
  @clocks_running.nil? ? @clocks_running = { pin.name.to_s => pin } : @clocks_running[pin.name.to_s] = pin
end

#pxie6570?Boolean

Returns:

  • (Boolean)


112
113
114
# File 'lib/origen_testers/api.rb', line 112

def pxie6570?
  is_a?(OrigenTesters::LabVIEWBasedTester::Pxie6570)
end

#slice_repeats(options = {}) ⇒ Object



299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/origen_testers/api.rb', line 299

def slice_repeats(options = {})
  slices = {}
  repeat_ary = []
  clocks_running.each do |name, clock_pin|
    if clock_pin.next_edge < (cycle_count + options[:repeat])
      if clock_pin.respond_to?(:duty_cycles)
        d0, d1 = clock_pin.duty_cycles
      else
        # keep legacy support for older pin_clock styling, supports only 50% duty-cycle
        d0 = clock_pin.half_period
        d1 = clock_pin.half_period
      end
      pin_slices = (clock_pin.next_edge..(cycle_count + options[:repeat])).step(d0 + d1).to_a
      pin_slices += ((clock_pin.next_edge + d0)..(cycle_count + options[:repeat])).step(d0 + d1).to_a
      pin_slices.sort!
      pin_slices.insert(0, cycle_count)
    else
      pin_slices = [cycle_count]
    end
    pin_slices.each do |cycle|
      slices[cycle].nil? ? slices[cycle] = name : slices[cycle] = "#{slices[cycle]},#{name}"
    end
    slices[cycle_count + options[:repeat]] = '' if pin_slices[-1] != cycle_count + options[:repeat]
  end
  slices.keys.sort.each do |edge_cycles|
    # puts "Toggle #{slices[edge_cycles]} on #{edge_cycles}"
    repeat_ary.push([edge_cycles, slices[edge_cycles].split(',')])
  end

  (repeat_ary.count - 1).downto(1).each { |i| repeat_ary[i][0] = repeat_ary[i][0] - repeat_ary[i - 1][0] }
  repeat_ary[1..-1]
end

#smt7?Boolean

Returns:

  • (Boolean)


120
121
122
# File 'lib/origen_testers/api.rb', line 120

def smt7?
  v93k? && smt_version.to_s[0] == '7'
end

#smt8?Boolean

Returns:

  • (Boolean)


124
125
126
# File 'lib/origen_testers/api.rb', line 124

def smt8?
  v93k? && smt_version.to_s[0] == '8'
end

#snip(number, options = {}) ⇒ Object



207
208
209
# File 'lib/origen_testers/api.rb', line 207

def snip(number, options = {})
  yield
end

#source_memory(type = :default) ⇒ Object

Configure source memory to a non-default setting

This method changes the way the instruments statement gets rendered if the tester’s source memory is used.

If called without a block, this method will return the instance of type OrigenTesters::MemoryStyle for the corresponding memory type

Examples:

tester.source_memory :default do |mem|
  mem.pin :tdi, size: 32, format: :long
end
mem_style = tester.source_memory(:default)
mem_style.contained_pins.each do |pin|
  attributes_hash = mem_style.accumulate_attributes(pin)

end


379
380
381
382
383
384
385
386
387
# File 'lib/origen_testers/api.rb', line 379

def source_memory(type = :default)
  type = :subroutine if type == :default
  source_memory_config[type] = OrigenTesters::MemoryStyle.new unless source_memory_config.key?(type)
  if block_given?
    yield source_memory_config[type]
  else
    source_memory_config[type]
  end
end

#source_memory_configObject



351
352
353
# File 'lib/origen_testers/api.rb', line 351

def source_memory_config
  @source_memory_config ||= {}
end

#ss(msg = nil) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/origen_testers/api.rb', line 187

def ss(msg = nil)
  div = step_comment_prefix.length
  div = 1 if div == 0
  c1(step_comment_prefix * (70 / div), no_thread_id: true)
  @step_comment_on = true
  if block_given?
    yield
  else
    c1(msg)
  end
  @step_comment_on = false
  if $_testers_enable_vector_comments
    timestamp = " #{execution_time_in_ns}ns #{step_comment_prefix}"
    str = step_comment_prefix * (70 / div)
    c1(str.sub(/#{step_comment_prefix}{#{timestamp.length - 1}}$/, timestamp), no_thread_id: true)
  else
    c1(step_comment_prefix * (70 / div), no_thread_id: true)
  end
end

#step_comment_prefixObject



66
67
68
# File 'lib/origen_testers/api.rb', line 66

def step_comment_prefix
  @step_comment_prefix || '##'
end

#stil?Boolean

Returns:

  • (Boolean)


100
101
102
# File 'lib/origen_testers/api.rb', line 100

def stil?
  is_a?(OrigenTesters::StilBasedTester::Base)
end

#transactionObject



346
347
348
349
# File 'lib/origen_testers/api.rb', line 346

def transaction
  yield
  true
end

#ultraflex?Boolean Also known as: uflex?

Returns:

  • (Boolean)


91
92
93
# File 'lib/origen_testers/api.rb', line 91

def ultraflex?
  is_a?(OrigenTesters::IGXLBasedTester::UltraFLEX)
end

#update_running_clocksObject



340
341
342
343
344
# File 'lib/origen_testers/api.rb', line 340

def update_running_clocks
  clocks_running.each do |name, clock_pin|
    clock_pin.update_clock
  end
end

#v93k?Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/origen_testers/api.rb', line 87

def v93k?
  is_a?(OrigenTesters::SmartestBasedTester::V93K)
end