origen_testers 0.31.0 → 0.40.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/config/application.rb +3 -1
  3. data/config/shared_commands.rb +4 -0
  4. data/config/version.rb +1 -1
  5. data/lib/origen_testers/api.rb +8 -0
  6. data/lib/origen_testers/atp/flow.rb +30 -9
  7. data/lib/origen_testers/flow.rb +36 -2
  8. data/lib/origen_testers/generator.rb +44 -5
  9. data/lib/origen_testers/interface.rb +22 -2
  10. data/lib/origen_testers/origen_ext/generator.rb +4 -3
  11. data/lib/origen_testers/origen_ext/generator/flow.rb +99 -5
  12. data/lib/origen_testers/program_generators.rb +5 -1
  13. data/lib/origen_testers/smartest_based_tester.rb +1 -0
  14. data/lib/origen_testers/smartest_based_tester/base.rb +177 -114
  15. data/lib/origen_testers/smartest_based_tester/base/flow.rb +329 -127
  16. data/lib/origen_testers/smartest_based_tester/base/generator.rb +25 -7
  17. data/lib/origen_testers/smartest_based_tester/base/limits_file.rb +186 -60
  18. data/lib/origen_testers/smartest_based_tester/base/pattern_compiler.rb +4 -0
  19. data/lib/origen_testers/smartest_based_tester/base/pattern_master.rb +4 -0
  20. data/lib/origen_testers/smartest_based_tester/base/processors/extract_bin_names.rb +5 -1
  21. data/lib/origen_testers/smartest_based_tester/base/processors/extract_flow_vars.rb +108 -0
  22. data/lib/origen_testers/smartest_based_tester/base/test_method.rb +8 -3
  23. data/lib/origen_testers/smartest_based_tester/base/test_suite.rb +9 -108
  24. data/lib/origen_testers/smartest_based_tester/base/test_suites.rb +17 -7
  25. data/lib/origen_testers/smartest_based_tester/base/variables_file.rb +29 -7
  26. data/lib/origen_testers/smartest_based_tester/smt7.rb +59 -0
  27. data/lib/origen_testers/smartest_based_tester/smt8.rb +218 -0
  28. data/lib/origen_testers/smartest_based_tester/v93k/flow.rb +32 -0
  29. data/lib/origen_testers/smartest_based_tester/v93k/templates/vars.tf.erb +2 -2
  30. data/lib/origen_testers/smartest_based_tester/v93k/test_suite.rb +109 -0
  31. data/lib/origen_testers/smartest_based_tester/v93k_smt8.rb +8 -0
  32. data/lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb +234 -0
  33. data/lib/origen_testers/smartest_based_tester/v93k_smt8/generator.rb +48 -0
  34. data/lib/origen_testers/smartest_based_tester/v93k_smt8/limits_file.rb +14 -0
  35. data/lib/origen_testers/smartest_based_tester/v93k_smt8/limits_workbook.rb +148 -0
  36. data/lib/origen_testers/smartest_based_tester/v93k_smt8/templates/limits.csv.erb +3 -0
  37. data/lib/origen_testers/smartest_based_tester/v93k_smt8/templates/template.flow.erb +41 -0
  38. data/lib/origen_testers/smartest_based_tester/v93k_smt8/test_suite.rb +66 -0
  39. data/lib/origen_testers/stil_based_tester/base.rb +4 -0
  40. data/lib/origen_testers/test/interface.rb +16 -2
  41. data/lib/origen_testers/vector_generator.rb +9 -4
  42. data/lib/origen_testers/vector_pipeline.rb +1 -1
  43. data/pattern/nvm/v93k/v93k_workout.rb +7 -0
  44. data/program/_erase_vfy.rb +2 -1
  45. data/program/components/_deep_nested.rb +3 -0
  46. data/program/components/_prb1_main.rb +1 -1
  47. data/program/components/_prb2_main.rb +6 -2
  48. data/program/flow_control.rb +3 -3
  49. data/program/prb1.rb +4 -0
  50. data/program/prb2.rb +7 -3
  51. data/templates/origen_guides/pattern/v93k.md.erb +24 -0
  52. data/templates/origen_guides/program/v93k.md.erb +6 -148
  53. data/templates/origen_guides/program/v93ksmt7.md.erb +165 -0
  54. data/templates/origen_guides/program/v93ksmt8.md.erb +112 -0
  55. metadata +30 -3
  56. data/lib/origen_testers/smartest_based_tester/base/test_methods/smart_calc_tml.rb +0 -23
