Class: OrigenTesters::SmartestBasedTester::Base
- Inherits:
-
Object
- Object
- OrigenTesters::SmartestBasedTester::Base
- 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
Defined Under Namespace
Modules: Generator, Processors Classes: Flow, LimitsFile, PatternCompiler, PatternMaster, ShmooTests, TestMethod, TestMethods, TestSuite, TestSuites, VariablesFile
Instance Attribute Summary collapse
-
#add_flow_enable ⇒ Object
Returns whether the tester has been configured to wrap top-level flow modules with an enable or not.
-
#create_limits_file ⇒ Object
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.
-
#delayed_binning ⇒ Object
When set to true, tests will be set to delayed binning by default (overon = on) unless delayed: false is supplied when defining the test.
-
#flow_variable_grouping ⇒ Object
use flow variable grouping or not.
-
#force_pass_on_continue ⇒ Object
When set to true, tests which are marked with continue: true will be forced to pass in generated test program flows.
-
#inline_comments ⇒ Object
Disable inline (end of vector) comments, enabled by default.
-
#insertion_in_the_flow_path ⇒ Object
readonly
When set to true, the flow path will have insertion in the subdirectories (SMT8 only).
-
#limitfile_test_modes ⇒ Object
Returns an array of strings that indicate which test modes will be included in limits files, by default returns an empty array.
-
#literal_enables ⇒ Object
whether enables should be exactly as indicated.
-
#literal_flags ⇒ Object
Control literal flag definitions.
-
#min_repeat_loop ⇒ Object
(also: #min_repeat_count)
permit modification of minimum repeat count.
-
#multiport ⇒ Object
(also: #multi_port)
permit option to generate multiport type patterns and use multiport type code.
-
#multiport_postfix ⇒ Object
multiport burst name postfix.
-
#multiport_prefix ⇒ Object
multiport burst name prefix.
-
#package_namespace ⇒ Object
Returns the package namespace that all generated test collateral should be placed under, defaults to the application’s namespace if not defined.
-
#print_all_params ⇒ Object
When set to true (the default), parameters will be generated in the flow file regardless if the default is selected (SMT8 only).
-
#separate_bins_file ⇒ Object
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).
- #seq_path ⇒ Object
-
#smt_version ⇒ Object
readonly
Returns the SMT version, defaults to 7.
- #spec_path ⇒ Object
-
#unique_test_names ⇒ Object
readonly
Returns the value defined at target-level on if/how to make test names unique within a flow, the default value is :signature.
-
#zip_patterns ⇒ Object
When set to true (the default), patterns will be generated in ZIP format instead of ASCII format (SMT8 only).
Instance Method Summary collapse
- #before_timeset_change(options = {}) ⇒ Object
-
#call_subroutine(name, options = {}) ⇒ Object
Call a subroutine.
-
#called_subroutines ⇒ Object
Returns an array of subroutines called while generating the current pattern.
- #cycle(options = {}) ⇒ Object
- #disable_pattern_diffs ⇒ Object
-
#end_subroutine(_cond = false) ⇒ Object
Ends the current subroutine that was started with a previous call to start_subroutine.
-
#freq_count(_pin, options = {}) ⇒ Object
Do a frequency measure.
-
#handshake(options = {}) ⇒ Object
Handshake with the tester.
-
#initialize(options = {}) ⇒ Base
constructor
A new instance of Base.
-
#local_subroutines ⇒ Object
Returns an array of subroutines created by the current pattern.
-
#loop_vectors(name = nil, number_of_loops = 1, _global = false) ⇒ Object
(also: #loop_vector)
Add a loop to the pattern.
-
#match(pin, state, timeout_in_cycles, options = {}) ⇒ Object
Generates a match loop on up to two pins.
- #match_block(timeout_in_cycles, options = {}, &block) ⇒ Object
-
#multiport_name(patt_name) ⇒ Object
return the multiport burst name provide the name you want to obtain multiport for.
-
#overlay_style_warn(overlay_str, options) ⇒ Object
Warn user of unsupported overlay style.
-
#pattern_footer(options = {}) ⇒ Object
An internal method called by Origen to generate the pattern footer.
-
#pattern_header(options = {}) ⇒ Object
An internal method called by Origen to create the pattern header.
-
#propagation_delay ⇒ Object
Returns the number of cycles to wait for any fails to propagate through the pipeline based on the current timeset.
-
#repeat_previous ⇒ Object
All vectors generated with the supplied block will have all pins set to the repeat previous state.
-
#start_subroutine(name) ⇒ Object
Start a subroutine.
-
#store(*pins) ⇒ Object
(also: #capture)
Capture the pin data from a vector to the tester.
-
#store_next_cycle(*pins) ⇒ Object
(also: #store!)
Same as the store method, except that the capture will be applied to the next vector to be generated.
-
#subroutine_overlay(sub_name, options = {}) ⇒ Object
Implement subroutine overlay, called by tester.cycle.
Methods included from VectorBasedTester
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( = {}) = { # 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() @smt_version = [:smt_version] || 7 @separate_bins_file = [:separate_bins_file] || false if .key?(:zip_patterns) @zip_patterns = .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 = [:print_all_params].nil? ? true : [: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 = [:multiport] @multiport_prefix = [:multiport_prefix] @multiport_postfix = [: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 = [:insertion_in_the_flow_path] # add insertion for path to the flows if [:add_flow_enable] self.add_flow_enable = [:add_flow_enable] end if .key?(:unique_test_names) @unique_test_names = [:unique_test_names] else if smt8? @unique_test_names = nil else @unique_test_names = :signature end end if .key?(:create_limits_file) @create_limits_file = [:create_limits_file] else if smt8? @create_limits_file = true else @create_limits_file = false end end if .key?(:flow_variable_grouping) @flow_variable_grouping = [:flow_variable_grouping] end if [:literal_flags] @literal_flags = true end if [:literal_enables] @literal_enables = true end @package_namespace = .delete(:package_namespace) @spec_path = .delete(:spec_path) @seq_path = .delete(:seq_path) self.limitfile_test_modes = [:limitfile_test_modes] || [:limitsfile_test_modes] self.force_pass_on_continue = [:force_pass_on_continue] self.delayed_binning = [:delayed_binning] end |
Instance Attribute Details
#add_flow_enable ⇒ Object
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_file ⇒ Object
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_binning ⇒ Object
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_grouping ⇒ Object
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_continue ⇒ Object
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_comments ⇒ Object
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_path ⇒ Object (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_modes ⇒ Object
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_enables ⇒ Object
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_flags ⇒ Object
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_loop ⇒ Object 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 |
#multiport ⇒ Object 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_postfix ⇒ Object
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_prefix ⇒ Object
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_namespace ⇒ Object
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 |
#print_all_params ⇒ Object
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_file ⇒ Object
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_path ⇒ Object
196 197 198 |
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 196 def seq_path @seq_path || 'specs' end |
#smt_version ⇒ Object (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_path ⇒ Object
192 193 194 |
# File 'lib/origen_testers/smartest_based_tester/base.rb', line 192 def spec_path @spec_path || 'specs' end |
#unique_test_names ⇒ Object (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_patterns ⇒ Object
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( = {}) microcode "SQPG CTIM #{[: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, = {}) = { offset: 0, suppress_repeated_calls: true }.merge() called_subroutines << name.to_s.chomp unless called_subroutines.include?(name.to_s.chomp) || @inhibit_vectors code = "SQPG JSUB #{name};" if ![:suppress_repeated_calls] || last_object != code microcode code, offset: ([:offset] * -1) end end |
#called_subroutines ⇒ Object
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( = {}) # handle overlay if requested ovly_style = nil if .key?(:overlay) ovly_style = [:overlay][:overlay_style].nil? ? @overlay_style : [:overlay][:overlay_style] = [:overlay][:overlay_str] # route the overlay request to the appropriate method case ovly_style when :subroutine, :default (, ) ovly_style = :subroutine when :label, :global_label [:dont_compress] = true unless @overlay_history.key?() cc "#{}" @overlay_history[] = { is_label: true } end when :handshake if @delayed_handshake if @delayed_handshake != handshake @delayed_handshake = end else @delayed_handshake = end else ovly_style = ([:overlay][:overlay_str], ) end # case ovly_style else handshake if @delayed_handshake @delayed_handshake = nil @overlay_subr = nil end # of handle overlay = .delete(:overlay) if .key?(:overlay) unless ovly_style == :subroutine || ovly_style == :handshake super() end unless .nil? # stage = :body if ovly_style == :subroutine # always set stage back to body in case subr overlay was selected end end |
#disable_pattern_diffs ⇒ Object
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, = {}) = { }.merge() ::Pattern.split() 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( = {}) = { }.merge() ::Pattern.split() end |
#local_subroutines ⇒ Object
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, = {}) = { check_for_fails: false, pin2: false, state2: false, global_loops: false, generate_subroutine: false, force_fail_on_timeout: true }.merge() # Ensure the match pins are don't care by default pin.dont_care [:pin2].dont_care if [:pin2] if ![:pin2] cc "for the #{pin.name.upcase} pin to go #{state.to_s.upcase}" match_block(timeout_in_cycles, ) 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 #{[:pin2].name.upcase} pin to go #{[:state2].to_s.upcase}" match_block(timeout_in_cycles, ) 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 [:state2] == :low ? [:pin2].expect_lo : [:pin2].expect_hi cycle [: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 [:state2] == :low ? [:pin2].expect_lo : [:pin2].expect_hi cycle pin.dont_care [: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, = {}, &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 [: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 [: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 (, ) Origen.log.warn("Unrecognized overlay style :#{@overlay_style}, defaulting to subroutine") Origen.log.warn('Available overlay styles :subroutine') (, ) @overlay_style = :subroutine # Just give 1 warning end |
#pattern_footer(options = {}) ⇒ Object
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 ( = {}) = { end_in_ka: false }.merge() if [: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 [: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( = {}) = { }.merge() 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_delay ⇒ Object
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_previous ⇒ Object
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) = pins.last.is_a?(Hash) ? pins.pop : {} = { offset: 0 }.merge() 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: [:offset] unless @inhibit_vectors last_vector([:offset]).dont_compress = true last_vector([: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.
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) = pins.last.is_a?(Hash) ? pins.pop : {} = { }.merge() 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 (sub_name, = {}) 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 |