Class: OrigenTesters::SmartestBasedTester::Base

Inherits:
Object
  • Object
show all
Includes:
VectorBasedTester
Defined in:
lib/origen_testers/smartest_based_tester/base.rb,
lib/origen_testers/smartest_based_tester/base/flow.rb,
lib/origen_testers/smartest_based_tester/base/generator.rb,
lib/origen_testers/smartest_based_tester/base/test_suite.rb,
lib/origen_testers/smartest_based_tester/base/limits_file.rb,
lib/origen_testers/smartest_based_tester/base/test_method.rb,
lib/origen_testers/smartest_based_tester/base/test_suites.rb,
lib/origen_testers/smartest_based_tester/base/test_methods.rb,
lib/origen_testers/smartest_based_tester/base/pattern_master.rb,
lib/origen_testers/smartest_based_tester/base/variables_file.rb,
lib/origen_testers/smartest_based_tester/base/pattern_compiler.rb,
lib/origen_testers/smartest_based_tester/base/test_methods/ac_tml.rb,
lib/origen_testers/smartest_based_tester/base/test_methods/dc_tml.rb,
lib/origen_testers/smartest_based_tester/base/test_methods/limits.rb,
lib/origen_testers/smartest_based_tester/base/test_methods/base_tml.rb,
lib/origen_testers/smartest_based_tester/base/test_methods/custom_tml.rb,
lib/origen_testers/smartest_based_tester/base/processors/extract_bin_names.rb,
lib/origen_testers/smartest_based_tester/base/processors/extract_flow_vars.rb

Direct Known Subclasses

V93K, V93K_SMT8

Defined Under Namespace

Modules: Generator, Processors Classes: Flow, LimitsFile, PatternCompiler, PatternMaster, TestMethod, TestMethods, TestSuite, TestSuites, VariablesFile

Instance Attribute Summary collapse

Attributes included from API

#capture_style, #comment_level, #generating, #includes, #overlay_style

Attributes included from Timing

#level_period, #timing_toggled_pins

Attributes included from VectorGenerator

#compress, #expand_repeats, #vector_comments

Instance Method Summary collapse

Methods included from VectorBasedTester

#register_tester

Methods included from API

#annotate, #any_clocks_running?, #c1, #c2, #capture_memory, #capture_memory_config, #clocks_running, #comment_char, #comment_char=, #d10?, #diff_friendly_output=, #diff_friendly_output?, #doc?, #generate?, #generating_pattern?, #generating_program?, #ignore_fails, #igxl?, #import_test_time, #inhibit_vectors_and_comments, #is_command_based?, #is_vector_based?, #j750?, #j750_hpt?, #link?, #name, #pat_extension, #pattern_section, #pins_need_toggling, #pop_running_clock, #program_comment_char, #program_comment_char=, #push_running_clock, #pxie6570?, #slice_repeats, #smt7?, #smt8?, #snip, #source_memory, #source_memory_config, #ss, #step_comment_prefix, #stil?, #transaction, #ultraflex?, #update_running_clocks, #v93k?

Methods included from Timing

_set_timeset_, called_timesets, called_timesets_by_name, current_period_in_ns, current_timeset, lookup_or_register_timeset, min_period_timeset, period_in_ns, period_in_secs, reset!, set_timeset, timeset, timeset?, timeset_changed, timesets, timesets!

Methods included from Timing::TimingAPI

#called_timesets, #called_timesets_by_name, #count, #current_period_in_ns, #current_timeset, #cycles_to_time, #delay, #max_repeat_loop, #min_period_timeset, #period_in_ns, #period_in_secs, #set_timeset, #timeset?, #timesets, #timing_toggled_pins, #wait

Methods included from VectorGenerator

#_render, #add_microcode_to_last_or_cycle, #align, #align_to_last, #before_write_pattern_line, #current_pin_vals, #cycle_count, #dec_vec_count, #dont_compress, #dont_compress=, #execution_time_in_ns, #expand_vector, #format, #format_pin_state, #format_vector, #get_pingroup, #inc_cycle_count, #inc_vec_count, #inhibit_pin, #inhibited_pins, #last_object, #last_vector, #microcode, #ordered_pins, #ordered_pins_cache, #ordered_pins_name, #pingroup_map, #pipeline, #preset_next_vector, #push_comment, #push_vector, #regex_for_pin, #regex_for_pin_sub, #remove_store_from_vector, #render, #render_body, #render_footer, #render_header, #render_template, #reset_cycle_count, #stage, #track_and_format_comment, #track_and_format_vector, #update_pin_from_formatted_state, #update_vector, #update_vector_pin_val, #vec_count, #vector_group_size, #vector_group_size=, #with_vector_group_size

