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/v93k_smt8/shmoo_tests.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, ShmooTests, TestMethod, TestMethods, TestSuite, TestSuites, VariablesFile

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from VectorBasedTester

#register_tester

Constructor Details

#initialize(options = {}) ⇒ Base

Returns a new instance of Base.



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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 90

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', '//']
    @print_all_params = options[:print_all_params].nil? ? true : options[:print_all_params]
  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
  @insertion_in_the_flow_path = options[:insertion_in_the_flow_path] # add insertion for path to the flows

  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 options.key?(:create_limits_file)
    @create_limits_file = options[:create_limits_file]
  else
    if smt8?
      @create_limits_file = true
    else
      @create_limits_file = false
    end
  end

  if options.key?(:flow_variable_grouping)
    @flow_variable_grouping = options[:flow_variable_grouping]
  end

  if options[:literal_flags]
    @literal_flags = true
  end
  if options[:literal_enables]
    @literal_enables = true
  end

  @package_namespace = options.delete(:package_namespace)
  @spec_path = options.delete(:spec_path)
  @seq_path = options.delete(:seq_path)
  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



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

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



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

def delayed_binning
  @delayed_binning
end

#flow_variable_groupingObject

use flow variable grouping or not



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

def flow_variable_grouping
  @flow_variable_grouping
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.



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

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

#insertion_in_the_flow_pathObject (readonly)

When set to true, the flow path will have insertion in the subdirectories (SMT8 only)



88
89
90
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 88

def insertion_in_the_flow_path
  @insertion_in_the_flow_path
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.



53
54
55
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 53

def limitfile_test_modes
  @limitfile_test_modes
end

#literal_enablesObject

whether enables should be exactly as indicated



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

def literal_enables
  @literal_enables
end

#literal_flagsObject

Control literal flag definitions



34
35
36
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 34

def literal_flags
  @literal_flags
end

#min_repeat_loopObject Also known as: min_repeat_count

permit modification of minimum repeat count



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

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



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

def multiport
  @multiport
end

#multiport_postfixObject

multiport burst name postfix



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

def multiport_postfix
  @multiport_postfix
end

#multiport_prefixObject

multiport burst name prefix



42
43
44
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 42

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



188
189
190
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 188

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

When set to true (the default), parameters will be generated in the flow file regardless if the default is selected (SMT8 only)



84
85
86
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 84

def print_all_params
  @print_all_params
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)



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

def separate_bins_file
  @separate_bins_file
end

#seq_pathObject



196
197
198
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 196

def seq_path
  @seq_path || 'specs'
end

#smt_versionObject (readonly)

Returns the SMT version, defaults to 7



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

def smt_version
  @smt_version
end

#spec_pathObject



192
193
194
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 192

def spec_path
  @spec_path || 'specs'
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)



80
81
82
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 80

def zip_patterns
  @zip_patterns
end

Instance Method Details

#before_timeset_change(options = {}) ⇒ Object



768
769
770
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 768

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)


444
445
446
447
448
449
450
451
452
453
454
455
456
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 444

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



741
742
743
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 741

def called_subroutines
  @called_subroutines ||= []
end

#cycle(options = {}) ⇒ Object



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
276
277
278
279
280
281
282
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 237

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



182
183
184
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 182

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



420
421
422
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 420

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"


472
473
474
475
476
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 472

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


462
463
464
465
466
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 462

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

#local_subroutinesObject

Returns an array of subroutines created by the current pattern



746
747
748
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 746

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


682
683
684
685
686
687
688
689
690
691
692
693
694
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 682

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)


497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
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
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 497

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



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
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 545

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



208
209
210
211
212
213
214
215
216
217
218
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 208

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



285
286
287
288
289
290
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 285

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



729
730
731
732
733
734
735
736
737
738
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 729

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



698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 698

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



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

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


762
763
764
765
766
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 762

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


413
414
415
416
417
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 413

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.



359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 359

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


386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 386

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



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 293

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