@@ -17,13 +17,17 @@ module OrigenTesters
17
17
  attr_accessor :abs_class_name
18
18
  attr_reader :limits
19
19
  attr_accessor :limits_id
20
+ alias_method :limit_id, :limits_id
21
+ alias_method :limit_id=, :limits_id=
22
+ # Used to store the name of the primary test logged in SMT8
23
+ attr_accessor :sub_test_name
20
24
 
21
25
  def initialize(options)
22
26
  @type = options[:type]
23
27
  @library = options[:library]
24
28
  @class_name = options[:methods].delete(:class_name)
25
29
  @parameters = {}
26
- @limits_id = options[:methods].delete(:limits_id)
30
+ @limits_id = options[:methods].delete(:limits_id) || options[:methods].delete(:limit_id)
27
31
  @limits = TestMethods::Limits.new(self)
28
32
  # Add any methods
29
33
  if options[:methods][:methods]
@@ -116,10 +120,11 @@ module OrigenTesters
116
120
  when :boolean
117
121
  # Check for valid values
118
122
  if [0, 1, true, false].include?(val)
123
+ # Use true/false for smt8 and 0/1 for smt7
119
124
  if [1, true].include?(val)
120
- 1
125
+ tester.smt8? ? true : 1
121
126
  else
122
- 0
127
+ tester.smt8? ? false : 0
123
128
  end
124
129
  else
125
130
  fail "Unknown boolean value for attribute #{attr}: #{val}"
@@ -4,87 +4,6 @@ module OrigenTesters
4
4
  class TestSuite
5
5
  attr_accessor :meta
6
6
 
7
- ATTRS =
8
- %w(name
9
- comment
10
-
11
- timing_equation timing_spec timing_set
12
- level_equation level_spec level_set
13
- analog_set
14
- pattern
15
- context
16
- test_type
17
- test_method
18
-
19
- test_number
20
- test_level
21
-
22
- bypass
23
- set_pass
24
- set_fail
25
- hold
26
- hold_on_fail
27
- output_on_pass
28
- output_on_fail
29
- pass_value
30
- fail_value
31
- per_pin_on_pass
32
- per_pin_on_fail
33
- log_mixed_signal_waveform
34
- fail_per_label
35
- ffc_enable
36
- log_first
37
- ffv_enable
38
- frg_enable
39
- hardware_dsp_disable
40
- )
41
-
42
- ALIASES = {
43
- tim_equ_set: :timing_equation,
44
- tim_spec_set: :timing_spec,
45
- timset: :timing_set,
46
- timeset: :timing_set,
47
- time_set: :timing_set,
48
- lev_equ_set: :level_equation,
49
- lev_spec_set: :level_spec,
50
- levset: :level_set,
51
- levels: :level_set,
52
- pin_levels: :level_set,
53
- anaset: :analog_set,
54
- test_num: :test_number,
55
- test_function: :test_method,
56
- value_on_pass: :pass_value,
57
- value_on_fail: :fail_value,
58
- seqlbl: :pattern,
59
- mx_waves_enable: :log_mixed_signal_waveform,
60
- hw_dsp_disable: :hardware_dsp_disable,
61
- ffc_on_fail: :log_first
62
- }
63
-
64
- DEFAULTS = {
65
- output_on_pass: true,
66
- output_on_fail: true,
67
- pass_value: true,
68
- fail_value: true,
69
- per_pin_on_pass: true,
70
- per_pin_on_fail: true
71
- }
72
-
73
- # Generate accessors for all attributes and their aliases
74
- ATTRS.each do |attr|
75
- attr_accessor attr.to_sym
76
- end
77
-
78
- # Define the aliases
79
- ALIASES.each do |_alias, val|
80
- define_method("#{_alias}=") do |v|
81
- send("#{val}=", v)
82
- end
83
- define_method("#{_alias}") do
84
- send(val)
85
- end
86
- end
87
-
88
7
  def initialize(name, attrs = {})