Constructor Details

#initialize(options = {}) ⇒ Base

Returns a new instance of Base.



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
122
123
124
125
126
127
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
154
155
156
157
158
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 77

def initialize(options = {})
  options = {
    # whether to use multiport bursts or not, if so this indicates the name of the port to use
    multiport:         false,
    multiport_prefix:  false,
    multiport_postfix: false
  }.merge(options)

  @smt_version = options[:smt_version] || 7

  @separate_bins_file = options[:separate_bins_file] || false
  if options.key?(:zip_patterns)
    @zip_patterns = options.delete(:zip_patterns)
  else
    @zip_patterns = true
  end

  if smt8?
    require_relative 'smt8'
    extend SMT8
  else
    require_relative 'smt7'
    extend SMT7
  end

  @max_repeat_loop = 65_535
  @min_repeat_loop = 33
  if smt8?
    @pat_extension = 'pat'
    @program_comment_char = ['println', '//']
  else
    @pat_extension = 'avc'
    @program_comment_char = ['print_dl', '//']
  end
  @compress = true
  # @support_repeat_previous = true
  @match_entries = 10
  @name = 'v93k'
  @comment_char = '#'
  @level_period = true
  @inline_comments = true
  @multiport = options[:multiport]
  @multiport_prefix = options[:multiport_prefix]
  @multiport_postfix = options[:multiport_postfix]
  @overlay_style = :subroutine	# default to use subroutine for overlay
  @capture_style = :hram			# default to use hram for capture
  @overlay_subr = nil
  @overlay_history = {} # used to track labels, subroutines, digsrc pins used etc

  if options[:add_flow_enable]
    self.add_flow_enable = options[:add_flow_enable]
  end
  if options.key?(:unique_test_names)
    @unique_test_names = options[:unique_test_names]
  else
    if smt8?
      @unique_test_names = nil
    else
      @unique_test_names = :signature
    end
  end
  if smt8?
    @create_limits_file = true
  else
    if options.key?(:create_limits_file)
      @create_limits_file = options[:create_limits_file]
    else
      @create_limits_file = false
    end
  end
  if options[:literal_flags]
    @literal_flags = true
  end
  if options[:literal_enables]
    @literal_enables = true
  end

  @package_namespace = options.delete(:package_namespace)
  self.limitfile_test_modes = options[:limitfile_test_modes] || options[:limitsfile_test_modes]
  self.force_pass_on_continue = options[:force_pass_on_continue]
  self.delayed_binning = options[:delayed_binning]
end

Instance Attribute Details

#add_flow_enableObject

Returns whether the tester has been configured to wrap top-level flow modules with an enable or not.

Returns nil if not.

Returns :enabled if the enable is configured to be on by default, or :disabled if it is configured to be off by default.



16
17
18
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 16

def add_flow_enable
  @add_flow_enable
end

#create_limits_fileObject

When set to true, all test flows will be generated with a corresponding testtable limits file, rather than having the limits attached inline to the test suites



44
45
46
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 44

def create_limits_file
  @create_limits_file
end

#delayed_binningObject

When set to true, tests will be set to delayed binning by default (overon = on) unless delayed: false is supplied when defining the test



63
64
65
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 63

def delayed_binning
  @delayed_binning
end

#force_pass_on_continueObject

When set to true, tests which are marked with continue: true will be forced to pass in generated test program flows. Flow branching based on the test result will be handled via some other means to give the same flow if the test 'fails', however the test will always appear as if it passed for data logging purposes.

Testers which do not implement this option will ignore it.



59
60
61
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 59

def force_pass_on_continue
  @force_pass_on_continue
end

#inline_commentsObject

Disable inline (end of vector) comments, enabled by default



7
8
9
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 7

def inline_comments
  @inline_comments
end

#limitfile_test_modesObject

Returns an array of strings that indicate which test modes will be included in limits files, by default returns an empty array. If no test modes have been specified then the limits file will simply be generated with no test modes.



50
51
52
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 50

def limitfile_test_modes
  @limitfile_test_modes
end

#literal_enablesObject

