origen_testers 0.31.0 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/config/application.rb +3 -1
- data/config/shared_commands.rb +4 -0
- data/config/version.rb +1 -1
- data/lib/origen_testers/api.rb +8 -0
- data/lib/origen_testers/atp/flow.rb +30 -9
- data/lib/origen_testers/flow.rb +36 -2
- data/lib/origen_testers/generator.rb +44 -5
- data/lib/origen_testers/interface.rb +22 -2
- data/lib/origen_testers/origen_ext/generator.rb +4 -3
- data/lib/origen_testers/origen_ext/generator/flow.rb +99 -5
- data/lib/origen_testers/program_generators.rb +5 -1
- data/lib/origen_testers/smartest_based_tester.rb +1 -0
- data/lib/origen_testers/smartest_based_tester/base.rb +177 -114
- data/lib/origen_testers/smartest_based_tester/base/flow.rb +329 -127
- data/lib/origen_testers/smartest_based_tester/base/generator.rb +25 -7
- data/lib/origen_testers/smartest_based_tester/base/limits_file.rb +186 -60
- data/lib/origen_testers/smartest_based_tester/base/pattern_compiler.rb +4 -0
- data/lib/origen_testers/smartest_based_tester/base/pattern_master.rb +4 -0
- data/lib/origen_testers/smartest_based_tester/base/processors/extract_bin_names.rb +5 -1
- data/lib/origen_testers/smartest_based_tester/base/processors/extract_flow_vars.rb +108 -0
- data/lib/origen_testers/smartest_based_tester/base/test_method.rb +8 -3
- data/lib/origen_testers/smartest_based_tester/base/test_suite.rb +9 -108
- data/lib/origen_testers/smartest_based_tester/base/test_suites.rb +17 -7
- data/lib/origen_testers/smartest_based_tester/base/variables_file.rb +29 -7
- data/lib/origen_testers/smartest_based_tester/smt7.rb +59 -0
- data/lib/origen_testers/smartest_based_tester/smt8.rb +218 -0
- data/lib/origen_testers/smartest_based_tester/v93k/flow.rb +32 -0
- data/lib/origen_testers/smartest_based_tester/v93k/templates/vars.tf.erb +2 -2
- data/lib/origen_testers/smartest_based_tester/v93k/test_suite.rb +109 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8.rb +8 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/flow.rb +234 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/generator.rb +48 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/limits_file.rb +14 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/limits_workbook.rb +148 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/templates/limits.csv.erb +3 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/templates/template.flow.erb +41 -0
- data/lib/origen_testers/smartest_based_tester/v93k_smt8/test_suite.rb +66 -0
- data/lib/origen_testers/stil_based_tester/base.rb +4 -0
- data/lib/origen_testers/test/interface.rb +16 -2
- data/lib/origen_testers/vector_generator.rb +9 -4
- data/lib/origen_testers/vector_pipeline.rb +1 -1
- data/pattern/nvm/v93k/v93k_workout.rb +7 -0
- data/program/_erase_vfy.rb +2 -1
- data/program/components/_deep_nested.rb +3 -0
- data/program/components/_prb1_main.rb +1 -1
- data/program/components/_prb2_main.rb +6 -2
- data/program/flow_control.rb +3 -3
- data/program/prb1.rb +4 -0
- data/program/prb2.rb +7 -3
- data/templates/origen_guides/pattern/v93k.md.erb +24 -0
- data/templates/origen_guides/program/v93k.md.erb +6 -148
- data/templates/origen_guides/program/v93ksmt7.md.erb +165 -0
- data/templates/origen_guides/program/v93ksmt8.md.erb +112 -0
- metadata +30 -3
- 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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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 :
|
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
|
21
|
-
|
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
|
-
|
29
|
-
|
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
|