origen_testers 0.13.1 → 0.13.2
Sign up to get free protection for your applications and to get access to all the features.
- 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,96 +1,96 @@
|
|
1
|
-
module OrigenTesters
|
2
|
-
module PatternCompilers
|
3
|
-
class Job
|
4
|
-
# Pattern to be compiled, is Pathname class. Will use full path
|
5
|
-
attr_accessor :pattern
|
6
|
-
|
7
|
-
# Type of pattern as designated by the LinuxPatternCompiler
|
8
|
-
attr_accessor :id
|
9
|
-
|
10
|
-
# Where the job is to be executed, either locally ('local') or on Linux Server Farm ('lsf')
|
11
|
-
attr_accessor :location
|
12
|
-
|
13
|
-
# Controls whether the compiler log files are kept: true/false
|
14
|
-
attr_accessor :clean
|
15
|
-
|
16
|
-
# Controls whether the compiler STDOUT is displayed
|
17
|
-
attr_accessor :verbose
|
18
|
-
|
19
|
-
# Output directory for the .PAT file
|
20
|
-
attr_accessor :output_directory
|
21
|
-
|
22
|
-
# Pinmap file
|
23
|
-
attr_accessor :pinmap_workbook
|
24
|
-
|
25
|
-
# Compiler options where only the opt has to be passed as '-opt'
|
26
|
-
attr_accessor :compiler_options
|
27
|
-
|
28
|
-
# Compiler options where an opt and an arg have to be passed '-opt:arg'
|
29
|
-
attr_accessor :compiler_options_with_args
|
30
|
-
|
31
|
-
# linux compiler full path
|
32
|
-
attr_reader :compiler
|
33
|
-
|
34
|
-
def initialize(pattern, options_with_args, options)
|
35
|
-
@pattern = pattern
|
36
|
-
@compiler = options_with_args.delete(:compiler)
|
37
|
-
@id = options_with_args.delete(:id)
|
38
|
-
@location = options_with_args.delete(:location)
|
39
|
-
@clean = options_with_args.delete(:clean)
|
40
|
-
@verbose = options_with_args.delete(:verbose)
|
41
|
-
@output_directory = options_with_args.delete(:output_directory)
|
42
|
-
@pinmap_workbook = options_with_args.delete(:pinmap_workbook)
|
43
|
-
@compiler_options_with_args = options_with_args.delete_if { |k, v| v.nil? } # Whatever's left has to be valid compiler options
|
44
|
-
@compiler_options = options.delete_if { |k, v| v == false }
|
45
|
-
end
|
46
|
-
|
47
|
-
def name
|
48
|
-
@pattern.basename
|
49
|
-
end
|
50
|
-
|
51
|
-
def cmd
|
52
|
-
cmd = ''
|
53
|
-
cmd = "#{@compiler} -pinmap_workbook:#{@pinmap_workbook} -output:#{@output_directory}/#{@pattern.basename.to_s.split('.').first}.PAT #{@pattern} "
|
54
|
-
# add in any remaining compiler options
|
55
|
-
compiler_options.each_key { |k| cmd += "-#{k} " }
|
56
|
-
compiler_options_with_args.each_pair { |k, v| cmd += "-#{k}:#{v} " }
|
57
|
-
if @verbose
|
58
|
-
cmd += ';'
|
59
|
-
else
|
60
|
-
cmd += '2>&1 > /dev/null;'
|
61
|
-
end
|
62
|
-
# If the job is to be run on the LSF add in the clean .log and mv the files if necessary
|
63
|
-
if @location == 'lsf'
|
64
|
-
cmd += clean_lsf if @clean == true
|
65
|
-
end
|
66
|
-
cmd
|
67
|
-
end
|
68
|
-
|
69
|
-
def ready?
|
70
|
-
ready = true
|
71
|
-
ready && @output_directory.directory? &&
|
72
|
-
@pattern.file? && @pinmap_workbook.file? &&
|
73
|
-
[true, false].include?(@clean) &&
|
74
|
-
[:local, :lsf].include?(@location)
|
75
|
-
end
|
76
|
-
|
77
|
-
private
|
78
|
-
|
79
|
-
def orig_dir
|
80
|
-
@pattern.dirname
|
81
|
-
end
|
82
|
-
|
83
|
-
# Generates the LSF commands to delete the pattern compiler log files
|
84
|
-
def clean_lsf
|
85
|
-
cmd = ''
|
86
|
-
logfile = Pathname.new("#{@pattern.dirname}/#{@pattern.basename.to_s.split('.').first}.log")
|
87
|
-
logfile.cleanpath
|
88
|
-
logfile.cleanpath
|
89
|
-
if @clean == true
|
90
|
-
cmd += "rm #{logfile}; "
|
91
|
-
end
|
92
|
-
cmd
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
1
|
+
module OrigenTesters
|
2
|
+
module PatternCompilers
|
3
|
+
class Job
|
4
|
+
# Pattern to be compiled, is Pathname class. Will use full path
|
5
|
+
attr_accessor :pattern
|
6
|
+
|
7
|
+
# Type of pattern as designated by the LinuxPatternCompiler
|
8
|
+
attr_accessor :id
|
9
|
+
|
10
|
+
# Where the job is to be executed, either locally ('local') or on Linux Server Farm ('lsf')
|
11
|
+
attr_accessor :location
|
12
|
+
|
13
|
+
# Controls whether the compiler log files are kept: true/false
|
14
|
+
attr_accessor :clean
|
15
|
+
|
16
|
+
# Controls whether the compiler STDOUT is displayed
|
17
|
+
attr_accessor :verbose
|
18
|
+
|
19
|
+
# Output directory for the .PAT file
|
20
|
+
attr_accessor :output_directory
|
21
|
+
|
22
|
+
# Pinmap file
|
23
|
+
attr_accessor :pinmap_workbook
|
24
|
+
|
25
|
+
# Compiler options where only the opt has to be passed as '-opt'
|
26
|
+
attr_accessor :compiler_options
|
27
|
+
|
28
|
+
# Compiler options where an opt and an arg have to be passed '-opt:arg'
|
29
|
+
attr_accessor :compiler_options_with_args
|
30
|
+
|
31
|
+
# linux compiler full path
|
32
|
+
attr_reader :compiler
|
33
|
+
|
34
|
+
def initialize(pattern, options_with_args, options)
|
35
|
+
@pattern = pattern
|
36
|
+
@compiler = options_with_args.delete(:compiler)
|
37
|
+
@id = options_with_args.delete(:id)
|
38
|
+
@location = options_with_args.delete(:location)
|
39
|
+
@clean = options_with_args.delete(:clean)
|
40
|
+
@verbose = options_with_args.delete(:verbose)
|
41
|
+
@output_directory = options_with_args.delete(:output_directory)
|
42
|
+
@pinmap_workbook = options_with_args.delete(:pinmap_workbook)
|
43
|
+
@compiler_options_with_args = options_with_args.delete_if { |k, v| v.nil? } # Whatever's left has to be valid compiler options
|
44
|
+
@compiler_options = options.delete_if { |k, v| v == false }
|
45
|
+
end
|
46
|
+
|
47
|
+
def name
|
48
|
+
@pattern.basename
|
49
|
+
end
|
50
|
+
|
51
|
+
def cmd
|
52
|
+
cmd = ''
|
53
|
+
cmd = "#{@compiler} -pinmap_workbook:#{@pinmap_workbook} -output:#{@output_directory}/#{@pattern.basename.to_s.split('.').first}.PAT #{@pattern} "
|
54
|
+
# add in any remaining compiler options
|
55
|
+
compiler_options.each_key { |k| cmd += "-#{k} " }
|
56
|
+
compiler_options_with_args.each_pair { |k, v| cmd += "-#{k}:#{v} " }
|
57
|
+
if @verbose
|
58
|
+
cmd += ';'
|
59
|
+
else
|
60
|
+
cmd += '2>&1 > /dev/null;'
|
61
|
+
end
|
62
|
+
# If the job is to be run on the LSF add in the clean .log and mv the files if necessary
|
63
|
+
if @location == 'lsf'
|
64
|
+
cmd += clean_lsf if @clean == true
|
65
|
+
end
|
66
|
+
cmd
|
67
|
+
end
|
68
|
+
|
69
|
+
def ready?
|
70
|
+
ready = true
|
71
|
+
ready && @output_directory.directory? &&
|
72
|
+
@pattern.file? && @pinmap_workbook.file? &&
|
73
|
+
[true, false].include?(@clean) &&
|
74
|
+
[:local, :lsf].include?(@location)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def orig_dir
|
80
|
+
@pattern.dirname
|
81
|
+
end
|
82
|
+
|
83
|
+
# Generates the LSF commands to delete the pattern compiler log files
|
84
|
+
def clean_lsf
|
85
|
+
cmd = ''
|
86
|
+
logfile = Pathname.new("#{@pattern.dirname}/#{@pattern.basename.to_s.split('.').first}.log")
|
87
|
+
logfile.cleanpath
|
88
|
+
logfile.cleanpath
|
89
|
+
if @clean == true
|
90
|
+
cmd += "rm #{logfile}; "
|
91
|
+
end
|
92
|
+
cmd
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -1,599 +1,599 @@
|
|
1
|
-
module OrigenTesters
|
2
|
-
module PatternCompilers
|
3
|
-
class UltraFlexPatternCompiler
|
4
|
-
require 'pathname'
|
5
|
-
require_relative 'assembler'
|
6
|
-
require_relative 'job'
|
7
|
-
|
8
|
-
# Linux compiler executable path
|
9
|
-
LINUX_PATTERN_COMPILER = "#{Origen.root!}/bin/latest/bin/atpcompiler"
|
10
|
-
# LINUX_PATTERN_COMPILER = "#{Origen.root!}/bin/latest/bin/atpcompiler"
|
11
|
-
|
12
|
-
# Windows compiler executable path
|
13
|
-
WINDOWS_PATTERN_COMPILER = "#{ENV['IGXLROOT']}/bin/apc.exe"
|
14
|
-
|
15
|
-
# Linux compiler preamble
|
16
|
-
ATPC_SETUP = "#{Origen.root!}/bin/latest/etc/atpcrc.csh"
|
17
|
-
|
18
|
-
# ID will allow users to set default configurations for the compiler for unique pattern types
|
19
|
-
attr_accessor :id
|
20
|
-
|
21
|
-
# Compiler commands array
|
22
|
-
attr_accessor :jobs
|
23
|
-
|
24
|
-
def initialize(id, options = {})
|
25
|
-
@id = id
|
26
|
-
@id = @id.to_sym
|
27
|
-
|
28
|
-
@user_options = {
|
29
|
-
path: nil, # required: will be passed in or parsed from a .list file
|
30
|
-
reference_directory: nil, # optional: will be set to @path or Origen.app.config.pattern_output_directory
|
31
|
-
target: nil, # optional: allows user to temporarily set target and run compilation
|
32
|
-
recursive: false # optional: controls whether to look for patterns in a directory recursively
|
33
|
-
}
|
34
|
-
@job_options = {
|
35
|
-
compiler: running_on_windows? ? WINDOWS_PATTERN_COMPILER : LINUX_PATTERN_COMPILER, # required
|
36
|
-
id: @id, # required
|
37
|
-
pinmap_workbook: $dut.pinmap, # required: will default to $dut.pinmap
|
38
|
-
location: :local, # optional: controls whether the commands go to the LSF or run locally
|
39
|
-
clean: false, # optional: controls whether compiler log files are deleted after compilation
|
40
|
-
output_directory: nil, # optional:
|
41
|
-
verbose: false # optional: controls whether the compiler output gets put to STDOUT
|
42
|
-
}
|
43
|
-
@compiler_options = { # Set all of these compiler options that don't have args to true/flase. if true then send compiler '-opt'
|
44
|
-
import_all_undefineds: false, # automatically import all undefined symbols. the key is mis-spelled but correct!
|
45
|
-
cpp: false, # runs C++ preprocessor on pattern file
|
46
|
-
comments: false, # saves comments in binary file for tools visibility. pass '-comments' if set to true
|
47
|
-
# pass nothing if set to false
|
48
|
-
nocompress: false, # do not compress pattern data blocks
|
49
|
-
suppress_log: false, # disables output to main log file
|
50
|
-
multiinst: false, # indicates more than one instrument is connected to a single pin
|
51
|
-
lock: false, # prevents pattern from being reverse compiled or opened in PatternTool
|
52
|
-
stdin: false, # Compile data from standard input. Do not use -cpp or specify any pattern file(s) when using this option.
|
53
|
-
debug: false, # generate intermediate file(s) to simplify debug ( application dependent )
|
54
|
-
template: false, # generate setup template
|
55
|
-
timestamp: false, # enable log timestamp
|
56
|
-
}
|
57
|
-
@compiler_options_with_args = {
|
58
|
-
output: nil, # Output filename, compiler defaults to <pattern name>.PAT
|
59
|
-
pinmap_sheet: nil, # <sheetname>
|
60
|
-
digital_inst: nil, # 'HSD4G', 'HSDM', or 'HSDMQ'
|
61
|
-
opcode_mode: nil, # HSDM mode: 'single' | 'dual'. HSDMQ mode: 'single' | 'dual' | 'quad'
|
62
|
-
pat_version: nil, # version of pattern file to compile
|
63
|
-
scan_type: nil, # type of scan data
|
64
|
-
max_errors: nil, # <n>, defaults to 200 on compiler side, valu eof 0 will never abort compilation
|
65
|
-
logfile: nil, # <filename>, directs any compiler messages to <filename>. will default to output directory if nil
|
66
|
-
define: nil, # defines values of macros passed to C++ preprocessor.
|
67
|
-
# can only be defined once per pattern with space delimited list
|
68
|
-
includes: nil, # include paths to be passed to C- preprocessor.
|
69
|
-
post_processor: nil, # <pathname> customer's post-process executable.
|
70
|
-
# need to pass 'post-processor' to compiler
|
71
|
-
post_processor_args: nil, # <args> customer's post-process executable arguments
|
72
|
-
# need to pass 'post-processor_args' to compiler
|
73
|
-
cdl_cache: nil, # 'yes' | 'no', turns on/off CDL caching, default on compiler side is 'yes'
|
74
|
-
init_pattern: nil, # <pattern>, uses the specified pattern module/file/set as an init patterns
|
75
|
-
check_set_msb: nil, # 'yes' | 'no', turns on/off check the 'set' or 'set_infinite' opcode
|
76
|
-
# is preceded by a 'set_msb' or 'set_msb_infinite' opcode. compiler default is 'yes'
|
77
|
-
time_domain: nil, # <time domain>, specifies time domain for pins in patterns
|
78
|
-
allow_mto_dash: nil, # Turn on/off support for channel data runtime repeat,i.e. vector dash in MTO patterns. Default value is "no".
|
79
|
-
check_vm_min_size: nil, # Turns on/off the check on minimum size of a VM pattern. Default value is "yes".
|
80
|
-
check_vm_mod_size: nil, # Turns on/off the check on a VM pattern module size. Default value is "yes".
|
81
|
-
check_oob_size: nil, # Turns on/off the check on size of OOB regions. Yes means size must be modulo 10. Default value is "no".
|
82
|
-
allow_mixed_1x2x: nil, # Turns on/off the support of mixed 1x/2x pin groups. Default value is "no".
|
83
|
-
allow_differential: nil, # Turns on/off support for differential pins. Default value is "yes".
|
84
|
-
allow_scan_in_srm: nil, # Allow/disallow scan vectors in SRM pattern modules. Default value is "no".
|
85
|
-
vm_block_size: nil, # Specifies uncompressed size in bytes of a pattern data block
|
86
|
-
setup: nil, # path to setup file
|
87
|
-
}
|
88
|
-
|
89
|
-
@user_options.update_common(options)
|
90
|
-
@job_options.update_common(options)
|
91
|
-
@compiler_options.update_common(options)
|
92
|
-
@compiler_options_with_args.update_common(options)
|
93
|
-
|
94
|
-
# Check to make sure @compiler_options and @compiler_options_with_args do not have any keys in common
|
95
|
-
fail "Error: @compiler_options and @compiler_options_with_args share keys #{@compiler_options.intersections(@compiler_options_with_args)}. They should be mutually exclusive, exiting..." if @compiler_options.intersect? @compiler_options_with_args
|
96
|
-
|
97
|
-
# Convert any path related options to Pathname object and expand the path
|
98
|
-
unless @user_options[:path].nil?
|
99
|
-
if @user_options[:path].is_a? Pathname
|
100
|
-
@path = @user_options[:path]
|
101
|
-
else
|
102
|
-
@path = Pathname.new(@user_options[:path])
|
103
|
-
end
|
104
|
-
@path = @path.expand_path
|
105
|
-
# path is set but output_directory is not so set output_directory to path
|
106
|
-
@job_options[:output_directory] = @path if @job_options[:output_directory].nil?
|
107
|
-
end
|
108
|
-
|
109
|
-
set_reference_directory
|
110
|
-
|
111
|
-
if @job_options[:output_directory].nil?
|
112
|
-
fail 'Output directory is not set!'
|
113
|
-
else
|
114
|
-
@job_options[:output_directory] = convert_to_pathname(@job_options[:output_directory])
|
115
|
-
# output_directory can not exist, will create for user
|
116
|
-
unless @job_options[:output_directory].directory?
|
117
|
-
puts "Output directory #{@job_options[:output_directory]} does not exist, creating it..."
|
118
|
-
FileUtils.mkdir_p(@job_options[:output_directory])
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
# Pinmap is required
|
123
|
-
if @job_options[:pinmap_workbook].nil?
|
124
|
-
# Check if the app has $dut.pinmap defined
|
125
|
-
if File.exist? $dut.pinmap
|
126
|
-
@job_options[:pinmap_workbook] = $dut.pinmap
|
127
|
-
else
|
128
|
-
fail 'Pinmap is not defined! Pass as an option or set $dut.pinmap.'
|
129
|
-
end
|
130
|
-
end
|
131
|
-
@job_options[:pinmap_workbook] = convert_to_pathname(@job_options[:pinmap_workbook])
|
132
|
-
fail 'Pinmap is not a file' unless @job_options[:pinmap_workbook].file?
|
133
|
-
|
134
|
-
# Logfile is optional
|
135
|
-
unless @compiler_options[:logfile].nil?
|
136
|
-
@compiler_options[:logfile] = convert_to_pathname(@compiler_options[:logfile])
|
137
|
-
fail 'Pinmap is not a file' unless @job_options[:pinmap_workbook].file?
|
138
|
-
end
|
139
|
-
|
140
|
-
# Check if the LSF is setup in the application
|
141
|
-
if Origen.app.config.lsf.project.nil? || Origen.app.config.lsf.project.empty?
|
142
|
-
puts 'LSF is not set at Origen.app.config.lsf.project, changing to local compilation'
|
143
|
-
@job_options[:location] = :local
|
144
|
-
end
|
145
|
-
|
146
|
-
# Compiler jobs
|
147
|
-
@jobs = []
|
148
|
-
|
149
|
-
# .atp/.atp.gz files found
|
150
|
-
@files = []
|
151
|
-
end
|
152
|
-
|
153
|
-
# Return the id/name of the compiler instance
|
154
|
-
def name
|
155
|
-
@id
|
156
|
-
end
|
157
|
-
|
158
|
-
# Return the compiler instance pinmap
|
159
|
-
def pinmap
|
160
|
-
@job_options[:pinmap_workbook]
|
161
|
-
end
|
162
|
-
|
163
|
-
# Allow users to search for a pattern in the job queue or default
|
164
|
-
# to return all jobs
|
165
|
-
def jobs(search = nil)
|
166
|
-
found = false
|
167
|
-
if search.nil?
|
168
|
-
inspect_jobs
|
169
|
-
found = true
|
170
|
-
elsif search.is_a? String
|
171
|
-
@jobs.each_with_index do |job, index|
|
172
|
-
if job.pattern.to_s.match(search)
|
173
|
-
inspect_jobs(index)
|
174
|
-
found = true
|
175
|
-
else
|
176
|
-
puts "No match found for #{search}"
|
177
|
-
end
|
178
|
-
end
|
179
|
-
elsif search.is_a? Regexp
|
180
|
-
@jobs.each_with_index do |job, index|
|
181
|
-
if search.match(job.pattern.to_s)
|
182
|
-
inspect_jobs(index)
|
183
|
-
found = true
|
184
|
-
else
|
185
|
-
puts "No match found for #{search}"
|
186
|
-
end
|
187
|
-
end
|
188
|
-
elsif search.is_a? Integer
|
189
|
-
if @jobs[search].nil?
|
190
|
-
puts "The compiler queue does not contain a job at index #{search}"
|
191
|
-
else
|
192
|
-
inspect_jobs(search)
|
193
|
-
found = true
|
194
|
-
end
|
195
|
-
else
|
196
|
-
fail 'Search argument must be of type String, Regexp, or Integer'
|
197
|
-
end
|
198
|
-
found
|
199
|
-
end
|
200
|
-
|
201
|
-
# Finds the patterns and creates a compiler job for each one found.
|
202
|
-
# Handles singles files (.atp, .atp.gz, or .list) and directories (recursively or flat)
|
203
|
-
def find_jobs(path = @path)
|
204
|
-
fail 'Pattern path is set to nil, pass in a valid file (.atp or .atp.gz) or a valid directory' if path.nil?
|
205
|
-
@path = Pathname.new(path)
|
206
|
-
fail 'Pattern path does not exist, pass in a valid file (.atp or .atp.gz) or a valid directory' unless @path.exist?
|
207
|
-
@path = @path.expand_path
|
208
|
-
# Set the reference directory for pattern sub-dir mirroring
|
209
|
-
set_reference_directory
|
210
|
-
Origen.profile 'Linux pattern compiler finds patterns' do
|
211
|
-
# Check if the path is a file or a directory
|
212
|
-
if @path.directory?
|
213
|
-
# Get all of the patterns inside this dir or inside this directory recursively
|
214
|
-
# Check if the recursive arg was passed
|
215
|
-
if @user_options[:recursive] == true
|
216
|
-
process_directory(@path, @files, true)
|
217
|
-
else # Just grab the files found inside this directory
|
218
|
-
process_directory(@path, @files, false)
|
219
|
-
end
|
220
|
-
elsif @path.file? # Found a file so no searching is necessary
|
221
|
-
process_file(@path, @files)
|
222
|
-
else # Didn't find a directory or a file so user must want a search for this arg string * NOT SUPPORTED YET
|
223
|
-
fail 'Error: Did not find a file or directory to compile, exiting...'
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
Origen.profile 'Linux pattern compiler creates jobs' do
|
228
|
-
@files.each do |f|
|
229
|
-
rel_dir = Pathname.new("#{f.dirname.to_s[@user_options[:reference_directory].to_s.size..-1]}")
|
230
|
-
output_dir = Pathname.new("#{@job_options[:output_directory]}#{rel_dir}")
|
231
|
-
unless output_dir.directory?
|
232
|
-
puts "Output directory #{output_dir} for pattern #{f.basename} does not exist, creating it..."
|
233
|
-
FileUtils.mkdir_p(output_dir)
|
234
|
-
end
|
235
|
-
current_job_options = @job_options.merge(@compiler_options_with_args)
|
236
|
-
current_job_options[:output_directory] = output_dir
|
237
|
-
@jobs << Job.new(f, current_job_options, @compiler_options)
|
238
|
-
current_job_options = {}
|
239
|
-
end
|
240
|
-
end
|
241
|
-
@files = []
|
242
|
-
if empty?
|
243
|
-
empty_msg
|
244
|
-
else
|
245
|
-
inspect_jobs
|
246
|
-
end
|
247
|
-
end
|
248
|
-
alias_method :find, :find_jobs
|
249
|
-
|
250
|
-
# Executes the compiler for each job in the queue
|
251
|
-
def run(list = nil, options = {})
|
252
|
-
fail "Error: the tester #{Origen.tester} is not an Ultrflex tester,exiting..." unless is_ultraflex?
|
253
|
-
fail "Error: application #{Origen.app.name} is running on Windows, to run the pattern compiler you must be on a Linux machine" if running_on_windows?
|
254
|
-
|
255
|
-
# Check if there was a pattern list passed as an argument
|
256
|
-
# If so, then compile the patterns inside it.
|
257
|
-
# Otherwise compile the jobs in the queue
|
258
|
-
if list.nil?
|
259
|
-
if empty?
|
260
|
-
empty_msg
|
261
|
-
return
|
262
|
-
end
|
263
|
-
@jobs.each do |job|
|
264
|
-
fail "Error: compiler #{job.id} not ready for pattern #{job.name}" unless job.ready?
|
265
|
-
if job.location == :lsf
|
266
|
-
Origen.app.lsf.submit(ATPC_SETUP + '; ' + job.cmd)
|
267
|
-
else
|
268
|
-
Origen.profile "Linux pattern compiler compiles pattern #{job.pattern}" do
|
269
|
-
system job.cmd
|
270
|
-
end
|
271
|
-
end
|
272
|
-
end
|
273
|
-
if @job_options[:location] == :local
|
274
|
-
if @job_options[:clean] == true
|
275
|
-
puts 'Log file :clean option set to true, deleting log files'
|
276
|
-
clean_output
|
277
|
-
end
|
278
|
-
end
|
279
|
-
# Clear @jobs
|
280
|
-
clear
|
281
|
-
else
|
282
|
-
list = convert_to_pathname(list)
|
283
|
-
fail "Error: pattern list #{list} does not exist, exiting..." unless list.file?
|
284
|
-
File.open(list, 'r') do |file|
|
285
|
-
while (line = file.gets)
|
286
|
-
current_job_options = @job_options.merge(@compiler_options_with_args)
|
287
|
-
current_job_options.update_common(options)
|
288
|
-
# puts "current job options is #{current_job_options}"
|
289
|
-
compiler_opts = {}
|
290
|
-
line.strip!
|
291
|
-
pattern = line.match(/^(\S+)\s+(.*)/).captures[0]
|
292
|
-
unless File.file? pattern
|
293
|
-
puts "Warning: Pattern #{pattern} does not exist, skipping..."
|
294
|
-
next
|
295
|
-
end
|
296
|
-
pattern = convert_to_pathname(pattern)
|
297
|
-
line.match(/^\S+\s+(.*)/).captures[0].split(/\s+/).each do |e|
|
298
|
-
opt, arg = e.split(':')
|
299
|
-
opt.gsub!('-', '')
|
300
|
-
if arg.nil?
|
301
|
-
compiler_opts[opt.to_sym] = true
|
302
|
-
else
|
303
|
-
# Check for some specific options
|
304
|
-
case opt
|
305
|
-
when 'pinmap_workbook'
|
306
|
-
current_job_options[opt.to_sym] = Pathname.new(arg)
|
307
|
-
when 'output'
|
308
|
-
dot_pat = Pathname.new(arg)
|
309
|
-
current_job_options[:output_directory] = dot_pat.dirname
|
310
|
-
else
|
311
|
-
current_job_options[opt.to_sym] = arg
|
312
|
-
end
|
313
|
-
end
|
314
|
-
end
|
315
|
-
@jobs << Job.new(pattern, current_job_options, compiler_opts)
|
316
|
-
inspect_jobs
|
317
|
-
end
|
318
|
-
end
|
319
|
-
run
|
320
|
-
# Clear @jobs
|
321
|
-
clear
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
|
-
# Clear the job queue
|
326
|
-
def clear
|
327
|
-
@jobs = []
|
328
|
-
@files = []
|
329
|
-
end
|
330
|
-
|
331
|
-
# Output all of the jobs into a pattern list so it can be compiled later
|
332
|
-
# Must be executed after the 'find_jobs' method and before the 'run' method
|
333
|
-
# or @jobs will be empty
|
334
|
-
def to_list(options = {})
|
335
|
-
options = {
|
336
|
-
name: @id,
|
337
|
-
output_directory: Dir.pwd,
|
338
|
-
expand: true,
|
339
|
-
force: false
|
340
|
-
}.update_common(options)
|
341
|
-
list = "#{options[:output_directory]}/#{options[:name]}.list"
|
342
|
-
list = convert_to_pathname(list)
|
343
|
-
if empty?
|
344
|
-
empty_msg
|
345
|
-
return
|
346
|
-
end
|
347
|
-
if list.file?
|
348
|
-
if options[:force] == true
|
349
|
-
puts "Pattern list file #{list} already exists, deleting it..."
|
350
|
-
list.delete
|
351
|
-
else
|
352
|
-
fail "Pattern list file #{list} already exists, exiting..."
|
353
|
-
end
|
354
|
-
end
|
355
|
-
File.open(list, 'w') do |patlist|
|
356
|
-
@jobs.each do |job|
|
357
|
-
if options[:expand] == true
|
358
|
-
pinmap = job.pinmap_workbook
|
359
|
-
dot_pat_name = "#{job.output_directory}/#{job.pattern.basename.to_s.split('.').first}.PAT"
|
360
|
-
dot_atp_name = job.pattern
|
361
|
-
else
|
362
|
-
pinmap = job.pinmap_workbook.basename
|
363
|
-
dot_pat_name = "#{job.pattern.basename.to_s.split('.').first}.PAT"
|
364
|
-
dot_atp_name = job.pattern.basename
|
365
|
-
end
|
366
|
-
patlist.print("#{dot_atp_name} -pinmap_workbook:#{pinmap} -output:#{dot_pat_name}")
|
367
|
-
job.compiler_options.each_key { |k| patlist.print(" -#{k}") }
|
368
|
-
job.compiler_options_with_args.each_pair { |k, v| patlist.print(" -#{k}:#{v}") }
|
369
|
-
patlist.puts('')
|
370
|
-
end
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
# For future checks on incorrect or incompatible arguments to compiler options
|
375
|
-
def options_ok?
|
376
|
-
end
|
377
|
-
|
378
|
-
def ready?
|
379
|
-
ready = true
|
380
|
-
paths_contain_data = true
|
381
|
-
# check for nil
|
382
|
-
ready = paths_contain_data && !@job_options[:output_directory].nil? &&
|
383
|
-
!@user_options[:reference_directory].nil? &&
|
384
|
-
!@path.nil? &&
|
385
|
-
!@job_options[:pinmap_workbook].nil?
|
386
|
-
ready && @job_options[:output_directory].directory? &&
|
387
|
-
@user_options[:reference_directory].directory? &&
|
388
|
-
@path.exist? &&
|
389
|
-
@job_options[:pinmap_workbook].file? &&
|
390
|
-
[true, false].include?(@job_options[:clean]) &&
|
391
|
-
[:local, :lsf].include?(@job_options[:location]) &&
|
392
|
-
File.exist?(@job_options[:compiler])
|
393
|
-
end
|
394
|
-
|
395
|
-
def bad_options
|
396
|
-
bad = []
|
397
|
-
options = {
|
398
|
-
output_directory: @job_options[:output_directory],
|
399
|
-
reference_directory: @user_options[:reference_directory],
|
400
|
-
path: @path,
|
401
|
-
pinmap_workbook: @job_options[:pinmap_workbook],
|
402
|
-
clean: @job_options[:clean],
|
403
|
-
location: @job_options[:location],
|
404
|
-
compiler: @job_options[:compiler]
|
405
|
-
}
|
406
|
-
options.each do |k, v|
|
407
|
-
bad << k if v.nil?
|
408
|
-
if v.is_a? String # compiler
|
409
|
-
v = Pathname.new(v)
|
410
|
-
bad << k unless v.file?
|
411
|
-
elsif v.is_a? Symbol # clean
|
412
|
-
bad << k unless [:local, :lsf].include? v
|
413
|
-
elsif v.is_a? Pathname
|
414
|
-
if k.match(/directory/)
|
415
|
-
bad << k unless v.directory?
|
416
|
-
elsif k == :path
|
417
|
-
bad << k unless v.exist?
|
418
|
-
else # pinmap
|
419
|
-
bad << k unless v.file?
|
420
|
-
end
|
421
|
-
end
|
422
|
-
end
|
423
|
-
bad
|
424
|
-
end
|
425
|
-
alias_method :bad_opts, :bad_options
|
426
|
-
|
427
|
-
# Output the compiler options to the console
|
428
|
-
def inspect_options(verbose = nil)
|
429
|
-
desc = []
|
430
|
-
# Find the longest option argument string
|
431
|
-
my_job_options = @job_options
|
432
|
-
my_job_options.delete(:compiler)
|
433
|
-
all_arguments = @user_options.values + my_job_options.values + @compiler_options.values + @compiler_options_with_args.values
|
434
|
-
min_argument_padding = 'Argument'.length + 2
|
435
|
-
argument_padding = all_arguments.max_by { |e| e.to_s.length }.to_s.length + 3
|
436
|
-
argument_padding = min_argument_padding if argument_padding < min_argument_padding
|
437
|
-
puts "\n"
|
438
|
-
header = '| Option ' + '| Argument'.ljust(argument_padding) + '| Required |'
|
439
|
-
desc << header
|
440
|
-
desc << '-' * header.length
|
441
|
-
[@user_options, my_job_options, @compiler_options, @compiler_options_with_args].each do |opt|
|
442
|
-
opt.each_pair do |k, v|
|
443
|
-
if k.match(/pinmap_workbook|path|id|directory|clean|location|recursive/i)
|
444
|
-
req = 'true '
|
445
|
-
else
|
446
|
-
next if v.nil? || v == false
|
447
|
-
req = 'false'
|
448
|
-
end
|
449
|
-
desc << "| #{k}".ljust(22) + "| #{v}".ljust(argument_padding) + "| #{req} |"
|
450
|
-
end
|
451
|
-
end
|
452
|
-
puts desc
|
453
|
-
end
|
454
|
-
|
455
|
-
# Output the compiler jobs in the queue to the console
|
456
|
-
def inspect_jobs(index = nil)
|
457
|
-
return empty_msg if empty?
|
458
|
-
desc = []
|
459
|
-
puts "\n"
|
460
|
-
@jobs.each_with_index do |j, i|
|
461
|
-
unless index.nil?
|
462
|
-
next unless i == index
|
463
|
-
end
|
464
|
-
desc << '| Job: ' + "#{i + 1} ".rjust(8) + '|' + 'Pattern:'.rjust(18) + " #{j.pattern.basename}".ljust(100) + '|'
|
465
|
-
desc << '| |' + 'Compiler ID:'.rjust(18) + " #{j.id}".ljust(100) + '|'
|
466
|
-
desc << '| |' + 'Pinmap:'.rjust(18) + " #{j.pinmap_workbook}".ljust(100) + '|'
|
467
|
-
desc << '| |' + '.atp directory:'.rjust(18) + " #{j.pattern.dirname}".ljust(100) + '|'
|
468
|
-
desc << '| |' + '.pat directory:'.rjust(18) + " #{j.output_directory}".ljust(100) + '|'
|
469
|
-
desc << '| |' + 'LSF:'.rjust(18) + " #{j.location == :lsf ? true : false}".ljust(100) + '|'
|
470
|
-
desc << '| |' + 'Delete log files:'.rjust(18) + " #{j.clean}".ljust(100) + '|'
|
471
|
-
desc << '| |' + 'Verbose:'.rjust(18) + " #{j.verbose}".ljust(100) + '|'
|
472
|
-
fragment = '| |' + 'Compiler args:'.rjust(18)
|
473
|
-
overflow_fragment = '| |' + ' '.rjust(18)
|
474
|
-
compiler_args = []
|
475
|
-
compiler_fragment = ''
|
476
|
-
j.compiler_options.each_key do |k|
|
477
|
-
if compiler_fragment.size + " -#{k}".size >= 100
|
478
|
-
compiler_args << compiler_fragment
|
479
|
-
compiler_fragment = nil
|
480
|
-
end
|
481
|
-
compiler_fragment += " -#{k}"
|
482
|
-
end
|
483
|
-
compiler_args << compiler_fragment unless compiler_fragment.nil?
|
484
|
-
compiler_fragment = ''
|
485
|
-
j.compiler_options_with_args.each_pair do |k, v|
|
486
|
-
if compiler_fragment.size + " -#{k}:#{v}".size >= 100
|
487
|
-
compiler_args << compiler_fragment
|
488
|
-
compiler_fragment = nil
|
489
|
-
end
|
490
|
-
compiler_fragment += " -#{k}:#{v}"
|
491
|
-
end
|
492
|
-
compiler_args << compiler_fragment unless compiler_fragment.nil?
|
493
|
-
if compiler_args.join.length <= 100
|
494
|
-
desc << fragment + "#{compiler_args.join}".ljust(100) + '|'
|
495
|
-
else
|
496
|
-
# Need to cycle through compiler args and build a fragment <= 100 characters
|
497
|
-
# and print it. Keep going until the remaining args is <= 100 and print again
|
498
|
-
char_cnt = 0
|
499
|
-
line_cnt = 0
|
500
|
-
args = []
|
501
|
-
compiler_args = compiler_args.join.strip.split(/\s+/)
|
502
|
-
until compiler_args.empty?
|
503
|
-
args = compiler_args.select { |e| (char_cnt += e.length + 1) < 100 }
|
504
|
-
# remove the args that fit on the first line
|
505
|
-
compiler_args -= args
|
506
|
-
if line_cnt == 0
|
507
|
-
desc << fragment + " #{args.join(' ')}".ljust(100) + '|'
|
508
|
-
else
|
509
|
-
desc << overflow_fragment + " #{args.join(' ')}".ljust(100) + '|'
|
510
|
-
end
|
511
|
-
args = []
|
512
|
-
line_cnt += 1
|
513
|
-
char_cnt = 0
|
514
|
-
end
|
515
|
-
end
|
516
|
-
desc << '-' * desc.first.size
|
517
|
-
end
|
518
|
-
puts desc.flatten.join("\n")
|
519
|
-
end
|
520
|
-
|
521
|
-
# Returns the number of jobs in the compiler
|
522
|
-
def count
|
523
|
-
@jobs.size
|
524
|
-
end
|
525
|
-
|
526
|
-
# Checks if the compiler queue is empty
|
527
|
-
def empty?
|
528
|
-
@jobs.empty?
|
529
|
-
end
|
530
|
-
|
531
|
-
private
|
532
|
-
|
533
|
-
def running_on_windows?
|
534
|
-
RUBY_PLATFORM == 'i386-mingw32'
|
535
|
-
end
|
536
|
-
|
537
|
-
def empty_msg
|
538
|
-
puts "No compiler jobs created, check the compiler options\n" if self.empty?
|
539
|
-
end
|
540
|
-
|
541
|
-
def convert_to_pathname(opt)
|
542
|
-
if opt.is_a? String
|
543
|
-
opt = Pathname.new(opt)
|
544
|
-
opt = opt.expand_path
|
545
|
-
elsif opt.is_a? Pathname
|
546
|
-
opt = opt.expand_path
|
547
|
-
else
|
548
|
-
fail "Option #{opt} is not a String, cannot convert to Pathname"
|
549
|
-
end
|
550
|
-
opt
|
551
|
-
end
|
552
|
-
|
553
|
-
def set_reference_directory
|
554
|
-
if @user_options[:reference_directory].nil?
|
555
|
-
# Nothing passed for reference directory so set it to Origen.app.config.pattern_output_directory if valid
|
556
|
-
if File.directory? Origen.app.config.pattern_output_directory
|
557
|
-
@user_options[:reference_directory] = Pathname.new(Origen.app.config.pattern_output_directory)
|
558
|
-
elsif @path
|
559
|
-
if @path.directory?
|
560
|
-
@user_options[:reference_directory] = @path
|
561
|
-
else
|
562
|
-
@user_options[:reference_directory] = @path.dirname
|
563
|
-
end
|
564
|
-
end
|
565
|
-
elsif File.directory?(@user_options[:reference_directory])
|
566
|
-
@user_options[:reference_directory] = Pathname.new(@user_options[:reference_directory])
|
567
|
-
else
|
568
|
-
debug 'Reference directory not set, creating it...'
|
569
|
-
@user_options[:reference_directory] = Pathname.new(@user_options[:reference_directory])
|
570
|
-
FileUtils.mkdir_p(@user_options[:reference_directory])
|
571
|
-
end
|
572
|
-
@user_options[:reference_directory] = @user_options[:reference_directory].expand_path
|
573
|
-
# reference_directory must be a subset of @path. if it is not then set to @path if @path exists
|
574
|
-
unless @path.nil?
|
575
|
-
if @path.directory?
|
576
|
-
@user_options[:reference_directory] = @path unless @path.to_s.include? @user_options[:reference_directory].to_s
|
577
|
-
elsif @path.file?
|
578
|
-
@user_options[:reference_directory] = @path.dirname
|
579
|
-
else
|
580
|
-
debug "Path is set to #{@path} which is not a valid directory or file!"
|
581
|
-
end
|
582
|
-
end
|
583
|
-
end
|
584
|
-
|
585
|
-
# Check if the current tester is an Ultraflex
|
586
|
-
def is_ultraflex?
|
587
|
-
platform == :ultraflex ? true : false
|
588
|
-
end
|
589
|
-
|
590
|
-
def platform
|
591
|
-
if $tester.nil?
|
592
|
-
fail 'No tester instantiated, $tester is set to nil'
|
593
|
-
else
|
594
|
-
$tester.class.to_s.downcase.split('::').last.to_sym
|
595
|
-
end
|
596
|
-
end
|
597
|
-
end
|
598
|
-
end
|
599
|
-
end
|
1
|
+
module OrigenTesters
|
2
|
+
module PatternCompilers
|
3
|
+
class UltraFlexPatternCompiler
|
4
|
+
require 'pathname'
|
5
|
+
require_relative 'assembler'
|
6
|
+
require_relative 'job'
|
7
|
+
|
8
|
+
# Linux compiler executable path
|
9
|
+
LINUX_PATTERN_COMPILER = "#{Origen.root!}/bin/latest/bin/atpcompiler"
|
10
|
+
# LINUX_PATTERN_COMPILER = "#{Origen.root!}/bin/latest/bin/atpcompiler"
|
11
|
+
|
12
|
+
# Windows compiler executable path
|
13
|
+
WINDOWS_PATTERN_COMPILER = "#{ENV['IGXLROOT']}/bin/apc.exe"
|
14
|
+
|
15
|
+
# Linux compiler preamble
|
16
|
+
ATPC_SETUP = "#{Origen.root!}/bin/latest/etc/atpcrc.csh"
|
17
|
+
|
18
|
+
# ID will allow users to set default configurations for the compiler for unique pattern types
|
19
|
+
attr_accessor :id
|
20
|
+
|
21
|
+
# Compiler commands array
|
22
|
+
attr_accessor :jobs
|
23
|
+
|
24
|
+
def initialize(id, options = {})
|
25
|
+
@id = id
|
26
|
+
@id = @id.to_sym
|
27
|
+
|
28
|
+
@user_options = {
|
29
|
+
path: nil, # required: will be passed in or parsed from a .list file
|
30
|
+
reference_directory: nil, # optional: will be set to @path or Origen.app.config.pattern_output_directory
|
31
|
+
target: nil, # optional: allows user to temporarily set target and run compilation
|
32
|
+
recursive: false # optional: controls whether to look for patterns in a directory recursively
|
33
|
+
}
|
34
|
+
@job_options = {
|
35
|
+
compiler: running_on_windows? ? WINDOWS_PATTERN_COMPILER : LINUX_PATTERN_COMPILER, # required
|
36
|
+
id: @id, # required
|
37
|
+
pinmap_workbook: $dut.pinmap, # required: will default to $dut.pinmap
|
38
|
+
location: :local, # optional: controls whether the commands go to the LSF or run locally
|
39
|
+
clean: false, # optional: controls whether compiler log files are deleted after compilation
|
40
|
+
output_directory: nil, # optional:
|
41
|
+
verbose: false # optional: controls whether the compiler output gets put to STDOUT
|
42
|
+
}
|
43
|
+
@compiler_options = { # Set all of these compiler options that don't have args to true/flase. if true then send compiler '-opt'
|
44
|
+
import_all_undefineds: false, # automatically import all undefined symbols. the key is mis-spelled but correct!
|
45
|
+
cpp: false, # runs C++ preprocessor on pattern file
|
46
|
+
comments: false, # saves comments in binary file for tools visibility. pass '-comments' if set to true
|
47
|
+
# pass nothing if set to false
|
48
|
+
nocompress: false, # do not compress pattern data blocks
|
49
|
+
suppress_log: false, # disables output to main log file
|
50
|
+
multiinst: false, # indicates more than one instrument is connected to a single pin
|
51
|
+
lock: false, # prevents pattern from being reverse compiled or opened in PatternTool
|
52
|
+
stdin: false, # Compile data from standard input. Do not use -cpp or specify any pattern file(s) when using this option.
|
53
|
+
debug: false, # generate intermediate file(s) to simplify debug ( application dependent )
|
54
|
+
template: false, # generate setup template
|
55
|
+
timestamp: false, # enable log timestamp
|
56
|
+
}
|
57
|
+
@compiler_options_with_args = {
|
58
|
+
output: nil, # Output filename, compiler defaults to <pattern name>.PAT
|
59
|
+
pinmap_sheet: nil, # <sheetname>
|
60
|
+
digital_inst: nil, # 'HSD4G', 'HSDM', or 'HSDMQ'
|
61
|
+
opcode_mode: nil, # HSDM mode: 'single' | 'dual'. HSDMQ mode: 'single' | 'dual' | 'quad'
|
62
|
+
pat_version: nil, # version of pattern file to compile
|
63
|
+
scan_type: nil, # type of scan data
|
64
|
+
max_errors: nil, # <n>, defaults to 200 on compiler side, valu eof 0 will never abort compilation
|
65
|
+
logfile: nil, # <filename>, directs any compiler messages to <filename>. will default to output directory if nil
|
66
|
+
define: nil, # defines values of macros passed to C++ preprocessor.
|
67
|
+
# can only be defined once per pattern with space delimited list
|
68
|
+
includes: nil, # include paths to be passed to C- preprocessor.
|
69
|
+
post_processor: nil, # <pathname> customer's post-process executable.
|
70
|
+
# need to pass 'post-processor' to compiler
|
71
|
+
post_processor_args: nil, # <args> customer's post-process executable arguments
|
72
|
+
# need to pass 'post-processor_args' to compiler
|
73
|
+
cdl_cache: nil, # 'yes' | 'no', turns on/off CDL caching, default on compiler side is 'yes'
|
74
|
+
init_pattern: nil, # <pattern>, uses the specified pattern module/file/set as an init patterns
|
75
|
+
check_set_msb: nil, # 'yes' | 'no', turns on/off check the 'set' or 'set_infinite' opcode
|
76
|
+
# is preceded by a 'set_msb' or 'set_msb_infinite' opcode. compiler default is 'yes'
|
77
|
+
time_domain: nil, # <time domain>, specifies time domain for pins in patterns
|
78
|
+
allow_mto_dash: nil, # Turn on/off support for channel data runtime repeat,i.e. vector dash in MTO patterns. Default value is "no".
|
79
|
+
check_vm_min_size: nil, # Turns on/off the check on minimum size of a VM pattern. Default value is "yes".
|
80
|
+
check_vm_mod_size: nil, # Turns on/off the check on a VM pattern module size. Default value is "yes".
|
81
|
+
check_oob_size: nil, # Turns on/off the check on size of OOB regions. Yes means size must be modulo 10. Default value is "no".
|
82
|
+
allow_mixed_1x2x: nil, # Turns on/off the support of mixed 1x/2x pin groups. Default value is "no".
|
83
|
+
allow_differential: nil, # Turns on/off support for differential pins. Default value is "yes".
|
84
|
+
allow_scan_in_srm: nil, # Allow/disallow scan vectors in SRM pattern modules. Default value is "no".
|
85
|
+
vm_block_size: nil, # Specifies uncompressed size in bytes of a pattern data block
|
86
|
+
setup: nil, # path to setup file
|
87
|
+
}
|
88
|
+
|
89
|
+
@user_options.update_common(options)
|
90
|
+
@job_options.update_common(options)
|
91
|
+
@compiler_options.update_common(options)
|
92
|
+
@compiler_options_with_args.update_common(options)
|
93
|
+
|
94
|
+
# Check to make sure @compiler_options and @compiler_options_with_args do not have any keys in common
|
95
|
+
fail "Error: @compiler_options and @compiler_options_with_args share keys #{@compiler_options.intersections(@compiler_options_with_args)}. They should be mutually exclusive, exiting..." if @compiler_options.intersect? @compiler_options_with_args
|
96
|
+
|
97
|
+
# Convert any path related options to Pathname object and expand the path
|
98
|
+
unless @user_options[:path].nil?
|
99
|
+
if @user_options[:path].is_a? Pathname
|
100
|
+
@path = @user_options[:path]
|
101
|
+
else
|
102
|
+
@path = Pathname.new(@user_options[:path])
|
103
|
+
end
|
104
|
+
@path = @path.expand_path
|
105
|
+
# path is set but output_directory is not so set output_directory to path
|
106
|
+
@job_options[:output_directory] = @path if @job_options[:output_directory].nil?
|
107
|
+
end
|
108
|
+
|
109
|
+
set_reference_directory
|
110
|
+
|
111
|
+
if @job_options[:output_directory].nil?
|
112
|
+
fail 'Output directory is not set!'
|
113
|
+
else
|
114
|
+
@job_options[:output_directory] = convert_to_pathname(@job_options[:output_directory])
|
115
|
+
# output_directory can not exist, will create for user
|
116
|
+
unless @job_options[:output_directory].directory?
|
117
|
+
puts "Output directory #{@job_options[:output_directory]} does not exist, creating it..."
|
118
|
+
FileUtils.mkdir_p(@job_options[:output_directory])
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Pinmap is required
|
123
|
+
if @job_options[:pinmap_workbook].nil?
|
124
|
+
# Check if the app has $dut.pinmap defined
|
125
|
+
if File.exist? $dut.pinmap
|
126
|
+
@job_options[:pinmap_workbook] = $dut.pinmap
|
127
|
+
else
|
128
|
+
fail 'Pinmap is not defined! Pass as an option or set $dut.pinmap.'
|
129
|
+
end
|
130
|
+
end
|
131
|
+
@job_options[:pinmap_workbook] = convert_to_pathname(@job_options[:pinmap_workbook])
|
132
|
+
fail 'Pinmap is not a file' unless @job_options[:pinmap_workbook].file?
|
133
|
+
|
134
|
+
# Logfile is optional
|
135
|
+
unless @compiler_options[:logfile].nil?
|
136
|
+
@compiler_options[:logfile] = convert_to_pathname(@compiler_options[:logfile])
|
137
|
+
fail 'Pinmap is not a file' unless @job_options[:pinmap_workbook].file?
|
138
|
+
end
|
139
|
+
|
140
|
+
# Check if the LSF is setup in the application
|
141
|
+
if Origen.app.config.lsf.project.nil? || Origen.app.config.lsf.project.empty?
|
142
|
+
puts 'LSF is not set at Origen.app.config.lsf.project, changing to local compilation'
|
143
|
+
@job_options[:location] = :local
|
144
|
+
end
|
145
|
+
|
146
|
+
# Compiler jobs
|
147
|
+
@jobs = []
|
148
|
+
|
149
|
+
# .atp/.atp.gz files found
|
150
|
+
@files = []
|
151
|
+
end
|
152
|
+
|
153
|
+
# Return the id/name of the compiler instance
|
154
|
+
def name
|
155
|
+
@id
|
156
|
+
end
|
157
|
+
|
158
|
+
# Return the compiler instance pinmap
|
159
|
+
def pinmap
|
160
|
+
@job_options[:pinmap_workbook]
|
161
|
+
end
|
162
|
+
|
163
|
+
# Allow users to search for a pattern in the job queue or default
|
164
|
+
# to return all jobs
|
165
|
+
def jobs(search = nil)
|
166
|
+
found = false
|
167
|
+
if search.nil?
|
168
|
+
inspect_jobs
|
169
|
+
found = true
|
170
|
+
elsif search.is_a? String
|
171
|
+
@jobs.each_with_index do |job, index|
|
172
|
+
if job.pattern.to_s.match(search)
|
173
|
+
inspect_jobs(index)
|
174
|
+
found = true
|
175
|
+
else
|
176
|
+
puts "No match found for #{search}"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
elsif search.is_a? Regexp
|
180
|
+
@jobs.each_with_index do |job, index|
|
181
|
+
if search.match(job.pattern.to_s)
|
182
|
+
inspect_jobs(index)
|
183
|
+
found = true
|
184
|
+
else
|
185
|
+
puts "No match found for #{search}"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
elsif search.is_a? Integer
|
189
|
+
if @jobs[search].nil?
|
190
|
+
puts "The compiler queue does not contain a job at index #{search}"
|
191
|
+
else
|
192
|
+
inspect_jobs(search)
|
193
|
+
found = true
|
194
|
+
end
|
195
|
+
else
|
196
|
+
fail 'Search argument must be of type String, Regexp, or Integer'
|
197
|
+
end
|
198
|
+
found
|
199
|
+
end
|
200
|
+
|
201
|
+
# Finds the patterns and creates a compiler job for each one found.
|
202
|
+
# Handles singles files (.atp, .atp.gz, or .list) and directories (recursively or flat)
|
203
|
+
def find_jobs(path = @path)
|
204
|
+
fail 'Pattern path is set to nil, pass in a valid file (.atp or .atp.gz) or a valid directory' if path.nil?
|
205
|
+
@path = Pathname.new(path)
|
206
|
+
fail 'Pattern path does not exist, pass in a valid file (.atp or .atp.gz) or a valid directory' unless @path.exist?
|
207
|
+
@path = @path.expand_path
|
208
|
+
# Set the reference directory for pattern sub-dir mirroring
|
209
|
+
set_reference_directory
|
210
|
+
Origen.profile 'Linux pattern compiler finds patterns' do
|
211
|
+
# Check if the path is a file or a directory
|
212
|
+
if @path.directory?
|
213
|
+
# Get all of the patterns inside this dir or inside this directory recursively
|
214
|
+
# Check if the recursive arg was passed
|
215
|
+
if @user_options[:recursive] == true
|
216
|
+
process_directory(@path, @files, true)
|
217
|
+
else # Just grab the files found inside this directory
|
218
|
+
process_directory(@path, @files, false)
|
219
|
+
end
|
220
|
+
elsif @path.file? # Found a file so no searching is necessary
|
221
|
+
process_file(@path, @files)
|
222
|
+
else # Didn't find a directory or a file so user must want a search for this arg string * NOT SUPPORTED YET
|
223
|
+
fail 'Error: Did not find a file or directory to compile, exiting...'
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
Origen.profile 'Linux pattern compiler creates jobs' do
|
228
|
+
@files.each do |f|
|
229
|
+
rel_dir = Pathname.new("#{f.dirname.to_s[@user_options[:reference_directory].to_s.size..-1]}")
|
230
|
+
output_dir = Pathname.new("#{@job_options[:output_directory]}#{rel_dir}")
|
231
|
+
unless output_dir.directory?
|
232
|
+
puts "Output directory #{output_dir} for pattern #{f.basename} does not exist, creating it..."
|
233
|
+
FileUtils.mkdir_p(output_dir)
|
234
|
+
end
|
235
|
+
current_job_options = @job_options.merge(@compiler_options_with_args)
|
236
|
+
current_job_options[:output_directory] = output_dir
|
237
|
+
@jobs << Job.new(f, current_job_options, @compiler_options)
|
238
|
+
current_job_options = {}
|
239
|
+
end
|
240
|
+
end
|
241
|
+
@files = []
|
242
|
+
if empty?
|
243
|
+
empty_msg
|
244
|
+
else
|
245
|
+
inspect_jobs
|
246
|
+
end
|
247
|
+
end
|
248
|
+
alias_method :find, :find_jobs
|
249
|
+
|
250
|
+
# Executes the compiler for each job in the queue
|
251
|
+
def run(list = nil, options = {})
|
252
|
+
fail "Error: the tester #{Origen.tester} is not an Ultrflex tester,exiting..." unless is_ultraflex?
|
253
|
+
fail "Error: application #{Origen.app.name} is running on Windows, to run the pattern compiler you must be on a Linux machine" if running_on_windows?
|
254
|
+
|
255
|
+
# Check if there was a pattern list passed as an argument
|
256
|
+
# If so, then compile the patterns inside it.
|
257
|
+
# Otherwise compile the jobs in the queue
|
258
|
+
if list.nil?
|
259
|
+
if empty?
|
260
|
+
empty_msg
|
261
|
+
return
|
262
|
+
end
|
263
|
+
@jobs.each do |job|
|
264
|
+
fail "Error: compiler #{job.id} not ready for pattern #{job.name}" unless job.ready?
|
265
|
+
if job.location == :lsf
|
266
|
+
Origen.app.lsf.submit(ATPC_SETUP + '; ' + job.cmd)
|
267
|
+
else
|
268
|
+
Origen.profile "Linux pattern compiler compiles pattern #{job.pattern}" do
|
269
|
+
system job.cmd
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
if @job_options[:location] == :local
|
274
|
+
if @job_options[:clean] == true
|
275
|
+
puts 'Log file :clean option set to true, deleting log files'
|
276
|
+
clean_output
|
277
|
+
end
|
278
|
+
end
|
279
|
+
# Clear @jobs
|
280
|
+
clear
|
281
|
+
else
|
282
|
+
list = convert_to_pathname(list)
|
283
|
+
fail "Error: pattern list #{list} does not exist, exiting..." unless list.file?
|
284
|
+
File.open(list, 'r') do |file|
|
285
|
+
while (line = file.gets)
|
286
|
+
current_job_options = @job_options.merge(@compiler_options_with_args)
|
287
|
+
current_job_options.update_common(options)
|
288
|
+
# puts "current job options is #{current_job_options}"
|
289
|
+
compiler_opts = {}
|
290
|
+
line.strip!
|
291
|
+
pattern = line.match(/^(\S+)\s+(.*)/).captures[0]
|
292
|
+
unless File.file? pattern
|
293
|
+
puts "Warning: Pattern #{pattern} does not exist, skipping..."
|
294
|
+
next
|
295
|
+
end
|
296
|
+
pattern = convert_to_pathname(pattern)
|
297
|
+
line.match(/^\S+\s+(.*)/).captures[0].split(/\s+/).each do |e|
|
298
|
+
opt, arg = e.split(':')
|
299
|
+
opt.gsub!('-', '')
|
300
|
+
if arg.nil?
|
301
|
+
compiler_opts[opt.to_sym] = true
|
302
|
+
else
|
303
|
+
# Check for some specific options
|
304
|
+
case opt
|
305
|
+
when 'pinmap_workbook'
|
306
|
+
current_job_options[opt.to_sym] = Pathname.new(arg)
|
307
|
+
when 'output'
|
308
|
+
dot_pat = Pathname.new(arg)
|
309
|
+
current_job_options[:output_directory] = dot_pat.dirname
|
310
|
+
else
|
311
|
+
current_job_options[opt.to_sym] = arg
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
@jobs << Job.new(pattern, current_job_options, compiler_opts)
|
316
|
+
inspect_jobs
|
317
|
+
end
|
318
|
+
end
|
319
|
+
run
|
320
|
+
# Clear @jobs
|
321
|
+
clear
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
# Clear the job queue
|
326
|
+
def clear
|
327
|
+
@jobs = []
|
328
|
+
@files = []
|
329
|
+
end
|
330
|
+
|
331
|
+
# Output all of the jobs into a pattern list so it can be compiled later
|
332
|
+
# Must be executed after the 'find_jobs' method and before the 'run' method
|
333
|
+
# or @jobs will be empty
|
334
|
+
def to_list(options = {})
|
335
|
+
options = {
|
336
|
+
name: @id,
|
337
|
+
output_directory: Dir.pwd,
|
338
|
+
expand: true,
|
339
|
+
force: false
|
340
|
+
}.update_common(options)
|
341
|
+
list = "#{options[:output_directory]}/#{options[:name]}.list"
|
342
|
+
list = convert_to_pathname(list)
|
343
|
+
if empty?
|
344
|
+
empty_msg
|
345
|
+
return
|
346
|
+
end
|
347
|
+
if list.file?
|
348
|
+
if options[:force] == true
|
349
|
+
puts "Pattern list file #{list} already exists, deleting it..."
|
350
|
+
list.delete
|
351
|
+
else
|
352
|
+
fail "Pattern list file #{list} already exists, exiting..."
|
353
|
+
end
|
354
|
+
end
|
355
|
+
File.open(list, 'w') do |patlist|
|
356
|
+
@jobs.each do |job|
|
357
|
+
if options[:expand] == true
|
358
|
+
pinmap = job.pinmap_workbook
|
359
|
+
dot_pat_name = "#{job.output_directory}/#{job.pattern.basename.to_s.split('.').first}.PAT"
|
360
|
+
dot_atp_name = job.pattern
|
361
|
+
else
|
362
|
+
pinmap = job.pinmap_workbook.basename
|
363
|
+
dot_pat_name = "#{job.pattern.basename.to_s.split('.').first}.PAT"
|
364
|
+
dot_atp_name = job.pattern.basename
|
365
|
+
end
|
366
|
+
patlist.print("#{dot_atp_name} -pinmap_workbook:#{pinmap} -output:#{dot_pat_name}")
|
367
|
+
job.compiler_options.each_key { |k| patlist.print(" -#{k}") }
|
368
|
+
job.compiler_options_with_args.each_pair { |k, v| patlist.print(" -#{k}:#{v}") }
|
369
|
+
patlist.puts('')
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
# For future checks on incorrect or incompatible arguments to compiler options
|
375
|
+
def options_ok?
|
376
|
+
end
|
377
|
+
|
378
|
+
def ready?
|
379
|
+
ready = true
|
380
|
+
paths_contain_data = true
|
381
|
+
# check for nil
|
382
|
+
ready = paths_contain_data && !@job_options[:output_directory].nil? &&
|
383
|
+
!@user_options[:reference_directory].nil? &&
|
384
|
+
!@path.nil? &&
|
385
|
+
!@job_options[:pinmap_workbook].nil?
|
386
|
+
ready && @job_options[:output_directory].directory? &&
|
387
|
+
@user_options[:reference_directory].directory? &&
|
388
|
+
@path.exist? &&
|
389
|
+
@job_options[:pinmap_workbook].file? &&
|
390
|
+
[true, false].include?(@job_options[:clean]) &&
|
391
|
+
[:local, :lsf].include?(@job_options[:location]) &&
|
392
|
+
File.exist?(@job_options[:compiler])
|
393
|
+
end
|
394
|
+
|
395
|
+
def bad_options
|
396
|
+
bad = []
|
397
|
+
options = {
|
398
|
+
output_directory: @job_options[:output_directory],
|
399
|
+
reference_directory: @user_options[:reference_directory],
|
400
|
+
path: @path,
|
401
|
+
pinmap_workbook: @job_options[:pinmap_workbook],
|
402
|
+
clean: @job_options[:clean],
|
403
|
+
location: @job_options[:location],
|
404
|
+
compiler: @job_options[:compiler]
|
405
|
+
}
|
406
|
+
options.each do |k, v|
|
407
|
+
bad << k if v.nil?
|
408
|
+
if v.is_a? String # compiler
|
409
|
+
v = Pathname.new(v)
|
410
|
+
bad << k unless v.file?
|
411
|
+
elsif v.is_a? Symbol # clean
|
412
|
+
bad << k unless [:local, :lsf].include? v
|
413
|
+
elsif v.is_a? Pathname
|
414
|
+
if k.match(/directory/)
|
415
|
+
bad << k unless v.directory?
|
416
|
+
elsif k == :path
|
417
|
+
bad << k unless v.exist?
|
418
|
+
else # pinmap
|
419
|
+
bad << k unless v.file?
|
420
|
+
end
|
421
|
+
end
|
422
|
+
end
|
423
|
+
bad
|
424
|
+
end
|
425
|
+
alias_method :bad_opts, :bad_options
|
426
|
+
|
427
|
+
# Output the compiler options to the console
|
428
|
+
def inspect_options(verbose = nil)
|
429
|
+
desc = []
|
430
|
+
# Find the longest option argument string
|
431
|
+
my_job_options = @job_options
|
432
|
+
my_job_options.delete(:compiler)
|
433
|
+
all_arguments = @user_options.values + my_job_options.values + @compiler_options.values + @compiler_options_with_args.values
|
434
|
+
min_argument_padding = 'Argument'.length + 2
|
435
|
+
argument_padding = all_arguments.max_by { |e| e.to_s.length }.to_s.length + 3
|
436
|
+
argument_padding = min_argument_padding if argument_padding < min_argument_padding
|
437
|
+
puts "\n"
|
438
|
+
header = '| Option ' + '| Argument'.ljust(argument_padding) + '| Required |'
|
439
|
+
desc << header
|
440
|
+
desc << '-' * header.length
|
441
|
+
[@user_options, my_job_options, @compiler_options, @compiler_options_with_args].each do |opt|
|
442
|
+
opt.each_pair do |k, v|
|
443
|
+
if k.match(/pinmap_workbook|path|id|directory|clean|location|recursive/i)
|
444
|
+
req = 'true '
|
445
|
+
else
|
446
|
+
next if v.nil? || v == false
|
447
|
+
req = 'false'
|
448
|
+
end
|
449
|
+
desc << "| #{k}".ljust(22) + "| #{v}".ljust(argument_padding) + "| #{req} |"
|
450
|
+
end
|
451
|
+
end
|
452
|
+
puts desc
|
453
|
+
end
|
454
|
+
|
455
|
+
# Output the compiler jobs in the queue to the console
|
456
|
+
def inspect_jobs(index = nil)
|
457
|
+
return empty_msg if empty?
|
458
|
+
desc = []
|
459
|
+
puts "\n"
|
460
|
+
@jobs.each_with_index do |j, i|
|
461
|
+
unless index.nil?
|
462
|
+
next unless i == index
|
463
|
+
end
|
464
|
+
desc << '| Job: ' + "#{i + 1} ".rjust(8) + '|' + 'Pattern:'.rjust(18) + " #{j.pattern.basename}".ljust(100) + '|'
|
465
|
+
desc << '| |' + 'Compiler ID:'.rjust(18) + " #{j.id}".ljust(100) + '|'
|
466
|
+
desc << '| |' + 'Pinmap:'.rjust(18) + " #{j.pinmap_workbook}".ljust(100) + '|'
|
467
|
+
desc << '| |' + '.atp directory:'.rjust(18) + " #{j.pattern.dirname}".ljust(100) + '|'
|
468
|
+
desc << '| |' + '.pat directory:'.rjust(18) + " #{j.output_directory}".ljust(100) + '|'
|
469
|
+
desc << '| |' + 'LSF:'.rjust(18) + " #{j.location == :lsf ? true : false}".ljust(100) + '|'
|
470
|
+
desc << '| |' + 'Delete log files:'.rjust(18) + " #{j.clean}".ljust(100) + '|'
|
471
|
+
desc << '| |' + 'Verbose:'.rjust(18) + " #{j.verbose}".ljust(100) + '|'
|
472
|
+
fragment = '| |' + 'Compiler args:'.rjust(18)
|
473
|
+
overflow_fragment = '| |' + ' '.rjust(18)
|
474
|
+
compiler_args = []
|
475
|
+
compiler_fragment = ''
|
476
|
+
j.compiler_options.each_key do |k|
|
477
|
+
if compiler_fragment.size + " -#{k}".size >= 100
|
478
|
+
compiler_args << compiler_fragment
|
479
|
+
compiler_fragment = nil
|
480
|
+
end
|
481
|
+
compiler_fragment += " -#{k}"
|
482
|
+
end
|
483
|
+
compiler_args << compiler_fragment unless compiler_fragment.nil?
|
484
|
+
compiler_fragment = ''
|
485
|
+
j.compiler_options_with_args.each_pair do |k, v|
|
486
|
+
if compiler_fragment.size + " -#{k}:#{v}".size >= 100
|
487
|
+
compiler_args << compiler_fragment
|
488
|
+
compiler_fragment = nil
|
489
|
+
end
|
490
|
+
compiler_fragment += " -#{k}:#{v}"
|
491
|
+
end
|
492
|
+
compiler_args << compiler_fragment unless compiler_fragment.nil?
|
493
|
+
if compiler_args.join.length <= 100
|
494
|
+
desc << fragment + "#{compiler_args.join}".ljust(100) + '|'
|
495
|
+
else
|
496
|
+
# Need to cycle through compiler args and build a fragment <= 100 characters
|
497
|
+
# and print it. Keep going until the remaining args is <= 100 and print again
|
498
|
+
char_cnt = 0
|
499
|
+
line_cnt = 0
|
500
|
+
args = []
|
501
|
+
compiler_args = compiler_args.join.strip.split(/\s+/)
|
502
|
+
until compiler_args.empty?
|
503
|
+
args = compiler_args.select { |e| (char_cnt += e.length + 1) < 100 }
|
504
|
+
# remove the args that fit on the first line
|
505
|
+
compiler_args -= args
|
506
|
+
if line_cnt == 0
|
507
|
+
desc << fragment + " #{args.join(' ')}".ljust(100) + '|'
|
508
|
+
else
|
509
|
+
desc << overflow_fragment + " #{args.join(' ')}".ljust(100) + '|'
|
510
|
+
end
|
511
|
+
args = []
|
512
|
+
line_cnt += 1
|
513
|
+
char_cnt = 0
|
514
|
+
end
|
515
|
+
end
|
516
|
+
desc << '-' * desc.first.size
|
517
|
+
end
|
518
|
+
puts desc.flatten.join("\n")
|
519
|
+
end
|
520
|
+
|
521
|
+
# Returns the number of jobs in the compiler
|
522
|
+
def count
|
523
|
+
@jobs.size
|
524
|
+
end
|
525
|
+
|
526
|
+
# Checks if the compiler queue is empty
|
527
|
+
def empty?
|
528
|
+
@jobs.empty?
|
529
|
+
end
|
530
|
+
|
531
|
+
private
|
532
|
+
|
533
|
+
def running_on_windows?
|
534
|
+
RUBY_PLATFORM == 'i386-mingw32'
|
535
|
+
end
|
536
|
+
|
537
|
+
def empty_msg
|
538
|
+
puts "No compiler jobs created, check the compiler options\n" if self.empty?
|
539
|
+
end
|
540
|
+
|
541
|
+
def convert_to_pathname(opt)
|
542
|
+
if opt.is_a? String
|
543
|
+
opt = Pathname.new(opt)
|
544
|
+
opt = opt.expand_path
|
545
|
+
elsif opt.is_a? Pathname
|
546
|
+
opt = opt.expand_path
|
547
|
+
else
|
548
|
+
fail "Option #{opt} is not a String, cannot convert to Pathname"
|
549
|
+
end
|
550
|
+
opt
|
551
|
+
end
|
552
|
+
|
553
|
+
def set_reference_directory
|
554
|
+
if @user_options[:reference_directory].nil?
|
555
|
+
# Nothing passed for reference directory so set it to Origen.app.config.pattern_output_directory if valid
|
556
|
+
if File.directory? Origen.app.config.pattern_output_directory
|
557
|
+
@user_options[:reference_directory] = Pathname.new(Origen.app.config.pattern_output_directory)
|
558
|
+
elsif @path
|
559
|
+
if @path.directory?
|
560
|
+
@user_options[:reference_directory] = @path
|
561
|
+
else
|
562
|
+
@user_options[:reference_directory] = @path.dirname
|
563
|
+
end
|
564
|
+
end
|
565
|
+
elsif File.directory?(@user_options[:reference_directory])
|
566
|
+
@user_options[:reference_directory] = Pathname.new(@user_options[:reference_directory])
|
567
|
+
else
|
568
|
+
debug 'Reference directory not set, creating it...'
|
569
|
+
@user_options[:reference_directory] = Pathname.new(@user_options[:reference_directory])
|
570
|
+
FileUtils.mkdir_p(@user_options[:reference_directory])
|
571
|
+
end
|
572
|
+
@user_options[:reference_directory] = @user_options[:reference_directory].expand_path
|
573
|
+
# reference_directory must be a subset of @path. if it is not then set to @path if @path exists
|
574
|
+
unless @path.nil?
|
575
|
+
if @path.directory?
|
576
|
+
@user_options[:reference_directory] = @path unless @path.to_s.include? @user_options[:reference_directory].to_s
|
577
|
+
elsif @path.file?
|
578
|
+
@user_options[:reference_directory] = @path.dirname
|
579
|
+
else
|
580
|
+
debug "Path is set to #{@path} which is not a valid directory or file!"
|
581
|
+
end
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
# Check if the current tester is an Ultraflex
|
586
|
+
def is_ultraflex?
|
587
|
+
platform == :ultraflex ? true : false
|
588
|
+
end
|
589
|
+
|
590
|
+
def platform
|
591
|
+
if $tester.nil?
|
592
|
+
fail 'No tester instantiated, $tester is set to nil'
|
593
|
+
else
|
594
|
+
$tester.class.to_s.downcase.split('::').last.to_sym
|
595
|
+
end
|
596
|
+
end
|
597
|
+
end
|
598
|
+
end
|
599
|
+
end
|