whether enables should be exactly as indicated



32
33
34
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 32

def literal_enables
  @literal_enables
end

#literal_flagsObject

Control literal flag definitions



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

def literal_flags
  @literal_flags
end

#min_repeat_loopObject Also known as: min_repeat_count

permit modification of minimum repeat count



26
27
28
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 26

def min_repeat_loop
  @min_repeat_loop
end

#multiportObject Also known as: multi_port

permit option to generate multiport type patterns and use multiport type code



36
37
38
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 36

def multiport
  @multiport
end

#multiport_postfixObject

multiport burst name postfix



40
41
42
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 40

def multiport_postfix
  @multiport_postfix
end

#multiport_prefixObject

multiport burst name prefix



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

def multiport_prefix
  @multiport_prefix
end

#package_namespaceObject

Returns the package namespace that all generated test collateral should be placed under, defaults to the application's namespace if not defined



166
167
168
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 166

def package_namespace
  @package_namespace || Origen.app.namespace
end

#separate_bins_fileObject

When set to true, the bins and softbins sheets from the limits spreadsheet will be written out to a standalone (spreadsheet) file instead (SMT8 only)



71
72
73
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 71

def separate_bins_file
  @separate_bins_file
end

#smt_versionObject (readonly)

Returns the SMT version, defaults to 7



23
24
25
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 23

def smt_version
  @smt_version
end

#unique_test_namesObject (readonly)

Returns the value defined at target-level on if/how to make test names unique within a flow, the default value is :signature



20
21
22
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 20

def unique_test_names
  @unique_test_names
end

#zip_patternsObject

When set to true (the default), patterns will be generated in ZIP format instead of ASCII format (SMT8 only)



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

def zip_patterns
  @zip_patterns
end

Instance Method Details

#before_timeset_change(options = {}) ⇒ Object



739
740
741
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 739

def before_timeset_change(options = {})
  microcode "SQPG CTIM #{options[:new].name};" unless level_period?
end

#call_subroutine(name, options = {}) ⇒ Object

Call a subroutine.

This calls a subroutine immediately following previous vector, it does not generate a new vector.

Subroutines should always be called through this method as it ensures a running log of called subroutines is maintained and which then gets output in the pattern header to import the right dependencies.

An offset option is available to make the call on earlier vectors.

Repeated calls to the same subroutine will automatically be compressed unless option :suppress_repeated_calls is supplied and set to false. This means that for the common use case of calling a subroutine to implement an overlay the subroutine can be called for every bit that has the overlay and the pattern will automatically generate correctly.

Examples

$tester.call_subroutine("mysub")
$tester.call_subroutine("my_other_sub", :offset => -1)


415
416
417
418
419
420
421
422
423
424
425
426
427
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 415

def call_subroutine(name, options = {})
  options = {
    offset:                  0,
    suppress_repeated_calls: true
  }.merge(options)
  called_subroutines << name.to_s.chomp unless called_subroutines.include?(name.to_s.chomp) || @inhibit_vectors

  code = "SQPG JSUB #{name};"
  if !options[:suppress_repeated_calls] ||
     last_object != code
    microcode code, offset: (options[:offset] * -1)
  end
end

#called_subroutinesObject

Returns an array of subroutines called while generating the current pattern



712
713
714
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 712

def called_subroutines
  @called_subroutines ||= []
end

#cycle(options = {}) ⇒ Object



208
209
210
211
212
213
214
215
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
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 208

def cycle(options = {})
  # handle overlay if requested
  ovly_style = nil
  if options.key?(:overlay)
    ovly_style = options[:overlay][:overlay_style].nil? ? @overlay_style : options[:overlay][:overlay_style]
    overlay_str = options[:overlay][:overlay_str]

    # route the overlay request to the appropriate method
    case ovly_style
      when :subroutine, :default
        subroutine_overlay(overlay_str, options)
        ovly_style = :subroutine
      when :label, :global_label
        options[:dont_compress] = true
        unless @overlay_history.key?(overlay_str)
          cc "#{overlay_str}"
          @overlay_history[overlay_str] = { is_label: true }
        end
      when :handshake
        if @delayed_handshake
          if @delayed_handshake != overlay_str
            handshake
            @delayed_handshake = overlay_str
          end
        else
          @delayed_handshake = overlay_str
        end
      else
        ovly_style = overlay_style_warn(options[:overlay][:overlay_str], options)
    end # case ovly_style
  else
    handshake if @delayed_handshake
    @delayed_handshake = nil
    @overlay_subr = nil
  end # of handle overlay

  options_overlay = options.delete(:overlay) if options.key?(:overlay)

  unless ovly_style == :subroutine || ovly_style == :handshake
    super(options)
  end

  unless options_overlay.nil?
    # stage = :body if ovly_style == :subroutine 		# always set stage back to body in case subr overlay was selected
  end