89
8
  @name = name
90
9
  if interface.unique_test_names == :signature
@@ -106,7 +25,7 @@ module OrigenTesters
106
25
  end
107
26
  end
108
27
  # Set the defaults
109
- DEFAULTS.each do |k, v|
28
+ self.class::DEFAULTS.each do |k, v|
110
29
  send("#{k}=", v)
111
30
  end
112
31
  # Then the values that have been supplied
@@ -115,6 +34,10 @@ module OrigenTesters
115
34
  end
116
35
  end
117
36
 
37
+ def smt8?
38
+ tester.smt8?
39
+ end
40
+
118
41
  def pattern=(name)
119
42
  Origen.interface.record_pattern_reference(name) if name
120
43
  @pattern = name
@@ -129,31 +52,6 @@ module OrigenTesters
129
52
  fail 'Once assigned the name of a test suite cannot be changed!'
130
53
  end
131
54
 
132
- def lines
133
- if pattern
134
- burst = $tester.multiport ? "#{$tester.multiport_name(pattern)}" : "#{pattern}"
135
- end
136
- l = []
137
- l << " comment = \"#{comment}\";" if comment
138
- l << " ffc_on_fail = #{wrap_if_string(log_first)};" if log_first
139
- l << " local_flags = #{flags};"
140
- l << ' override = 1;'
141
- l << " override_anaset = #{wrap_if_string(analog_set)};" if analog_set
142
- l << " override_lev_equ_set = #{wrap_if_string(level_equation)};" if level_equation
143
- l << " override_lev_spec_set = #{wrap_if_string(level_spec)};" if level_spec
144
- l << " override_levset = #{wrap_if_string(level_set)};" if level_set
145
- l << " override_seqlbl = #{wrap_if_string(burst)};" if pattern
146
- l << " override_test_number = #{test_number};" if test_number
147
- l << " override_testf = #{test_method.id};" if test_method
148
- l << " override_tim_equ_set = #{wrap_if_string(timing_equation)};" if timing_equation
149
- l << " override_tim_spec_set = #{wrap_if_string(timing_spec)};" if timing_spec
150
- l << " override_timset = #{wrap_if_string(timing_set)};" if timing_set
151
- l << ' site_control = "parallel:";'
152
- l << ' site_match = 2;'
153
- l << " test_level = #{test_level};" if test_level
154
- l
155
- end
156
-
157
55
  def method_missing(method, *args, &block)
158
56
  if test_method && test_method.respond_to?(method)
159
57
  test_method.send(method, *args, &block)
@@ -171,7 +69,10 @@ module OrigenTesters
171
69
  end
172
70
 
173
71
  def to_meta
174
- meta || {}
72
+ m = meta || {}
73
+ m['Test'] = name
74
+ m['Test Name'] ||= try(:test_name)
75
+ m
175
76
  end
176
77
 
177
78
  def extract_atp_attributes(options)
@@ -10,6 +10,11 @@ module OrigenTesters
10
10
  def initialize(flow)
11
11
  @flow = flow
12
12
  @collection = []
13
+ @existing_names = {}
14
+ # Test names also have to be unique vs. the current flow name
15
+ if tester.smt8?
16
+ @existing_names[flow.filename.sub('.flow', '').to_s] = true
17
+ end
13
18
  end
14
19
 
