origen_testers 0.13.1 → 0.13.2
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 +4 -4
- data/config/application.rb +151 -151
- data/config/boot.rb +13 -13
- data/config/commands.rb +85 -86
- data/config/users.rb +18 -18
- data/config/version.rb +8 -8
- data/lib/commands/build.rb +69 -69
- data/lib/commands/run.rb +48 -48
- data/lib/origen_testers.rb +47 -47
- data/lib/origen_testers/api.rb +381 -381
- data/lib/origen_testers/basic_test_setups.rb +105 -105
- data/lib/origen_testers/callback_handlers.rb +59 -59
- data/lib/origen_testers/command_based_tester.rb +45 -45
- data/lib/origen_testers/flow.rb +382 -382
- data/lib/origen_testers/generator.rb +283 -283
- data/lib/origen_testers/generator/identity_map.rb +23 -23
- data/lib/origen_testers/generator/placeholder.rb +11 -11
- data/lib/origen_testers/generator/test_numberer.rb +23 -23
- data/lib/origen_testers/igxl_based_tester.rb +12 -12
- data/lib/origen_testers/igxl_based_tester/base.rb +1100 -1099
- data/lib/origen_testers/igxl_based_tester/base/ac_specsets.rb +79 -79
- data/lib/origen_testers/igxl_based_tester/base/custom_test_instance.rb +169 -169
- data/lib/origen_testers/igxl_based_tester/base/dc_specsets.rb +98 -98
- data/lib/origen_testers/igxl_based_tester/base/edge.rb +60 -60
- data/lib/origen_testers/igxl_based_tester/base/edges.rb +24 -24
- data/lib/origen_testers/igxl_based_tester/base/edgeset.rb +39 -39
- data/lib/origen_testers/igxl_based_tester/base/edgesets.rb +130 -130
- data/lib/origen_testers/igxl_based_tester/base/flow.rb +460 -460
- data/lib/origen_testers/igxl_based_tester/base/flow_line.rb +276 -276
- data/lib/origen_testers/igxl_based_tester/base/generator.rb +607 -607
- data/lib/origen_testers/igxl_based_tester/base/global_specs.rb +83 -83
- data/lib/origen_testers/igxl_based_tester/base/job.rb +75 -75
- data/lib/origen_testers/igxl_based_tester/base/jobs.rb +44 -44
- data/lib/origen_testers/igxl_based_tester/base/level_io_se.rb +59 -59
- data/lib/origen_testers/igxl_based_tester/base/level_supply.rb +39 -39
- data/lib/origen_testers/igxl_based_tester/base/levels.rb +31 -31
- data/lib/origen_testers/igxl_based_tester/base/levelset.rb +110 -110
- data/lib/origen_testers/igxl_based_tester/base/patgroup.rb +109 -109
- data/lib/origen_testers/igxl_based_tester/base/patgroups.rb +38 -38
- data/lib/origen_testers/igxl_based_tester/base/patset.rb +68 -68
- data/lib/origen_testers/igxl_based_tester/base/patset_pattern.rb +56 -56
- data/lib/origen_testers/igxl_based_tester/base/patsets.rb +38 -38
- data/lib/origen_testers/igxl_based_tester/base/patsubr.rb +68 -68
- data/lib/origen_testers/igxl_based_tester/base/patsubr_pattern.rb +56 -56
- data/lib/origen_testers/igxl_based_tester/base/patsubrs.rb +38 -38
- data/lib/origen_testers/igxl_based_tester/base/pinmap.rb +93 -93
- data/lib/origen_testers/igxl_based_tester/base/references.rb +25 -25
- data/lib/origen_testers/igxl_based_tester/base/test_instance.rb +322 -322
- data/lib/origen_testers/igxl_based_tester/base/test_instance_group.rb +66 -66
- data/lib/origen_testers/igxl_based_tester/base/test_instances.rb +212 -212
- data/lib/origen_testers/igxl_based_tester/base/test_instances/custom_til.rb +37 -37
- data/lib/origen_testers/igxl_based_tester/base/timeset.rb +37 -37
- data/lib/origen_testers/igxl_based_tester/base/timesets.rb +49 -49
- data/lib/origen_testers/igxl_based_tester/base/timesets_basic.rb +49 -49
- data/lib/origen_testers/igxl_based_tester/files.rb +43 -43
- data/lib/origen_testers/igxl_based_tester/j750.rb +269 -269
- data/lib/origen_testers/igxl_based_tester/j750/custom_test_instance.rb +32 -32
- data/lib/origen_testers/igxl_based_tester/j750/flow.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/j750/flow_line.rb +19 -19
- data/lib/origen_testers/igxl_based_tester/j750/generator.rb +19 -19
- data/lib/origen_testers/igxl_based_tester/j750/patgroup.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750/patgroups.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/j750/patset.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750/patset_pattern.rb +18 -18
- data/lib/origen_testers/igxl_based_tester/j750/patsets.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/j750/patsubr.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750/patsubr_pattern.rb +18 -18
- data/lib/origen_testers/igxl_based_tester/j750/patsubrs.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/j750/test_instance.rb +746 -746
- data/lib/origen_testers/igxl_based_tester/j750/test_instance_group.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750/test_instances.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/j750_hpt.rb +34 -34
- data/lib/origen_testers/igxl_based_tester/j750_hpt/custom_test_instance.rb +32 -32
- data/lib/origen_testers/igxl_based_tester/j750_hpt/flow.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750_hpt/flow_line.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750_hpt/generator.rb +19 -19
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patgroup.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patgroups.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patset.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patset_pattern.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patsets.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubr.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubr_pattern.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750_hpt/patsubrs.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instance.rb +599 -599
- data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instance_group.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/j750_hpt/test_instances.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/parser.rb +102 -102
- data/lib/origen_testers/igxl_based_tester/parser/ac_spec.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/parser/dc_spec.rb +33 -33
- data/lib/origen_testers/igxl_based_tester/parser/dc_specs.rb +48 -48
- data/lib/origen_testers/igxl_based_tester/parser/descriptions.rb +339 -339
- data/lib/origen_testers/igxl_based_tester/parser/flow.rb +109 -109
- data/lib/origen_testers/igxl_based_tester/parser/flow_line.rb +203 -203
- data/lib/origen_testers/igxl_based_tester/parser/flows.rb +21 -21
- data/lib/origen_testers/igxl_based_tester/parser/pattern_set.rb +92 -92
- data/lib/origen_testers/igxl_based_tester/parser/pattern_sets.rb +31 -31
- data/lib/origen_testers/igxl_based_tester/parser/test_instance.rb +420 -420
- data/lib/origen_testers/igxl_based_tester/parser/test_instances.rb +24 -24
- data/lib/origen_testers/igxl_based_tester/parser/timeset.rb +13 -13
- data/lib/origen_testers/igxl_based_tester/ultraflex.rb +798 -798
- data/lib/origen_testers/igxl_based_tester/ultraflex/ac_specsets.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/ultraflex/ate_hardware.rb +949 -949
- data/lib/origen_testers/igxl_based_tester/ultraflex/custom_test_instance.rb +36 -36
- data/lib/origen_testers/igxl_based_tester/ultraflex/dc_specsets.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/ultraflex/edge.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/ultraflex/edges.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/ultraflex/edgeset.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/ultraflex/edgesets.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/ultraflex/flow.rb +158 -158
- data/lib/origen_testers/igxl_based_tester/ultraflex/flow_line.rb +19 -19
- data/lib/origen_testers/igxl_based_tester/ultraflex/generator.rb +19 -19
- data/lib/origen_testers/igxl_based_tester/ultraflex/global_specs.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/ultraflex/job.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/ultraflex/jobs.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/ultraflex/level_io_se.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/ultraflex/level_supply.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/ultraflex/levels.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/ultraflex/levelset.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/ultraflex/patgroup.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/ultraflex/patgroups.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/ultraflex/patset.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/ultraflex/patset_pattern.rb +18 -18
- data/lib/origen_testers/igxl_based_tester/ultraflex/patsets.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/ultraflex/patsubr.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/ultraflex/patsubr_pattern.rb +18 -18
- data/lib/origen_testers/igxl_based_tester/ultraflex/patsubrs.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/ultraflex/pinmap.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/ultraflex/references.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/ac_specsets.txt.erb +0 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/dc_specsets.txt.erb +0 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/edgesets.txt.erb +0 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/global_specs.txt.erb +0 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/jobs.txt.erb +0 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/levelset.txt.erb +0 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/pinmap.txt.erb +0 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/references.txt.erb +0 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/timesets.txt.erb +0 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/templates/timesets_basic.txt.erb +0 -0
- data/lib/origen_testers/igxl_based_tester/ultraflex/test_instance.rb +315 -315
- data/lib/origen_testers/igxl_based_tester/ultraflex/test_instance_group.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/ultraflex/test_instances.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/ultraflex/timeset.rb +9 -9
- data/lib/origen_testers/igxl_based_tester/ultraflex/timesets.rb +10 -10
- data/lib/origen_testers/igxl_based_tester/ultraflex/timesets_basic.rb +10 -10
- data/lib/origen_testers/interface.rb +345 -324
- data/lib/origen_testers/memory_style.rb +77 -77
- data/lib/origen_testers/no_interface.rb +7 -7
- data/lib/origen_testers/origen_ext/application/runner.rb +25 -25
- data/lib/origen_testers/origen_ext/generator.rb +54 -54
- data/lib/origen_testers/origen_ext/generator/flow.rb +91 -77
- data/lib/origen_testers/origen_ext/generator/resources.rb +21 -21
- data/lib/origen_testers/origen_ext/pins/pin.rb +78 -78
- data/lib/origen_testers/origen_ext/pins/pin_collection.rb +84 -84
- data/lib/origen_testers/parser.rb +22 -22
- data/lib/origen_testers/parser/description_lookup.rb +62 -62
- data/lib/origen_testers/parser/searchable_array.rb +30 -30
- data/lib/origen_testers/parser/searchable_hash.rb +30 -30
- data/lib/origen_testers/pattern_compilers.rb +116 -116
- data/lib/origen_testers/pattern_compilers/assembler.rb +88 -88
- data/lib/origen_testers/pattern_compilers/job.rb +96 -96
- data/lib/origen_testers/pattern_compilers/ultraflex_pattern_compiler.rb +599 -599
- data/lib/origen_testers/program_generators.rb +62 -62
- data/lib/origen_testers/smartest_based_tester.rb +8 -8
- data/lib/origen_testers/smartest_based_tester/base.rb +576 -567
- data/lib/origen_testers/smartest_based_tester/base/flow.rb +296 -291
- data/lib/origen_testers/smartest_based_tester/base/generator.rb +207 -194
- data/lib/origen_testers/smartest_based_tester/base/pattern_compiler.rb +32 -32
- data/lib/origen_testers/smartest_based_tester/base/pattern_master.rb +69 -69
- data/lib/origen_testers/smartest_based_tester/base/processors.rb +16 -16
- data/lib/origen_testers/smartest_based_tester/base/processors/adjacent_if_combiner.rb +106 -106
- data/lib/origen_testers/smartest_based_tester/base/processors/continue_implementer.rb +39 -39
- data/lib/origen_testers/smartest_based_tester/base/processors/empty_branch_cleaner.rb +21 -21
- data/lib/origen_testers/smartest_based_tester/base/processors/extract_run_flag_table.rb +33 -33
- data/lib/origen_testers/smartest_based_tester/base/processors/extract_set_variables.rb +22 -22
- data/lib/origen_testers/smartest_based_tester/base/processors/flag_optimizer.rb +188 -188
- data/lib/origen_testers/smartest_based_tester/base/processors/if_ran_cleaner.rb +34 -34
- data/lib/origen_testers/smartest_based_tester/base/test_method.rb +178 -164
- data/lib/origen_testers/smartest_based_tester/base/test_methods.rb +77 -73
- data/lib/origen_testers/smartest_based_tester/base/test_methods/ac_tml.rb +33 -33
- data/lib/origen_testers/smartest_based_tester/base/test_methods/base_tml.rb +38 -38
- data/lib/origen_testers/smartest_based_tester/base/test_methods/custom_tml.rb +19 -19
- data/lib/origen_testers/smartest_based_tester/base/test_methods/dc_tml.rb +147 -147
- data/lib/origen_testers/smartest_based_tester/base/test_methods/limits.rb +65 -65
- data/lib/origen_testers/smartest_based_tester/base/test_suite.rb +208 -193
- data/lib/origen_testers/smartest_based_tester/base/test_suites.rb +58 -54
- data/lib/origen_testers/smartest_based_tester/base/variables_file.rb +38 -38
- data/lib/origen_testers/smartest_based_tester/v93k.rb +8 -8
- data/lib/origen_testers/smartest_based_tester/v93k/builder.rb +89 -89
- data/lib/origen_testers/smartest_based_tester/v93k/builder/flow.rb +181 -181
- data/lib/origen_testers/smartest_based_tester/v93k/builder/pattern_master.rb +54 -54
- data/lib/origen_testers/smartest_based_tester/v93k/flow.rb +10 -10
- data/lib/origen_testers/smartest_based_tester/v93k/generator.rb +19 -19
- data/lib/origen_testers/smartest_based_tester/v93k/pattern_compiler.rb +10 -10
- data/lib/origen_testers/smartest_based_tester/v93k/pattern_master.rb +10 -10
- data/lib/origen_testers/smartest_based_tester/v93k/templates/template.aiv.erb +17 -17
- data/lib/origen_testers/smartest_based_tester/v93k/templates/template.pmfl.erb +13 -13
- data/lib/origen_testers/smartest_based_tester/v93k/templates/template.tf.erb +236 -214
- data/lib/origen_testers/smartest_based_tester/v93k/templates/vars.tf.erb +48 -48
- data/lib/origen_testers/smartest_based_tester/v93k/test_method.rb +9 -9
- data/lib/origen_testers/smartest_based_tester/v93k/test_methods.rb +9 -9
- data/lib/origen_testers/smartest_based_tester/v93k/test_suite.rb +9 -9
- data/lib/origen_testers/smartest_based_tester/v93k/test_suites.rb +9 -9
- data/lib/origen_testers/smartest_based_tester/v93k/variables_file.rb +10 -10
- data/lib/origen_testers/test/basic_interface.rb +17 -17
- data/lib/origen_testers/test/block.rb +21 -21
- data/lib/origen_testers/test/custom_test_interface.rb +111 -111
- data/lib/origen_testers/test/dut.rb +295 -295
- data/lib/origen_testers/test/dut2.rb +76 -76
- data/lib/origen_testers/test/dut3.rb +244 -244
- data/lib/origen_testers/test/interface.rb +503 -503
- data/lib/origen_testers/test/nvm.rb +94 -94
- data/lib/origen_testers/timing.rb +368 -368
- data/lib/origen_testers/vector.rb +207 -207
- data/lib/origen_testers/vector_based_tester.rb +41 -41
- data/lib/origen_testers/vector_generator.rb +655 -655
- data/lib/origen_testers/vector_pipeline.rb +302 -302
- data/pattern/bitmap.rb +7 -7
- data/pattern/dc_instr.rb +7 -7
- data/pattern/delay.rb +7 -7
- data/pattern/freq_counter.rb +6 -6
- data/pattern/mem_test.rb +8 -8
- data/pattern/multi_vector.rb +122 -122
- data/pattern/multi_vector_plus1.rb +125 -125
- data/pattern/nvm/j750/add_late_pins.rb +3 -3
- data/pattern/nvm/j750/iterator_postfix_test_x_bx.rb +8 -8
- data/pattern/nvm/j750/iterator_test_x_bx.rb +8 -8
- data/pattern/nvm/j750/j750_halt.rb +159 -159
- data/pattern/nvm/j750/j750_workout.rb +209 -209
- data/pattern/nvm/j750/timing.rb +73 -73
- data/pattern/read_write_reg.rb +61 -61
- data/pattern/reset.rb +4 -4
- data/pattern/subroutines.rb +69 -69
- data/pattern/tester_overlay.rb +61 -52
- data/pattern/tester_store.rb +28 -28
- data/program/_additional_erase.rb +7 -7
- data/program/_efa_resources.rb +7 -7
- data/program/_erase.rb +25 -25
- data/program/_erase_vfy.rb +5 -5
- data/program/_iv_resources.rb +10 -10
- data/program/basic_interface.rb +5 -5
- data/program/components/_prb1_main.rb +222 -222
- data/program/components/_temp.rb +6 -6
- data/program/custom_tests.rb +10 -10
- data/program/flow_control.rb +422 -422
- data/program/prb1.rb +11 -11
- data/program/prb1_resources.rb +28 -28
- data/program/prb2.rb +27 -27
- data/program/test.rb +29 -29
- data/program/uflex_resources.rb +199 -199
- data/templates/example.txt.erb +53 -53
- data/templates/j750/program_sheet.txt.erb +9 -9
- data/templates/manifest/v93k.yaml.erb +22 -22
- data/templates/web/index.md.erb +51 -51
- data/templates/web/layouts/_basic.html.erb +15 -15
- data/templates/web/partials/_navbar.html.erb +22 -22
- data/templates/web/release_notes.md.erb +5 -5
- metadata +2 -2
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
module OrigenTesters
|
|
2
|
-
module Generator
|
|
3
|
-
class IdentityMap
|
|
4
|
-
def initialize
|
|
5
|
-
@store = {}
|
|
6
|
-
@versions = {}
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def current_version_of(obj)
|
|
10
|
-
map = map_for(obj)
|
|
11
|
-
if map
|
|
12
|
-
map[:replaced_by] || map[:instance]
|
|
13
|
-
else
|
|
14
|
-
obj
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def map_for(obj)
|
|
19
|
-
@store[obj.object_id]
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
1
|
+
module OrigenTesters
|
|
2
|
+
module Generator
|
|
3
|
+
class IdentityMap
|
|
4
|
+
def initialize
|
|
5
|
+
@store = {}
|
|
6
|
+
@versions = {}
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def current_version_of(obj)
|
|
10
|
+
map = map_for(obj)
|
|
11
|
+
if map
|
|
12
|
+
map[:replaced_by] || map[:instance]
|
|
13
|
+
else
|
|
14
|
+
obj
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def map_for(obj)
|
|
19
|
+
@store[obj.object_id]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
module OrigenTesters
|
|
2
|
-
module Generator
|
|
3
|
-
class Placeholder
|
|
4
|
-
attr_accessor :type, :file, :options, :id
|
|
5
|
-
|
|
6
|
-
def initialize(type, file, options = {})
|
|
7
|
-
@type, @file, @options = type, file, options
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
end
|
|
1
|
+
module OrigenTesters
|
|
2
|
+
module Generator
|
|
3
|
+
class Placeholder
|
|
4
|
+
attr_accessor :type, :file, :options, :id
|
|
5
|
+
|
|
6
|
+
def initialize(type, file, options = {})
|
|
7
|
+
@type, @file, @options = type, file, options
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
module OrigenTesters
|
|
2
|
-
module Generator
|
|
3
|
-
class TestNumberer
|
|
4
|
-
# Will return a test number for the given test.
|
|
5
|
-
#
|
|
6
|
-
# @param [Hash] options Options to customize the number generation
|
|
7
|
-
# @option options [Integer] :bits (6) The number of bits in the DAC code
|
|
8
|
-
# @option options [Float] :range (1.26) The range parameter, see code formula
|
|
9
|
-
# @option options [Integer] :offset (0) The o
|
|
10
|
-
def test_number_for(test_name, options = {})
|
|
11
|
-
options = {
|
|
12
|
-
|
|
13
|
-
}.merge(options)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
private
|
|
17
|
-
|
|
18
|
-
def store_file
|
|
19
|
-
@store_file ||= Pathname.new "#{Origen.root}/.test_program/test_numbers"
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
1
|
+
module OrigenTesters
|
|
2
|
+
module Generator
|
|
3
|
+
class TestNumberer
|
|
4
|
+
# Will return a test number for the given test.
|
|
5
|
+
#
|
|
6
|
+
# @param [Hash] options Options to customize the number generation
|
|
7
|
+
# @option options [Integer] :bits (6) The number of bits in the DAC code
|
|
8
|
+
# @option options [Float] :range (1.26) The range parameter, see code formula
|
|
9
|
+
# @option options [Integer] :offset (0) The o
|
|
10
|
+
def test_number_for(test_name, options = {})
|
|
11
|
+
options = {
|
|
12
|
+
|
|
13
|
+
}.merge(options)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def store_file
|
|
19
|
+
@store_file ||= Pathname.new "#{Origen.root}/.test_program/test_numbers"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
module OrigenTesters
|
|
2
|
-
module IGXLBasedTester
|
|
3
|
-
autoload :Base, 'origen_testers/igxl_based_tester/base.rb'
|
|
4
|
-
autoload :J750, 'origen_testers/igxl_based_tester/j750.rb'
|
|
5
|
-
autoload :J750_HPT, 'origen_testers/igxl_based_tester/j750_hpt.rb'
|
|
6
|
-
autoload :UltraFLEX, 'origen_testers/igxl_based_tester/ultraflex.rb'
|
|
7
|
-
end
|
|
8
|
-
# Convenience/Legacy names without the IGXLBasedTester namespace
|
|
9
|
-
autoload :J750, 'origen_testers/igxl_based_tester/j750.rb'
|
|
10
|
-
autoload :J750_HPT, 'origen_testers/igxl_based_tester/j750_hpt.rb'
|
|
11
|
-
autoload :UltraFLEX, 'origen_testers/igxl_based_tester/ultraflex.rb'
|
|
12
|
-
end
|
|
1
|
+
module OrigenTesters
|
|
2
|
+
module IGXLBasedTester
|
|
3
|
+
autoload :Base, 'origen_testers/igxl_based_tester/base.rb'
|
|
4
|
+
autoload :J750, 'origen_testers/igxl_based_tester/j750.rb'
|
|
5
|
+
autoload :J750_HPT, 'origen_testers/igxl_based_tester/j750_hpt.rb'
|
|
6
|
+
autoload :UltraFLEX, 'origen_testers/igxl_based_tester/ultraflex.rb'
|
|
7
|
+
end
|
|
8
|
+
# Convenience/Legacy names without the IGXLBasedTester namespace
|
|
9
|
+
autoload :J750, 'origen_testers/igxl_based_tester/j750.rb'
|
|
10
|
+
autoload :J750_HPT, 'origen_testers/igxl_based_tester/j750_hpt.rb'
|
|
11
|
+
autoload :UltraFLEX, 'origen_testers/igxl_based_tester/ultraflex.rb'
|
|
12
|
+
end
|
|
@@ -1,1099 +1,1100 @@
|
|
|
1
|
-
module OrigenTesters
|
|
2
|
-
module IGXLBasedTester
|
|
3
|
-
# This is the base class of all IGXL-based testers
|
|
4
|
-
class Base
|
|
5
|
-
include VectorBasedTester
|
|
6
|
-
|
|
7
|
-
attr_accessor :software_version
|
|
8
|
-
attr_accessor :pattern_compiler_pinmap
|
|
9
|
-
attr_accessor :memory_test_en
|
|
10
|
-
attr_accessor :testerconfig
|
|
11
|
-
attr_accessor :channelmap
|
|
12
|
-
attr_accessor :default_channelmap
|
|
13
|
-
attr_accessor :default_testerconfig
|
|
14
|
-
attr_accessor :max_site
|
|
15
|
-
# permit modification of minimum repeat count
|
|
16
|
-
attr_accessor :min_repeat_loop
|
|
17
|
-
alias_method :min_repeat_count, :min_repeat_loop
|
|
18
|
-
alias_method :min_repeat_count=, :min_repeat_loop=
|
|
19
|
-
# NOTE: DO NOT USE THIS CLASS DIRECTLY ONLY USED AS PARENT FOR
|
|
20
|
-
# DESIRED TESTER CLASS
|
|
21
|
-
|
|
22
|
-
# Returns a new IGXLBasedTester instance, normally there would only ever be one of these
|
|
23
|
-
# assigned to the global variable such as $tester by your target.
|
|
24
|
-
def initialize
|
|
25
|
-
@unique_counter = 0
|
|
26
|
-
@counter_lsb_bits = 0
|
|
27
|
-
@counter_msb_bits = 0
|
|
28
|
-
@max_repeat_loop = 65_535 # 16 bits
|
|
29
|
-
@min_repeat_loop = 2
|
|
30
|
-
@pat_extension = 'atp'
|
|
31
|
-
@active_loads = true
|
|
32
|
-
@pipeline_depth = 34
|
|
33
|
-
@software_version = ''
|
|
34
|
-
@compress = true
|
|
35
|
-
@support_repeat_previous = true
|
|
36
|
-
@match_entries = 10
|
|
37
|
-
@name = ''
|
|
38
|
-
@program_comment_char = ['logprint', "'"]
|
|
39
|
-
@opcode_mode = :extended
|
|
40
|
-
@flags = %w(cpuA cpuB cpuC cpuD)
|
|
41
|
-
@microcode = {}
|
|
42
|
-
@microcode[:enable] = 'enable'
|
|
43
|
-
@microcode[:set_flag] = 'set_cpu'
|
|
44
|
-
@microcode[:mask_vector] = 'ign ifc icc'
|
|
45
|
-
|
|
46
|
-
@mask_vector = false # sticky option to mask all subsequent vectors
|
|
47
|
-
|
|
48
|
-
@min_pattern_vectors = 0 # no minimum
|
|
49
|
-
|
|
50
|
-
@memory_test_en = false # memory test enabled (for all patterns?)
|
|
51
|
-
|
|
52
|
-
@testerconfig ||= {}
|
|
53
|
-
@channelmap ||= {}
|
|
54
|
-
@pushed_instrument_configs = {}
|
|
55
|
-
@overlay_style = :subroutine # default to use subroutine for overlay
|
|
56
|
-
@capture_style = :hram # default to use hram for capture
|
|
57
|
-
@overlay_history = {} # used to track labels, subroutines, digsrc pins used etc
|
|
58
|
-
@overlay_subr = nil
|
|
59
|
-
@capture_history = {}
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def igxl_based?
|
|
63
|
-
true
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def import_tester_config(testconfigname, fullconfigpath)
|
|
67
|
-
# This function reads in CurrentConfig.txt file generated by IG-XL.
|
|
68
|
-
# testconfigname example ==> "FT", "WT", "Production"
|
|
69
|
-
# fullconfigpath example ==> "/product_folder/CurrentConfig.txt"
|
|
70
|
-
|
|
71
|
-
puts "importing Testerconfig #{testconfigname}..."
|
|
72
|
-
slotnum = Struct.new(:slot, :instrument, :idprom)
|
|
73
|
-
@testerconfig[testconfigname] ||= {}
|
|
74
|
-
current_config_file = Pathname.new(fullconfigpath)
|
|
75
|
-
File.open(current_config_file, 'r').each_line do |line|
|
|
76
|
-
if line =~ /^\d*.0/
|
|
77
|
-
(slot, blank1, instrument, blank2, idprom) = line.split(/\t/)
|
|
78
|
-
if (!slot.nil?) && (!instrument.nil?) && (!idprom.nil?)
|
|
79
|
-
@testerconfig[testconfigname][slot.split('.').first.to_i] = slotnum.new(slot.split('.').first.to_i, instrument, idprom.chomp)
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
@default_testerconfig ||= testconfigname # Default TesterConfig gets set if it's not nil
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def get_tester_instrument(testconfigname, slot)
|
|
88
|
-
@testerconfig[testconfigname].each_with_index do |element, index|
|
|
89
|
-
if slot.to_s == element[0].to_s
|
|
90
|
-
return element[1][:instrument]
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
nil # if no corresponding slot
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def get_instrument_slots(testconfigname, instrument) # testconfigname example "WT", "FT", "Production"
|
|
97
|
-
@slots = []
|
|
98
|
-
@testerconfig[testconfigname].each_with_index do |element, index|
|
|
99
|
-
if instrument.to_s == element[1][:instrument].to_s
|
|
100
|
-
@slots << element[0].to_i
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
@slots # if no corresponding slot
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def import_chanmap(chanmapname, fullchanmappath)
|
|
107
|
-
# This function reads IG-XL ChannelMap file
|
|
108
|
-
# chanmapname example ==> "FT", "WT", "FTX2"
|
|
109
|
-
# fullchanmappath example ==> "/product_folder/Chans_FT.txt"
|
|
110
|
-
|
|
111
|
-
puts "importing ChannelMap #{fullchanmappath}..."
|
|
112
|
-
|
|
113
|
-
chanassignment = Struct.new(:pinname, :site, :channel, :type, :packagepin)
|
|
114
|
-
chanmap_file = Pathname.new(fullchanmappath)
|
|
115
|
-
@channelmap[chanmapname] ||= {}
|
|
116
|
-
File.open(chanmap_file, 'r').each_line.with_index do |line, index|
|
|
117
|
-
if index == 0
|
|
118
|
-
unless line =~ /DTChanMap/
|
|
119
|
-
puts "#{fullchanmappath} is not a valid IG-XL ChannelMap!"
|
|
120
|
-
break
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
if index == 5
|
|
124
|
-
siteloc = line.strip.split(/\t/).size - 1 # strip all white spaces and grab second to last
|
|
125
|
-
@max_site_s = line.split(/\t/)[siteloc].strip.split(/\s/)[1]
|
|
126
|
-
@max_site = @max_site_s.to_i
|
|
127
|
-
(0..@max_site).each do |sitenum|
|
|
128
|
-
@channelmap[chanmapname][sitenum] ||= {}
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
if index > 5
|
|
132
|
-
(blank1, pinname, packagepin, type) = line.split(/\t/)
|
|
133
|
-
(0..@max_site).each do |sitenum|
|
|
134
|
-
channel = line.split(/\t/)[4 + sitenum].to_s
|
|
135
|
-
@channelmap[chanmapname][sitenum][pinname.downcase.intern] = chanassignment.new(pinname.downcase.intern, sitenum, channel.chomp, type.chomp, packagepin)
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
@default_channelmap ||= chanmapname # Default Channelmap gets set if it's not nil
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def get_tester_channel(chanmapname, pinname, sitenum)
|
|
143
|
-
if sitenum <= @max_site
|
|
144
|
-
@testerchannel = @channelmap[chanmapname][sitenum][pinname].channel
|
|
145
|
-
return @testerchannel
|
|
146
|
-
else
|
|
147
|
-
return nil
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
# Check if a specific pin for a given channelmap for a given site number is using merged channel.
|
|
152
|
-
# If yes, return x2 for Merged2, x4 for Merged4, etc. If no, return nil.
|
|
153
|
-
def merged_channels(chanmapname, pinname, sitenum)
|
|
154
|
-
if sitenum <= @max_site
|
|
155
|
-
if @channelmap[chanmapname][sitenum][pinname].type.include?('Merged')
|
|
156
|
-
@merged_channels = @channelmap[chanmapname][sitenum][pinname].type.split('Merged')[1]
|
|
157
|
-
return 'x' + @merged_channels
|
|
158
|
-
end
|
|
159
|
-
else
|
|
160
|
-
return nil
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
# Check if a specific HexVS supply is HexVS+ variety, which has +/-2mV accuracy as opposed to
|
|
165
|
-
# +/-7mV accuracy.
|
|
166
|
-
# If the specific HexVS is HexVS+ variety, returns a "+" string, otherwise nil.
|
|
167
|
-
def is_hexvs_plus(testconfigname, slot)
|
|
168
|
-
if @testerconfig[testconfigname][slot][:instrument].to_s == 'HexVS'
|
|
169
|
-
@productnum = @testerconfig[testconfigname][slot][:idprom].split(' ')[0]
|
|
170
|
-
if (@productnum.include?('974-294-')) && (@productnum.split('-')[2].to_i >= 20)
|
|
171
|
-
return '+'
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
nil # if nothing matched
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
# Check if a specific VHDVS (UVS256) supply is High-Accuracy (HA) variety, which has +/-5mV+0.1%*SUPPLY accuracy as opposed to
|
|
178
|
-
# +/-10mV+0.1%*SUPPLY accuracy.
|
|
179
|
-
# If the specific VHDVS is of High-Accuracy variety, returns a "+" string, otherwise nil.
|
|
180
|
-
def is_vhdvs_plus(testconfigname, slot)
|
|
181
|
-
if @testerconfig[testconfigname][slot][:instrument].to_s == 'VHDVS'
|
|
182
|
-
@productnum = @testerconfig[testconfigname][slot][:idprom].split(' ')[0]
|
|
183
|
-
# binding.pry
|
|
184
|
-
if (@productnum.include?('805-052-')) && (@productnum.split('-')[2].to_i >= 05)
|
|
185
|
-
return '+'
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
nil # if nothing matched
|
|
189
|
-
end
|
|
190
|
-
# Check if a specific VHDVS (UVS256) channel assignment is _HC variety (high-current)
|
|
191
|
-
# If the specific VHDVS channel is _HC variety, returns a "_HC" string, otherwise nil.
|
|
192
|
-
def is_vhdvs_hc(chanmapname, pinname, sitenum)
|
|
193
|
-
if sitenum <= @max_site
|
|
194
|
-
if @channelmap[chanmapname][sitenum][pinname].channel.downcase.include?('hc')
|
|
195
|
-
return '_HC'
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
nil # if nothing matched
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
def assign_dc_instr_pins(dc_pins)
|
|
202
|
-
if !dc_pins.is_a?(Array)
|
|
203
|
-
@dc_pins = [] << dc_pins
|
|
204
|
-
else
|
|
205
|
-
@dc_pins = dc_pins
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
def assign_digsrc_pins(digsrc_pins)
|
|
210
|
-
if !digsrc_pins.is_a?(Array)
|
|
211
|
-
@digsrc_pins = [] << digsrc_pins
|
|
212
|
-
else
|
|
213
|
-
@digsrc_pins = digsrc_pins
|
|
214
|
-
end
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
def assign_digcap_pins(digcap_pins)
|
|
218
|
-
if !digcap_pins.is_a?(Array)
|
|
219
|
-
@digcap_pins = [] << digcap_pins
|
|
220
|
-
else
|
|
221
|
-
@digcap_pins = digcap_pins
|
|
222
|
-
end
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
def get_dc_instr_pins
|
|
226
|
-
@dc_pins
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
def get_digsrc_pins
|
|
230
|
-
@digsrc_pins
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
def get_digcap_pins
|
|
234
|
-
@digcap_pins
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
def flows
|
|
238
|
-
parser.flows
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
# Main accessor to all content parsed from existing test program sheets found in the
|
|
242
|
-
# supplied directory or in Origen.config.test_program_output_directory
|
|
243
|
-
def parser(prog_dir = Origen.config.test_program_output_directory)
|
|
244
|
-
unless prog_dir
|
|
245
|
-
fail 'You must supply the directory containing the test program sheets, or define it via Origen.config.test_program_output_directory'
|
|
246
|
-
end
|
|
247
|
-
@parser ||= IGXLBasedTester::Parser.new
|
|
248
|
-
@parsed_dir ||= false
|
|
249
|
-
if @parsed_dir != prog_dir
|
|
250
|
-
@parser.parse(prog_dir)
|
|
251
|
-
@parsed_dir = prog_dir
|
|
252
|
-
end
|
|
253
|
-
@parser
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
# Capture a vector to the tester HRAM.
|
|
257
|
-
#
|
|
258
|
-
# This method applies a store vector (stv) opcode to the previous vector, note that is does
|
|
259
|
-
# not actually generate a new vector.
|
|
260
|
-
#
|
|
261
|
-
# Sometimes when generating vectors within a loop you may want to apply a stv opcode
|
|
262
|
-
# retrospectively to a previous vector, passing in an offset option will allow you
|
|
263
|
-
# to do this.
|
|
264
|
-
#
|
|
265
|
-
# On J750 the pins argument is ignored since the tester only supports whole vector capture.
|
|
266
|
-
#
|
|
267
|
-
# @example
|
|
268
|
-
# $tester.cycle # This is the vector you want to capture
|
|
269
|
-
# $tester.store # This applies the STV opcode
|
|
270
|
-
#
|
|
271
|
-
# $tester.cycle # This one gets stored
|
|
272
|
-
# $tester.cycle
|
|
273
|
-
# $tester.cycle
|
|
274
|
-
# $tester.store(:offset => -2) # Just realized I need to capture that earlier vector
|
|
275
|
-
def store(*pins)
|
|
276
|
-
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
|
277
|
-
options = { offset: 0
|
|
278
|
-
}.merge(options)
|
|
279
|
-
update_vector microcode: 'stv', offset: options[:offset]
|
|
280
|
-
last_vector(options[:offset]).contains_capture = true
|
|
281
|
-
end
|
|
282
|
-
alias_method :to_hram, :store
|
|
283
|
-
alias_method :capture, :store
|
|
284
|
-
|
|
285
|
-
# Capture the next vector generated to HRAM
|
|
286
|
-
#
|
|
287
|
-
# This method applies a store vector (stv) opcode to the next vector to be generated,
|
|
288
|
-
# note that is does not actually generate a new vector.
|
|
289
|
-
#
|
|
290
|
-
# On J750 the pins argument is ignored since the tester only supports whole vector capture.
|
|
291
|
-
#
|
|
292
|
-
# @example
|
|
293
|
-
# $tester.store_next_cycle
|
|
294
|
-
# $tester.cycle # This is the vector that will be captured
|
|
295
|
-
def store_next_cycle(*pins)
|
|
296
|
-
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
|
297
|
-
options = {
|
|
298
|
-
}.merge(options)
|
|
299
|
-
|
|
300
|
-
preset_next_vector microcode: 'stv' do |vector|
|
|
301
|
-
vector.contains_capture = true
|
|
302
|
-
end
|
|
303
|
-
end
|
|
304
|
-
alias_method :store!, :store_next_cycle
|
|
305
|
-
|
|
306
|
-
# @api private
|
|
307
|
-
def remove_store_from_vector(vector)
|
|
308
|
-
super
|
|
309
|
-
vector.microcode = nil
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
# Call a subroutine.
|
|
313
|
-
#
|
|
314
|
-
# This method applies a call subroutine opcode to the previous vector, it does not
|
|
315
|
-
# generate a new vector.
|
|
316
|
-
#
|
|
317
|
-
# Subroutines should always be called through this method as it ensures a running
|
|
318
|
-
# log of called subroutines is maintained and which then gets output in the pattern
|
|
319
|
-
# header to import the right dependencies.
|
|
320
|
-
#
|
|
321
|
-
# An offset option is available to make the call on earlier vectors.
|
|
322
|
-
#
|
|
323
|
-
# ==== Examples
|
|
324
|
-
# $tester.call_subroutine("mysub")
|
|
325
|
-
# $tester.call_subroutine("my_other_sub", :offset => -1)
|
|
326
|
-
def call_subroutine(name, options = {})
|
|
327
|
-
options = {
|
|
328
|
-
offset: 0
|
|
329
|
-
}.merge(options)
|
|
330
|
-
called_subroutines << name.to_s.chomp unless called_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
|
|
331
|
-
update_vector microcode: "call #{name}", offset: options[:offset]
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
# Start a subroutine.
|
|
335
|
-
#
|
|
336
|
-
# Generates a global subroutine label. Global is used to adhere to the best practice of
|
|
337
|
-
# containing all subroutines in dedicated patterns, e.g. global_subs.atp
|
|
338
|
-
#
|
|
339
|
-
# ==== Examples
|
|
340
|
-
# $tester.start_subroutine("wait_for_done")
|
|
341
|
-
# < generate your subroutine vectors here >
|
|
342
|
-
# $tester.end_subroutine
|
|
343
|
-
def start_subroutine(name, options = {})
|
|
344
|
-
local_subroutines << name.to_s.chomp unless local_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
|
|
345
|
-
if $tester.ultraflex? && (name =~ /keep_?alive/ || options[:keep_alive])
|
|
346
|
-
microcode "keepalive subr #{name}:"
|
|
347
|
-
else
|
|
348
|
-
microcode "global subr #{name}:"
|
|
349
|
-
end
|
|
350
|
-
end
|
|
351
|
-
|
|
352
|
-
# End a subroutine.
|
|
353
|
-
#
|
|
354
|
-
# Generates a return opcode on the last vector.
|
|
355
|
-
#
|
|
356
|
-
# ==== Examples
|
|
357
|
-
# $tester.start_subroutine("wait_for_done")
|
|
358
|
-
# < generate your subroutine vectors here >
|
|
359
|
-
# $tester.end_subroutine
|
|
360
|
-
# cond: whether return is conditional on a flag (to permit to mix subrs together)
|
|
361
|
-
def end_subroutine(cond = false, options = {})
|
|
362
|
-
(cond, options) = false, cond if cond.is_a?(Hash)
|
|
363
|
-
if cond
|
|
364
|
-
update_vector microcode: 'if (flag) return'
|
|
365
|
-
else
|
|
366
|
-
update_vector microcode: 'return'
|
|
367
|
-
end
|
|
368
|
-
end
|
|
369
|
-
|
|
370
|
-
# Do a frequency measure.
|
|
371
|
-
#
|
|
372
|
-
# Write the necessary micro code to do a frequency measure on the given pin,
|
|
373
|
-
# optionally supply a read code to pass information to the tester.
|
|
374
|
-
#
|
|
375
|
-
# ==== Examples
|
|
376
|
-
# $tester.freq_count($top.pin(:d_out)) # Freq measure on pin "d_out"
|
|
377
|
-
# $tester.freq_count($top.pin(:d_out):readcode => 10)
|
|
378
|
-
def freq_count(pin, options = {})
|
|
379
|
-
options = { readcode: false
|
|
380
|
-
}.merge(options)
|
|
381
|
-
|
|
382
|
-
set_code(options[:readcode]) if options[:readcode]
|
|
383
|
-
cycle(microcode: "#{@microcode[:set_flag]} (cpuA)")
|
|
384
|
-
cycle(microcode: "#{@microcode[:set_flag]} (cpuA)")
|
|
385
|
-
cycle(microcode: "#{@microcode[:set_flag]} (cpuB)")
|
|
386
|
-
cycle(microcode: "#{@microcode[:set_flag]} (cpuC)")
|
|
387
|
-
cycle(microcode: 'freq_loop_1:')
|
|
388
|
-
cycle(microcode: 'if (cpuA) jump freq_loop_1')
|
|
389
|
-
pin.drive_lo
|
|
390
|
-
delay(2000)
|
|
391
|
-
pin.dont_care
|
|
392
|
-
cycle(microcode: "freq_loop_2: #{@microcode[:enable]} (#{@flags[1]})")
|
|
393
|
-
cycle(microcode: 'if (flag) jump freq_loop_2')
|
|
394
|
-
cycle(microcode: "#{@microcode[:enable]} (#{@flags[2]})")
|
|
395
|
-
cycle(microcode: 'if (flag) jump freq_loop_1')
|
|
396
|
-
end
|
|
397
|
-
|
|
398
|
-
# * J750 Specific *
|
|
399
|
-
#
|
|
400
|
-
# Generates a single MTO opcode line for J750
|
|
401
|
-
#
|
|
402
|
-
# Codes implemented: xa load_preset, xa inc, ya load_preset, ya inc, stv_m0, stv_m1, stv_c<br>
|
|
403
|
-
def memory_test(options = {})
|
|
404
|
-
options = {
|
|
405
|
-
gen_vector: true, # Default generate vector not just MTO opcode
|
|
406
|
-
init_counter_x: false, # initialize counter X
|
|
407
|
-
inc_counter_x: false, # increment counter X
|
|
408
|
-
init_counter_y: false, # initialize counter X
|
|
409
|
-
inc_counter_y: false, # increment counter X
|
|
410
|
-
capture_vector: false, # capture vector to memory using all mem types
|
|
411
|
-
capture_vector_mem0: false, # capture vector to memory type 0, here for J750 will be stv_m0
|
|
412
|
-
capture_vector_mem1: false, # capture vector to memory type 1, here for J750 will be stv_m1
|
|
413
|
-
capture_vector_mem2: false, # capture vector to memory type 2, here for J750 will be stv_c
|
|
414
|
-
pin: false, # pin on which to drive or expect data, pass pin object here!
|
|
415
|
-
pin_data: false, # pin data (:none, :drive, :expect)
|
|
416
|
-
}.merge(options)
|
|
417
|
-
|
|
418
|
-
mto_opcode = ''
|
|
419
|
-
|
|
420
|
-
if options[:init_counter_x]
|
|
421
|
-
mto_opcode += ' xa load_preset'
|
|
422
|
-
end
|
|
423
|
-
if options[:inc_counter_x]
|
|
424
|
-
mto_opcode += ' xa inc'
|
|
425
|
-
end
|
|
426
|
-
if options[:init_counter_y]
|
|
427
|
-
mto_opcode += ' ya load_preset'
|
|
428
|
-
end
|
|
429
|
-
if options[:inc_counter_y]
|
|
430
|
-
mto_opcode += ' ya inc'
|
|
431
|
-
end
|
|
432
|
-
if options[:capture_vector]
|
|
433
|
-
mto_opcode += ' stv_m0 stv_m1 stv_c'
|
|
434
|
-
end
|
|
435
|
-
if options[:capture_vector_mem0]
|
|
436
|
-
mto_opcode += ' stv_m0'
|
|
437
|
-
end
|
|
438
|
-
if options[:capture_vector_mem1]
|
|
439
|
-
mto_opcode += ' stv_m1'
|
|
440
|
-
end
|
|
441
|
-
if options[:capture_vector_mem2]
|
|
442
|
-
mto_opcode += ' stv_c'
|
|
443
|
-
end
|
|
444
|
-
|
|
445
|
-
unless mto_opcode.eql?('')
|
|
446
|
-
mto_opcode = '(mto:' + mto_opcode + ')'
|
|
447
|
-
end
|
|
448
|
-
|
|
449
|
-
if options[:gen_vector]
|
|
450
|
-
if options[:pin]
|
|
451
|
-
case options[:pin_data]
|
|
452
|
-
when :drive
|
|
453
|
-
# store current pin state
|
|
454
|
-
cur_pin_state = options[:pin].state.to_sym
|
|
455
|
-
options[:pin].drive_mem
|
|
456
|
-
when :expect
|
|
457
|
-
# store current pin state
|
|
458
|
-
cur_pin_state = options[:pin].state.to_sym
|
|
459
|
-
options[:pin].expect_mem
|
|
460
|
-
end
|
|
461
|
-
end
|
|
462
|
-
cycle(microcode: "#{mto_opcode}")
|
|
463
|
-
if options[:pin]
|
|
464
|
-
# restore previous pin state
|
|
465
|
-
case options[:pin_data]
|
|
466
|
-
when :drive
|
|
467
|
-
options[:pin].state = cur_pin_state
|
|
468
|
-
when :expect
|
|
469
|
-
options[:pin].state = cur_pin_state
|
|
470
|
-
end
|
|
471
|
-
end
|
|
472
|
-
else
|
|
473
|
-
microcode "#{mto_opcode}"
|
|
474
|
-
end
|
|
475
|
-
end
|
|
476
|
-
|
|
477
|
-
# Generates a match loop on up to two pins.
|
|
478
|
-
#
|
|
479
|
-
# This method is not really intended to be called directly, rather you should call
|
|
480
|
-
# via Tester#wait e.g. $tester.wait(:match => true).
|
|
481
|
-
#
|
|
482
|
-
# The timeout should be provided in cycles, however when called via the wait method the
|
|
483
|
-
# time-based helpers (time_in_us, etc) will be converted to cycles for you.
|
|
484
|
-
# The following options are available to tailor the match loop behavior, defaults in
|
|
485
|
-
# parenthesis:
|
|
486
|
-
# * :pin - The pin object to match on (*required*)
|
|
487
|
-
# * :state - The pin state to match on, :low or :high (*required*)
|
|
488
|
-
# * :pin2 (nil) - Optionally supply a second pin to match on
|
|
489
|
-
# * :state2 (nil) - State for the second pin (required if :pin2 is supplied)
|
|
490
|
-
# * :check_for_fails (false) - Flushes the pipeline and handshakes with the tester (passing readcode 100) prior to the match (to allow binout of fails encountered before the match)
|
|
491
|
-
# * :force_fail_on_timeout (true) - Force a vector mis-compare if the match loop times out
|
|
492
|
-
# * :on_timeout_goto ("") - Optionally supply a label to branch to on timeout, by default will continue from the end of the match loop
|
|
493
|
-
# * :on_pin_match_goto ("") - Optionally supply a label to branch to when pin 1 matches, by default will continue from the end of the match loop
|
|
494
|
-
# * :on_pin2_match_goto ("") - Optionally supply a label to branch to when pin 2 matches, by default will continue from the end of the match loop
|
|
495
|
-
# * :multiple_entries (false) - Supply an integer to generate multiple entries into the match (each with a unique readcode), this can be useful when debugging patterns with multiple matches
|
|
496
|
-
# * :force_fail_on_timeout (true) - force pattern to fail if timeout occurs
|
|
497
|
-
# * :global_loops (false) - whether match loop loops should use global labels
|
|
498
|
-
# * :manual_stop (false) - whether to use extra cpuB flag to resolve IG-XL v.3.50.xx bug where VBT clears cpuA immediately
|
|
499
|
-
# at start of PatFlagFunc instead of at end. Use will have to manually clear cpuB to resume this pattern.
|
|
500
|
-
# ==== Examples
|
|
501
|
-
# $tester.wait(:match => true, :time_in_us => 5000, :pin => $top.pin(:done), :state => :high)
|
|
502
|
-
def match(pin, state, timeout, options = {})
|
|
503
|
-
options = {
|
|
504
|
-
check_for_fails: false,
|
|
505
|
-
on_timeout_goto: false,
|
|
506
|
-
pin2: false,
|
|
507
|
-
state2: false,
|
|
508
|
-
on_pin_match_goto: false,
|
|
509
|
-
multiple_entries: false,
|
|
510
|
-
force_fail_on_timeout: true,
|
|
511
|
-
global_loops: false,
|
|
512
|
-
manual_stop: false,
|
|
513
|
-
clr_fail_post_match: false
|
|
514
|
-
}.merge(options)
|
|
515
|
-
options[:on_block_match_goto] ||= options.delete(:on_pin_match_goto)
|
|
516
|
-
|
|
517
|
-
match_block(timeout, options) do |match_conditions, fail_conditions|
|
|
518
|
-
# Define match conditions
|
|
519
|
-
match_conditions.add do
|
|
520
|
-
state == :low ? pin.expect_lo : pin.expect_hi
|
|
521
|
-
cc "Check if #{pin.name} is #{state == :low ? 'low' : 'high'}"
|
|
522
|
-
cycle
|
|
523
|
-
pin.dont_care
|
|
524
|
-
end
|
|
525
|
-
|
|
526
|
-
if options[:pin2]
|
|
527
|
-
match_conditions.add do
|
|
528
|
-
state == :low ? pin.expect_hi : pin.expect_lo
|
|
529
|
-
options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi
|
|
530
|
-
cc "Check if #{options[:pin2].name} is #{options[:state2] == :low ? 'low' : 'high'}"
|
|
531
|
-
cycle
|
|
532
|
-
options[:pin2].dont_care
|
|
533
|
-
pin.dont_care
|
|
534
|
-
end
|
|
535
|
-
end
|
|
536
|
-
|
|
537
|
-
# Define fail conditions
|
|
538
|
-
fail_conditions.add do
|
|
539
|
-
state == :low ? pin.expect_lo : pin.expect_hi
|
|
540
|
-
cc "Check if #{pin.name} is #{state == :low ? 'low' : 'high'}"
|
|
541
|
-
if options[:pin2]
|
|
542
|
-
options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi
|
|
543
|
-
cc "Check if #{options[:pin2].name} is #{options[:state2] == :low ? 'low' : 'high'}"
|
|
544
|
-
end
|
|
545
|
-
cycle
|
|
546
|
-
pin.dont_care
|
|
547
|
-
options[:pin2].dont_care if options[:pin2]
|
|
548
|
-
end
|
|
549
|
-
end
|
|
550
|
-
end
|
|
551
|
-
|
|
552
|
-
# Call a match loop.
|
|
553
|
-
#
|
|
554
|
-
# Normally you would put your match loop in a global subs pattern, then you can
|
|
555
|
-
# call it via this method. This method automatically syncs match loop naming with
|
|
556
|
-
# the match generation flow, no arguments required.
|
|
557
|
-
#
|
|
558
|
-
# This is an IGXLBasedTester specific API.
|
|
559
|
-
#
|
|
560
|
-
# ==== Examples
|
|
561
|
-
# $tester.cycle
|
|
562
|
-
# $tester.call_match # Calls the match loop, or the first entry point if you have multiple
|
|
563
|
-
# $tester.cycle
|
|
564
|
-
# $tester.call_match # Calls the match loop, or the second entry point if you have multiple
|
|
565
|
-
def call_match
|
|
566
|
-
@match_counter = @match_counter || 0
|
|
567
|
-
call_subroutine("match_done_#{@match_counter}")
|
|
568
|
-
@match_counter += 1 unless @match_counter == (@match_entries || 1) - 1
|
|
569
|
-
end
|
|
570
|
-
|
|
571
|
-
# Apply a label to the pattern.
|
|
572
|
-
#
|
|
573
|
-
# No additional vector is generated.
|
|
574
|
-
# Arguments:
|
|
575
|
-
# name : label name
|
|
576
|
-
# global : (optional) whether to apply global label, default=false
|
|
577
|
-
#
|
|
578
|
-
# ==== Examples
|
|
579
|
-
# $tester.label("something_significant")
|
|
580
|
-
# $tester.label("something_significant",true) # apply global label
|
|
581
|
-
def label(name, global = false)
|
|
582
|
-
global_opt = (global) ? 'global ' : ''
|
|
583
|
-
microcode global_opt + name + ':'
|
|
584
|
-
end
|
|
585
|
-
|
|
586
|
-
# * J750 Specific *
|
|
587
|
-
#
|
|
588
|
-
# Set a readcode.
|
|
589
|
-
#
|
|
590
|
-
# Use the set an explicit readcode for communicating with the tester. This method
|
|
591
|
-
# will generate an additional vector.
|
|
592
|
-
#
|
|
593
|
-
# ==== Examples
|
|
594
|
-
# $tester.set_code(55)
|
|
595
|
-
def set_code(code)
|
|
596
|
-
cycle(microcode: "set_code #{code}")
|
|
597
|
-
end
|
|
598
|
-
|
|
599
|
-
# Branch execution to the given point.
|
|
600
|
-
#
|
|
601
|
-
# This generates a new vector with a jump instruction to a given label. This method
|
|
602
|
-
# will generate an additional vector.
|
|
603
|
-
#
|
|
604
|
-
# ==== Examples
|
|
605
|
-
# $tester.branch_to("something_significant")
|
|
606
|
-
def branch_to(label)
|
|
607
|
-
cycle(microcode: "jump #{label}")
|
|
608
|
-
end
|
|
609
|
-
alias_method :branch, :branch_to
|
|
610
|
-
|
|
611
|
-
# Add loop to the pattern.
|
|
612
|
-
#
|
|
613
|
-
# Pass in a name for the loop and the number of times to execute it, all vectors
|
|
614
|
-
# generated by the given block will be captured in the loop.
|
|
615
|
-
#
|
|
616
|
-
# Optional arguments: global - whether to apply global label (default=false)
|
|
617
|
-
# label_first - whether to apply loop label before loop vector or not
|
|
618
|
-
#
|
|
619
|
-
# ==== Examples
|
|
620
|
-
# $tester.loop_vectors("pulse_loop", 3) do # Do this 3 times...
|
|
621
|
-
# $tester.cycle
|
|
622
|
-
# some_other_method_to_generate_vectors
|
|
623
|
-
# end
|
|
624
|
-
def loop_vectors(name, number_of_loops, global = false, label_first = false)
|
|
625
|
-
if number_of_loops > 1
|
|
626
|
-
@loop_counters ||= {}
|
|
627
|
-
if @loop_counters[name]
|
|
628
|
-
@loop_counters[name] += 1
|
|
629
|
-
else
|
|
630
|
-
@loop_counters[name] = 0
|
|
631
|
-
end
|
|
632
|
-
loop_name = @loop_counters[name] == 0 ? name : "#{name}_#{@loop_counters[name]}"
|
|
633
|
-
if label_first
|
|
634
|
-
global_opt = (global) ? 'global ' : ''
|
|
635
|
-
microcode "#{global_opt}#{loop_name}: "
|
|
636
|
-
end
|
|
637
|
-
cycle(microcode: "loopA #{number_of_loops}")
|
|
638
|
-
unless label_first
|
|
639
|
-
global_opt = (global) ? 'global ' : ''
|
|
640
|
-
cycle(microcode: "#{global_opt}#{loop_name}: ")
|
|
641
|
-
end
|
|
642
|
-
yield
|
|
643
|
-
cycle(microcode: "end_loopA #{loop_name}")
|
|
644
|
-
else
|
|
645
|
-
yield
|
|
646
|
-
end
|
|
647
|
-
end
|
|
648
|
-
alias_method :loop_vector, :loop_vectors
|
|
649
|
-
|
|
650
|
-
# An internal method called by Origen Pattern Create to create the pattern header
|
|
651
|
-
def pattern_header(options = {})
|
|
652
|
-
options = {
|
|
653
|
-
instruments: {}, # Provide instruments here if desired as a hash (e.g. "mto" => "dgen_2bit")
|
|
654
|
-
subroutine_pat: false,
|
|
655
|
-
svm_only: true, # Whether 'svm_only' can be specified
|
|
656
|
-
group: false, # If true the end pattern is intended to run within a pattern group
|
|
657
|
-
high_voltage: false, # Supply a pin name here to declare it as an HV instrument (not yet defined)
|
|
658
|
-
freq_counter: false, # Supply a pin name here to declare it as a frequency counter
|
|
659
|
-
memory_test: false, # If true, define 2-bit MTO DGEN as instrument
|
|
660
|
-
}.merge(options)
|
|
661
|
-
|
|
662
|
-
if level_period?
|
|
663
|
-
microcode "import tset #{min_period_timeset.name};"
|
|
664
|
-
else
|
|
665
|
-
called_timesets.each do |timeset|
|
|
666
|
-
microcode "import tset #{timeset.name};"
|
|
667
|
-
end
|
|
668
|
-
end
|
|
669
|
-
unless options[:group] # Withhold imports for pattern groups, is this correct?
|
|
670
|
-
called_subroutines.each do |sub_name|
|
|
671
|
-
# Don't import any called subroutines that are declared in the current pattern
|
|
672
|
-
microcode "import svm_subr #{sub_name};" unless local_subroutines.include?(sub_name)
|
|
673
|
-
end
|
|
674
|
-
end
|
|
675
|
-
|
|
676
|
-
# If memory test, then add to instruments hash
|
|
677
|
-
if options[:memory_test]
|
|
678
|
-
options[:instruments].merge!('mto' => 'dgen_2bit')
|
|
679
|
-
end
|
|
680
|
-
|
|
681
|
-
if options[:svm_only]
|
|
682
|
-
microcode "svm_only_file = #{options[:subroutine_pat] ? 'yes' : 'no'};"
|
|
683
|
-
end
|
|
684
|
-
|
|
685
|
-
microcode "opcode_mode = #{@opcode_mode};"
|
|
686
|
-
microcode "digital_inst = #{options[:digital_inst]};" if options[:digital_inst]
|
|
687
|
-
microcode 'compressed = yes;' # if $dut.gzip_patterns
|
|
688
|
-
if tester.j750? && options[:freq_counter]
|
|
689
|
-
# pin setup type => freq_counter is only for the J750.
|
|
690
|
-
# UltraFLEX has frequency counter capability behind every pin.
|
|
691
|
-
# need to make sure the pin_setup freq_count is defined after opcode_mode extended since freq count only work in extended mode
|
|
692
|
-
if @opcode_mode == :extended
|
|
693
|
-
microcode "pin_setup = {#{options[:freq_counter]} freq_count;}"
|
|
694
|
-
else
|
|
695
|
-
fail 'pin_setup freq_count can only work in extended mode'
|
|
696
|
-
end
|
|
697
|
-
end
|
|
698
|
-
|
|
699
|
-
# Take care of any instruments
|
|
700
|
-
options[:instruments] = options[:instruments].merge(@pushed_instrument_configs)
|
|
701
|
-
if options[:instruments].length > 0
|
|
702
|
-
microcode 'instruments = {'
|
|
703
|
-
options[:instruments].each do |pins, instrument|
|
|
704
|
-
if "#{pins}" == 'nil'
|
|
705
|
-
microcode " #{instrument};"
|
|
706
|
-
elsif instrument == 'digsrc'
|
|
707
|
-
microcode " #{pins}:#{instrument} #{options[:digsrc_width]}:#{options[:digsrc_bit_order]}:#{options[:digsrc_mode]}:format=#{options[:digsrc_format]}:#{options[:digsrc_site_uniqueness]}:#{options[:digsrc_auto_cond]};"
|
|
708
|
-
elsif instrument == 'digcap'
|
|
709
|
-
microcode " #{pins}:#{instrument} #{options[:digcap_width]}:#{options[:digcap_bit_order]}:#{options[:digcap_mode]}:format=#{options[:digcap_format]}:data_type=#{options[:digcap_data_type]}:#{options[:digcap_auto_cond]}:#{options[:digcap_auto_trig_enable]}:#{options[:digcap_store_stv]}:#{options[:digcap_receive_data]};"
|
|
710
|
-
else
|
|
711
|
-
microcode " #{pins}:#{instrument};"
|
|
712
|
-
end
|
|
713
|
-
end
|
|
714
|
-
microcode '}'
|
|
715
|
-
end
|
|
716
|
-
|
|
717
|
-
options[:high_voltage] = @use_hv_pin
|
|
718
|
-
microcode "pin_setup = {#{options[:high_voltage]} high_voltage;}" if options[:high_voltage]
|
|
719
|
-
microcode ''
|
|
720
|
-
|
|
721
|
-
pin_list = ordered_pins.map(&:name).join(', ')
|
|
722
|
-
|
|
723
|
-
# here indicate pattern header specific stuff
|
|
724
|
-
yield pin_list
|
|
725
|
-
if ordered_pins.size > 0
|
|
726
|
-
max_pin_name_length = ordered_pins.map(&:name).max { |a, b| a.length <=> b.length }.length
|
|
727
|
-
pin_widths = ordered_pins.map { |p| p.size - 1 }
|
|
728
|
-
|
|
729
|
-
max_pin_name_length.times do |i|
|
|
730
|
-
cc((' ' * 93) + ordered_pins.map.with_index { |p, x| ((p.name[i] || ' ') + ' ' * pin_widths[x]).gsub('_', '-') }.join(' '))
|
|
731
|
-
end
|
|
732
|
-
end
|
|
733
|
-
end
|
|
734
|
-
|
|
735
|
-
# An internal method called by Origen to generate the pattern footer
|
|
736
|
-
def pattern_footer(options = {})
|
|
737
|
-
options = {
|
|
738
|
-
subroutine_pat: false,
|
|
739
|
-
end_in_ka: false,
|
|
740
|
-
end_with_halt: false,
|
|
741
|
-
end_module: true
|
|
742
|
-
}.merge(options)
|
|
743
|
-
$tester.align_to_last
|
|
744
|
-
# cycle(:microcode => "#{$dut.end_of_pattern_label}:") if $dut.end_of_pattern_label
|
|
745
|
-
if options[:end_in_ka]
|
|
746
|
-
keep_alive(options)
|
|
747
|
-
else
|
|
748
|
-
if options[:end_with_halt]
|
|
749
|
-
$tester.cycle microcode: 'halt'
|
|
750
|
-
else
|
|
751
|
-
if options[:end_module]
|
|
752
|
-
$tester.cycle microcode: 'end_module' unless options[:subroutine_pat]
|
|
753
|
-
else
|
|
754
|
-
$tester.cycle
|
|
755
|
-
end
|
|
756
|
-
end
|
|
757
|
-
end
|
|
758
|
-
microcode '}'
|
|
759
|
-
end
|
|
760
|
-
|
|
761
|
-
# Returns an array of subroutines called while generating the current pattern
|
|
762
|
-
def called_subroutines
|
|
763
|
-
@called_subroutines ||= []
|
|
764
|
-
end
|
|
765
|
-
|
|
766
|
-
# Returns an array of subroutines created by the current pattern
|
|
767
|
-
def local_subroutines # :nodoc:
|
|
768
|
-
@local_subroutines ||= []
|
|
769
|
-
end
|
|
770
|
-
|
|
771
|
-
# This is an internal method use by Origen which returns a fully formatted vector
|
|
772
|
-
# You can override this if you wish to change the output formatting at vector level
|
|
773
|
-
def format_vector(vec)
|
|
774
|
-
timeset = vec.timeset ? "> #{vec.timeset.name}" : ''
|
|
775
|
-
pin_vals = vec.pin_vals ? "#{vec.pin_vals} ;" : ''
|
|
776
|
-
if vec.repeat > 1
|
|
777
|
-
microcode = "repeat #{vec.repeat}"
|
|
778
|
-
else
|
|
779
|
-
microcode = vec.microcode ? vec.microcode : ''
|
|
780
|
-
end
|
|
781
|
-
if vec.pin_vals && ($_testers_enable_vector_comments || vector_comments)
|
|
782
|
-
comment = " // #{vec.number}:#{vec.cycle} #{vec.inline_comment}"
|
|
783
|
-
else
|
|
784
|
-
comment = vec.inline_comment.empty? ? '' : " // #{vec.inline_comment}"
|
|
785
|
-
end
|
|
786
|
-
|
|
787
|
-
"#{microcode.ljust(65)}#{timeset.ljust(31)}#{pin_vals}#{comment}"
|
|
788
|
-
end
|
|
789
|
-
|
|
790
|
-
# Override this to force the formatting to match the v1 J750 model (easier diffs)
|
|
791
|
-
def push_microcode(code) # :nodoc:
|
|
792
|
-
stage.store(code.ljust(65) + ''.ljust(31))
|
|
793
|
-
end
|
|
794
|
-
alias_method :microcode, :push_microcode
|
|
795
|
-
|
|
796
|
-
# All vectors generated with the supplied block will have all pins set
|
|
797
|
-
# to the repeat previous state. Any pins that are changed state within
|
|
798
|
-
# the block will still update to the supplied value.
|
|
799
|
-
# ==== Example
|
|
800
|
-
# # All pins except invoke will be assigned the repeat previous code
|
|
801
|
-
# # in the generated vector. On completion of the block they will
|
|
802
|
-
# # return to their previous state, except for invoke which will
|
|
803
|
-
# # retain the value assigned within the block.
|
|
804
|
-
# $tester.repeat_previous do
|
|
805
|
-
# $top.pin(:invoke).drive(1)
|
|
806
|
-
# $tester.cycle
|
|
807
|
-
# end
|
|
808
|
-
def repeat_previous
|
|
809
|
-
pinmap = Origen.pin_bank.pins
|
|
810
|
-
pinmap.each { |id, pin| pin.repeat_previous = true }
|
|
811
|
-
yield
|
|
812
|
-
pinmap.each { |id, pin| pin.repeat_previous = false }
|
|
813
|
-
end
|
|
814
|
-
|
|
815
|
-
def ignore_fails(*pins)
|
|
816
|
-
pins.each(&:suspend)
|
|
817
|
-
yield
|
|
818
|
-
pins.each(&:resume)
|
|
819
|
-
end
|
|
820
|
-
|
|
821
|
-
def enable_flag(options = {})
|
|
822
|
-
options = { flagnum: 4, # default flag to use
|
|
823
|
-
}.merge(options)
|
|
824
|
-
|
|
825
|
-
if options[:flagnum] > @flags.length
|
|
826
|
-
abort "ERROR! Invalid flag value passed to 'enable_flag' method!\n"
|
|
827
|
-
end
|
|
828
|
-
flagname = @flags[options[:flagnum] - 1]
|
|
829
|
-
update_vector(microcode: "#{@microcode[:enable]}(#{flagname})")
|
|
830
|
-
end
|
|
831
|
-
|
|
832
|
-
def set_flag(options = {})
|
|
833
|
-
options = { flagnum: 4, # default flag to use
|
|
834
|
-
}.merge(options)
|
|
835
|
-
|
|
836
|
-
if options[:flagnum] > @flags.length
|
|
837
|
-
abort "ERROR! Invalid flag value passed to 'set_flag' method!\n"
|
|
838
|
-
end
|
|
839
|
-
flagname = @flags[options[:flagnum] - 1]
|
|
840
|
-
update_vector(microcode: "#{@microcode[:set_flag]}(#{flagname})")
|
|
841
|
-
end
|
|
842
|
-
|
|
843
|
-
def cycle(options = {})
|
|
844
|
-
# handle overlay if requested
|
|
845
|
-
ovly_style = nil
|
|
846
|
-
if options.key?(:overlay)
|
|
847
|
-
ovly_style = options[:overlay][:overlay_style].nil? ? @overlay_style : options[:overlay][:overlay_style]
|
|
848
|
-
overlay_str = options[:overlay][:overlay_str]
|
|
849
|
-
|
|
850
|
-
# route the overlay request to the appropriate method
|
|
851
|
-
case ovly_style
|
|
852
|
-
when :subroutine, :default
|
|
853
|
-
subroutine_overlay(overlay_str, options)
|
|
854
|
-
ovly_style = :subroutine
|
|
855
|
-
when :label
|
|
856
|
-
options[:dont_compress] = true
|
|
857
|
-
unless @overlay_history.key?(overlay_str)
|
|
858
|
-
label
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
options[:overlay][:pins].
|
|
865
|
-
options
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
Origen.log.warn(
|
|
896
|
-
Origen.log.warn('Available overlay styles :
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
#
|
|
903
|
-
#
|
|
904
|
-
#
|
|
905
|
-
#
|
|
906
|
-
#
|
|
907
|
-
#
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
#
|
|
928
|
-
#
|
|
929
|
-
#
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
options.merge!(
|
|
951
|
-
options.merge!(
|
|
952
|
-
options.merge!(
|
|
953
|
-
options.merge!(
|
|
954
|
-
options.merge!(
|
|
955
|
-
options.merge!(
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
options.merge!(
|
|
962
|
-
options.merge!(
|
|
963
|
-
options.merge!(
|
|
964
|
-
options.merge!(
|
|
965
|
-
options.merge!(
|
|
966
|
-
options.merge!(
|
|
967
|
-
options.merge!(
|
|
968
|
-
options.merge!(
|
|
969
|
-
options.merge!(
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
# this method
|
|
975
|
-
#
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
return_value +=
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
#
|
|
991
|
-
#
|
|
992
|
-
#
|
|
993
|
-
#
|
|
994
|
-
# #
|
|
995
|
-
# #
|
|
996
|
-
# #
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
i
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
v
|
|
1013
|
-
v.
|
|
1014
|
-
stage.bank[i].
|
|
1015
|
-
stage.
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
i
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
v
|
|
1065
|
-
v.
|
|
1066
|
-
v.
|
|
1067
|
-
v.
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
d
|
|
1080
|
-
d.
|
|
1081
|
-
d.
|
|
1082
|
-
d.
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
i
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
options
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
end
|
|
1
|
+
module OrigenTesters
|
|
2
|
+
module IGXLBasedTester
|
|
3
|
+
# This is the base class of all IGXL-based testers
|
|
4
|
+
class Base
|
|
5
|
+
include VectorBasedTester
|
|
6
|
+
|
|
7
|
+
attr_accessor :software_version
|
|
8
|
+
attr_accessor :pattern_compiler_pinmap
|
|
9
|
+
attr_accessor :memory_test_en
|
|
10
|
+
attr_accessor :testerconfig
|
|
11
|
+
attr_accessor :channelmap
|
|
12
|
+
attr_accessor :default_channelmap
|
|
13
|
+
attr_accessor :default_testerconfig
|
|
14
|
+
attr_accessor :max_site
|
|
15
|
+
# permit modification of minimum repeat count
|
|
16
|
+
attr_accessor :min_repeat_loop
|
|
17
|
+
alias_method :min_repeat_count, :min_repeat_loop
|
|
18
|
+
alias_method :min_repeat_count=, :min_repeat_loop=
|
|
19
|
+
# NOTE: DO NOT USE THIS CLASS DIRECTLY ONLY USED AS PARENT FOR
|
|
20
|
+
# DESIRED TESTER CLASS
|
|
21
|
+
|
|
22
|
+
# Returns a new IGXLBasedTester instance, normally there would only ever be one of these
|
|
23
|
+
# assigned to the global variable such as $tester by your target.
|
|
24
|
+
def initialize
|
|
25
|
+
@unique_counter = 0
|
|
26
|
+
@counter_lsb_bits = 0
|
|
27
|
+
@counter_msb_bits = 0
|
|
28
|
+
@max_repeat_loop = 65_535 # 16 bits
|
|
29
|
+
@min_repeat_loop = 2
|
|
30
|
+
@pat_extension = 'atp'
|
|
31
|
+
@active_loads = true
|
|
32
|
+
@pipeline_depth = 34
|
|
33
|
+
@software_version = ''
|
|
34
|
+
@compress = true
|
|
35
|
+
@support_repeat_previous = true
|
|
36
|
+
@match_entries = 10
|
|
37
|
+
@name = ''
|
|
38
|
+
@program_comment_char = ['logprint', "'"]
|
|
39
|
+
@opcode_mode = :extended
|
|
40
|
+
@flags = %w(cpuA cpuB cpuC cpuD)
|
|
41
|
+
@microcode = {}
|
|
42
|
+
@microcode[:enable] = 'enable'
|
|
43
|
+
@microcode[:set_flag] = 'set_cpu'
|
|
44
|
+
@microcode[:mask_vector] = 'ign ifc icc'
|
|
45
|
+
|
|
46
|
+
@mask_vector = false # sticky option to mask all subsequent vectors
|
|
47
|
+
|
|
48
|
+
@min_pattern_vectors = 0 # no minimum
|
|
49
|
+
|
|
50
|
+
@memory_test_en = false # memory test enabled (for all patterns?)
|
|
51
|
+
|
|
52
|
+
@testerconfig ||= {}
|
|
53
|
+
@channelmap ||= {}
|
|
54
|
+
@pushed_instrument_configs = {}
|
|
55
|
+
@overlay_style = :subroutine # default to use subroutine for overlay
|
|
56
|
+
@capture_style = :hram # default to use hram for capture
|
|
57
|
+
@overlay_history = {} # used to track labels, subroutines, digsrc pins used etc
|
|
58
|
+
@overlay_subr = nil
|
|
59
|
+
@capture_history = {}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def igxl_based?
|
|
63
|
+
true
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def import_tester_config(testconfigname, fullconfigpath)
|
|
67
|
+
# This function reads in CurrentConfig.txt file generated by IG-XL.
|
|
68
|
+
# testconfigname example ==> "FT", "WT", "Production"
|
|
69
|
+
# fullconfigpath example ==> "/product_folder/CurrentConfig.txt"
|
|
70
|
+
|
|
71
|
+
puts "importing Testerconfig #{testconfigname}..."
|
|
72
|
+
slotnum = Struct.new(:slot, :instrument, :idprom)
|
|
73
|
+
@testerconfig[testconfigname] ||= {}
|
|
74
|
+
current_config_file = Pathname.new(fullconfigpath)
|
|
75
|
+
File.open(current_config_file, 'r').each_line do |line|
|
|
76
|
+
if line =~ /^\d*.0/
|
|
77
|
+
(slot, blank1, instrument, blank2, idprom) = line.split(/\t/)
|
|
78
|
+
if (!slot.nil?) && (!instrument.nil?) && (!idprom.nil?)
|
|
79
|
+
@testerconfig[testconfigname][slot.split('.').first.to_i] = slotnum.new(slot.split('.').first.to_i, instrument, idprom.chomp)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
@default_testerconfig ||= testconfigname # Default TesterConfig gets set if it's not nil
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def get_tester_instrument(testconfigname, slot)
|
|
88
|
+
@testerconfig[testconfigname].each_with_index do |element, index|
|
|
89
|
+
if slot.to_s == element[0].to_s
|
|
90
|
+
return element[1][:instrument]
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
nil # if no corresponding slot
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def get_instrument_slots(testconfigname, instrument) # testconfigname example "WT", "FT", "Production"
|
|
97
|
+
@slots = []
|
|
98
|
+
@testerconfig[testconfigname].each_with_index do |element, index|
|
|
99
|
+
if instrument.to_s == element[1][:instrument].to_s
|
|
100
|
+
@slots << element[0].to_i
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
@slots # if no corresponding slot
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def import_chanmap(chanmapname, fullchanmappath)
|
|
107
|
+
# This function reads IG-XL ChannelMap file
|
|
108
|
+
# chanmapname example ==> "FT", "WT", "FTX2"
|
|
109
|
+
# fullchanmappath example ==> "/product_folder/Chans_FT.txt"
|
|
110
|
+
|
|
111
|
+
puts "importing ChannelMap #{fullchanmappath}..."
|
|
112
|
+
|
|
113
|
+
chanassignment = Struct.new(:pinname, :site, :channel, :type, :packagepin)
|
|
114
|
+
chanmap_file = Pathname.new(fullchanmappath)
|
|
115
|
+
@channelmap[chanmapname] ||= {}
|
|
116
|
+
File.open(chanmap_file, 'r').each_line.with_index do |line, index|
|
|
117
|
+
if index == 0
|
|
118
|
+
unless line =~ /DTChanMap/
|
|
119
|
+
puts "#{fullchanmappath} is not a valid IG-XL ChannelMap!"
|
|
120
|
+
break
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
if index == 5
|
|
124
|
+
siteloc = line.strip.split(/\t/).size - 1 # strip all white spaces and grab second to last
|
|
125
|
+
@max_site_s = line.split(/\t/)[siteloc].strip.split(/\s/)[1]
|
|
126
|
+
@max_site = @max_site_s.to_i
|
|
127
|
+
(0..@max_site).each do |sitenum|
|
|
128
|
+
@channelmap[chanmapname][sitenum] ||= {}
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
if index > 5
|
|
132
|
+
(blank1, pinname, packagepin, type) = line.split(/\t/)
|
|
133
|
+
(0..@max_site).each do |sitenum|
|
|
134
|
+
channel = line.split(/\t/)[4 + sitenum].to_s
|
|
135
|
+
@channelmap[chanmapname][sitenum][pinname.downcase.intern] = chanassignment.new(pinname.downcase.intern, sitenum, channel.chomp, type.chomp, packagepin)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
@default_channelmap ||= chanmapname # Default Channelmap gets set if it's not nil
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def get_tester_channel(chanmapname, pinname, sitenum)
|
|
143
|
+
if sitenum <= @max_site
|
|
144
|
+
@testerchannel = @channelmap[chanmapname][sitenum][pinname].channel
|
|
145
|
+
return @testerchannel
|
|
146
|
+
else
|
|
147
|
+
return nil
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Check if a specific pin for a given channelmap for a given site number is using merged channel.
|
|
152
|
+
# If yes, return x2 for Merged2, x4 for Merged4, etc. If no, return nil.
|
|
153
|
+
def merged_channels(chanmapname, pinname, sitenum)
|
|
154
|
+
if sitenum <= @max_site
|
|
155
|
+
if @channelmap[chanmapname][sitenum][pinname].type.include?('Merged')
|
|
156
|
+
@merged_channels = @channelmap[chanmapname][sitenum][pinname].type.split('Merged')[1]
|
|
157
|
+
return 'x' + @merged_channels
|
|
158
|
+
end
|
|
159
|
+
else
|
|
160
|
+
return nil
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Check if a specific HexVS supply is HexVS+ variety, which has +/-2mV accuracy as opposed to
|
|
165
|
+
# +/-7mV accuracy.
|
|
166
|
+
# If the specific HexVS is HexVS+ variety, returns a "+" string, otherwise nil.
|
|
167
|
+
def is_hexvs_plus(testconfigname, slot)
|
|
168
|
+
if @testerconfig[testconfigname][slot][:instrument].to_s == 'HexVS'
|
|
169
|
+
@productnum = @testerconfig[testconfigname][slot][:idprom].split(' ')[0]
|
|
170
|
+
if (@productnum.include?('974-294-')) && (@productnum.split('-')[2].to_i >= 20)
|
|
171
|
+
return '+'
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
nil # if nothing matched
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Check if a specific VHDVS (UVS256) supply is High-Accuracy (HA) variety, which has +/-5mV+0.1%*SUPPLY accuracy as opposed to
|
|
178
|
+
# +/-10mV+0.1%*SUPPLY accuracy.
|
|
179
|
+
# If the specific VHDVS is of High-Accuracy variety, returns a "+" string, otherwise nil.
|
|
180
|
+
def is_vhdvs_plus(testconfigname, slot)
|
|
181
|
+
if @testerconfig[testconfigname][slot][:instrument].to_s == 'VHDVS'
|
|
182
|
+
@productnum = @testerconfig[testconfigname][slot][:idprom].split(' ')[0]
|
|
183
|
+
# binding.pry
|
|
184
|
+
if (@productnum.include?('805-052-')) && (@productnum.split('-')[2].to_i >= 05)
|
|
185
|
+
return '+'
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
nil # if nothing matched
|
|
189
|
+
end
|
|
190
|
+
# Check if a specific VHDVS (UVS256) channel assignment is _HC variety (high-current)
|
|
191
|
+
# If the specific VHDVS channel is _HC variety, returns a "_HC" string, otherwise nil.
|
|
192
|
+
def is_vhdvs_hc(chanmapname, pinname, sitenum)
|
|
193
|
+
if sitenum <= @max_site
|
|
194
|
+
if @channelmap[chanmapname][sitenum][pinname].channel.downcase.include?('hc')
|
|
195
|
+
return '_HC'
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
nil # if nothing matched
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def assign_dc_instr_pins(dc_pins)
|
|
202
|
+
if !dc_pins.is_a?(Array)
|
|
203
|
+
@dc_pins = [] << dc_pins
|
|
204
|
+
else
|
|
205
|
+
@dc_pins = dc_pins
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def assign_digsrc_pins(digsrc_pins)
|
|
210
|
+
if !digsrc_pins.is_a?(Array)
|
|
211
|
+
@digsrc_pins = [] << digsrc_pins
|
|
212
|
+
else
|
|
213
|
+
@digsrc_pins = digsrc_pins
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def assign_digcap_pins(digcap_pins)
|
|
218
|
+
if !digcap_pins.is_a?(Array)
|
|
219
|
+
@digcap_pins = [] << digcap_pins
|
|
220
|
+
else
|
|
221
|
+
@digcap_pins = digcap_pins
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def get_dc_instr_pins
|
|
226
|
+
@dc_pins
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def get_digsrc_pins
|
|
230
|
+
@digsrc_pins
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def get_digcap_pins
|
|
234
|
+
@digcap_pins
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def flows
|
|
238
|
+
parser.flows
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Main accessor to all content parsed from existing test program sheets found in the
|
|
242
|
+
# supplied directory or in Origen.config.test_program_output_directory
|
|
243
|
+
def parser(prog_dir = Origen.config.test_program_output_directory)
|
|
244
|
+
unless prog_dir
|
|
245
|
+
fail 'You must supply the directory containing the test program sheets, or define it via Origen.config.test_program_output_directory'
|
|
246
|
+
end
|
|
247
|
+
@parser ||= IGXLBasedTester::Parser.new
|
|
248
|
+
@parsed_dir ||= false
|
|
249
|
+
if @parsed_dir != prog_dir
|
|
250
|
+
@parser.parse(prog_dir)
|
|
251
|
+
@parsed_dir = prog_dir
|
|
252
|
+
end
|
|
253
|
+
@parser
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Capture a vector to the tester HRAM.
|
|
257
|
+
#
|
|
258
|
+
# This method applies a store vector (stv) opcode to the previous vector, note that is does
|
|
259
|
+
# not actually generate a new vector.
|
|
260
|
+
#
|
|
261
|
+
# Sometimes when generating vectors within a loop you may want to apply a stv opcode
|
|
262
|
+
# retrospectively to a previous vector, passing in an offset option will allow you
|
|
263
|
+
# to do this.
|
|
264
|
+
#
|
|
265
|
+
# On J750 the pins argument is ignored since the tester only supports whole vector capture.
|
|
266
|
+
#
|
|
267
|
+
# @example
|
|
268
|
+
# $tester.cycle # This is the vector you want to capture
|
|
269
|
+
# $tester.store # This applies the STV opcode
|
|
270
|
+
#
|
|
271
|
+
# $tester.cycle # This one gets stored
|
|
272
|
+
# $tester.cycle
|
|
273
|
+
# $tester.cycle
|
|
274
|
+
# $tester.store(:offset => -2) # Just realized I need to capture that earlier vector
|
|
275
|
+
def store(*pins)
|
|
276
|
+
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
|
277
|
+
options = { offset: 0
|
|
278
|
+
}.merge(options)
|
|
279
|
+
update_vector microcode: 'stv', offset: options[:offset]
|
|
280
|
+
last_vector(options[:offset]).contains_capture = true
|
|
281
|
+
end
|
|
282
|
+
alias_method :to_hram, :store
|
|
283
|
+
alias_method :capture, :store
|
|
284
|
+
|
|
285
|
+
# Capture the next vector generated to HRAM
|
|
286
|
+
#
|
|
287
|
+
# This method applies a store vector (stv) opcode to the next vector to be generated,
|
|
288
|
+
# note that is does not actually generate a new vector.
|
|
289
|
+
#
|
|
290
|
+
# On J750 the pins argument is ignored since the tester only supports whole vector capture.
|
|
291
|
+
#
|
|
292
|
+
# @example
|
|
293
|
+
# $tester.store_next_cycle
|
|
294
|
+
# $tester.cycle # This is the vector that will be captured
|
|
295
|
+
def store_next_cycle(*pins)
|
|
296
|
+
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
|
297
|
+
options = {
|
|
298
|
+
}.merge(options)
|
|
299
|
+
|
|
300
|
+
preset_next_vector microcode: 'stv' do |vector|
|
|
301
|
+
vector.contains_capture = true
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
alias_method :store!, :store_next_cycle
|
|
305
|
+
|
|
306
|
+
# @api private
|
|
307
|
+
def remove_store_from_vector(vector)
|
|
308
|
+
super
|
|
309
|
+
vector.microcode = nil
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
# Call a subroutine.
|
|
313
|
+
#
|
|
314
|
+
# This method applies a call subroutine opcode to the previous vector, it does not
|
|
315
|
+
# generate a new vector.
|
|
316
|
+
#
|
|
317
|
+
# Subroutines should always be called through this method as it ensures a running
|
|
318
|
+
# log of called subroutines is maintained and which then gets output in the pattern
|
|
319
|
+
# header to import the right dependencies.
|
|
320
|
+
#
|
|
321
|
+
# An offset option is available to make the call on earlier vectors.
|
|
322
|
+
#
|
|
323
|
+
# ==== Examples
|
|
324
|
+
# $tester.call_subroutine("mysub")
|
|
325
|
+
# $tester.call_subroutine("my_other_sub", :offset => -1)
|
|
326
|
+
def call_subroutine(name, options = {})
|
|
327
|
+
options = {
|
|
328
|
+
offset: 0
|
|
329
|
+
}.merge(options)
|
|
330
|
+
called_subroutines << name.to_s.chomp unless called_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
|
|
331
|
+
update_vector microcode: "call #{name}", offset: options[:offset]
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
# Start a subroutine.
|
|
335
|
+
#
|
|
336
|
+
# Generates a global subroutine label. Global is used to adhere to the best practice of
|
|
337
|
+
# containing all subroutines in dedicated patterns, e.g. global_subs.atp
|
|
338
|
+
#
|
|
339
|
+
# ==== Examples
|
|
340
|
+
# $tester.start_subroutine("wait_for_done")
|
|
341
|
+
# < generate your subroutine vectors here >
|
|
342
|
+
# $tester.end_subroutine
|
|
343
|
+
def start_subroutine(name, options = {})
|
|
344
|
+
local_subroutines << name.to_s.chomp unless local_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
|
|
345
|
+
if $tester.ultraflex? && (name =~ /keep_?alive/ || options[:keep_alive])
|
|
346
|
+
microcode "keepalive subr #{name}:"
|
|
347
|
+
else
|
|
348
|
+
microcode "global subr #{name}:"
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# End a subroutine.
|
|
353
|
+
#
|
|
354
|
+
# Generates a return opcode on the last vector.
|
|
355
|
+
#
|
|
356
|
+
# ==== Examples
|
|
357
|
+
# $tester.start_subroutine("wait_for_done")
|
|
358
|
+
# < generate your subroutine vectors here >
|
|
359
|
+
# $tester.end_subroutine
|
|
360
|
+
# cond: whether return is conditional on a flag (to permit to mix subrs together)
|
|
361
|
+
def end_subroutine(cond = false, options = {})
|
|
362
|
+
(cond, options) = false, cond if cond.is_a?(Hash)
|
|
363
|
+
if cond
|
|
364
|
+
update_vector microcode: 'if (flag) return'
|
|
365
|
+
else
|
|
366
|
+
update_vector microcode: 'return'
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# Do a frequency measure.
|
|
371
|
+
#
|
|
372
|
+
# Write the necessary micro code to do a frequency measure on the given pin,
|
|
373
|
+
# optionally supply a read code to pass information to the tester.
|
|
374
|
+
#
|
|
375
|
+
# ==== Examples
|
|
376
|
+
# $tester.freq_count($top.pin(:d_out)) # Freq measure on pin "d_out"
|
|
377
|
+
# $tester.freq_count($top.pin(:d_out):readcode => 10)
|
|
378
|
+
def freq_count(pin, options = {})
|
|
379
|
+
options = { readcode: false
|
|
380
|
+
}.merge(options)
|
|
381
|
+
|
|
382
|
+
set_code(options[:readcode]) if options[:readcode]
|
|
383
|
+
cycle(microcode: "#{@microcode[:set_flag]} (cpuA)")
|
|
384
|
+
cycle(microcode: "#{@microcode[:set_flag]} (cpuA)")
|
|
385
|
+
cycle(microcode: "#{@microcode[:set_flag]} (cpuB)")
|
|
386
|
+
cycle(microcode: "#{@microcode[:set_flag]} (cpuC)")
|
|
387
|
+
cycle(microcode: 'freq_loop_1:')
|
|
388
|
+
cycle(microcode: 'if (cpuA) jump freq_loop_1')
|
|
389
|
+
pin.drive_lo
|
|
390
|
+
delay(2000)
|
|
391
|
+
pin.dont_care
|
|
392
|
+
cycle(microcode: "freq_loop_2: #{@microcode[:enable]} (#{@flags[1]})")
|
|
393
|
+
cycle(microcode: 'if (flag) jump freq_loop_2')
|
|
394
|
+
cycle(microcode: "#{@microcode[:enable]} (#{@flags[2]})")
|
|
395
|
+
cycle(microcode: 'if (flag) jump freq_loop_1')
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
# * J750 Specific *
|
|
399
|
+
#
|
|
400
|
+
# Generates a single MTO opcode line for J750
|
|
401
|
+
#
|
|
402
|
+
# Codes implemented: xa load_preset, xa inc, ya load_preset, ya inc, stv_m0, stv_m1, stv_c<br>
|
|
403
|
+
def memory_test(options = {})
|
|
404
|
+
options = {
|
|
405
|
+
gen_vector: true, # Default generate vector not just MTO opcode
|
|
406
|
+
init_counter_x: false, # initialize counter X
|
|
407
|
+
inc_counter_x: false, # increment counter X
|
|
408
|
+
init_counter_y: false, # initialize counter X
|
|
409
|
+
inc_counter_y: false, # increment counter X
|
|
410
|
+
capture_vector: false, # capture vector to memory using all mem types
|
|
411
|
+
capture_vector_mem0: false, # capture vector to memory type 0, here for J750 will be stv_m0
|
|
412
|
+
capture_vector_mem1: false, # capture vector to memory type 1, here for J750 will be stv_m1
|
|
413
|
+
capture_vector_mem2: false, # capture vector to memory type 2, here for J750 will be stv_c
|
|
414
|
+
pin: false, # pin on which to drive or expect data, pass pin object here!
|
|
415
|
+
pin_data: false, # pin data (:none, :drive, :expect)
|
|
416
|
+
}.merge(options)
|
|
417
|
+
|
|
418
|
+
mto_opcode = ''
|
|
419
|
+
|
|
420
|
+
if options[:init_counter_x]
|
|
421
|
+
mto_opcode += ' xa load_preset'
|
|
422
|
+
end
|
|
423
|
+
if options[:inc_counter_x]
|
|
424
|
+
mto_opcode += ' xa inc'
|
|
425
|
+
end
|
|
426
|
+
if options[:init_counter_y]
|
|
427
|
+
mto_opcode += ' ya load_preset'
|
|
428
|
+
end
|
|
429
|
+
if options[:inc_counter_y]
|
|
430
|
+
mto_opcode += ' ya inc'
|
|
431
|
+
end
|
|
432
|
+
if options[:capture_vector]
|
|
433
|
+
mto_opcode += ' stv_m0 stv_m1 stv_c'
|
|
434
|
+
end
|
|
435
|
+
if options[:capture_vector_mem0]
|
|
436
|
+
mto_opcode += ' stv_m0'
|
|
437
|
+
end
|
|
438
|
+
if options[:capture_vector_mem1]
|
|
439
|
+
mto_opcode += ' stv_m1'
|
|
440
|
+
end
|
|
441
|
+
if options[:capture_vector_mem2]
|
|
442
|
+
mto_opcode += ' stv_c'
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
unless mto_opcode.eql?('')
|
|
446
|
+
mto_opcode = '(mto:' + mto_opcode + ')'
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
if options[:gen_vector]
|
|
450
|
+
if options[:pin]
|
|
451
|
+
case options[:pin_data]
|
|
452
|
+
when :drive
|
|
453
|
+
# store current pin state
|
|
454
|
+
cur_pin_state = options[:pin].state.to_sym
|
|
455
|
+
options[:pin].drive_mem
|
|
456
|
+
when :expect
|
|
457
|
+
# store current pin state
|
|
458
|
+
cur_pin_state = options[:pin].state.to_sym
|
|
459
|
+
options[:pin].expect_mem
|
|
460
|
+
end
|
|
461
|
+
end
|
|
462
|
+
cycle(microcode: "#{mto_opcode}")
|
|
463
|
+
if options[:pin]
|
|
464
|
+
# restore previous pin state
|
|
465
|
+
case options[:pin_data]
|
|
466
|
+
when :drive
|
|
467
|
+
options[:pin].state = cur_pin_state
|
|
468
|
+
when :expect
|
|
469
|
+
options[:pin].state = cur_pin_state
|
|
470
|
+
end
|
|
471
|
+
end
|
|
472
|
+
else
|
|
473
|
+
microcode "#{mto_opcode}"
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
# Generates a match loop on up to two pins.
|
|
478
|
+
#
|
|
479
|
+
# This method is not really intended to be called directly, rather you should call
|
|
480
|
+
# via Tester#wait e.g. $tester.wait(:match => true).
|
|
481
|
+
#
|
|
482
|
+
# The timeout should be provided in cycles, however when called via the wait method the
|
|
483
|
+
# time-based helpers (time_in_us, etc) will be converted to cycles for you.
|
|
484
|
+
# The following options are available to tailor the match loop behavior, defaults in
|
|
485
|
+
# parenthesis:
|
|
486
|
+
# * :pin - The pin object to match on (*required*)
|
|
487
|
+
# * :state - The pin state to match on, :low or :high (*required*)
|
|
488
|
+
# * :pin2 (nil) - Optionally supply a second pin to match on
|
|
489
|
+
# * :state2 (nil) - State for the second pin (required if :pin2 is supplied)
|
|
490
|
+
# * :check_for_fails (false) - Flushes the pipeline and handshakes with the tester (passing readcode 100) prior to the match (to allow binout of fails encountered before the match)
|
|
491
|
+
# * :force_fail_on_timeout (true) - Force a vector mis-compare if the match loop times out
|
|
492
|
+
# * :on_timeout_goto ("") - Optionally supply a label to branch to on timeout, by default will continue from the end of the match loop
|
|
493
|
+
# * :on_pin_match_goto ("") - Optionally supply a label to branch to when pin 1 matches, by default will continue from the end of the match loop
|
|
494
|
+
# * :on_pin2_match_goto ("") - Optionally supply a label to branch to when pin 2 matches, by default will continue from the end of the match loop
|
|
495
|
+
# * :multiple_entries (false) - Supply an integer to generate multiple entries into the match (each with a unique readcode), this can be useful when debugging patterns with multiple matches
|
|
496
|
+
# * :force_fail_on_timeout (true) - force pattern to fail if timeout occurs
|
|
497
|
+
# * :global_loops (false) - whether match loop loops should use global labels
|
|
498
|
+
# * :manual_stop (false) - whether to use extra cpuB flag to resolve IG-XL v.3.50.xx bug where VBT clears cpuA immediately
|
|
499
|
+
# at start of PatFlagFunc instead of at end. Use will have to manually clear cpuB to resume this pattern.
|
|
500
|
+
# ==== Examples
|
|
501
|
+
# $tester.wait(:match => true, :time_in_us => 5000, :pin => $top.pin(:done), :state => :high)
|
|
502
|
+
def match(pin, state, timeout, options = {})
|
|
503
|
+
options = {
|
|
504
|
+
check_for_fails: false,
|
|
505
|
+
on_timeout_goto: false,
|
|
506
|
+
pin2: false,
|
|
507
|
+
state2: false,
|
|
508
|
+
on_pin_match_goto: false,
|
|
509
|
+
multiple_entries: false,
|
|
510
|
+
force_fail_on_timeout: true,
|
|
511
|
+
global_loops: false,
|
|
512
|
+
manual_stop: false,
|
|
513
|
+
clr_fail_post_match: false
|
|
514
|
+
}.merge(options)
|
|
515
|
+
options[:on_block_match_goto] ||= options.delete(:on_pin_match_goto)
|
|
516
|
+
|
|
517
|
+
match_block(timeout, options) do |match_conditions, fail_conditions|
|
|
518
|
+
# Define match conditions
|
|
519
|
+
match_conditions.add do
|
|
520
|
+
state == :low ? pin.expect_lo : pin.expect_hi
|
|
521
|
+
cc "Check if #{pin.name} is #{state == :low ? 'low' : 'high'}"
|
|
522
|
+
cycle
|
|
523
|
+
pin.dont_care
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
if options[:pin2]
|
|
527
|
+
match_conditions.add do
|
|
528
|
+
state == :low ? pin.expect_hi : pin.expect_lo
|
|
529
|
+
options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi
|
|
530
|
+
cc "Check if #{options[:pin2].name} is #{options[:state2] == :low ? 'low' : 'high'}"
|
|
531
|
+
cycle
|
|
532
|
+
options[:pin2].dont_care
|
|
533
|
+
pin.dont_care
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
# Define fail conditions
|
|
538
|
+
fail_conditions.add do
|
|
539
|
+
state == :low ? pin.expect_lo : pin.expect_hi
|
|
540
|
+
cc "Check if #{pin.name} is #{state == :low ? 'low' : 'high'}"
|
|
541
|
+
if options[:pin2]
|
|
542
|
+
options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi
|
|
543
|
+
cc "Check if #{options[:pin2].name} is #{options[:state2] == :low ? 'low' : 'high'}"
|
|
544
|
+
end
|
|
545
|
+
cycle
|
|
546
|
+
pin.dont_care
|
|
547
|
+
options[:pin2].dont_care if options[:pin2]
|
|
548
|
+
end
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
# Call a match loop.
|
|
553
|
+
#
|
|
554
|
+
# Normally you would put your match loop in a global subs pattern, then you can
|
|
555
|
+
# call it via this method. This method automatically syncs match loop naming with
|
|
556
|
+
# the match generation flow, no arguments required.
|
|
557
|
+
#
|
|
558
|
+
# This is an IGXLBasedTester specific API.
|
|
559
|
+
#
|
|
560
|
+
# ==== Examples
|
|
561
|
+
# $tester.cycle
|
|
562
|
+
# $tester.call_match # Calls the match loop, or the first entry point if you have multiple
|
|
563
|
+
# $tester.cycle
|
|
564
|
+
# $tester.call_match # Calls the match loop, or the second entry point if you have multiple
|
|
565
|
+
def call_match
|
|
566
|
+
@match_counter = @match_counter || 0
|
|
567
|
+
call_subroutine("match_done_#{@match_counter}")
|
|
568
|
+
@match_counter += 1 unless @match_counter == (@match_entries || 1) - 1
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
# Apply a label to the pattern.
|
|
572
|
+
#
|
|
573
|
+
# No additional vector is generated.
|
|
574
|
+
# Arguments:
|
|
575
|
+
# name : label name
|
|
576
|
+
# global : (optional) whether to apply global label, default=false
|
|
577
|
+
#
|
|
578
|
+
# ==== Examples
|
|
579
|
+
# $tester.label("something_significant")
|
|
580
|
+
# $tester.label("something_significant",true) # apply global label
|
|
581
|
+
def label(name, global = false)
|
|
582
|
+
global_opt = (global) ? 'global ' : ''
|
|
583
|
+
microcode global_opt + name + ':'
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
# * J750 Specific *
|
|
587
|
+
#
|
|
588
|
+
# Set a readcode.
|
|
589
|
+
#
|
|
590
|
+
# Use the set an explicit readcode for communicating with the tester. This method
|
|
591
|
+
# will generate an additional vector.
|
|
592
|
+
#
|
|
593
|
+
# ==== Examples
|
|
594
|
+
# $tester.set_code(55)
|
|
595
|
+
def set_code(code)
|
|
596
|
+
cycle(microcode: "set_code #{code}")
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
# Branch execution to the given point.
|
|
600
|
+
#
|
|
601
|
+
# This generates a new vector with a jump instruction to a given label. This method
|
|
602
|
+
# will generate an additional vector.
|
|
603
|
+
#
|
|
604
|
+
# ==== Examples
|
|
605
|
+
# $tester.branch_to("something_significant")
|
|
606
|
+
def branch_to(label)
|
|
607
|
+
cycle(microcode: "jump #{label}")
|
|
608
|
+
end
|
|
609
|
+
alias_method :branch, :branch_to
|
|
610
|
+
|
|
611
|
+
# Add loop to the pattern.
|
|
612
|
+
#
|
|
613
|
+
# Pass in a name for the loop and the number of times to execute it, all vectors
|
|
614
|
+
# generated by the given block will be captured in the loop.
|
|
615
|
+
#
|
|
616
|
+
# Optional arguments: global - whether to apply global label (default=false)
|
|
617
|
+
# label_first - whether to apply loop label before loop vector or not
|
|
618
|
+
#
|
|
619
|
+
# ==== Examples
|
|
620
|
+
# $tester.loop_vectors("pulse_loop", 3) do # Do this 3 times...
|
|
621
|
+
# $tester.cycle
|
|
622
|
+
# some_other_method_to_generate_vectors
|
|
623
|
+
# end
|
|
624
|
+
def loop_vectors(name, number_of_loops, global = false, label_first = false)
|
|
625
|
+
if number_of_loops > 1
|
|
626
|
+
@loop_counters ||= {}
|
|
627
|
+
if @loop_counters[name]
|
|
628
|
+
@loop_counters[name] += 1
|
|
629
|
+
else
|
|
630
|
+
@loop_counters[name] = 0
|
|
631
|
+
end
|
|
632
|
+
loop_name = @loop_counters[name] == 0 ? name : "#{name}_#{@loop_counters[name]}"
|
|
633
|
+
if label_first
|
|
634
|
+
global_opt = (global) ? 'global ' : ''
|
|
635
|
+
microcode "#{global_opt}#{loop_name}: "
|
|
636
|
+
end
|
|
637
|
+
cycle(microcode: "loopA #{number_of_loops}")
|
|
638
|
+
unless label_first
|
|
639
|
+
global_opt = (global) ? 'global ' : ''
|
|
640
|
+
cycle(microcode: "#{global_opt}#{loop_name}: ")
|
|
641
|
+
end
|
|
642
|
+
yield
|
|
643
|
+
cycle(microcode: "end_loopA #{loop_name}")
|
|
644
|
+
else
|
|
645
|
+
yield
|
|
646
|
+
end
|
|
647
|
+
end
|
|
648
|
+
alias_method :loop_vector, :loop_vectors
|
|
649
|
+
|
|
650
|
+
# An internal method called by Origen Pattern Create to create the pattern header
|
|
651
|
+
def pattern_header(options = {})
|
|
652
|
+
options = {
|
|
653
|
+
instruments: {}, # Provide instruments here if desired as a hash (e.g. "mto" => "dgen_2bit")
|
|
654
|
+
subroutine_pat: false,
|
|
655
|
+
svm_only: true, # Whether 'svm_only' can be specified
|
|
656
|
+
group: false, # If true the end pattern is intended to run within a pattern group
|
|
657
|
+
high_voltage: false, # Supply a pin name here to declare it as an HV instrument (not yet defined)
|
|
658
|
+
freq_counter: false, # Supply a pin name here to declare it as a frequency counter
|
|
659
|
+
memory_test: false, # If true, define 2-bit MTO DGEN as instrument
|
|
660
|
+
}.merge(options)
|
|
661
|
+
|
|
662
|
+
if level_period?
|
|
663
|
+
microcode "import tset #{min_period_timeset.name};"
|
|
664
|
+
else
|
|
665
|
+
called_timesets.each do |timeset|
|
|
666
|
+
microcode "import tset #{timeset.name};"
|
|
667
|
+
end
|
|
668
|
+
end
|
|
669
|
+
unless options[:group] # Withhold imports for pattern groups, is this correct?
|
|
670
|
+
called_subroutines.each do |sub_name|
|
|
671
|
+
# Don't import any called subroutines that are declared in the current pattern
|
|
672
|
+
microcode "import svm_subr #{sub_name};" unless local_subroutines.include?(sub_name)
|
|
673
|
+
end
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
# If memory test, then add to instruments hash
|
|
677
|
+
if options[:memory_test]
|
|
678
|
+
options[:instruments].merge!('mto' => 'dgen_2bit')
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
if options[:svm_only]
|
|
682
|
+
microcode "svm_only_file = #{options[:subroutine_pat] ? 'yes' : 'no'};"
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
microcode "opcode_mode = #{@opcode_mode};"
|
|
686
|
+
microcode "digital_inst = #{options[:digital_inst]};" if options[:digital_inst]
|
|
687
|
+
microcode 'compressed = yes;' # if $dut.gzip_patterns
|
|
688
|
+
if tester.j750? && options[:freq_counter]
|
|
689
|
+
# pin setup type => freq_counter is only for the J750.
|
|
690
|
+
# UltraFLEX has frequency counter capability behind every pin.
|
|
691
|
+
# need to make sure the pin_setup freq_count is defined after opcode_mode extended since freq count only work in extended mode
|
|
692
|
+
if @opcode_mode == :extended
|
|
693
|
+
microcode "pin_setup = {#{options[:freq_counter]} freq_count;}"
|
|
694
|
+
else
|
|
695
|
+
fail 'pin_setup freq_count can only work in extended mode'
|
|
696
|
+
end
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
# Take care of any instruments
|
|
700
|
+
options[:instruments] = options[:instruments].merge(@pushed_instrument_configs)
|
|
701
|
+
if options[:instruments].length > 0
|
|
702
|
+
microcode 'instruments = {'
|
|
703
|
+
options[:instruments].each do |pins, instrument|
|
|
704
|
+
if "#{pins}" == 'nil'
|
|
705
|
+
microcode " #{instrument};"
|
|
706
|
+
elsif instrument == 'digsrc'
|
|
707
|
+
microcode " #{pins}:#{instrument} #{options[:digsrc_width]}:#{options[:digsrc_bit_order]}:#{options[:digsrc_mode]}:format=#{options[:digsrc_format]}:#{options[:digsrc_site_uniqueness]}:#{options[:digsrc_auto_cond]};"
|
|
708
|
+
elsif instrument == 'digcap'
|
|
709
|
+
microcode " #{pins}:#{instrument} #{options[:digcap_width]}:#{options[:digcap_bit_order]}:#{options[:digcap_mode]}:format=#{options[:digcap_format]}:data_type=#{options[:digcap_data_type]}:#{options[:digcap_auto_cond]}:#{options[:digcap_auto_trig_enable]}:#{options[:digcap_store_stv]}:#{options[:digcap_receive_data]};"
|
|
710
|
+
else
|
|
711
|
+
microcode " #{pins}:#{instrument};"
|
|
712
|
+
end
|
|
713
|
+
end
|
|
714
|
+
microcode '}'
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
options[:high_voltage] = @use_hv_pin
|
|
718
|
+
microcode "pin_setup = {#{options[:high_voltage]} high_voltage;}" if options[:high_voltage]
|
|
719
|
+
microcode ''
|
|
720
|
+
|
|
721
|
+
pin_list = ordered_pins.map(&:name).join(', ')
|
|
722
|
+
|
|
723
|
+
# here indicate pattern header specific stuff
|
|
724
|
+
yield pin_list
|
|
725
|
+
if ordered_pins.size > 0
|
|
726
|
+
max_pin_name_length = ordered_pins.map(&:name).max { |a, b| a.length <=> b.length }.length
|
|
727
|
+
pin_widths = ordered_pins.map { |p| p.size - 1 }
|
|
728
|
+
|
|
729
|
+
max_pin_name_length.times do |i|
|
|
730
|
+
cc((' ' * 93) + ordered_pins.map.with_index { |p, x| ((p.name[i] || ' ') + ' ' * pin_widths[x]).gsub('_', '-') }.join(' '))
|
|
731
|
+
end
|
|
732
|
+
end
|
|
733
|
+
end
|
|
734
|
+
|
|
735
|
+
# An internal method called by Origen to generate the pattern footer
|
|
736
|
+
def pattern_footer(options = {})
|
|
737
|
+
options = {
|
|
738
|
+
subroutine_pat: false,
|
|
739
|
+
end_in_ka: false,
|
|
740
|
+
end_with_halt: false,
|
|
741
|
+
end_module: true
|
|
742
|
+
}.merge(options)
|
|
743
|
+
$tester.align_to_last
|
|
744
|
+
# cycle(:microcode => "#{$dut.end_of_pattern_label}:") if $dut.end_of_pattern_label
|
|
745
|
+
if options[:end_in_ka]
|
|
746
|
+
keep_alive(options)
|
|
747
|
+
else
|
|
748
|
+
if options[:end_with_halt]
|
|
749
|
+
$tester.cycle microcode: 'halt'
|
|
750
|
+
else
|
|
751
|
+
if options[:end_module]
|
|
752
|
+
$tester.cycle microcode: 'end_module' unless options[:subroutine_pat]
|
|
753
|
+
else
|
|
754
|
+
$tester.cycle
|
|
755
|
+
end
|
|
756
|
+
end
|
|
757
|
+
end
|
|
758
|
+
microcode '}'
|
|
759
|
+
end
|
|
760
|
+
|
|
761
|
+
# Returns an array of subroutines called while generating the current pattern
|
|
762
|
+
def called_subroutines
|
|
763
|
+
@called_subroutines ||= []
|
|
764
|
+
end
|
|
765
|
+
|
|
766
|
+
# Returns an array of subroutines created by the current pattern
|
|
767
|
+
def local_subroutines # :nodoc:
|
|
768
|
+
@local_subroutines ||= []
|
|
769
|
+
end
|
|
770
|
+
|
|
771
|
+
# This is an internal method use by Origen which returns a fully formatted vector
|
|
772
|
+
# You can override this if you wish to change the output formatting at vector level
|
|
773
|
+
def format_vector(vec)
|
|
774
|
+
timeset = vec.timeset ? "> #{vec.timeset.name}" : ''
|
|
775
|
+
pin_vals = vec.pin_vals ? "#{vec.pin_vals} ;" : ''
|
|
776
|
+
if vec.repeat > 1
|
|
777
|
+
microcode = "repeat #{vec.repeat}"
|
|
778
|
+
else
|
|
779
|
+
microcode = vec.microcode ? vec.microcode : ''
|
|
780
|
+
end
|
|
781
|
+
if vec.pin_vals && ($_testers_enable_vector_comments || vector_comments)
|
|
782
|
+
comment = " // #{vec.number}:#{vec.cycle} #{vec.inline_comment}"
|
|
783
|
+
else
|
|
784
|
+
comment = vec.inline_comment.empty? ? '' : " // #{vec.inline_comment}"
|
|
785
|
+
end
|
|
786
|
+
|
|
787
|
+
"#{microcode.ljust(65)}#{timeset.ljust(31)}#{pin_vals}#{comment}"
|
|
788
|
+
end
|
|
789
|
+
|
|
790
|
+
# Override this to force the formatting to match the v1 J750 model (easier diffs)
|
|
791
|
+
def push_microcode(code) # :nodoc:
|
|
792
|
+
stage.store(code.ljust(65) + ''.ljust(31))
|
|
793
|
+
end
|
|
794
|
+
alias_method :microcode, :push_microcode
|
|
795
|
+
|
|
796
|
+
# All vectors generated with the supplied block will have all pins set
|
|
797
|
+
# to the repeat previous state. Any pins that are changed state within
|
|
798
|
+
# the block will still update to the supplied value.
|
|
799
|
+
# ==== Example
|
|
800
|
+
# # All pins except invoke will be assigned the repeat previous code
|
|
801
|
+
# # in the generated vector. On completion of the block they will
|
|
802
|
+
# # return to their previous state, except for invoke which will
|
|
803
|
+
# # retain the value assigned within the block.
|
|
804
|
+
# $tester.repeat_previous do
|
|
805
|
+
# $top.pin(:invoke).drive(1)
|
|
806
|
+
# $tester.cycle
|
|
807
|
+
# end
|
|
808
|
+
def repeat_previous
|
|
809
|
+
pinmap = Origen.pin_bank.pins
|
|
810
|
+
pinmap.each { |id, pin| pin.repeat_previous = true }
|
|
811
|
+
yield
|
|
812
|
+
pinmap.each { |id, pin| pin.repeat_previous = false }
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
def ignore_fails(*pins)
|
|
816
|
+
pins.each(&:suspend)
|
|
817
|
+
yield
|
|
818
|
+
pins.each(&:resume)
|
|
819
|
+
end
|
|
820
|
+
|
|
821
|
+
def enable_flag(options = {})
|
|
822
|
+
options = { flagnum: 4, # default flag to use
|
|
823
|
+
}.merge(options)
|
|
824
|
+
|
|
825
|
+
if options[:flagnum] > @flags.length
|
|
826
|
+
abort "ERROR! Invalid flag value passed to 'enable_flag' method!\n"
|
|
827
|
+
end
|
|
828
|
+
flagname = @flags[options[:flagnum] - 1]
|
|
829
|
+
update_vector(microcode: "#{@microcode[:enable]}(#{flagname})")
|
|
830
|
+
end
|
|
831
|
+
|
|
832
|
+
def set_flag(options = {})
|
|
833
|
+
options = { flagnum: 4, # default flag to use
|
|
834
|
+
}.merge(options)
|
|
835
|
+
|
|
836
|
+
if options[:flagnum] > @flags.length
|
|
837
|
+
abort "ERROR! Invalid flag value passed to 'set_flag' method!\n"
|
|
838
|
+
end
|
|
839
|
+
flagname = @flags[options[:flagnum] - 1]
|
|
840
|
+
update_vector(microcode: "#{@microcode[:set_flag]}(#{flagname})")
|
|
841
|
+
end
|
|
842
|
+
|
|
843
|
+
def cycle(options = {})
|
|
844
|
+
# handle overlay if requested
|
|
845
|
+
ovly_style = nil
|
|
846
|
+
if options.key?(:overlay)
|
|
847
|
+
ovly_style = options[:overlay][:overlay_style].nil? ? @overlay_style : options[:overlay][:overlay_style]
|
|
848
|
+
overlay_str = options[:overlay][:overlay_str]
|
|
849
|
+
|
|
850
|
+
# route the overlay request to the appropriate method
|
|
851
|
+
case ovly_style
|
|
852
|
+
when :subroutine, :default
|
|
853
|
+
subroutine_overlay(overlay_str, options)
|
|
854
|
+
ovly_style = :subroutine
|
|
855
|
+
when :label, :global_label
|
|
856
|
+
options[:dont_compress] = true
|
|
857
|
+
unless @overlay_history.key?(overlay_str)
|
|
858
|
+
# J750 behavior is local label not global
|
|
859
|
+
label "#{overlay_str}", (ovly_style == :global_label)
|
|
860
|
+
@overlay_history[overlay_str] = { is_label: true }
|
|
861
|
+
end
|
|
862
|
+
when :digsrc
|
|
863
|
+
if ultraflex?
|
|
864
|
+
cur_pin_state = options[:overlay][:pins].state.to_sym
|
|
865
|
+
options[:overlay][:pins].drive_mem
|
|
866
|
+
options = digsrc_overlay(options)
|
|
867
|
+
else
|
|
868
|
+
ovly_style = overlay_style_warn(options[:overlay][:overlay_str], options)
|
|
869
|
+
end
|
|
870
|
+
else
|
|
871
|
+
ovly_style = overlay_style_warn(options[:overlay][:overlay_str], options)
|
|
872
|
+
end # case ovly_style
|
|
873
|
+
else
|
|
874
|
+
@overlay_subr = nil
|
|
875
|
+
end # of handle overlay
|
|
876
|
+
|
|
877
|
+
options_overlay = options.delete(:overlay) if options.key?(:overlay)
|
|
878
|
+
unless ovly_style == :subroutine
|
|
879
|
+
if @mask_vector
|
|
880
|
+
# tack on masking opcodes
|
|
881
|
+
super(options.merge(microcode: "#{options[:microcode]} #{@microcode[:mask_vector]}"))
|
|
882
|
+
else
|
|
883
|
+
super(options)
|
|
884
|
+
end
|
|
885
|
+
end # unless ovly_style
|
|
886
|
+
|
|
887
|
+
unless options_overlay.nil?
|
|
888
|
+
options_overlay[:pins].state = cur_pin_state if ovly_style == :digsrc
|
|
889
|
+
# stage = :body if ovly_style == :subroutine # always set stage back to body in case subr overlay was selected
|
|
890
|
+
end
|
|
891
|
+
end
|
|
892
|
+
|
|
893
|
+
# Warn user of unsupported overlay style
|
|
894
|
+
def overlay_style_warn(overlay_str, options)
|
|
895
|
+
Origen.log.warn("Unrecognized overlay style :#{@overlay_style}, defaulting to subroutine")
|
|
896
|
+
Origen.log.warn('Available overlay styles :label, :global_label, :subroutine') if j750? || j750_hpt?
|
|
897
|
+
Origen.log.warn('Available overlay styles :digsrc, :digsrc_subroutine, :label, :global_label, :subroutine') if ultraflex?
|
|
898
|
+
subroutine_overlay(overlay_str, options)
|
|
899
|
+
@overlay_style = :subroutine # Just give 1 warning
|
|
900
|
+
end
|
|
901
|
+
|
|
902
|
+
# Call this method at the start of any digsrc overlay operations, this method
|
|
903
|
+
# takes care of all the microcodes and delays that's needed for digsrc overlay
|
|
904
|
+
# Required arguments:
|
|
905
|
+
# pins
|
|
906
|
+
# Optionsal arguments:
|
|
907
|
+
# options[:dssc_mode] = :single or :dual, anything else wil be
|
|
908
|
+
# treated as if it's operating in :quad mode
|
|
909
|
+
def digsrc_start(pins, options = {})
|
|
910
|
+
options = {
|
|
911
|
+
dssc_mode: :single # defaults dssc_mode to single mode
|
|
912
|
+
}.merge(options)
|
|
913
|
+
if pins.size > 1
|
|
914
|
+
microcode "((#{format_multiple_instrument_pins(pins)}):DigSrc = Start)"
|
|
915
|
+
else
|
|
916
|
+
microcode "((#{pin}):DigSrc = Start)"
|
|
917
|
+
end
|
|
918
|
+
if options[:dssc_mode] == :single
|
|
919
|
+
$tester.cycle(repeat: 145) # minimum of 144 cycles, adding 1 for safey measures
|
|
920
|
+
elsif options[:dssc_mode] == :dual
|
|
921
|
+
$tester.cycle(repeat: 289) # minimum of 288 cycles, adding 1 for safety measures
|
|
922
|
+
else
|
|
923
|
+
$tester.cycle(repeat: 577) # minimum of 577 cycles, adding 1 for safety measures
|
|
924
|
+
end
|
|
925
|
+
end
|
|
926
|
+
|
|
927
|
+
# Call this method at the end of each digscr overlay operation to clear the pattern
|
|
928
|
+
# memory pipeline, so that the pattern is ready to do the next digsrc overlay operation.
|
|
929
|
+
# Required arguments:
|
|
930
|
+
# pins
|
|
931
|
+
def digsrc_stop(pins, options = {})
|
|
932
|
+
if pins.size > 1
|
|
933
|
+
microcode "((#{format_multiple_instrument_pins(pins)}):DigSrc = Stop)"
|
|
934
|
+
else
|
|
935
|
+
microcode "((#{pins}):DigSrc = Stop)"
|
|
936
|
+
end
|
|
937
|
+
end
|
|
938
|
+
|
|
939
|
+
# Call this method before each tester cycle to insert the digsrc overlay microcode
|
|
940
|
+
def digsrc_send(pins)
|
|
941
|
+
microcode "((#{format_multiple_instrument_pins(pins)}):DigSrc = SEND)"
|
|
942
|
+
end
|
|
943
|
+
|
|
944
|
+
# Call this method before each tester cycle to inser the digcap overlay microcode
|
|
945
|
+
def digcap_store(pins)
|
|
946
|
+
microcode "((#{format_multiple_instrument_pins(pins)}):DigCap = STORE)"
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
def apply_digsrc_settings(options = {})
|
|
950
|
+
options.merge!(digsrc_width: 1) if options[:digsrc_width].nil? # default to digsrc 1
|
|
951
|
+
options.merge!(digsrc_bit_order: :lsb) if options[:digsrc_bit_order].nil? # default to lsb
|
|
952
|
+
options.merge!(digsrc_mode: :serial) if options[:digsrc_mode].nil? # default to serial mode
|
|
953
|
+
options.merge!(digsrc_format: :binary) if options[:digsrc_format].nil? # default to binary
|
|
954
|
+
options.merge!(digsrc_site_uniqueness: :unique_sites) if options[:digsrc_site_uniqueness].nil? # default to unique sites
|
|
955
|
+
options.merge!(digsrc_data_type: :default) if options[:digsrc_data_type].nil? # default to default
|
|
956
|
+
options.merge!(digsrc_auto_cond: :auto_cond_disable) if options[:digsrc_auto_cond].nil? # default to disable
|
|
957
|
+
@digsrc_settings = options
|
|
958
|
+
end
|
|
959
|
+
|
|
960
|
+
def apply_digcap_settings(options = {})
|
|
961
|
+
options.merge!(digcap_width: 8) if options[:digcap_width].nil? # default to digcap 8
|
|
962
|
+
options.merge!(digcap_bit_order: :lsb) if options[:digcap_bit_order].nil? # default to lsb
|
|
963
|
+
options.merge!(digcap_mode: :serial) if options[:digcap_mode].nil? # default to serial mode
|
|
964
|
+
options.merge!(digcap_site_uniqueness: :unique_sites) if options[:digcap_site_uniqueness].nil? # default to unique sites
|
|
965
|
+
options.merge!(digcap_format: :binary) if options[:digcap_format].nil? # default to binary
|
|
966
|
+
options.merge!(digcap_data_type: :default) if options[:digcap_data_type].nil? # default to default
|
|
967
|
+
options.merge!(digcap_auto_cond: :auto_cond_disable) if options[:digcap_auto_cond].nil? # default to disable
|
|
968
|
+
options.merge!(digcap_auto_trig_enable: :auto_trig_disable) if options[:digcap_auto_trig_enable].nil? # default to disable
|
|
969
|
+
options.merge!(digcap_store_stv: :store_stv_disable) if options[:digcap_store_stv].nil? # default to disable
|
|
970
|
+
options.merge!(digcap_receive_data: :store_stv_disable) if options[:digcap_receive_data].nil? # default to logic
|
|
971
|
+
@digcap_settings = options
|
|
972
|
+
end
|
|
973
|
+
|
|
974
|
+
# Call this method if there are more than one pin/pin groups used with an instrument,
|
|
975
|
+
# this method will format an array of pins into the correct format required by igxl
|
|
976
|
+
# pattern microcodes.
|
|
977
|
+
def format_multiple_instrument_pins(pins, options = {})
|
|
978
|
+
return_value = ''
|
|
979
|
+
pins.each do |pin|
|
|
980
|
+
return_value += "#{pin}"
|
|
981
|
+
return_value += ',' unless pins.last == pin
|
|
982
|
+
end
|
|
983
|
+
return_value
|
|
984
|
+
end
|
|
985
|
+
|
|
986
|
+
def mask_fails(setclr)
|
|
987
|
+
@mask_vector = setclr
|
|
988
|
+
end
|
|
989
|
+
|
|
990
|
+
# Similar to push_microcode, but for the instrument statement in the pattern header
|
|
991
|
+
#
|
|
992
|
+
# @example
|
|
993
|
+
# tester.push_instrument 'SAR_IN_1', 'UltraSource'
|
|
994
|
+
# # results in the below line added
|
|
995
|
+
# # instruments = {
|
|
996
|
+
# # SAR_IN_1:UltraSource;
|
|
997
|
+
# # }
|
|
998
|
+
def push_instrument(pin_spec, instrument_def)
|
|
999
|
+
@pushed_instrument_configs[pin_spec] = instrument_def
|
|
1000
|
+
end
|
|
1001
|
+
|
|
1002
|
+
# Implement subroutine overlay, called by tester.cycle
|
|
1003
|
+
def subroutine_overlay(sub_name, options = {})
|
|
1004
|
+
if @overlay_subr != sub_name
|
|
1005
|
+
# unless last staged vector already has the subr call do the following
|
|
1006
|
+
i = -1
|
|
1007
|
+
i -= 1 until stage.bank[i].is_a?(OrigenTesters::Vector)
|
|
1008
|
+
if stage.bank[i].microcode !~ /call #{sub_name}/
|
|
1009
|
+
|
|
1010
|
+
# check for repeat on new last vector, unroll 1 if needed
|
|
1011
|
+
if stage.bank[i].repeat > 1
|
|
1012
|
+
v = OrigenTesters::Vector.new
|
|
1013
|
+
v.pin_vals = stage.bank[i].pin_vals
|
|
1014
|
+
v.timeset = stage.bank[i].timeset
|
|
1015
|
+
stage.bank[i].repeat -= 1
|
|
1016
|
+
stage.store(v)
|
|
1017
|
+
i = -1
|
|
1018
|
+
end
|
|
1019
|
+
|
|
1020
|
+
# mark last vector as dont_compress
|
|
1021
|
+
stage.bank[i].dont_compress = true
|
|
1022
|
+
# insert subroutine call
|
|
1023
|
+
call_subroutine sub_name
|
|
1024
|
+
end # if microcode not placed
|
|
1025
|
+
@overlay_subr = sub_name
|
|
1026
|
+
end
|
|
1027
|
+
|
|
1028
|
+
# stage = sub_name
|
|
1029
|
+
end # subroutine_overlay
|
|
1030
|
+
|
|
1031
|
+
# Perform digsrc overlay (called by tester.cycle)
|
|
1032
|
+
def digsrc_overlay(options = {})
|
|
1033
|
+
options[:overlay] = { change_data: true }.merge(options[:overlay])
|
|
1034
|
+
pin_name = dut.pin(options[:overlay][:pins]).name
|
|
1035
|
+
repeat_count = options[:repeat].nil? ? 1 : options[:repeat]
|
|
1036
|
+
|
|
1037
|
+
if options[:overlay][:change_data]
|
|
1038
|
+
# add the send microcode
|
|
1039
|
+
microcode "((#{pin_name}):DigSrc = SEND)"
|
|
1040
|
+
|
|
1041
|
+
# keep track of amount of digsrc used for header comment
|
|
1042
|
+
if @overlay_history[pin_name].nil?
|
|
1043
|
+
@overlay_history[pin_name] = { count: repeat_count, is_digsrc: true }
|
|
1044
|
+
else
|
|
1045
|
+
@overlay_history[pin_name][:count] += repeat_count
|
|
1046
|
+
end
|
|
1047
|
+
|
|
1048
|
+
# ensure no unwanted repeats on the send vector
|
|
1049
|
+
options[:dont_compress] = true
|
|
1050
|
+
|
|
1051
|
+
# ensure start microcode is placed at the beginning of the pattern
|
|
1052
|
+
if @overlay_history[pin_name][:start_applied].nil?
|
|
1053
|
+
# insert start microcode at the beginning of the pattern
|
|
1054
|
+
stage.insert_from_start "((#{pin_name}):DigSrc = Start)", 0
|
|
1055
|
+
@overlay_history[pin_name][:start_applied] = true
|
|
1056
|
+
|
|
1057
|
+
# get the first vector of the pattern
|
|
1058
|
+
i = 0
|
|
1059
|
+
i += 1 until stage.bank[i].is_a?(OrigenTesters::Vector)
|
|
1060
|
+
first_vector = stage.bank[i]
|
|
1061
|
+
|
|
1062
|
+
# insert a copy of the first vector with no repeats
|
|
1063
|
+
unless first_vector.inline_comment == 'added for digsrc start opcode'
|
|
1064
|
+
v = OrigenTesters::Vector.new
|
|
1065
|
+
v.pin_vals = stage.bank[i].pin_vals
|
|
1066
|
+
v.timeset = stage.bank[i].timeset
|
|
1067
|
+
v.inline_comment = 'added for digsrc start opcode'
|
|
1068
|
+
v.dont_compress = true
|
|
1069
|
+
stage.insert_from_start v, i
|
|
1070
|
+
|
|
1071
|
+
# decrement repeat count of previous first vector if > 1
|
|
1072
|
+
first_vector.repeat -= 1 if first_vector.repeat > 1
|
|
1073
|
+
end
|
|
1074
|
+
|
|
1075
|
+
# get cycle count up to this point, add repeat to beginning if needed
|
|
1076
|
+
cycle_count = -1
|
|
1077
|
+
stage.bank.each { |v| cycle_count += v.repeat if v.is_a?(OrigenTesters::Vector) }
|
|
1078
|
+
if cycle_count < @dssc_send_delay
|
|
1079
|
+
d = OrigenTesters::Vector.new
|
|
1080
|
+
d.pin_vals = first_vector.pin_vals
|
|
1081
|
+
d.timeset = first_vector.timeset
|
|
1082
|
+
d.inline_comment = 'added for dssc start to send delay'
|
|
1083
|
+
d.repeat = @dssc_send_delay - cycle_count
|
|
1084
|
+
|
|
1085
|
+
# get the first vector of the pattern
|
|
1086
|
+
i = 0
|
|
1087
|
+
i += 1 until stage.bank[i].is_a?(OrigenTesters::Vector)
|
|
1088
|
+
|
|
1089
|
+
# insert new vector after the first vector
|
|
1090
|
+
stage.insert_from_start d, i + 1
|
|
1091
|
+
end
|
|
1092
|
+
|
|
1093
|
+
end # of place start microcode
|
|
1094
|
+
|
|
1095
|
+
end # if options[:change_data]
|
|
1096
|
+
options
|
|
1097
|
+
end # digsrc overlay
|
|
1098
|
+
end
|
|
1099
|
+
end
|
|
1100
|
+
end
|