end

#disable_pattern_diffsObject



160
161
162
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 160

def disable_pattern_diffs
  smt8? && zip_patterns
end

#end_subroutine(_cond = false) ⇒ Object

Ends the current subroutine that was started with a previous call to start_subroutine



391
392
393
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 391

def end_subroutine(_cond = false)
  ::Pattern.close call_shutdown_callbacks: false, subroutine: true
end

#freq_count(_pin, options = {}) ⇒ Object

Do a frequency measure.

Examples

$tester.freq_count($top.pin(:d_out))                 # Freq measure on pin "d_out"


443
444
445
446
447
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 443

def freq_count(_pin, options = {})
  options = {
  }.merge(options)
  ::Pattern.split(options)
end

#handshake(options = {}) ⇒ Object

Handshake with the tester.

Examples

$tester.handshake                   # Pass control to the tester for a measurement


433
434
435
436
437
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 433

def handshake(options = {})
  options = {
  }.merge(options)
  ::Pattern.split(options)
end

#local_subroutinesObject

Returns an array of subroutines created by the current pattern



717
718
719
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 717

def local_subroutines # :nodoc:
  @local_subroutines ||= []
end

#loop_vectors(name = nil, number_of_loops = 1, _global = false) ⇒ Object Also known as: loop_vector

Add a loop to the pattern.

Pass in the number of times to execute it, all vectors generated by the given block will be captured in the loop.

Examples

$tester.loop_vectors 3 do   # Do this 3 times...
    $tester.cycle
    some_other_method_to_generate_vectors
end

For compatibility with the J750 you can supply a name as the first argument and that will simply be ignored when generated for the V93K tester…

$tester.loop_vectors "my_loop", 3 do   # Do this 3 times...
    $tester.cycle
    some_other_method_to_generate_vectors
end


653
654
655
656
657
658
659
660
661
662
663
664
665
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 653

def loop_vectors(name = nil, number_of_loops = 1, _global = false)
  # The name argument is present to maych J750 API, sort out the
  unless name.is_a?(String)
    name, number_of_loops, global = nil, name, number_of_loops
  end
  if number_of_loops > 1
    microcode "SQPG LBGN #{number_of_loops};"
    yield
    microcode 'SQPG LEND;'
  else
    yield
  end
end

#match(pin, state, timeout_in_cycles, options = {}) ⇒ Object

Generates a match loop on up to two pins.

This method is not really intended to be called directly, rather you should call via Tester#wait e.g. $tester.wait(:match => true).

The timeout should be provided in cycles, however when called via the wait method the time-based helpers (time_in_us, etc) will be converted to cycles for you. The following options are available to tailor the match loop behavior, defaults in parenthesis:

  • :pin - The pin object to match on (required)

  • :state - The pin state to match on, :low or :high (required)

  • :check_for_fails (false) - Flushes the pipeline and checks for fails prior to the match (to allow binout of fails encountered before the match)

  • :pin2 (nil) - Optionally supply a second pin to match on

  • :state2 (nil) - State for the second pin (required if :pin2 is supplied)

  • :force_fail_on_timeout (true) - Force a vector mis-compare if the match loop times out

Examples

$tester.wait(:match => true, :time_in_us => 5000, :pin => $top.pin(:done), :state => :high)


468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 468