15
20
  def filename
@@ -17,7 +22,11 @@ module OrigenTesters
17
22
  end
18
23
 
19
24
  def add(name, options = {})
25
+ symbol = name.is_a?(Symbol)
20
26
  name = make_unique(name)
27
+ # Ensure names given as a symbol stay as a symbol, this is more for
28
+ # alignment to existing test cases than anything else
29
+ name = name.to_sym if symbol
21
30
  suite = platform::TestSuite.new(name, options)
22
31
  @collection << suite
23
32
  # c = Origen.interface.consume_comments
@@ -43,14 +52,15 @@ module OrigenTesters
43
52
  private
44
53
 
45
54
  def make_unique(name)
46
- @existing_names ||= {}
47
- if @existing_names[name.to_sym]
48
- @existing_names[name.to_sym] += 1
49
- "#{name}_#{@existing_names[name.to_sym]}"
50
- else
51
- @existing_names[name.to_sym] = 0
52
- name
55
+ name = name.to_s
56
+ tempname = name
57
+ i = 0
58
+ while @existing_names[tempname]
59
+ i += 1
60
+ tempname = "#{name}_#{i}"
53
61
  end
62
+ @existing_names[tempname] = true
63
+ tempname
54
64
  end
55
65
  end
56
66
  end
@@ -5,33 +5,55 @@ module OrigenTesters
5
5
  class VariablesFile
6
6
  include OrigenTesters::Generator
7
7
 
8
- attr_reader :flow_control_variables, :runtime_control_variables
8
+ attr_reader :variables
9
9
  attr_accessor :filename, :id
10
10
 
11
11
  def initialize(options = {})
12
- @flow_control_variables = []
13
- @runtime_control_variables = []
14
12
  end
15
13
 
16
14
  def subdirectory
17
15
  'testflow/mfh.testflow.setup'
18
16
  end
19
17
 
20
- def clean_flow_control_variables
21
- flow_control_variables.uniq.sort do |x, y|
18
+ def add_variables(vars)
19
+ if @variables
20
+ vars.each do |k, v|
21
+ if k == :empty?
22
+ @variables[:empty?] ||= v
23
+ else
24
+ v.each do |k2, v2|
25
+ unless v2.empty?
26
+ @variables[k][k2] |= v2
27
+ end
28
+ end
29
+ end
30
+ end
31
+ else
32
+ @variables = vars
33
+ end
34
+ end
35
+
36
+ # What SMT7 calls a flag
37
+ def flags
38
+ (variables[:all][:referenced_enables] + variables[:all][:set_enables]).uniq.sort do |x, y|
22
39
  x = x[0] if x.is_a?(Array)
23
40
  y = y[0] if y.is_a?(Array)
24
41
  x <=> y
25
42
  end
26
43
  end
27
44
 
28
- def clean_runtime_control_variables
29
- runtime_control_variables.uniq.sort do |x, y|
45
+ # What SMT7 calls a declaration
46
+ def declarations
47
+ (variables[:all][:jobs] + variables[:all][:referenced_flags] + variables[:all][:set_flags]).uniq.sort do |x, y|
30
48
  x = x[0] if x.is_a?(Array)
31
49
  y = y[0] if y.is_a?(Array)
32
50
  x <=> y
33
51
  end
34
52
  end
53
+
54
+ def to_be_written?
55
+ tester.smt7?
56
+ end
35
57
  end
36
58
  end
37
59
  end
