origen_testers 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/config/application.rb +140 -0
- data/config/commands.rb +73 -0
- data/config/development.rb +12 -0
- data/config/environment.rb +1 -0
- data/config/shared_commands.rb +47 -0
- data/config/users.rb +18 -0
- data/config/version.rb +8 -0
- data/lib/commands/build.rb +69 -0
- data/lib/origen_testers.rb +23 -0
- data/lib/origen_testers/api.rb +258 -0
- data/lib/origen_testers/basic_test_setups.rb +105 -0
- data/lib/origen_testers/callback_handlers.rb +58 -0
- data/lib/origen_testers/generator.rb +279 -0
- data/lib/origen_testers/generator/flow_control_api.rb +611 -0
- data/lib/origen_testers/generator/identity_map.rb +23 -0
- data/lib/origen_testers/generator/placeholder.rb +11 -0
- data/lib/origen_testers/generator/test_numberer.rb +23 -0
- data/lib/origen_testers/igxl_based_tester.rb +12 -0
- data/lib/origen_testers/igxl_based_tester/base.rb +641 -0
- data/lib/origen_testers/igxl_based_tester/base/flow.rb +171 -0
- data/lib/origen_testers/igxl_based_tester/base/flow_line.rb +322 -0
- data/lib/origen_testers/igxl_based_tester/base/generator.rb +217 -0
- data/lib/origen_testers/igxl_based_tester/base/patgroup.rb +109 -0
- data/lib/origen_testers/igxl_based_tester/base/patgroups.rb +38 -0
- data/lib/origen_testers/igxl_based_tester/base/patset.rb +68 -0
- data/lib/origen_testers/igxl_based_tester/base/patset_pattern.rb +56 -0
- data/lib/origen_testers/igxl_based_tester/base/patsets.rb +38 -0
- data/lib/origen_testers/igxl_based_tester/base/patsubr.rb +68 -0
- data/lib/origen_testers/igxl_based_tester/base/patsubr_pattern.rb +56 -0
- data/lib/origen_testers/igxl_based_tester/base/patsubrs.rb +38 -0
- data/lib/origen_testers/igxl_based_tester/base/test_instance.rb +326 -0
- data/lib/origen_testers/igxl_based_tester/base/test_instance_group.rb +58 -0
- data/lib/origen_testers/igxl_based_tester/base/test_instances.rb +179 -0
- data/lib/origen_testers/igxl_based_tester/files.rb +43 -0
- data/lib/origen_testers/igxl_based_tester/j750.rb +248 -0
- data/lib/origen_testers/igxl_based_tester/j750/flow.rb +10 -0
- data/lib/origen_testers/igxl_based_tester/j750/flow_line.rb +19 -0
- data/lib/origen_testers/igxl_based_tester/j750/generator.rb +19 -0
- data/lib/origen_testers/igxl_based_tester/j750/patgroup.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750/patgroups.rb +10 -0
- data/lib/origen_testers/igxl_based_tester/j750/patset.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750/patset_pattern.rb +18 -0
- data/lib/origen_testers/igxl_based_tester/j750/patsets.rb +10 -0
- data/lib/origen_testers/igxl_based_tester/j750/patsubr.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750/patsubr_pattern.rb +18 -0
- data/lib/origen_testers/igxl_based_tester/j750/patsubrs.rb +10 -0
- data/lib/origen_testers/igxl_based_tester/j750/templates/flow.txt.erb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750/templates/instances.txt.erb +16 -0
- data/lib/origen_testers/igxl_based_tester/j750/templates/patgroups.txt.erb +8 -0
- data/lib/origen_testers/igxl_based_tester/j750/templates/patsets.txt.erb +10 -0
- data/lib/origen_testers/igxl_based_tester/j750/templates/patsubrs.txt.erb +10 -0
- data/lib/origen_testers/igxl_based_tester/j750/test_instance.rb +547 -0
- data/lib/origen_testers/igxl_based_tester/j750/test_instance_group.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750/test_instances.rb +10 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt.rb +34 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/flow.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/flow_line.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/generator.rb +19 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patgroup.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patgroups.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patset.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patset_pattern.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patsets.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubr.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubr_pattern.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubrs.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instance.rb +515 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instance_group.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instances.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/parser.rb +102 -0
- data/lib/origen_testers/igxl_based_tester/parser/ac_spec.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/parser/ac_specs.rb +0 -0
- data/lib/origen_testers/igxl_based_tester/parser/dc_spec.rb +33 -0
- data/lib/origen_testers/igxl_based_tester/parser/dc_specs.rb +48 -0
- data/lib/origen_testers/igxl_based_tester/parser/descriptions.rb +339 -0
- data/lib/origen_testers/igxl_based_tester/parser/flow.rb +109 -0
- data/lib/origen_testers/igxl_based_tester/parser/flow_line.rb +203 -0
- data/lib/origen_testers/igxl_based_tester/parser/flows.rb +21 -0
- data/lib/origen_testers/igxl_based_tester/parser/pattern_set.rb +92 -0
- data/lib/origen_testers/igxl_based_tester/parser/pattern_sets.rb +31 -0
- data/lib/origen_testers/igxl_based_tester/parser/test_instance.rb +341 -0
- data/lib/origen_testers/igxl_based_tester/parser/test_instances.rb +24 -0
- data/lib/origen_testers/igxl_based_tester/parser/timeset.rb +13 -0
- data/lib/origen_testers/igxl_based_tester/parser/timesets.rb +0 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex.rb +477 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/flow.rb +10 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/flow_line.rb +19 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/generator.rb +19 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/patgroup.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/patgroups.rb +10 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/patset.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/patset_pattern.rb +18 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/patsets.rb +10 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/patsubr.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/patsubr_pattern.rb +18 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/patsubrs.rb +10 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/flow.txt.erb +9 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/instances.txt.erb +16 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/patgroups.txt.erb +9 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/patsets.txt.erb +10 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/patsubrs.txt.erb +10 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/test_instance.rb +270 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/test_instance_group.rb +9 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/test_instances.rb +10 -0
- data/lib/origen_testers/interface.rb +183 -0
- data/lib/origen_testers/parser.rb +22 -0
- data/lib/origen_testers/parser/description_lookup.rb +62 -0
- data/lib/origen_testers/parser/searchable_array.rb +30 -0
- data/lib/origen_testers/parser/searchable_hash.rb +30 -0
- data/lib/origen_testers/pattern_compilers.rb +116 -0
- data/lib/origen_testers/pattern_compilers/assembler.rb +88 -0
- data/lib/origen_testers/pattern_compilers/job.rb +96 -0
- data/lib/origen_testers/pattern_compilers/ultraflex_pattern_compiler.rb +599 -0
- data/lib/origen_testers/program_generators.rb +55 -0
- data/lib/origen_testers/smartest_based_tester.rb +8 -0
- data/lib/origen_testers/smartest_based_tester/base.rb +411 -0
- data/lib/origen_testers/smartest_based_tester/base/flow.rb +188 -0
- data/lib/origen_testers/smartest_based_tester/base/flow_node.rb +476 -0
- data/lib/origen_testers/smartest_based_tester/base/generator.rb +123 -0
- data/lib/origen_testers/smartest_based_tester/base/pattern_compiler.rb +23 -0
- data/lib/origen_testers/smartest_based_tester/base/pattern_master.rb +47 -0
- data/lib/origen_testers/smartest_based_tester/base/test_method.rb +143 -0
- data/lib/origen_testers/smartest_based_tester/base/test_methods.rb +73 -0
- data/lib/origen_testers/smartest_based_tester/base/test_methods/ac_tml.rb +33 -0
- data/lib/origen_testers/smartest_based_tester/base/test_methods/base_tml.rb +38 -0
- data/lib/origen_testers/smartest_based_tester/base/test_methods/custom_tml.rb +19 -0
- data/lib/origen_testers/smartest_based_tester/base/test_methods/dc_tml.rb +147 -0
- data/lib/origen_testers/smartest_based_tester/base/test_methods/limits.rb +43 -0
- data/lib/origen_testers/smartest_based_tester/base/test_suite.rb +166 -0
- data/lib/origen_testers/smartest_based_tester/base/test_suites.rb +58 -0
- data/lib/origen_testers/smartest_based_tester/v93k.rb +8 -0
- data/lib/origen_testers/smartest_based_tester/v93k/builder.rb +89 -0
- data/lib/origen_testers/smartest_based_tester/v93k/builder/flow.rb +169 -0
- data/lib/origen_testers/smartest_based_tester/v93k/builder/pattern_master.rb +54 -0
- data/lib/origen_testers/smartest_based_tester/v93k/flow.rb +10 -0
- data/lib/origen_testers/smartest_based_tester/v93k/flow_node.rb +9 -0
- data/lib/origen_testers/smartest_based_tester/v93k/generator.rb +19 -0
- data/lib/origen_testers/smartest_based_tester/v93k/pattern_compiler.rb +10 -0
- data/lib/origen_testers/smartest_based_tester/v93k/pattern_master.rb +10 -0
- data/lib/origen_testers/smartest_based_tester/v93k/templates/template.aiv.erb +17 -0
- data/lib/origen_testers/smartest_based_tester/v93k/templates/template.flow.erb +201 -0
- data/lib/origen_testers/smartest_based_tester/v93k/templates/template.pmfl.erb +13 -0
- data/lib/origen_testers/smartest_based_tester/v93k/test_method.rb +9 -0
- data/lib/origen_testers/smartest_based_tester/v93k/test_methods.rb +9 -0
- data/lib/origen_testers/smartest_based_tester/v93k/test_suite.rb +9 -0
- data/lib/origen_testers/smartest_based_tester/v93k/test_suites.rb +9 -0
- data/lib/origen_testers/test/basic_interface.rb +17 -0
- data/lib/origen_testers/test/block.rb +21 -0
- data/lib/origen_testers/test/dut.rb +184 -0
- data/lib/origen_testers/test/dut2.rb +76 -0
- data/lib/origen_testers/test/j750_base_interface.rb +119 -0
- data/lib/origen_testers/test/j750_hpt_interface.rb +8 -0
- data/lib/origen_testers/test/j750_interface.rb +8 -0
- data/lib/origen_testers/test/nvm.rb +94 -0
- data/lib/origen_testers/test/ultraflex_interface.rb +110 -0
- data/lib/origen_testers/test/v93k_interface.rb +115 -0
- data/lib/origen_testers/timing.rb +362 -0
- data/lib/origen_testers/vector.rb +203 -0
- data/lib/origen_testers/vector_based_tester.rb +42 -0
- data/lib/origen_testers/vector_generator.rb +623 -0
- data/lib/origen_testers/vector_pipeline.rb +288 -0
- data/pattern/dc_instr.rb +7 -0
- data/pattern/delay.rb +7 -0
- data/pattern/mem_test.rb +8 -0
- data/pattern/multi_vector.rb +117 -0
- data/pattern/multi_vector_plus1.rb +125 -0
- data/pattern/nvm/j750/add_late_pins.rb +3 -0
- data/pattern/nvm/j750/iterator_postfix_test_x_bx.rb +8 -0
- data/pattern/nvm/j750/iterator_test_x_bx.rb +8 -0
- data/pattern/nvm/j750/j750_halt.rb +159 -0
- data/pattern/nvm/j750/j750_workout.rb +202 -0
- data/pattern/nvm/j750/timing.rb +73 -0
- data/pattern/nvm/v93k/v93k_workout.rb +136 -0
- data/pattern/read_write_reg.rb +58 -0
- data/pattern/reset.rb +4 -0
- data/pattern/subroutines.rb +38 -0
- data/program/_additional_erase.rb +7 -0
- data/program/_efa_resources.rb +7 -0
- data/program/_erase.rb +25 -0
- data/program/_erase_vfy.rb +5 -0
- data/program/_iv_resources.rb +10 -0
- data/program/basic_interface.rb +5 -0
- data/program/components/_prb2_main.rb +6 -0
- data/program/flow_control.rb +164 -0
- data/program/prb1.rb +226 -0
- data/program/prb1_resources.rb +28 -0
- data/program/prb2.rb +40 -0
- data/program/test.rb +20 -0
- data/templates/example.txt.erb +53 -0
- data/templates/j750/_vt_flow.txt.erb +8 -0
- data/templates/j750/_vt_instances.txt.erb +4 -0
- data/templates/j750/program_sheet.txt.erb +9 -0
- data/templates/manifest/v93k.yaml.erb +22 -0
- data/templates/web/index.md.erb +51 -0
- data/templates/web/layouts/_basic.html.erb +15 -0
- data/templates/web/partials/_navbar.html.erb +22 -0
- data/templates/web/release_notes.md.erb +5 -0
- metadata +332 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
module OrigenTesters
|
|
3
|
+
# Include this module to create an interface that supports multiple tester
|
|
4
|
+
# types.
|
|
5
|
+
#
|
|
6
|
+
# This module will expose generators for all test platforms supported by
|
|
7
|
+
# the Testers plugin.
|
|
8
|
+
module ProgramGenerators
|
|
9
|
+
extend ActiveSupport::Concern
|
|
10
|
+
|
|
11
|
+
PLATFORMS = [J750, J750_HPT, UltraFLEX, V93K]
|
|
12
|
+
|
|
13
|
+
included do
|
|
14
|
+
Origen.add_interface(self)
|
|
15
|
+
include Generator::FlowControlAPI::Interface
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module ClassMethods
|
|
19
|
+
# Ensures that the correct generator is loaded before initialize is called
|
|
20
|
+
def new(*args, &block)
|
|
21
|
+
x = allocate
|
|
22
|
+
x._load_generator
|
|
23
|
+
x.send(:initialize, *args, &block)
|
|
24
|
+
x
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Returns true if the interface class supports the
|
|
28
|
+
# given tester instance
|
|
29
|
+
def supports?(tester_instance)
|
|
30
|
+
PLATFORMS.include?(tester_instance.class)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def initialize(options = {})
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def tester
|
|
38
|
+
Origen.tester
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def _load_generator
|
|
42
|
+
if tester.v93k?
|
|
43
|
+
class << self; include OrigenTesters::V93K::Generator; end
|
|
44
|
+
elsif tester.j750_hpt?
|
|
45
|
+
class << self; include OrigenTesters::J750_HPT::Generator; end
|
|
46
|
+
elsif tester.j750?
|
|
47
|
+
class << self; include OrigenTesters::J750::Generator; end
|
|
48
|
+
elsif tester.ultraflex?
|
|
49
|
+
class << self; include OrigenTesters::UltraFLEX::Generator; end
|
|
50
|
+
else
|
|
51
|
+
fail "The Testers::ProgramGenerators module does not support #{tester.class}!"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
module OrigenTesters
|
|
2
|
+
module SmartestBasedTester
|
|
3
|
+
autoload :Base, 'origen_testers/smartest_based_tester/base.rb'
|
|
4
|
+
autoload :V93K, 'origen_testers/smartest_based_tester/v93k.rb'
|
|
5
|
+
end
|
|
6
|
+
# Convenience/Legacy names without the SmartestBasedTester namespace
|
|
7
|
+
autoload :V93K, 'origen_testers/smartest_based_tester/v93k.rb'
|
|
8
|
+
end
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
module OrigenTesters
|
|
2
|
+
module SmartestBasedTester
|
|
3
|
+
class Base
|
|
4
|
+
include VectorBasedTester
|
|
5
|
+
|
|
6
|
+
# Returns a new J750 instance, normally there would only ever be one of these
|
|
7
|
+
# assigned to the global variable such as $tester by your target:
|
|
8
|
+
# $tester = J750.new
|
|
9
|
+
def initialize
|
|
10
|
+
@max_repeat_loop = 65_535
|
|
11
|
+
@min_repeat_loop = 17
|
|
12
|
+
@pat_extension = 'avc'
|
|
13
|
+
@compress = true
|
|
14
|
+
# @support_repeat_previous = true
|
|
15
|
+
@match_entries = 10
|
|
16
|
+
@name = 'v93k'
|
|
17
|
+
@comment_char = '#'
|
|
18
|
+
@level_period = true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Capture the pin data from a vector to the tester.
|
|
22
|
+
#
|
|
23
|
+
# This method uses the Digital Capture feature (Selective mode) of the V93000 to capture
|
|
24
|
+
# the data from the given pins on the previous vector.
|
|
25
|
+
# Note that is does not actually generate a new vector.
|
|
26
|
+
#
|
|
27
|
+
# Note also that any drive cycles on the target pins can also be captured, to avoid this
|
|
28
|
+
# the wavetable should be set up like this to infer a 'D' (Don't Capture) on vectors where
|
|
29
|
+
# the target pin is being used to drive data:
|
|
30
|
+
#
|
|
31
|
+
# PINS nvm_fail
|
|
32
|
+
# 0 d1:0 r1:D 0
|
|
33
|
+
# 1 d1:1 r1:D 1
|
|
34
|
+
# 2 r1:C Capt
|
|
35
|
+
# 3 r1:D NoCapt
|
|
36
|
+
#
|
|
37
|
+
# Sometimes when generating vectors within a loop you may want to apply a capture
|
|
38
|
+
# retrospectively to a previous vector, passing in an offset option will allow you
|
|
39
|
+
# to do this.
|
|
40
|
+
#
|
|
41
|
+
# ==== Examples
|
|
42
|
+
# $tester.cycle # This is the vector you want to capture
|
|
43
|
+
# $tester.store :pin => pin(:fail) # This applys the required opcode to the given pins
|
|
44
|
+
#
|
|
45
|
+
# $tester.cycle # This one gets captured
|
|
46
|
+
# $tester.cycle
|
|
47
|
+
# $tester.cycle
|
|
48
|
+
# $tester.store(:pin => pin(:fail), :offset => -2) # Just realized I need to capture that earlier vector
|
|
49
|
+
#
|
|
50
|
+
# # Capturing multiple pins:
|
|
51
|
+
# $tester.cycle
|
|
52
|
+
# $tester.store :pins => [pin(:fail), pin(:done)]
|
|
53
|
+
#
|
|
54
|
+
# Since the V93K store operates on a pin level (rather than vector level as on the J750)
|
|
55
|
+
# equivalent functionality can also be achieved by setting the store attribute of the pin
|
|
56
|
+
# itself prior to calling $tester.cycle.
|
|
57
|
+
# However it is recommended to use the tester API to do the store if cross-compatiblity with
|
|
58
|
+
# other platforms, such as the J750, is required.
|
|
59
|
+
def store(*pins)
|
|
60
|
+
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
|
61
|
+
options = { offset: 0
|
|
62
|
+
}.merge(options)
|
|
63
|
+
pins = pins.flatten.compact
|
|
64
|
+
if pins.empty?
|
|
65
|
+
fail 'For the V93K you must supply the pins to store/capture'
|
|
66
|
+
end
|
|
67
|
+
pins.each do |pin|
|
|
68
|
+
pin.restore_state do
|
|
69
|
+
pin.capture
|
|
70
|
+
update_vector_pin_val pin, offset: options[:offset]
|
|
71
|
+
last_vector(options[:offset]).dont_compress = true
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
alias_method :capture, :store
|
|
76
|
+
|
|
77
|
+
# Capture the next vector generated to HRAM
|
|
78
|
+
#
|
|
79
|
+
# This method applys a store vector (stv) opcode to the next vector to be generated,
|
|
80
|
+
# note that is does not actually generate a new vector.
|
|
81
|
+
#
|
|
82
|
+
# On J750 the pins argument is ignored since the tester only supports whole vector capture.
|
|
83
|
+
#
|
|
84
|
+
# @example
|
|
85
|
+
# $tester.store_next_cycle
|
|
86
|
+
# $tester.cycle # This is the vector that will be captured
|
|
87
|
+
def store_next_cycle(*pins)
|
|
88
|
+
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
|
89
|
+
options = {
|
|
90
|
+
}.merge(options)
|
|
91
|
+
pins = pins.flatten.compact
|
|
92
|
+
if pins.empty?
|
|
93
|
+
fail 'For the V93K you must supply the pins to store/capture'
|
|
94
|
+
end
|
|
95
|
+
pins.each { |pin| pin.save; pin.capture }
|
|
96
|
+
# Register this clean up function to be run after the next vector
|
|
97
|
+
# is generated, cool or what!
|
|
98
|
+
preset_next_vector do
|
|
99
|
+
pins.each(&:restore)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Start a subroutine.
|
|
104
|
+
#
|
|
105
|
+
# Generates a global subroutine label. Global is used to adhere to the best practice of
|
|
106
|
+
# containing all subroutines in dedicated patterns, e.g. global_subs.atp
|
|
107
|
+
#
|
|
108
|
+
# ==== Examples
|
|
109
|
+
# $tester.start_subroutine("wait_for_done")
|
|
110
|
+
# < generate your subroutine vectors here >
|
|
111
|
+
# $tester.end_subroutine
|
|
112
|
+
def start_subroutine(name)
|
|
113
|
+
local_subroutines << name.to_s.chomp unless local_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
|
|
114
|
+
# name += "_subr" unless name =~ /sub/
|
|
115
|
+
Pattern.open name: name, call_startup_callbacks: false, subroutine: true
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Ends the current subroutine that was started with a previous call to start_subroutine
|
|
119
|
+
def end_subroutine(_cond = false)
|
|
120
|
+
Pattern.close call_shutdown_callbacks: false, subroutine: true
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Call a subroutine.
|
|
124
|
+
#
|
|
125
|
+
# This calls a subroutine immediately following previous vector, it does not
|
|
126
|
+
# generate a new vector.
|
|
127
|
+
#
|
|
128
|
+
# Subroutines should always be called through this method as it ensures a running
|
|
129
|
+
# log of called subroutines is maintained and which then gets output in the pattern
|
|
130
|
+
# header to import the right dependencies.
|
|
131
|
+
#
|
|
132
|
+
# An offset option is available to make the call on earlier vectors.
|
|
133
|
+
#
|
|
134
|
+
# Repeated calls to the same subroutine will automatically be compressed unless
|
|
135
|
+
# option :suppress_repeated_calls is supplied and set to false. This means that for
|
|
136
|
+
# the common use case of calling a subroutine to implement an overlay the subroutine
|
|
137
|
+
# can be called for every bit that has the overlay and the pattern will automatically
|
|
138
|
+
# generate correctly.
|
|
139
|
+
#
|
|
140
|
+
# ==== Examples
|
|
141
|
+
# $tester.call_subroutine("mysub")
|
|
142
|
+
# $tester.call_subroutine("my_other_sub", :offset => -1)
|
|
143
|
+
def call_subroutine(name, options = {})
|
|
144
|
+
options = {
|
|
145
|
+
offset: 0,
|
|
146
|
+
suppress_repeated_calls: true
|
|
147
|
+
}.merge(options)
|
|
148
|
+
called_subroutines << name.to_s.chomp unless called_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
|
|
149
|
+
|
|
150
|
+
code = "SQPG JSUB #{name};"
|
|
151
|
+
if !options[:suppress_repeated_calls] ||
|
|
152
|
+
last_object != code
|
|
153
|
+
microcode code, offset: (options[:offset] * -1)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Handshake with the tester.
|
|
158
|
+
#
|
|
159
|
+
# ==== Examples
|
|
160
|
+
# $tester.handshake # Pass control to the tester for a measurement
|
|
161
|
+
def handshake(options = {})
|
|
162
|
+
options = {
|
|
163
|
+
}.merge(options)
|
|
164
|
+
Pattern.split(options)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Do a frequency measure.
|
|
168
|
+
#
|
|
169
|
+
# ==== Examples
|
|
170
|
+
# $tester.freq_count($top.pin(:d_out)) # Freq measure on pin "d_out"
|
|
171
|
+
def freq_count(_pin, options = {})
|
|
172
|
+
options = {
|
|
173
|
+
}.merge(options)
|
|
174
|
+
Pattern.split(options)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Generates a match loop on up to two pins.
|
|
178
|
+
#
|
|
179
|
+
# This method is not really intended to be called directly, rather you should call
|
|
180
|
+
# via Tester#wait e.g. $tester.wait(:match => true).
|
|
181
|
+
#
|
|
182
|
+
# The timeout should be provided in cycles, however when called via the wait method the
|
|
183
|
+
# time-based helpers (time_in_us, etc) will be converted to cycles for you.
|
|
184
|
+
# The following options are available to tailor the match loop behavior, defaults in
|
|
185
|
+
# parenthesis:
|
|
186
|
+
#
|
|
187
|
+
# * :pin - The pin object to match on (*required*)
|
|
188
|
+
# * :state - The pin state to match on, :low or :high (*required*)
|
|
189
|
+
# * :check_for_fails (false) - Flushes the pipeline and checks for fails prior to the match (to allow binout of fails encountered before the match)
|
|
190
|
+
# * :pin2 (nil) - Optionally supply a second pin to match on
|
|
191
|
+
# * :state2 (nil) - State for the second pin (required if :pin2 is supplied)
|
|
192
|
+
# * :force_fail_on_timeout (true) - Force a vector mis-compare if the match loop times out
|
|
193
|
+
#
|
|
194
|
+
# ==== Examples
|
|
195
|
+
# $tester.wait(:match => true, :time_in_us => 5000, :pin => $top.pin(:done), :state => :high)
|
|
196
|
+
def match(pin, state, timeout_in_cycles, options = {})
|
|
197
|
+
options = {
|
|
198
|
+
check_for_fails: false,
|
|
199
|
+
pin2: false,
|
|
200
|
+
state2: false,
|
|
201
|
+
force_fail_on_timeout: true,
|
|
202
|
+
global_loops: false,
|
|
203
|
+
generate_subroutine: false,
|
|
204
|
+
force_fail_on_timeout: true
|
|
205
|
+
}.merge(options)
|
|
206
|
+
|
|
207
|
+
# Ensure the match pins are don't care by default
|
|
208
|
+
pin.dont_care
|
|
209
|
+
options[:pin2].dont_care if options[:pin2]
|
|
210
|
+
|
|
211
|
+
# Single condition loops are simple
|
|
212
|
+
if !options[:pin2]
|
|
213
|
+
# Use the counted match loop (rather than timed) which is recommended in the V93K docs for new applications
|
|
214
|
+
# No pre-match failure handling is required here because the system will cleanly record failure info
|
|
215
|
+
# for this kind of match loop
|
|
216
|
+
cc "for the #{pin.name.upcase} pin to go #{state.to_s.upcase}"
|
|
217
|
+
# Need to ensure at least 8 cycles with no compares before entering
|
|
218
|
+
8.cycles
|
|
219
|
+
number_of_loops = (timeout_in_cycles.to_f / 72).ceil
|
|
220
|
+
# This seems to be a limit on the max MACT value, so account for longer times by expanding
|
|
221
|
+
# the wait loop
|
|
222
|
+
if number_of_loops > 262_144
|
|
223
|
+
mrpt = ((timeout_in_cycles.to_f / 262_144) - 8).ceil
|
|
224
|
+
mrpt = Math.sqrt(mrpt).ceil
|
|
225
|
+
mrpt += (8 - (mrpt % 8)) # Keep to a multiple of 8, but round up to be safe
|
|
226
|
+
number_of_loops = 262_144
|
|
227
|
+
else
|
|
228
|
+
mrpt = 8
|
|
229
|
+
end
|
|
230
|
+
microcode "SQPG MACT #{number_of_loops};"
|
|
231
|
+
# Strobe the pin for the required state
|
|
232
|
+
state == :low ? pin.expect_lo : pin.expect_hi
|
|
233
|
+
# Always do 8 vectors here as this allows reconstruction of test results if multiple loops
|
|
234
|
+
# are called in a pattern
|
|
235
|
+
8.cycles
|
|
236
|
+
pin.dont_care
|
|
237
|
+
# Now do the wait loop, mrpt should always be a multiple of 8
|
|
238
|
+
microcode "SQPG MRPT #{mrpt};"
|
|
239
|
+
mrpt.times do
|
|
240
|
+
cycle(dont_compress: true)
|
|
241
|
+
end
|
|
242
|
+
microcode 'SQPG PADDING;'
|
|
243
|
+
8.cycles
|
|
244
|
+
|
|
245
|
+
else
|
|
246
|
+
|
|
247
|
+
# For two pins do something more like the J750 approach where branching based on miscompares is used
|
|
248
|
+
# to keep the loop going
|
|
249
|
+
cc "for the #{pin.name.upcase} pin to go #{state.to_s.upcase}"
|
|
250
|
+
cc "or the #{options[:pin2].name.upcase} pin to go #{options[:state2].to_s.upcase}"
|
|
251
|
+
|
|
252
|
+
if options[:check_for_fails]
|
|
253
|
+
cc 'Return preserving existing errors if the pattern has already failed before arriving here'
|
|
254
|
+
cycle(repeat: propagation_delay)
|
|
255
|
+
microcode 'SQPG RETC 1 1;'
|
|
256
|
+
end
|
|
257
|
+
number_of_loops = (timeout_in_cycles.to_f / ((propagation_delay * 2) + 2)).ceil
|
|
258
|
+
|
|
259
|
+
loop_vectors number_of_loops do
|
|
260
|
+
# Check pin 1
|
|
261
|
+
cc "Check if #{pin.name.upcase} is #{state.to_s.upcase} yet"
|
|
262
|
+
state == :low ? pin.expect_lo! : pin.expect_hi!
|
|
263
|
+
pin.dont_care
|
|
264
|
+
cc 'Wait for failure to propagate'
|
|
265
|
+
cycle(repeat: propagation_delay)
|
|
266
|
+
cc 'Exit match loop if pin has matched (no error), otherwise clear error and remain in loop'
|
|
267
|
+
microcode 'SQPG RETC 0 0;'
|
|
268
|
+
|
|
269
|
+
# Check pin 2
|
|
270
|
+
cc "Check if #{options[:pin2].name.upcase} is #{options[:state2].to_s.upcase} yet"
|
|
271
|
+
options[:state2] == :low ? options[:pin2].expect_lo! : options[:pin2].expect_hi!
|
|
272
|
+
options[:pin2].dont_care
|
|
273
|
+
cc 'Wait for failure to propagate'
|
|
274
|
+
cycle(repeat: propagation_delay)
|
|
275
|
+
cc 'Exit match loop if pin has matched (no error), otherwise clear error and remain in loop'
|
|
276
|
+
microcode 'SQPG RETC 0 0;'
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
if options[:force_fail_on_timeout]
|
|
280
|
+
cc 'To get here something has gone wrong, strobe again to force a pattern failure'
|
|
281
|
+
state == :low ? pin.expect_lo : pin.expect_hi
|
|
282
|
+
options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi if options[:pin2]
|
|
283
|
+
cycle
|
|
284
|
+
pin.dont_care
|
|
285
|
+
options[:pin2].dont_care if options[:pin2]
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# Returns the number of cycles to wait for any fails to propagate through the pipeline based on
|
|
291
|
+
# the current timeset
|
|
292
|
+
def propagation_delay
|
|
293
|
+
# From 'Calculating the buffer cycles for JMPE and RETC (and match loops)' in SmarTest docs
|
|
294
|
+
data_queue_buffer = (([105, 64 + ((125 + current_period_in_ns - 1) / current_period_in_ns).ceil].min + 3) * 8) + 72
|
|
295
|
+
# Don't know how to calculate at runtime, hardcoding these to some default values for now
|
|
296
|
+
number_of_sites = 128
|
|
297
|
+
sclk_period = 40
|
|
298
|
+
prop_delay_buffer = 195 + ((2 * number_of_sites + 3) * (sclk_period / 2))
|
|
299
|
+
data_queue_buffer + prop_delay_buffer
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# Add a loop to the pattern.
|
|
303
|
+
#
|
|
304
|
+
# Pass in the number of times to execute it, all vectors
|
|
305
|
+
# generated by the given block will be captured in the loop.
|
|
306
|
+
#
|
|
307
|
+
# ==== Examples
|
|
308
|
+
# $tester.loop_vectors 3 do # Do this 3 times...
|
|
309
|
+
# $tester.cycle
|
|
310
|
+
# some_other_method_to_generate_vectors
|
|
311
|
+
# end
|
|
312
|
+
#
|
|
313
|
+
# For compatibility with the J750 you can supply a name as the first argument
|
|
314
|
+
# and that will simply be ignored when generated for the V93K tester...
|
|
315
|
+
#
|
|
316
|
+
# $tester.loop_vectors "my_loop", 3 do # Do this 3 times...
|
|
317
|
+
# $tester.cycle
|
|
318
|
+
# some_other_method_to_generate_vectors
|
|
319
|
+
# end
|
|
320
|
+
def loop_vectors(name = nil, number_of_loops = 1, _global = false)
|
|
321
|
+
# The name argument is present to maych J750 API, sort out the
|
|
322
|
+
unless name.is_a?(String)
|
|
323
|
+
name, number_of_loops, global = nil, name, number_of_loops
|
|
324
|
+
end
|
|
325
|
+
if number_of_loops > 1
|
|
326
|
+
microcode "SQPG LBGN #{number_of_loops};"
|
|
327
|
+
yield
|
|
328
|
+
microcode 'SQPG LEND;'
|
|
329
|
+
else
|
|
330
|
+
yield
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
alias_method :loop_vector, :loop_vectors
|
|
334
|
+
|
|
335
|
+
# An internal method called by Origen to create the pattern header
|
|
336
|
+
def pattern_header(options = {})
|
|
337
|
+
options = {
|
|
338
|
+
}.merge(options)
|
|
339
|
+
pin_list = ordered_pins.map do |p|
|
|
340
|
+
if Origen.app.pin_pattern_order.include?(p.id)
|
|
341
|
+
p.id.to_s.upcase # specified name overrides pin name
|
|
342
|
+
else
|
|
343
|
+
p.name.to_s.upcase
|
|
344
|
+
end
|
|
345
|
+
end.join(' ')
|
|
346
|
+
microcode "FORMAT #{pin_list};"
|
|
347
|
+
max_pin_name_length = ordered_pins.map(&:name).max { |a, b| a.length <=> b.length }.length
|
|
348
|
+
pin_widths = ordered_pins.map { |p| p.size - 1 }
|
|
349
|
+
|
|
350
|
+
max_pin_name_length.times do |i|
|
|
351
|
+
cc((' ' * 50) + ordered_pins.map.with_index { |p, x| ((p.name[i] || ' ') + ' ' * pin_widths[x]).gsub('_', '-') }.join(' '))
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# An internal method called by Origen to generate the pattern footer
|
|
356
|
+
def pattern_footer(options = {})
|
|
357
|
+
microcode 'SQPG STOP;' unless options[:subroutine]
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Returns an array of subroutines called while generating the current pattern
|
|
361
|
+
def called_subroutines
|
|
362
|
+
@called_subroutines ||= []
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
# Returns an array of subroutines created by the current pattern
|
|
366
|
+
def local_subroutines # :nodoc:
|
|
367
|
+
@local_subroutines ||= []
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# This is an internal method use by Origen which returns a fully formatted vector
|
|
371
|
+
# You can override this if you wish to change the output formatting at vector level
|
|
372
|
+
def format_vector(vec)
|
|
373
|
+
timeset = vec.timeset ? "#{vec.timeset.name}" : ''
|
|
374
|
+
pin_vals = vec.pin_vals ? "#{vec.pin_vals} ;" : ''
|
|
375
|
+
if vec.repeat # > 1
|
|
376
|
+
microcode = "R#{vec.repeat}"
|
|
377
|
+
else
|
|
378
|
+
microcode = vec.microcode ? vec.microcode : ''
|
|
379
|
+
end
|
|
380
|
+
if vec.pin_vals && ($_testers_enable_vector_comments || vector_comments)
|
|
381
|
+
comment = " # #{vec.number}:#{vec.cycle} #{vec.inline_comment}"
|
|
382
|
+
else
|
|
383
|
+
comment = vec.inline_comment.empty? ? '' : " # #{vec.inline_comment}"
|
|
384
|
+
end
|
|
385
|
+
"#{microcode.ljust(25)}#{timeset.ljust(27)}#{pin_vals}#{comment}"
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# All vectors generated with the supplied block will have all pins set
|
|
389
|
+
# to the repeat previous state. Any pins that are changed state within
|
|
390
|
+
# the block will still update to the supplied value.
|
|
391
|
+
# ==== Example
|
|
392
|
+
# # All pins except invoke will be assigned the repeat previous code
|
|
393
|
+
# # in the generated vector. On completion of the block they will
|
|
394
|
+
# # return to their previous state, except for invoke which will
|
|
395
|
+
# # retain the value assigned within the block.
|
|
396
|
+
# $tester.repeat_previous do
|
|
397
|
+
# $top.pin(:invoke).drive(1)
|
|
398
|
+
# $tester.cycle
|
|
399
|
+
# end
|
|
400
|
+
def repeat_previous
|
|
401
|
+
Origen.app.pin_map.each { |_id, pin| pin.repeat_previous = true }
|
|
402
|
+
yield
|
|
403
|
+
Origen.app.pin_map.each { |_id, pin| pin.repeat_previous = false }
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def before_timeset_change(options = {})
|
|
407
|
+
microcode "SQPG CTIM #{options[:new].name};" unless level_period?
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
end
|