def match(pin, state, timeout_in_cycles, options = {})
  options = {
    check_for_fails:       false,
    pin2:                  false,
    state2:                false,
    global_loops:          false,
    generate_subroutine:   false,
    force_fail_on_timeout: true
  }.merge(options)

  # Ensure the match pins are don't care by default
  pin.dont_care
  options[:pin2].dont_care if options[:pin2]
  if !options[:pin2]
    cc "for the #{pin.name.upcase} pin to go #{state.to_s.upcase}"
    match_block(timeout_in_cycles, options) do |match_or_conditions, fail_conditions|
      match_or_conditions.add do
        state == :low ? pin.expect_lo : pin.expect_hi
        cycle
        pin.dont_care
      end
    end
  else
    cc "for the #{pin.name.upcase} pin to go #{state.to_s.upcase}"
    cc "or the #{options[:pin2].name.upcase} pin to go #{options[:state2].to_s.upcase}"
    match_block(timeout_in_cycles, options) do |match_or_conditions, fail_conditions|
      match_or_conditions.add do
        state == :low ? pin.expect_lo : pin.expect_hi
        cycle
        pin.dont_care
      end
      match_or_conditions.add do
        options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi
        cycle
        options[:pin2].dont_care
      end
      fail_conditions.add do
        cc 'To get here something has gone wrong, strobe again to force a pattern failure'
        state == :low ? pin.expect_lo : pin.expect_hi
        options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi
        cycle
        pin.dont_care
        options[:pin2].dont_care
      end
    end
  end
end

#match_block(timeout_in_cycles, options = {}, &block) ⇒ Object



516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 516

def match_block(timeout_in_cycles, options = {}, &block)
  unless block_given?
    fail 'ERROR: block not passed to match_block!'
  end

  # Create BlockArgs objects in order to receive multiple blocks
  match_conditions = Origen::Utility::BlockArgs.new
  fail_conditions = Origen::Utility::BlockArgs.new

  if block.arity > 0
    yield match_conditions, fail_conditions
  else
    match_conditions.add(&block)
  end

  # Generate a conventional match loop when there is only one match condition block
  if match_conditions.instance_variable_get(:@block_args).size == 1
    # Need to ensure at least 8 cycles with no compares before entering
    dut.pins.each do |name, pin|
      pin.save
      pin.dont_care if pin.comparing?
    end
    8.cycles
    dut.pins.each { |name, pin| pin.restore }

    # Placeholder, real number of loops required to implement the required timeout will be
    # concatenated onto the end later once the length of the match loop is known
    microcode 'SQPG MACT'
    match_microcode = stage.current_bank.last

    prematch_cycle_count = cycle_count
    match_conditions.each(&:call)

    match_loop_cycle_count = cycle_count - prematch_cycle_count

    # Pad the compare vectors out to a multiple of 8 per the ADV documentation
    until match_loop_cycle_count % 8 == 0
      cycle
      match_loop_cycle_count += 1
    end

    # Use 8 wait vectors by default to keep the overall number of cycles as a multiple of 8
    mrpt = 8

    number_of_loops = (timeout_in_cycles.to_f / (match_loop_cycle_count + mrpt)).ceil

    # There seems to be a limit on the max MACT value, so account for longer times by expanding
    # the wait loop
    while number_of_loops > 262_144
      mrpt = mrpt * 2 # Keep this as a multiple of 8
      number_of_loops = (timeout_in_cycles.to_f / (match_loop_cycle_count + mrpt)).ceil
    end

    match_microcode.concat(" #{number_of_loops};") unless @inhibit_vectors

    # Now do the wait loop, mrpt should always be a multiple of 8
    microcode "SQPG MRPT #{mrpt};"

    # Should be no compares in the wait cycles
    dut.pins.each do |name, pin|
      pin.save
      pin.dont_care if pin.comparing?
    end
    mrpt.cycles
    dut.pins.each { |name, pin| pin.restore }

    # This is just used as a marker by the vector translator to indicate the end of the MRPT
    # vectors, it does not end up in the final pattern binary.
    # It is also used in a similar manner by Origen when generating SMT8 patterns.
    microcode 'SQPG PADDING;'

  # For multiple match conditions do something more like the J750 approach where branching based on
  # miscompares is used to keep the loop going
  else
    if options[:check_for_fails]
      cc 'Return preserving existing errors if the pattern has already failed before arriving here'
      cycle(repeat: propagation_delay)
      microcode 'SQPG RETC 1 1;'
    end

    loop_microcode = ''
    loop_cycles = 0
    loop_vectors 2 do
      loop_microcode = stage.current_bank.last
      preloop_cycle_count = cycle_count
      match_conditions.each do |condition|
        condition.call
        cc 'Wait for failure to propagate'
        cycle(repeat: propagation_delay)
        cc 'Exit match loop if pin has matched (no error), otherwise clear error and remain in loop'
        microcode 'SQPG RETC 0 0;'
      end
      loop_cycles = cycle_count - preloop_cycle_count
    end

    unless @inhibit_vectors
      number_of_loops = (timeout_in_cycles.to_f / loop_cycles).ceil

      loop_microcode.sub!('2', number_of_loops.to_s)
    end

    if options[:force_fail_on_timeout]
      fail_conditions.each(&:call)
    end
  end