@@ -0,0 +1,59 @@
1
+ module OrigenTesters
2
+ module SmartestBasedTester
3
+ module SMT7
4
+ # This is an internal method use by Origen which returns a fully formatted vector
5
+ # You can override this if you wish to change the output formatting at vector level
6
+ def format_vector(vec)
7
+ timeset = vec.timeset ? "#{vec.timeset.name}" : ''
8
+ pin_vals = vec.pin_vals ? "#{vec.pin_vals} " : ''
9
+ if vec.repeat # > 1
10
+ microcode = "R#{vec.repeat}"
11
+ else
12
+ microcode = vec.microcode ? vec.microcode : ''
13
+ end
14
+
15
+ if Origen.mode.simulation? || !inline_comments || $_testers_no_inline_comments
16
+ comment = ''
17
+ else
18
+
19
+ header_comments = []
20
+ repeat_comment = ''
21
+ vec.comments.each_with_index do |comment, i|
22
+ if comment =~ /^#/
23
+ if comment =~ /^#(R\d+)$/
24
+ repeat_comment = Regexp.last_match(1) + ' '
25
+ # Throw away the ############# headers and footers
26
+ elsif comment !~ /^# ####################/
27
+ comment = comment.strip.sub(/^# (## )?/, '')
28
+ if comment == ''
29
+ # Throw away empty lines at the start/end, but preserve them in the middle
30
+ unless header_comments.empty? || i == vec.comments.size - 1
31
+ header_comments << comment
32
+ end
33
+ else
34
+ header_comments << comment
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ if vec.pin_vals && ($_testers_enable_vector_comments || vector_comments)
41
+ comment = "#{vec.number}:#{vec.cycle}"
42
+ comment += ': ' if !header_comments.empty? || !vec.inline_comment.empty?
43
+ else
44
+ comment = ''
45
+ end
46
+ comment += header_comments.join("\cm") unless header_comments.empty?
47
+ unless vec.inline_comment.empty?
48
+ comment += "\cm" unless header_comments.empty?
49
+ comment += "(#{vec.inline_comment})"
50
+ end
51
+ comment = "#{repeat_comment}#{comment}"
52
+ end
53
+
54
+ # Max comment length 250 at the end
55
+ "#{microcode.ljust(25)}#{timeset.ljust(27)}#{pin_vals}# #{comment[0, 247]};"
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,218 @@
1
+ module OrigenTesters
2
+ module SmartestBasedTester
3
+ module SMT8
4
+ # This currently defines what subdirectory of the pattern output directory that
5
+ # patterns will be output to
6
+ def subdirectory
7
+ File.join(package_namespace, 'patterns')
8
+ end
9
+
10
+ # An internal method called by Origen to create the pattern header
11
+ def pattern_header(options = {})
12
+ options = {
13
+ }.merge(options)
14
+ @program_lines = []
15
+ @program_action_lines = []
16
+ if zip_patterns
17
+ @program_lines << '<?xml version="1.0" encoding="UTF-8"?>'
18
+ @program_lines << '<Program xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Program.xsd">'
19
+ end
20
+ @program_lines << ' <Assignment id="memory" value="SM"/>'
21
+ pin_list = ordered_pins.map do |p|
22
+ if Origen.app.pin_pattern_order.include?(p.id)
23
+ # specified name overrides pin name
24
+ if (p.is_a?(Origen::Pins::PinCollection)) || p.id != p.name
25
+ p.id.to_s # groups or aliases can be lower case
26
+ else
27
+ p.id.to_s.upcase # pins must be uppercase
28
+ end
29
+ else
30
+ if (p.is_a?(Origen::Pins::PinCollection)) || p.id != p.name
31
+ p.name.to_s # groups or aliases can be lower case
32
+ else
33
+ p.name.to_s.upcase # pins must be uppercase
34
+ end
35
+ end
36
+ end.join(',')
37
+ @program_lines << " <Instrument id=\"#{pin_list}\">"
38
+ end
39
+
40
+ # An internal method called by Origen to generate the pattern footer
41
+ def pattern_footer(options = {})
42
+ options = {
43
+ end_in_ka: false
44
+ }.merge(options)
45
+ if options[:end_in_ka]
46
+ Origen.log.warning '93K keep alive not yet implemented!'
47
+ ss 'WARNING: 93K keep alive not yet implemented!'
48
+ end
49
+ @program_footer_lines = []
50
+ @program_footer_lines << '</Program>' if zip_patterns
51
+ end
52
+
53
+ # @api private
54
+ def open_and_write_pattern(filename)
55
+ pat_name = Pathname.new(filename).basename.to_s
56
+
57
+ @gen_vec = 0
58
+ @vector_number = 0
59
+ @vector_lines = []
60
+ @comment_lines = []
61
+ # @program_lines was already created with the pattern_header
62
+
63
+ yield
64
+
65
+ write_gen_vec
66
+ @program_lines << ' </Instrument>'
67
+
68
+ if zip_patterns
69
+ tmp_dir = filename.gsub('.', '_')
70
+ FileUtils.mkdir_p(tmp_dir)
71
+ program_file = File.join(tmp_dir, 'Program.sprg')
72
+ vector_file = File.join(tmp_dir, 'Vectors.vec')
73
+ comments_file = File.join(tmp_dir, 'Comments.cmt')
74
+
75
+ File.open(program_file, 'w') do |f|
76
+ (@program_lines + @program_action_lines + @program_footer_lines).each do |line|
77
+ f.puts line
78
+ end
79
+ end
80
+
81
+ File.open(vector_file, 'w') { |f| @vector_lines.each { |l| f.puts l } }
82
+ File.open(comments_file, 'w') { |f| @comment_lines.each { |l| f.puts l } }
83
+
84
+ Dir.chdir tmp_dir do
85
+ `zip #{pat_name} Program.sprg Vectors.vec Comments.cmt`
86
+ FileUtils.mv pat_name, filename
87
+ end
88
+ else
89
+ File.open filename, 'w' do |f|
90
+ f.puts '<Pattern>'
91
+ f.puts ' <Program>'
92
+ (@program_lines + @program_action_lines + @program_footer_lines).each do |line|
93
+ f.puts ' ' + line
94
+ end
95
+ f.puts ' </Program>'
96
+ f.puts ' <Vector>'
97
+ @vector_lines.each { |l| f.puts ' ' + l }
98
+ f.puts ' </Vector>'
99
+ f.puts ' <Comment>'
100
+ @comment_lines.each { |l| f.puts ' ' + l }
101
+ f.puts ' </Comment>'
102
+ f.puts '</Pattern>'
103
+ end
104
+ end
105
+ ensure
106
+ FileUtils.rm_rf(tmp_dir) if zip_patterns && File.exist?(tmp_dir)
107
+ end
108
+
109
+ # @api private
110
+ #
111
+ # The SMT8 microcode is implemented as a post conversion of the SMT7 microcode, rather than
112
+ # generating SMT8 microcode originally.
113
+ # This is generally an easier implementation and since they both run on the same h/ware there
114
+ # should always be a 1:1 feature mapping between the 2 systems.
115
+ def track_and_format_comment(comment)
116
+ if comment =~ /^SQPG/
117
+ if comment =~ /^SQPG PADDING/
118
+ # A gen vec should not be used for MRPT vectors, the padding instruction marks the end of them
119
+ @gen_vec = 0
120
+ else
121
+ write_gen_vec
122
+ if comment =~ /^SQPG JSUB ([^;]+);/
123
+ @program_lines << " <Instruction id=\"patternCall\" value=\"#{tester.package_namespace}.patterns.#{Regexp.last_match(1)}\"/>"
124
+ elsif comment =~ /^SQPG MACT (\d+);/
125
+ @program_lines << " <Instruction id=\"match\" value=\"#{Regexp.last_match(1)}\"/>"
126
+ elsif comment =~ /^SQPG MRPT (\d+);/
127
+ @program_lines << " <Instruction id=\"matchRepeat\" value=\"#{Regexp.last_match(1)}\"/>"
128
+ elsif comment =~ /^SQPG LBGN (\d+);/
129
+ @program_lines << " <Instruction id=\"loop\" value=\"#{Regexp.last_match(1)}\"/>"
130
+ elsif comment =~ /^SQPG LEND;/
131
+ @program_lines << " <Instruction id=\"loopEnd\"/>"
132
+ elsif comment =~ /^SQPG RETC (\d) (\d);/
133
+ @program_lines << " <Instruction id=\"returnConditional\">"
134
+ @program_lines << " <Assignment id=\"onFail\" value=\"#{Regexp.last_match(1) == '0' ? 'false' : 'true'}\"/>"
135
+ @program_lines << " <Assignment id=\"resetFail\" value=\"#{Regexp.last_match(2) == '0' ? 'false' : 'true'}\"/>"
136
+ @program_lines << ' </Instruction>'
137
+ else
138
+ Origen.log.warning "This SMT7 microcode was not converted to SMT8: #{comment}"
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ # This is an internal method use by Origen which returns a fully formatted vector
145
+ # You can override this if you wish to change the output formatting at vector level
146
+ def format_vector(vec)
147
+ has_microcode = vec.microcode && !vec.microcode.empty?
148
+ has_repeat = vec.repeat && vec.repeat > 1
149
+ if has_microcode || has_repeat
150
+ # Close out current gen_vec group
151
+ write_gen_vec
152
+ if has_repeat
153
+ @program_lines << " <Instruction id=\"genVec\" value=\"1\">"
154
+ @program_lines << " <Assignment id=\"repeat\" value=\"#{vec.repeat}\"/>"
155
+ @program_lines << ' </Instruction>'
156
+ @gen_vec -= 1
157
+ end
158
+ if has_microcode
159
+ puts vec.microcode
160
+ end
161
+ end
162
+
163
+ unless Origen.mode.simulation? || !inline_comments || $_testers_no_inline_comments
164
+ header_comments = []
165
+ repeat_comment = ''
166
+ vec.comments.each_with_index do |comment, i|
167
+ if comment =~ /^#/
168
+ if comment =~ /^#(R\d+)$/
169
+ repeat_comment = Regexp.last_match(1) + ' '
170
+ # Throw away the ############# headers and footers
171
+ elsif comment !~ /^# ####################/
172
+ comment = comment.strip.sub(/^# (## )?/, '')
173
+ if comment == ''
174
+ # Throw away empty lines at the start/end, but preserve them in the middle
175
+ unless header_comments.empty? || i == vec.comments.size - 1
176
+ header_comments << comment
177
+ end
178
+ else
179
+ header_comments << comment
180
+ end
181
+ end
182
+ end
183
+ end
184
+
185
+ if vec.pin_vals && ($_testers_enable_vector_comments || vector_comments)
186
+ comment = "#{vec.number}:#{vec.cycle}"
187
+ comment += ': ' if !header_comments.empty? || !vec.inline_comment.empty?
188
+ else
189
+ comment = ''
190
+ end
191
+ # comment += header_comments.join("\cm") unless header_comments.empty?
192
+ # Seems that SMT8 does not support the above newline char, so identify split lines with something else
193
+ comment += header_comments.join('----') unless header_comments.empty?
194
+ unless vec.inline_comment.empty?
195
+ comment += "\cm" unless header_comments.empty?
196
+ comment += "(#{vec.inline_comment})"
197
+ end
198
+ c = "#{repeat_comment}#{comment}"
199
+ @comment_lines << "#{@vector_number} #{c}"[0, 3000] unless c.empty?
200
+ end
201
+
202
+ if vec.pin_vals
203
+ @vector_lines << vec.pin_vals.gsub(' ', '')
204
+ @vector_number += 1
205
+ @gen_vec += 1
206
+ end
207
+ end
208
+
209
+ # @api private
210
+ def write_gen_vec
211
+ if @gen_vec > 0
212
+ @program_lines << " <Instruction id=\"genVec\" value=\"#{@gen_vec}\"/>"
213
+ @gen_vec = 0
214
+ end
215
+ end
216
+ end
217
+ end
218
+ end