end

#multiport_name(patt_name) ⇒ Object

return the multiport burst name provide the name you want to obtain multiport for



179
180
181
182
183
184
185
186
187
188
189
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 179

def multiport_name(patt_name)
  name = "#{patt_name}"
  if @multiport
    name = "#{@multiport_prefix}_#{name}" if @multiport_prefix
    name = "#{name}_#{@multiport_postfix}" if @multiport_postfix
    unless @multiport_prefix || @multiport_postfix
      name = "#{@multiport}_#{name}"
    end
  end
  name
end

#overlay_style_warn(overlay_str, options) ⇒ Object

Warn user of unsupported overlay style



256
257
258
259
260
261
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 256

def overlay_style_warn(overlay_str, options)
  Origen.log.warn("Unrecognized overlay style :#{@overlay_style}, defaulting to subroutine")
  Origen.log.warn('Available overlay styles :subroutine')
  subroutine_overlay(overlay_str, options)
  @overlay_style = :subroutine		# Just give 1 warning
end

An internal method called by Origen to generate the pattern footer



700
701
702
703
704
705
706
707
708
709
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 700

def pattern_footer(options = {})
  options = {
    end_in_ka:      false
  }.merge(options)
  if options[:end_in_ka]
    Origen.log.warning '93K keep alive not yet implemented!'
    ss 'WARNING: 93K keep alive not yet implemented!'
  end
  microcode 'SQPG STOP;' unless options[:subroutine]
end

#pattern_header(options = {}) ⇒ Object

An internal method called by Origen to create the pattern header



669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 669

def pattern_header(options = {})
  options = {
  }.merge(options)
  pin_list = ordered_pins.map do |p|
    if Origen.app.pin_pattern_order.include?(p.id)
      # specified name overrides pin name
      if (p.is_a?(Origen::Pins::PinCollection)) || p.id != p.name
        p.id.to_s # groups or aliases can be lower case
      else
        p.id.to_s.upcase # pins must be uppercase
      end
    else
      if (p.is_a?(Origen::Pins::PinCollection)) || p.id != p.name
        p.name.to_s # groups or aliases can be lower case
      else
        p.name.to_s.upcase # pins must be uppercase
      end
    end
  end.join(' ')
  microcode "FORMAT #{pin_list};"
  if ordered_pins.size > 0
    max_pin_name_length = ordered_pins.map(&:name).max { |a, b| a.length <=> b.length }.length
    pin_widths = ordered_pins.map { |p| p.size - 1 }

    max_pin_name_length.times do |i|
      cc((' ' * 50) + ordered_pins.map.with_index { |p, x| ((p.name[i] || ' ') + ' ' * pin_widths[x]).gsub('_', '-') }.join(' '))
    end
  end
end

#propagation_delayObject

Returns the number of cycles to wait for any fails to propagate through the pipeline based on the current timeset



625
626
627
628
629
630
631
632
633
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 625

def propagation_delay
  # From 'Calculating the buffer cycles for JMPE and RETC (and match loops)' in SmarTest docs
  data_queue_buffer = (([105, 64 + ((125 + current_period_in_ns - 1) / current_period_in_ns).ceil].min + 3) * 8) + 72
  # Don't know how to calculate at runtime, hardcoding these to some default values for now
  number_of_sites = 128
  sclk_period = 40
  prop_delay_buffer = 195 + ((2 * number_of_sites + 3) * (sclk_period / 2))
  data_queue_buffer + prop_delay_buffer
end

#repeat_previousObject

All vectors generated with the supplied block will have all pins set to the repeat previous state. Any pins that are changed state within the block will still update to the supplied value.

Example

# All pins except invoke will be assigned the repeat previous code
# in the generated vector. On completion of the block they will
# return to their previous state, except for invoke which will
# retain the value assigned within the block.
$tester.repeat_previous do
    $top.pin(:invoke).drive(1)
    $tester.cycle
end


733
734
735
736
737
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 733

def repeat_previous
  Origen.app.pin_map.each { |_id, pin| pin.repeat_previous = true }
  yield
  Origen.app.pin_map.each { |_id, pin| pin.repeat_previous = false }
end

#start_subroutine(name) ⇒ Object

Start a subroutine.

Generates a global subroutine label. Global is used to adhere to the best practice of containing all subroutines in dedicated patterns, e.g. global_subs.atp

Examples

$tester.start_subroutine("wait_for_done")
< generate your subroutine vectors here >
$tester.end_subroutine


384
385
386
387
388
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 384

def start_subroutine(name)
  local_subroutines << name.to_s.chomp unless local_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
  # name += "_subr" unless name =~ /sub/
  ::Pattern.open name: name, call_startup_callbacks: false, subroutine: true
end

#store(*pins) ⇒ Object Also known as: capture

Capture the pin data from a vector to the tester.

This method uses the Digital Capture feature (Selective mode) of the V93000 to capture the data from the given pins on the previous vector. Note that is does not actually generate a new vector.

Note also that any drive cycles on the target pins can also be captured, to avoid this the wavetable should be set up like this to infer a 'D' (Don't Capture) on vectors where the target pin is being used to drive data:

PINS nvm_fail
0  d1:0  r1:D  0
1  d1:1  r1:D  1
2  r1:C  Capt
3  r1:D  NoCapt

Sometimes when generating vectors within a loop you may want to apply a capture retrospectively to a previous vector, passing in an offset option will allow you to do this.

Examples

$tester.cycle                     # This is the vector you want to capture
$tester.store :pin => pin(:fail)  # This applys the required opcode to the given pins

$tester.cycle                     # This one gets captured
$tester.cycle
$tester.cycle
$tester.store(:pin => pin(:fail), :offset => -2) # Just realized I need to capture that earlier vector

# Capturing multiple pins:
$tester.cycle
$tester.store :pins => [pin(:fail), pin(:done)]

Since the V93K store operates on a pin level (rather than vector level as on the J750) equivalent functionality can also be achieved by setting the store attribute of the pin itself prior to calling $tester.cycle. However it is recommended to use the tester API to do the store if cross-compatiblity with other platforms, such as the J750, is required.



330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 330

def store(*pins)
  options = pins.last.is_a?(Hash) ? pins.pop : {}
  options = { offset: 0
            }.merge(options)
  pins = pins.flatten.compact
  if pins.empty?
    fail 'For the V93K you must supply the pins to store/capture'
  end
  pins.each do |pin|
    pin.restore_state do
      pin.capture
      update_vector_pin_val pin, offset: options[:offset]
      unless @inhibit_vectors
        last_vector(options[:offset]).dont_compress = true
        last_vector(options[:offset]).contains_capture = true
      end
    end
  end
end

#store_next_cycle(*pins) ⇒ Object Also known as: store!

Same as the store method, except that the capture will be applied to the next vector to be generated.

Examples:

$tester.store_next_cycle
$tester.cycle                # This is the vector that will be captured


357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 357

def store_next_cycle(*pins)
  options = pins.last.is_a?(Hash) ? pins.pop : {}
  options = {
  }.merge(options)
  pins = pins.flatten.compact
  if pins.empty?
    fail 'For the V93K you must supply the pins to store/capture'
  end
  pins.each { |pin| pin.save; pin.capture }
  # Register this clean up function to be run after the next vector
  # is generated, cool or what!
  preset_next_vector do |vector|
    vector.contains_capture = true
    pins.each(&:restore)
  end
end

#subroutine_overlay(sub_name, options = {}) ⇒ Object

Implement subroutine overlay, called by tester.cycle



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 264

def subroutine_overlay(sub_name, options = {})
  if @overlay_subr != sub_name
    # unless last staged vector already has the subr call do the following
    i = -1
    i -= 1 until stage.bank[i].is_a?(OrigenTesters::Vector)
    if stage.bank[i].microcode !~ /#{sub_name}/

      # check for repeat on new last vector, unroll 1 if needed
      if stage.bank[i].repeat > 1
        v = OrigenTesters::Vector.new
        v.pin_vals = stage.bank[i].pin_vals
        v.timeset = stage.bank[i].timeset
        stage.bank[i].repeat -= 1
        stage.store(v)
        i = -1
      end

      # mark last vector as dont_compress
      stage.bank[i].dont_compress = true
      # insert subroutine call
      call_subroutine sub_name
    end # if microcode not placed
    @overlay_subr = sub_name
  end

  # stage = sub_name
end