origen 0.2.6 → 0.3.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/bin/origen +3 -1
- data/config/boot.rb +1 -7
- data/config/commands.rb +0 -1
- data/config/version.rb +2 -2
- data/lib/c99/{j750_interface.rb → ate_interface.rb} +3 -11
- data/lib/c99/doc_interface.rb +1 -1
- data/lib/origen.rb +9 -30
- data/lib/origen/application.rb +10 -8
- data/lib/origen/application/configuration.rb +13 -26
- data/lib/origen/application/plugins.rb +122 -0
- data/lib/origen/application/plugins_manager.rb +16 -254
- data/lib/origen/application/release.rb +2 -2
- data/lib/origen/application/runner.rb +2 -4
- data/lib/origen/chips.rb +0 -0
- data/lib/origen/chips/chip.rb +0 -0
- data/lib/origen/chips/design_entry.rb +0 -0
- data/lib/origen/chips/doc_entry.rb +0 -0
- data/lib/origen/chips/note.rb +0 -0
- data/lib/origen/commands.rb +4 -44
- data/lib/origen/commands/compile.rb +1 -2
- data/lib/origen/commands/generate.rb +1 -1
- data/lib/origen/commands/interactive.rb +1 -2
- data/lib/origen/commands/plugin.rb +49 -56
- data/lib/origen/commands/program.rb +1 -1
- data/lib/origen/commands/rc.rb +2 -2
- data/lib/origen/commands/version.rb +2 -17
- data/lib/origen/commands_global.rb +3 -0
- data/lib/origen/file_handler.rb +10 -10
- data/lib/origen/generator.rb +1 -1
- data/lib/origen/generator/job.rb +1 -1
- data/lib/origen/generator/pattern.rb +2 -2
- data/lib/origen/generator/pattern_finder.rb +10 -9
- data/lib/origen/pins/pin.rb +0 -0
- data/lib/origen/regression_manager.rb +0 -0
- data/lib/origen/remote_manager.rb +2 -8
- data/lib/origen/revision_control/design_sync.rb +0 -0
- data/lib/origen/revision_control/git.rb +0 -0
- data/lib/origen/specs.rb +0 -0
- data/lib/origen/specs/checkers.rb +0 -0
- data/lib/origen/specs/creation_info.rb +0 -0
- data/lib/origen/specs/exhibit.rb +0 -0
- data/lib/origen/specs/spec.rb +0 -0
- data/lib/origen/utility.rb +0 -1
- data/lib/origen/utility/diff.rb +0 -0
- metadata +42 -119
- data/lib/origen/import_manager.rb +0 -596
- data/lib/origen/nvm.rb +0 -6
- data/lib/origen/nvm/block_array.rb +0 -72
- data/lib/origen/tester.rb +0 -56
- data/lib/origen/tester/api.rb +0 -277
- data/lib/origen/tester/bdm/bdm.rb +0 -25
- data/lib/origen/tester/doc/doc.rb +0 -226
- data/lib/origen/tester/doc/generator.rb +0 -126
- data/lib/origen/tester/doc/generator/flow.rb +0 -71
- data/lib/origen/tester/doc/generator/flow_line.rb +0 -203
- data/lib/origen/tester/doc/generator/test.rb +0 -68
- data/lib/origen/tester/doc/generator/test_group.rb +0 -66
- data/lib/origen/tester/doc/generator/tests.rb +0 -47
- data/lib/origen/tester/doc/model.rb +0 -162
- data/lib/origen/tester/generator.rb +0 -271
- data/lib/origen/tester/generator/flow_control_api.rb +0 -606
- data/lib/origen/tester/generator/identity_map.rb +0 -25
- data/lib/origen/tester/generator/placeholder.rb +0 -13
- data/lib/origen/tester/generator/test_numberer.rb +0 -25
- data/lib/origen/tester/interface.rb +0 -154
- data/lib/origen/tester/j750/files.rb +0 -45
- data/lib/origen/tester/j750/generator.rb +0 -203
- data/lib/origen/tester/j750/generator/flow.rb +0 -123
- data/lib/origen/tester/j750/generator/flow_line.rb +0 -288
- data/lib/origen/tester/j750/generator/patgroup.rb +0 -111
- data/lib/origen/tester/j750/generator/patgroups.rb +0 -41
- data/lib/origen/tester/j750/generator/patset.rb +0 -111
- data/lib/origen/tester/j750/generator/patsets.rb +0 -41
- data/lib/origen/tester/j750/generator/templates/flow.txt.erb +0 -9
- data/lib/origen/tester/j750/generator/templates/instances.txt.erb +0 -16
- data/lib/origen/tester/j750/generator/templates/patgroups.txt.erb +0 -8
- data/lib/origen/tester/j750/generator/templates/patsets.txt.erb +0 -10
- data/lib/origen/tester/j750/generator/test_instance.rb +0 -846
- data/lib/origen/tester/j750/generator/test_instance_group.rb +0 -60
- data/lib/origen/tester/j750/generator/test_instances.rb +0 -182
- data/lib/origen/tester/j750/j750.rb +0 -845
- data/lib/origen/tester/j750/j750_hpt.rb +0 -35
- data/lib/origen/tester/j750/parser.rb +0 -104
- data/lib/origen/tester/j750/parser/ac_spec.rb +0 -11
- data/lib/origen/tester/j750/parser/ac_specs.rb +0 -0
- data/lib/origen/tester/j750/parser/dc_spec.rb +0 -36
- data/lib/origen/tester/j750/parser/dc_specs.rb +0 -50
- data/lib/origen/tester/j750/parser/descriptions.rb +0 -340
- data/lib/origen/tester/j750/parser/flow.rb +0 -111
- data/lib/origen/tester/j750/parser/flow_line.rb +0 -207
- data/lib/origen/tester/j750/parser/flows.rb +0 -23
- data/lib/origen/tester/j750/parser/pattern_set.rb +0 -94
- data/lib/origen/tester/j750/parser/pattern_sets.rb +0 -33
- data/lib/origen/tester/j750/parser/test_instance.rb +0 -322
- data/lib/origen/tester/j750/parser/test_instances.rb +0 -26
- data/lib/origen/tester/j750/parser/timeset.rb +0 -15
- data/lib/origen/tester/j750/parser/timesets.rb +0 -0
- data/lib/origen/tester/jlink/jlink.rb +0 -33
- data/lib/origen/tester/parser.rb +0 -24
- data/lib/origen/tester/parser/description_lookup.rb +0 -64
- data/lib/origen/tester/parser/searchable_array.rb +0 -32
- data/lib/origen/tester/parser/searchable_hash.rb +0 -32
- data/lib/origen/tester/time.rb +0 -338
- data/lib/origen/tester/timing.rb +0 -253
- data/lib/origen/tester/ultraflex/files.rb +0 -45
- data/lib/origen/tester/ultraflex/generator.rb +0 -200
- data/lib/origen/tester/ultraflex/generator/flow.rb +0 -119
- data/lib/origen/tester/ultraflex/generator/flow_line.rb +0 -269
- data/lib/origen/tester/ultraflex/generator/patgroup.rb +0 -111
- data/lib/origen/tester/ultraflex/generator/patgroups.rb +0 -41
- data/lib/origen/tester/ultraflex/generator/patset.rb +0 -111
- data/lib/origen/tester/ultraflex/generator/patsets.rb +0 -41
- data/lib/origen/tester/ultraflex/generator/templates/flow.txt.erb +0 -9
- data/lib/origen/tester/ultraflex/generator/templates/instances.txt.erb +0 -16
- data/lib/origen/tester/ultraflex/generator/templates/patgroups.txt.erb +0 -8
- data/lib/origen/tester/ultraflex/generator/templates/patsets.txt.erb +0 -10
- data/lib/origen/tester/ultraflex/generator/test_instance.rb +0 -622
- data/lib/origen/tester/ultraflex/generator/test_instance_group.rb +0 -60
- data/lib/origen/tester/ultraflex/generator/test_instances.rb +0 -174
- data/lib/origen/tester/ultraflex/parser.rb +0 -104
- data/lib/origen/tester/ultraflex/parser/ac_spec.rb +0 -11
- data/lib/origen/tester/ultraflex/parser/ac_specs.rb +0 -0
- data/lib/origen/tester/ultraflex/parser/dc_spec.rb +0 -36
- data/lib/origen/tester/ultraflex/parser/dc_specs.rb +0 -50
- data/lib/origen/tester/ultraflex/parser/descriptions.rb +0 -342
- data/lib/origen/tester/ultraflex/parser/flow.rb +0 -111
- data/lib/origen/tester/ultraflex/parser/flow_line.rb +0 -207
- data/lib/origen/tester/ultraflex/parser/flows.rb +0 -23
- data/lib/origen/tester/ultraflex/parser/pattern_set.rb +0 -94
- data/lib/origen/tester/ultraflex/parser/pattern_sets.rb +0 -33
- data/lib/origen/tester/ultraflex/parser/test_instance.rb +0 -262
- data/lib/origen/tester/ultraflex/parser/test_instances.rb +0 -26
- data/lib/origen/tester/ultraflex/parser/timeset.rb +0 -15
- data/lib/origen/tester/ultraflex/parser/timesets.rb +0 -0
- data/lib/origen/tester/ultraflex/ultraflex.rb +0 -759
- data/lib/origen/tester/v93k/generator.rb +0 -80
- data/lib/origen/tester/v93k/generator/flow.rb +0 -63
- data/lib/origen/tester/v93k/generator/flow_node.rb +0 -17
- data/lib/origen/tester/v93k/generator/flow_node/print.rb +0 -10
- data/lib/origen/tester/v93k/generator/pattern.rb +0 -16
- data/lib/origen/tester/v93k/generator/pattern_master.rb +0 -54
- data/lib/origen/tester/v93k/generator/templates/_test_method.txt.erb +0 -6
- data/lib/origen/tester/v93k/generator/templates/_test_suite.txt.erb +0 -11
- data/lib/origen/tester/v93k/generator/templates/template.flow.erb +0 -121
- data/lib/origen/tester/v93k/generator/templates/template.pmfl.erb +0 -9
- data/lib/origen/tester/v93k/generator/test_function.rb +0 -103
- data/lib/origen/tester/v93k/generator/test_functions.rb +0 -79
- data/lib/origen/tester/v93k/generator/test_method.rb +0 -46
- data/lib/origen/tester/v93k/generator/test_methods.rb +0 -75
- data/lib/origen/tester/v93k/generator/test_suite.rb +0 -54
- data/lib/origen/tester/v93k/generator/test_suites.rb +0 -65
- data/lib/origen/tester/v93k/v93k.rb +0 -420
- data/lib/origen/tester/vector.rb +0 -86
- data/lib/origen/tester/vector_generator.rb +0 -637
- data/lib/origen/tester/vector_pipeline.rb +0 -150
- data/lib/origen/utility/design_sync.rb +0 -494
- data/lib/origen/version_checker.rb +0 -117
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
module Origen
|
|
2
|
-
module Tester
|
|
3
|
-
class J750
|
|
4
|
-
module Generator
|
|
5
|
-
class TestInstanceGroup
|
|
6
|
-
attr_accessor :name, :version, :append_version
|
|
7
|
-
|
|
8
|
-
include Enumerable
|
|
9
|
-
|
|
10
|
-
def initialize(name, _options = {})
|
|
11
|
-
@name = name
|
|
12
|
-
@store = []
|
|
13
|
-
@append_version = true
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def name
|
|
17
|
-
if unversioned_name
|
|
18
|
-
if version && @append_version
|
|
19
|
-
"#{unversioned_name}_v#{version}"
|
|
20
|
-
else
|
|
21
|
-
unversioned_name.to_s
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def unversioned_name
|
|
27
|
-
if @name
|
|
28
|
-
if @name =~ /grp$/
|
|
29
|
-
@name
|
|
30
|
-
else
|
|
31
|
-
"#{@name}_grp"
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def <<(instance)
|
|
37
|
-
@store << instance
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def size
|
|
41
|
-
@store.size
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def each
|
|
45
|
-
@store.each { |ins| yield ins }
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def ==(other_instance_group)
|
|
49
|
-
self.class == other_instance_group.class &&
|
|
50
|
-
unversioned_name.to_s == other_instance_group.unversioned_name.to_s &&
|
|
51
|
-
size == other_instance_group.size &&
|
|
52
|
-
self.all? do |ins|
|
|
53
|
-
other_instance_group.any? { |other_ins| ins == other_ins }
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
module Origen
|
|
2
|
-
module Tester
|
|
3
|
-
class J750
|
|
4
|
-
module Generator
|
|
5
|
-
class TestInstances
|
|
6
|
-
include Origen::Tester::Generator
|
|
7
|
-
|
|
8
|
-
TEMPLATE = "#{Origen.top}/lib/origen/tester/j750/generator/templates/instances.txt.erb"
|
|
9
|
-
OUTPUT_POSTFIX = 'instances'
|
|
10
|
-
|
|
11
|
-
class IndexedString < ::String
|
|
12
|
-
attr_accessor :index
|
|
13
|
-
|
|
14
|
-
def name
|
|
15
|
-
self
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def add(name, type, options = {})
|
|
20
|
-
options = {
|
|
21
|
-
test_instance_class: TestInstance
|
|
22
|
-
}.merge(options)
|
|
23
|
-
ins = options.delete(:test_instance_class).new(name, type, options)
|
|
24
|
-
if @current_group
|
|
25
|
-
@current_group << ins
|
|
26
|
-
else
|
|
27
|
-
collection << ins
|
|
28
|
-
end
|
|
29
|
-
c = Origen.interface.consume_comments
|
|
30
|
-
Origen.interface.descriptions.add_for_test_definition(name, c)
|
|
31
|
-
ins
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# IG-XL doesn't have a formal instance group type and instead declares them anonymously
|
|
35
|
-
# whenever test instances of the same name appear consecutively in the test instance sheet.
|
|
36
|
-
# However when it comes to generating a test program life becomes much easier if we have
|
|
37
|
-
# a way to explicitly declare instances as part of a group - this makes duplicate tracking
|
|
38
|
-
# and sorting of the test instance sheet much easier.
|
|
39
|
-
#
|
|
40
|
-
# Use this method to generate instance groups via a block. Within the the block you should
|
|
41
|
-
# generate instances as normal and they will automatically be assigned to the current group.
|
|
42
|
-
# Note that the name of the instances generated within the group is discarded and replaced
|
|
43
|
-
# with the name of the group. Origen automatically appends "grp" to this name to highlight
|
|
44
|
-
# instances that were generated as part of the group.
|
|
45
|
-
#
|
|
46
|
-
# test_instances.group("erase_all_blocks") do |group|
|
|
47
|
-
# # Generate instances here as normal
|
|
48
|
-
# test_instances.functional("erase_blk0")
|
|
49
|
-
# test_instances.functional("erase_blk1")
|
|
50
|
-
# end
|
|
51
|
-
#
|
|
52
|
-
# The group object is passed into the block but usually you should not need to interact
|
|
53
|
-
# with this directly except maybe to set the name if it is not yet established at the point
|
|
54
|
-
# where the group is initiated:
|
|
55
|
-
#
|
|
56
|
-
# test_instances.group do |group|
|
|
57
|
-
# # Generate instances here as normal
|
|
58
|
-
# group.name = "group_blah"
|
|
59
|
-
# end
|
|
60
|
-
#
|
|
61
|
-
# A common way to generate groups is to create a helper method in your application which
|
|
62
|
-
# is responsible for creating groups as required:
|
|
63
|
-
#
|
|
64
|
-
# def group_wrapper(name, options)
|
|
65
|
-
# if options[:by_block]
|
|
66
|
-
# test_instances.group(name) do |group|
|
|
67
|
-
# yield group
|
|
68
|
-
# end
|
|
69
|
-
# else
|
|
70
|
-
# yield
|
|
71
|
-
# end
|
|
72
|
-
# end
|
|
73
|
-
#
|
|
74
|
-
# In that case the group argument becomes quite useful for branching based on whether you
|
|
75
|
-
# are generating a group or standalone instances:
|
|
76
|
-
#
|
|
77
|
-
# group_wrapper(name, options) do |group|
|
|
78
|
-
# if group
|
|
79
|
-
# # Generate group instances
|
|
80
|
-
# else
|
|
81
|
-
# # Generate standalone instances
|
|
82
|
-
# end
|
|
83
|
-
# end
|
|
84
|
-
def group(name = nil, options = {})
|
|
85
|
-
name, options = nil, name if name.is_a?(Hash)
|
|
86
|
-
@current_group = TestInstanceGroup.new(name, options)
|
|
87
|
-
collection << @current_group
|
|
88
|
-
yield @current_group
|
|
89
|
-
@current_group = nil
|
|
90
|
-
end
|
|
91
|
-
alias_method :add_group, :group
|
|
92
|
-
|
|
93
|
-
def finalize(_options = {}) # :nodoc:
|
|
94
|
-
uniq!
|
|
95
|
-
sort!
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def uniq! # :nodoc:
|
|
99
|
-
uniques = []
|
|
100
|
-
versions = {}
|
|
101
|
-
multi_version_tests = {}
|
|
102
|
-
collection.each do |instance|
|
|
103
|
-
# If a uniquely named instance is found add it, otherwise update the version
|
|
104
|
-
# of the current instance to match that of the existing instance that it duplicates
|
|
105
|
-
unless uniques.any? do |i|
|
|
106
|
-
if i == instance
|
|
107
|
-
instance.version = i.version
|
|
108
|
-
true
|
|
109
|
-
else
|
|
110
|
-
false
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
if instance.respond_to?(:version=)
|
|
114
|
-
versions[instance.unversioned_name] ||= 0
|
|
115
|
-
versions[instance.unversioned_name] += 1
|
|
116
|
-
if versions[instance.unversioned_name] > 1
|
|
117
|
-
multi_version_tests[instance.unversioned_name] = true
|
|
118
|
-
end
|
|
119
|
-
instance.version = versions[instance.unversioned_name]
|
|
120
|
-
end
|
|
121
|
-
uniques << instance
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
# This final loop disables the version identifier for tests that have only a single version,
|
|
125
|
-
# this makes it clearer when multiple versions exist - whenever you see a v1 you know there
|
|
126
|
-
# is at least a v2 also.
|
|
127
|
-
collection.map! do |instance|
|
|
128
|
-
if instance.respond_to?(:version=)
|
|
129
|
-
unless multi_version_tests[instance.unversioned_name]
|
|
130
|
-
instance.append_version = false
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
instance
|
|
134
|
-
end
|
|
135
|
-
self.collection = uniques
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def sort! # :nodoc:
|
|
139
|
-
# Present the instances in the final sheet in alphabetical order
|
|
140
|
-
collection.map!.with_index do |ins, _i|
|
|
141
|
-
if ins.is_a?(String) # Can happen if content has been rendered in from a template
|
|
142
|
-
ins = IndexedString.new(ins)
|
|
143
|
-
end
|
|
144
|
-
ins
|
|
145
|
-
end
|
|
146
|
-
collection.sort! { |a, b| [a.name.to_s] <=> [b.name.to_s] }
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
def bpmu(name, options = {})
|
|
150
|
-
add(name, :board_pmu, options)
|
|
151
|
-
end
|
|
152
|
-
alias_method :board_pmu, :bpmu
|
|
153
|
-
|
|
154
|
-
def ppmu(name, options = {})
|
|
155
|
-
add(name, :pin_pmu, options)
|
|
156
|
-
end
|
|
157
|
-
alias_method :pin_pmu, :ppmu
|
|
158
|
-
|
|
159
|
-
def functional(name, options = {})
|
|
160
|
-
add(name, :functional, options)
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
def empty(name, options = {})
|
|
164
|
-
add(name, :empty, options)
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
def other(name, options = {})
|
|
168
|
-
add(name, :other, options)
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
def apmu_powersupply(name, options = {})
|
|
172
|
-
add(name, :apmu_powersupply, options)
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
def mto_memory(name, options = {})
|
|
176
|
-
add(name, :mto_memory, options)
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
end
|
|
@@ -1,845 +0,0 @@
|
|
|
1
|
-
module Origen
|
|
2
|
-
module Tester
|
|
3
|
-
# This class is soon to be deprecated
|
|
4
|
-
# Origen.deprecate <<-END
|
|
5
|
-
# J750 Tester in Origen core is currently being moved to a dedicated plugin,
|
|
6
|
-
# use Testers::J750 from this plugin instead of Origen::Tester::J750
|
|
7
|
-
# http://origen.freescale.net/testers
|
|
8
|
-
# END
|
|
9
|
-
|
|
10
|
-
# Tester model to generate .atp patterns for the Teradyne J750
|
|
11
|
-
#
|
|
12
|
-
# == Basic Usage
|
|
13
|
-
# $tester = Origen::Tester::J750.new
|
|
14
|
-
# $tester.cycle # Generate a vector
|
|
15
|
-
#
|
|
16
|
-
# Many more methods exist to generate J750 specific micro-code, see below for
|
|
17
|
-
# details.
|
|
18
|
-
#
|
|
19
|
-
# Also note that this class inherits from the base Tester class and so all methods
|
|
20
|
-
# described there are also available.
|
|
21
|
-
class J750
|
|
22
|
-
include Tester
|
|
23
|
-
include Parser
|
|
24
|
-
require 'origen/tester/j750/files'
|
|
25
|
-
include Files
|
|
26
|
-
|
|
27
|
-
autoload :Parser, 'origen/tester/j750/parser'
|
|
28
|
-
autoload :Generator, 'origen/tester/j750/generator'
|
|
29
|
-
|
|
30
|
-
attr_accessor :use_hv_pin
|
|
31
|
-
attr_accessor :software_version
|
|
32
|
-
|
|
33
|
-
def self.hpt_mode
|
|
34
|
-
@@hpt_mode
|
|
35
|
-
end
|
|
36
|
-
def self.hpt_mode?
|
|
37
|
-
@@hpt_mode
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Returns a new J750 instance, normally there would only ever be one of these
|
|
41
|
-
# assigned to the global variable such as $tester by your target:
|
|
42
|
-
# $tester = J750.new
|
|
43
|
-
def initialize
|
|
44
|
-
@unique_counter = 0
|
|
45
|
-
@max_repeat_loop = 65_535
|
|
46
|
-
@min_repeat_loop = 2
|
|
47
|
-
@pat_extension = 'atp'
|
|
48
|
-
@active_loads = true
|
|
49
|
-
@pipeline_depth = 34 # for extended mode is vectors, for normal mode is vector pairs (54 for J750Ex)
|
|
50
|
-
@use_hv_pin = false # allows to use high voltage for a pin for all patterns
|
|
51
|
-
@software_version = '3.50.40'
|
|
52
|
-
@compress = true
|
|
53
|
-
@support_repeat_previous = true
|
|
54
|
-
@match_entries = 10
|
|
55
|
-
@name = 'j750'
|
|
56
|
-
@program_comment_char = ['logprint', "'"]
|
|
57
|
-
@@hpt_mode = false
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def flows
|
|
61
|
-
parser.flows
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Main accessor to all content parsed from existing test program sheets found in the
|
|
65
|
-
# supplied directory or in Origen.config.test_program_output_directory
|
|
66
|
-
def parser(prog_dir = Origen.config.test_program_output_directory)
|
|
67
|
-
unless prog_dir
|
|
68
|
-
fail 'You must supply the directory containing the test program sheets, or define it via Origen.config.test_program_output_directory'
|
|
69
|
-
end
|
|
70
|
-
@parser ||= J750::Parser.new
|
|
71
|
-
@parsed_dir ||= false
|
|
72
|
-
if @parsed_dir != prog_dir
|
|
73
|
-
@parser.parse(prog_dir)
|
|
74
|
-
@parsed_dir = prog_dir
|
|
75
|
-
end
|
|
76
|
-
@parser
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# Capture a vector to the tester HRAM.
|
|
80
|
-
#
|
|
81
|
-
# This method applys a store vector (stv) opcode to the previous vector, note that is does
|
|
82
|
-
# not actually generate a new vector.
|
|
83
|
-
#
|
|
84
|
-
# Sometimes when generating vectors within a loop you may want to apply a stv opcode
|
|
85
|
-
# retrospectively to a previous vector, passing in an offset option will allow you
|
|
86
|
-
# to do this.
|
|
87
|
-
#
|
|
88
|
-
# On J750 the pins argument is ignored since the tester only supports whole vector capture.
|
|
89
|
-
#
|
|
90
|
-
# @example
|
|
91
|
-
# $tester.cycle # This is the vector you want to capture
|
|
92
|
-
# $tester.store # This applys the STV opcode
|
|
93
|
-
#
|
|
94
|
-
# $tester.cycle # This one gets stored
|
|
95
|
-
# $tester.cycle
|
|
96
|
-
# $tester.cycle
|
|
97
|
-
# $tester.store(:offset => -2) # Just realized I need to capture that earlier vector
|
|
98
|
-
def store(*pins)
|
|
99
|
-
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
|
100
|
-
options = { offset: 0
|
|
101
|
-
}.merge(options)
|
|
102
|
-
update_vector microcode: 'stv', offset: options[:offset]
|
|
103
|
-
end
|
|
104
|
-
alias_method :to_hram, :store
|
|
105
|
-
alias_method :capture, :store
|
|
106
|
-
|
|
107
|
-
# Capture the next vector generated to HRAM
|
|
108
|
-
#
|
|
109
|
-
# This method applys a store vector (stv) opcode to the next vector to be generated,
|
|
110
|
-
# note that is does not actually generate a new vector.
|
|
111
|
-
#
|
|
112
|
-
# On J750 the pins argument is ignored since the tester only supports whole vector capture.
|
|
113
|
-
#
|
|
114
|
-
# @example
|
|
115
|
-
# $tester.store_next_cycle
|
|
116
|
-
# $tester.cycle # This is the vector that will be captured
|
|
117
|
-
def store_next_cycle(*pins)
|
|
118
|
-
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
|
119
|
-
options = {
|
|
120
|
-
}.merge(options)
|
|
121
|
-
preset_next_vector microcode: 'stv'
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
# Call a subroutine.
|
|
125
|
-
#
|
|
126
|
-
# This method applies a call subroutine opcode to the previous vector, it does not
|
|
127
|
-
# generate a new vector.
|
|
128
|
-
#
|
|
129
|
-
# Subroutines should always be called through this method as it ensures a running
|
|
130
|
-
# log of called subroutines is maintained and which then gets output in the pattern
|
|
131
|
-
# header to import the right dependencies.
|
|
132
|
-
#
|
|
133
|
-
# An offset option is available to make the call on earlier vectors.
|
|
134
|
-
#
|
|
135
|
-
# ==== Examples
|
|
136
|
-
# $tester.call_subroutine("mysub")
|
|
137
|
-
# $tester.call_subroutine("my_other_sub", :offset => -1)
|
|
138
|
-
def call_subroutine(name, options = {})
|
|
139
|
-
options = {
|
|
140
|
-
offset: 0
|
|
141
|
-
}.merge(options)
|
|
142
|
-
called_subroutines << name.to_s.chomp unless called_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
|
|
143
|
-
update_vector microcode: "call #{name}", offset: options[:offset]
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
# Start a subroutine.
|
|
147
|
-
#
|
|
148
|
-
# Generates a global subroutine label. Global is used to adhere to the best practice of
|
|
149
|
-
# containing all subroutines in dedicated patterns, e.g. global_subs.atp
|
|
150
|
-
#
|
|
151
|
-
# ==== Examples
|
|
152
|
-
# $tester.start_subroutine("wait_for_done")
|
|
153
|
-
# < generate your subroutine vectors here >
|
|
154
|
-
# $tester.end_subroutine
|
|
155
|
-
def start_subroutine(name)
|
|
156
|
-
local_subroutines << name.to_s.chomp unless local_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
|
|
157
|
-
microcode "global subr #{name}:"
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
# * J750 Specific *
|
|
161
|
-
#
|
|
162
|
-
#
|
|
163
|
-
def enable_flag(options = {})
|
|
164
|
-
options = { flagnum: 4, # which flag to enable for later checking
|
|
165
|
-
}.merge(options)
|
|
166
|
-
|
|
167
|
-
case options[:flagnum]
|
|
168
|
-
when 1
|
|
169
|
-
flagname = 'cpuA'
|
|
170
|
-
when 2
|
|
171
|
-
flagname = 'cpuB'
|
|
172
|
-
when 3
|
|
173
|
-
flagname = 'cpuC'
|
|
174
|
-
when 4
|
|
175
|
-
flagname = 'cpuD'
|
|
176
|
-
else
|
|
177
|
-
abort "ERROR! Invalid flag name passed to 'enable_flag' method!\n"
|
|
178
|
-
end
|
|
179
|
-
update_vector(microcode: "enable(#{flagname})")
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
# * J750 Specific *
|
|
183
|
-
#
|
|
184
|
-
#
|
|
185
|
-
def set_flag(options = {})
|
|
186
|
-
options = { flagnum: 4, # which flag to set
|
|
187
|
-
}.merge(options)
|
|
188
|
-
|
|
189
|
-
case options[:flagnum]
|
|
190
|
-
when 1
|
|
191
|
-
flagname = 'cpuA'
|
|
192
|
-
when 2
|
|
193
|
-
flagname = 'cpuB'
|
|
194
|
-
when 3
|
|
195
|
-
flagname = 'cpuC'
|
|
196
|
-
when 4
|
|
197
|
-
flagname = 'cpuD'
|
|
198
|
-
else
|
|
199
|
-
abort "ERROR! Invalid flag name passed to 'set_flag' method!\n"
|
|
200
|
-
end
|
|
201
|
-
update_vector(microcode: "set_cpu(#{flagname})")
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
# End a subroutine.
|
|
205
|
-
#
|
|
206
|
-
# Generates a return opcode on the last vector.
|
|
207
|
-
#
|
|
208
|
-
# ==== Examples
|
|
209
|
-
# $tester.start_subroutine("wait_for_done")
|
|
210
|
-
# < generate your subroutine vectors here >
|
|
211
|
-
# $tester.end_subroutine
|
|
212
|
-
# cond: whether return is conditional on a flag (to permit to mix subrs together)
|
|
213
|
-
def end_subroutine(cond = false)
|
|
214
|
-
if cond
|
|
215
|
-
update_vector microcode: 'if (flag) return'
|
|
216
|
-
else
|
|
217
|
-
update_vector microcode: 'return'
|
|
218
|
-
end
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
# Handshake with the tester.
|
|
222
|
-
#
|
|
223
|
-
# Will set a cpu flag (A) and wait for it to be cleared by the tester, optionally
|
|
224
|
-
# pass in a read code to pass information to the tester.
|
|
225
|
-
#
|
|
226
|
-
# ==== Examples
|
|
227
|
-
# $tester.handshake # Pass control to the tester for a measurement
|
|
228
|
-
# $tester.handshake(:readcode => 10) # Trigger a specific action by the tester
|
|
229
|
-
def handshake(options = {})
|
|
230
|
-
options = {
|
|
231
|
-
readcode: false,
|
|
232
|
-
manual_stop: false, # set a 2nd CPU flag in case 1st flag is automatically cleared
|
|
233
|
-
}.merge(options)
|
|
234
|
-
if options[:readcode]
|
|
235
|
-
cycle(microcode: "set_code #{options[:readcode]}")
|
|
236
|
-
end
|
|
237
|
-
if options[:manual_stop]
|
|
238
|
-
cycle(microcode: 'enable (cpuB)')
|
|
239
|
-
cycle(microcode: 'set_cpu (cpuA cpuB)')
|
|
240
|
-
cycle(microcode: "loop_here_#{@unique_counter}: if (flag) jump loop_here_#{@unique_counter}")
|
|
241
|
-
else
|
|
242
|
-
cycle(microcode: 'set_cpu (cpuA)')
|
|
243
|
-
cycle(microcode: "loop_here_#{@unique_counter}: if (cpuA) jump loop_here_#{@unique_counter}")
|
|
244
|
-
end
|
|
245
|
-
@unique_counter += 1 # Increment so a different label will be applied if another
|
|
246
|
-
# handshake is called in the same pattern
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
# Do a frequency measure.
|
|
250
|
-
#
|
|
251
|
-
# Write the necessary micro code to do a frequency measure on the given pin,
|
|
252
|
-
# optionally supply a read code to pass information to the tester.
|
|
253
|
-
#
|
|
254
|
-
# ==== Examples
|
|
255
|
-
# $tester.freq_count($top.pin(:d_out)) # Freq measure on pin "d_out"
|
|
256
|
-
# $tester.freq_count($top.pin(:d_out):readcode => 10)
|
|
257
|
-
def freq_count(pin, options = {})
|
|
258
|
-
options = { readcode: false
|
|
259
|
-
}.merge(options)
|
|
260
|
-
|
|
261
|
-
cycle(microcode: "set_code #{options[:readcode]}") if options[:readcode]
|
|
262
|
-
cycle(microcode: 'set_cpu (cpuA)')
|
|
263
|
-
cycle(microcode: 'set_cpu (cpuA)')
|
|
264
|
-
cycle(microcode: 'set_cpu (cpuB)')
|
|
265
|
-
cycle(microcode: 'set_cpu (cpuC)')
|
|
266
|
-
cycle(microcode: 'freq_loop_1:')
|
|
267
|
-
cycle(microcode: 'if (cpuA) jump freq_loop_1')
|
|
268
|
-
pin.drive_lo
|
|
269
|
-
delay(2000)
|
|
270
|
-
pin.dont_care
|
|
271
|
-
cycle(microcode: 'freq_loop_2: enable (cpuB)')
|
|
272
|
-
cycle(microcode: 'if (flag) jump freq_loop_2')
|
|
273
|
-
cycle(microcode: 'enable (cpuC)')
|
|
274
|
-
cycle(microcode: 'if (flag) jump freq_loop_1')
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
# * J750 Specific *
|
|
278
|
-
#
|
|
279
|
-
# Generates a single MTO opcode line for J750
|
|
280
|
-
#
|
|
281
|
-
# Codes implemented: xa load_preset, xa inc, ya load_preset, ya inc, stv_m0, stv_m1, stv_c<br>
|
|
282
|
-
def memory_test(options = {})
|
|
283
|
-
options = {
|
|
284
|
-
gen_vector: true, # Default generate vector not just MTO opcode
|
|
285
|
-
init_counter_x: false, # initialize counter X
|
|
286
|
-
inc_counter_x: false, # increment counter X
|
|
287
|
-
init_counter_y: false, # initialize counter X
|
|
288
|
-
inc_counter_y: false, # increment counter X
|
|
289
|
-
capture_vector: false, # capture vector to memory using all mem types
|
|
290
|
-
capture_vector_mem0: false, # capture vector to memory type 0, here for J750 will be stv_m0
|
|
291
|
-
capture_vector_mem1: false, # capture vector to memory type 1, here for J750 will be stv_m1
|
|
292
|
-
capture_vector_mem2: false, # capture vector to memory type 2, here for J750 will be stv_c
|
|
293
|
-
pin: false, # pin on which to drive or expect data, pass pin object here!
|
|
294
|
-
pin_data: false, # pin data (:none, :drive, :expect)
|
|
295
|
-
}.merge(options)
|
|
296
|
-
|
|
297
|
-
mto_opcode = ''
|
|
298
|
-
|
|
299
|
-
if options[:init_counter_x]
|
|
300
|
-
mto_opcode += ' xa load_preset'
|
|
301
|
-
end
|
|
302
|
-
if options[:inc_counter_x]
|
|
303
|
-
mto_opcode += ' xa inc'
|
|
304
|
-
end
|
|
305
|
-
if options[:init_counter_y]
|
|
306
|
-
mto_opcode += ' ya load_preset'
|
|
307
|
-
end
|
|
308
|
-
if options[:inc_counter_y]
|
|
309
|
-
mto_opcode += ' ya inc'
|
|
310
|
-
end
|
|
311
|
-
if options[:capture_vector]
|
|
312
|
-
mto_opcode += ' stv_m0 stv_m1 stv_c'
|
|
313
|
-
end
|
|
314
|
-
if options[:capture_vector_mem0]
|
|
315
|
-
mto_opcode += ' stv_m0'
|
|
316
|
-
end
|
|
317
|
-
if options[:capture_vector_mem1]
|
|
318
|
-
mto_opcode += ' stv_m1'
|
|
319
|
-
end
|
|
320
|
-
if options[:capture_vector_mem2]
|
|
321
|
-
mto_opcode += ' stv_c'
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
unless mto_opcode.eql?('')
|
|
325
|
-
mto_opcode = '(mto:' + mto_opcode + ')'
|
|
326
|
-
end
|
|
327
|
-
|
|
328
|
-
if options[:gen_vector]
|
|
329
|
-
if options[:pin]
|
|
330
|
-
case options[:pin_data]
|
|
331
|
-
when :drive
|
|
332
|
-
# store current pin state
|
|
333
|
-
cur_pin_state = options[:pin].state.to_sym
|
|
334
|
-
options[:pin].drive_mem
|
|
335
|
-
when :expect
|
|
336
|
-
# store current pin state
|
|
337
|
-
cur_pin_state = options[:pin].state.to_sym
|
|
338
|
-
options[:pin].expect_mem
|
|
339
|
-
end
|
|
340
|
-
end
|
|
341
|
-
cycle(microcode: "#{mto_opcode}")
|
|
342
|
-
if options[:pin]
|
|
343
|
-
# restore previous pin state
|
|
344
|
-
case options[:pin_data]
|
|
345
|
-
when :drive
|
|
346
|
-
options[:pin].state = cur_pin_state
|
|
347
|
-
when :expect
|
|
348
|
-
options[:pin].state = cur_pin_state
|
|
349
|
-
end
|
|
350
|
-
end
|
|
351
|
-
else
|
|
352
|
-
microcode "#{mto_opcode}"
|
|
353
|
-
end
|
|
354
|
-
end
|
|
355
|
-
|
|
356
|
-
# Generates a match loop on up to two pins.
|
|
357
|
-
#
|
|
358
|
-
# This method is not really intended to be called directly, rather you should call
|
|
359
|
-
# via Tester#wait e.g. $tester.wait(:match => true).
|
|
360
|
-
#
|
|
361
|
-
# The timeout should be provided in cycles, however when called via the wait method the
|
|
362
|
-
# time-based helpers (time_in_us, etc) will be converted to cycles for you.
|
|
363
|
-
# The following options are available to tailor the match loop behavior, defaults in
|
|
364
|
-
# parenthesis:
|
|
365
|
-
# * :pin - The pin object to match on (*required*)
|
|
366
|
-
# * :state - The pin state to match on, :low or :high (*required*)
|
|
367
|
-
# * :pin2 (nil) - Optionally supply a second pin to match on
|
|
368
|
-
# * :state2 (nil) - State for the second pin (required if :pin2 is supplied)
|
|
369
|
-
# * :check_for_fails (false) - Flushes the pipeline and handshakes with the tester (passing readcode 100) prior to the match (to allow binout of fails encountered before the match)
|
|
370
|
-
# * :force_fail_on_timeout (true) - Force a vector mis-compare if the match loop times out
|
|
371
|
-
# * :on_timeout_goto ("") - Optionally supply a label to branch to on timeout, by default will continue from the end of the match loop
|
|
372
|
-
# * :on_pin_match_goto ("") - Optionally supply a label to branch to when pin 1 matches, by default will continue from the end of the match loop
|
|
373
|
-
# * :on_pin2_match_goto ("") - Optionally supply a label to branch to when pin 2 matches, by default will continue from the end of the match loop
|
|
374
|
-
# * :multiple_entries (false) - Supply an integer to generate multiple entries into the match (each with a unique readcode), this can be useful when debugging patterns with multiple matches
|
|
375
|
-
# * :force_fail_on_timeout (true) - force pattern to fail if timeout occurs
|
|
376
|
-
# * :global_loops (false) - whether match loop loops should use global labels
|
|
377
|
-
# * :manual_stop (false) - whether to use extra cpuB flag to resolve IG-XL v.3.50.xx bug where VBT clears cpuA immediately
|
|
378
|
-
# at start of PatFlagFunc instead of at end. Use will have to manually clear cpuB to resume this pattern.
|
|
379
|
-
# ==== Examples
|
|
380
|
-
# $tester.wait(:match => true, :time_in_us => 5000, :pin => $top.pin(:done), :state => :high)
|
|
381
|
-
def match(pin, state, timeout, options = {})
|
|
382
|
-
options = {
|
|
383
|
-
check_for_fails: false,
|
|
384
|
-
on_timeout_goto: false,
|
|
385
|
-
pin2: false,
|
|
386
|
-
state2: false,
|
|
387
|
-
on_pin_match_goto: false,
|
|
388
|
-
on_pin2_match_goto: false,
|
|
389
|
-
multiple_entries: false,
|
|
390
|
-
force_fail_on_timeout: true,
|
|
391
|
-
global_loops: false,
|
|
392
|
-
manual_stop: false,
|
|
393
|
-
clr_fail_post_match: false
|
|
394
|
-
}.merge(options)
|
|
395
|
-
|
|
396
|
-
# Flush the pipeline first and then pass control to the program to bin out any failures
|
|
397
|
-
# prior to entering the match loop
|
|
398
|
-
if options[:check_for_fails]
|
|
399
|
-
if options[:multiple_entries]
|
|
400
|
-
@match_entries.times do |i|
|
|
401
|
-
microcode "global subr match_done_#{i}:"
|
|
402
|
-
cycle(microcode: "set_code #{i + 100}")
|
|
403
|
-
cycle(microcode: 'jump call_tester') unless i == @match_entries - 1
|
|
404
|
-
end
|
|
405
|
-
microcode 'call_tester:'
|
|
406
|
-
else
|
|
407
|
-
cycle(microcode: 'set_code 100')
|
|
408
|
-
end
|
|
409
|
-
cc 'Wait for any prior failures to propagate through the pipeline'
|
|
410
|
-
cycle(microcode: 'pipe_minus 1')
|
|
411
|
-
cc 'Now handshake with the tester to bin out and parts that have failed before they got here'
|
|
412
|
-
handshake(manual_stop: options[:manual_stop])
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
# Now do the main match loop
|
|
416
|
-
cc 'Start the match loop'
|
|
417
|
-
|
|
418
|
-
# Calculate the loop counts for the 2 loops to appropriately hit the timeout requested
|
|
419
|
-
inner_loop_vectors = (@pipeline_depth - 1) + 4 # num vectors in inner loop
|
|
420
|
-
if timeout.to_f < @max_repeat_loop * inner_loop_vectors * @min_repeat_loop
|
|
421
|
-
# Handle case for smaller timeouts (that would force small outer loop count)
|
|
422
|
-
inner_loop_count = (timeout.to_f / (inner_loop_vectors * @min_repeat_loop)).ceil
|
|
423
|
-
outer_loop_count = @min_repeat_loop
|
|
424
|
-
else
|
|
425
|
-
# Handle longer delays
|
|
426
|
-
inner_loop_count = @max_repeat_loop
|
|
427
|
-
outer_loop_count = (timeout.to_f / (@max_repeat_loop * inner_loop_vectors)).ceil # Will do a minimum of 1 * max_repeat_loop * (pipeline_depth-1)
|
|
428
|
-
end
|
|
429
|
-
|
|
430
|
-
global_opt = (options[:global_loops]) ? 'global ' : ''
|
|
431
|
-
microcode "#{global_opt}match_outer_loop_#{@unique_counter}:"
|
|
432
|
-
cycle(microcode: "loopB #{outer_loop_count} ign ifc icc")
|
|
433
|
-
microcode "#{global_opt}match_inner_loop_#{@unique_counter}:"
|
|
434
|
-
state == :low ? pin.expect_lo : pin.expect_hi
|
|
435
|
-
cc "Check if #{pin.name} is #{state == :low ? 'low' : 'high'} yet"
|
|
436
|
-
cycle(microcode: "loopA #{inner_loop_count} ign ifc icc")
|
|
437
|
-
pin.dont_care
|
|
438
|
-
cc ' Wait for the result to propagate through the pipeline'
|
|
439
|
-
cycle(microcode: 'pipe_minus 1 ign ifc icc')
|
|
440
|
-
cc "Branch if #{pin.name} was #{state == :low ? 'low' : 'high'}"
|
|
441
|
-
cycle(microcode: "if (pass) jump #{pin.name}_matched_#{@unique_counter} icc ifc")
|
|
442
|
-
cycle(microcode: 'clr_flag (fail) icc')
|
|
443
|
-
if options[:pin2]
|
|
444
|
-
cc "Check if #{options[:pin2].name} is #{options[:state2] == :low ? 'low' : 'high'} yet"
|
|
445
|
-
options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi
|
|
446
|
-
state == :low ? pin.expect_hi : pin.expect_lo # Give priority to pin 1, don't match pin 2 on this cycle
|
|
447
|
-
# if it is really a pin 1 match
|
|
448
|
-
cycle # Read for pin 2 and !pin 1
|
|
449
|
-
options[:pin2].dont_care
|
|
450
|
-
pin.dont_care
|
|
451
|
-
cc 'Again wait for the result to propagate through the pipeline'
|
|
452
|
-
cycle(microcode: 'pipe_minus 1 ign ifc icc')
|
|
453
|
-
cc "Branch if #{options[:pin2].name} was #{options[:state2] == :low ? 'low' : 'high'}"
|
|
454
|
-
cycle(microcode: "if (pass) jump #{options[:pin2].name}_matched_#{@unique_counter} icc ifc")
|
|
455
|
-
cycle(microcode: 'clr_flag (fail) icc')
|
|
456
|
-
end
|
|
457
|
-
cc 'Loop back around if time remaining'
|
|
458
|
-
cycle(microcode: "end_loopA match_inner_loop_#{@unique_counter} icc")
|
|
459
|
-
cycle(microcode: "end_loopB match_outer_loop_#{@unique_counter} icc")
|
|
460
|
-
if options[:force_fail_on_timeout]
|
|
461
|
-
cc 'To get here something has gone wrong, strobe again to force a pattern failure'
|
|
462
|
-
state == :low ? pin.expect_lo : pin.expect_hi
|
|
463
|
-
options[:state2] == :low ? options[:pin2].expect_lo : options[:pin2].expect_hi if options[:pin2]
|
|
464
|
-
cycle
|
|
465
|
-
pin.dont_care
|
|
466
|
-
options[:pin2].dont_care if options[:pin2]
|
|
467
|
-
end
|
|
468
|
-
if options[:on_timeout_goto]
|
|
469
|
-
cycle(microcode: "jump #{options[:on_timeout_goto]} icc")
|
|
470
|
-
else
|
|
471
|
-
cycle(microcode: "jump match_loop_end_#{@unique_counter} icc")
|
|
472
|
-
# cycle(:microcode => 'halt')
|
|
473
|
-
end
|
|
474
|
-
microcode "#{pin.name}_matched_#{@unique_counter}:"
|
|
475
|
-
cycle(microcode: 'pop_loop icc')
|
|
476
|
-
unless options[:clr_fail_post_match]
|
|
477
|
-
cycle(microcode: 'clr_fail')
|
|
478
|
-
end
|
|
479
|
-
if options[:on_pin_match_goto]
|
|
480
|
-
cycle(microcode: "jump #{options[:on_pin_match_goto]}")
|
|
481
|
-
end
|
|
482
|
-
if options[:pin2]
|
|
483
|
-
microcode "#{options[:pin2].name}_matched_#{@unique_counter}:"
|
|
484
|
-
cycle(microcode: 'pop_loop icc')
|
|
485
|
-
cycle(microcode: 'clr_fail')
|
|
486
|
-
if options[:on_pin2_match_goto]
|
|
487
|
-
cycle(microcode: "jump #{options[:on_pin2_match_goto]}")
|
|
488
|
-
end
|
|
489
|
-
end
|
|
490
|
-
microcode "match_loop_end_#{@unique_counter}:"
|
|
491
|
-
if options[:clr_fail_post_match]
|
|
492
|
-
cycle(microcode: 'clr_fail')
|
|
493
|
-
end
|
|
494
|
-
|
|
495
|
-
@unique_counter += 1 # Increment so a different label will be applied if another
|
|
496
|
-
# handshake is called in the same pattern
|
|
497
|
-
end
|
|
498
|
-
|
|
499
|
-
# Generates a match loop based on vector condition passed in via block
|
|
500
|
-
#
|
|
501
|
-
# This method is not really intended to be called directly, rather you should call
|
|
502
|
-
# via Tester#wait:
|
|
503
|
-
# e.g. $tester.wait(:match => true) do
|
|
504
|
-
# reg(:status_reg).bit(:done).read(1)! # vector condition that you want to match
|
|
505
|
-
# end
|
|
506
|
-
#
|
|
507
|
-
# The timeout should be provided in cycles, however when called via the wait method the
|
|
508
|
-
# time-based helpers (time_in_us, etc) will be converted to cycles for you.
|
|
509
|
-
#
|
|
510
|
-
# The following options are available to tailor the match loop behavior, defaults in
|
|
511
|
-
# parenthesis:
|
|
512
|
-
# * :check_for_fails (false) - Flushes the pipeline and handshakes with the tester (passing readcode 100) prior to the match (to allow binout of fails encountered before the match)
|
|
513
|
-
# * :force_fail_on_timeout (true) - Force a vector mis-compare if the match loop times out
|
|
514
|
-
# * :on_timeout_goto ("") - Optionally supply a label to branch to on timeout, by default will continue from the end of the match loop
|
|
515
|
-
# * :on_block_match_goto ("") - Optionally supply a label to branch to when block condition is met, by default will continue from the end of the match loop
|
|
516
|
-
# * :multiple_entries (false) - Supply an integer to generate multiple entries into the match (each with a unique readcode), this can be useful when debugging patterns with multiple matches
|
|
517
|
-
# * :force_fail_on_timeout (true) - force pattern to fail if timeout occurs
|
|
518
|
-
# * :global_loops (false) - whether match loop loops should use global labels
|
|
519
|
-
# * :manual_stop (false) - whether to use extra cpuB flag to resolve IG-XL v.3.50.xx bug where VBT clears cpuA immediately
|
|
520
|
-
# at start of PatFlagFunc instead of at end. Use will have to manually clear cpuB to resume this pattern.
|
|
521
|
-
# ==== Examples
|
|
522
|
-
# $tester.wait(:match => true, :time_in_us => 5000, :pin => $top.pin(:done), :state => :high)
|
|
523
|
-
def match_block(timeout, options = {})
|
|
524
|
-
options = {
|
|
525
|
-
check_for_fails: false,
|
|
526
|
-
on_timeout_goto: false,
|
|
527
|
-
on_block_match_goto: false,
|
|
528
|
-
multiple_entries: false,
|
|
529
|
-
force_fail_on_timeout: true,
|
|
530
|
-
global_loops: false,
|
|
531
|
-
manual_stop: false,
|
|
532
|
-
clr_fail_post_match: false
|
|
533
|
-
}.merge(options)
|
|
534
|
-
|
|
535
|
-
unless block_given?
|
|
536
|
-
fail 'ERROR: block not passed to match_block!'
|
|
537
|
-
end
|
|
538
|
-
|
|
539
|
-
# Flush the pipeline first and then pass control to the program to bin out any failures
|
|
540
|
-
# prior to entering the match loop
|
|
541
|
-
if options[:check_for_fails]
|
|
542
|
-
if options[:multiple_entries]
|
|
543
|
-
@match_entries.times do |i|
|
|
544
|
-
microcode "global subr match_done_#{i}:"
|
|
545
|
-
cycle(microcode: "set_code #{i + 100}")
|
|
546
|
-
cycle(microcode: 'jump call_tester') unless i == @match_entries - 1
|
|
547
|
-
end
|
|
548
|
-
microcode 'call_tester:'
|
|
549
|
-
else
|
|
550
|
-
cycle(microcode: 'set_code 100')
|
|
551
|
-
end
|
|
552
|
-
cc 'Wait for any prior failures to propagate through the pipeline'
|
|
553
|
-
cycle(microcode: 'pipe_minus 1')
|
|
554
|
-
cc 'Now handshake with the tester to bin out and parts that have failed before they got here'
|
|
555
|
-
handshake(manual_stop: options[:manual_stop])
|
|
556
|
-
end
|
|
557
|
-
|
|
558
|
-
# Now do the main match loop
|
|
559
|
-
cc 'Start the match loop'
|
|
560
|
-
|
|
561
|
-
# Calculate the loop counts for the 2 loops to appropriately hit the timeout requested
|
|
562
|
-
inner_loop_vectors = (@pipeline_depth - 1) + 4 # num vectors in inner loop
|
|
563
|
-
if timeout.to_f < @max_repeat_loop * inner_loop_vectors * @min_repeat_loop
|
|
564
|
-
# Handle case for smaller timeouts (that would force small outer loop count)
|
|
565
|
-
inner_loop_count = (timeout.to_f / (inner_loop_vectors * @min_repeat_loop)).ceil
|
|
566
|
-
outer_loop_count = @min_repeat_loop
|
|
567
|
-
else
|
|
568
|
-
# Handle longer delays
|
|
569
|
-
inner_loop_count = @max_repeat_loop
|
|
570
|
-
outer_loop_count = (timeout.to_f / (@max_repeat_loop * inner_loop_vectors)).ceil # Will do a minimum of 1 * max_repeat_loop * (pipeline_depth-1)
|
|
571
|
-
end
|
|
572
|
-
|
|
573
|
-
global_opt = (options[:global_loops]) ? 'global ' : ''
|
|
574
|
-
microcode "#{global_opt}match_outer_loop_#{@unique_counter}:"
|
|
575
|
-
cycle(microcode: "loopB #{outer_loop_count} ign ifc icc")
|
|
576
|
-
microcode "#{global_opt}match_inner_loop_#{@unique_counter}:"
|
|
577
|
-
cycle(microcode: "loopA #{inner_loop_count} ign ifc icc")
|
|
578
|
-
cc 'Check if block condition met'
|
|
579
|
-
yield
|
|
580
|
-
cc ' Wait for the result to propagate through the pipeline'
|
|
581
|
-
cycle(microcode: 'pipe_minus 1 ign ifc icc')
|
|
582
|
-
cc 'Branch if block condition met'
|
|
583
|
-
cycle(microcode: "if (pass) jump block_matched_#{@unique_counter} icc ifc")
|
|
584
|
-
cycle(microcode: 'clr_flag (fail) icc')
|
|
585
|
-
cc 'Loop back around if time remaining'
|
|
586
|
-
cycle(microcode: "end_loopA match_inner_loop_#{@unique_counter} icc")
|
|
587
|
-
cycle(microcode: "end_loopB match_outer_loop_#{@unique_counter} icc")
|
|
588
|
-
if options[:force_fail_on_timeout]
|
|
589
|
-
cc 'To get here something has gone wrong, check block again to force a pattern failure'
|
|
590
|
-
yield
|
|
591
|
-
end
|
|
592
|
-
if options[:on_timeout_goto]
|
|
593
|
-
cycle(microcode: "jump #{options[:on_timeout_goto]} icc")
|
|
594
|
-
else
|
|
595
|
-
cycle(microcode: "jump match_loop_end_#{@unique_counter} icc")
|
|
596
|
-
# cycle(:microcode => 'halt')
|
|
597
|
-
end
|
|
598
|
-
microcode "block_matched_#{@unique_counter}:"
|
|
599
|
-
cycle(microcode: 'pop_loop icc')
|
|
600
|
-
unless options[:clr_fail_post_match]
|
|
601
|
-
cycle(microcode: 'clr_fail')
|
|
602
|
-
end
|
|
603
|
-
if options[:on_block_match_goto]
|
|
604
|
-
cycle(microcode: "jump #{options[:on_block_match_goto]}")
|
|
605
|
-
end
|
|
606
|
-
microcode "match_loop_end_#{@unique_counter}:"
|
|
607
|
-
if options[:clr_fail_post_match]
|
|
608
|
-
cycle(microcode: 'clr_fail')
|
|
609
|
-
end
|
|
610
|
-
|
|
611
|
-
@unique_counter += 1 # Increment so a different label will be applied if another
|
|
612
|
-
# handshake is called in the same pattern
|
|
613
|
-
end
|
|
614
|
-
|
|
615
|
-
# Call a match loop.
|
|
616
|
-
#
|
|
617
|
-
# Normally you would put your match loop in a global subs pattern, then you can
|
|
618
|
-
# call it via this method. This method automatically syncs match loop naming with
|
|
619
|
-
# the match generation flow, no arguments required.
|
|
620
|
-
#
|
|
621
|
-
# This is a J750 specific API.
|
|
622
|
-
#
|
|
623
|
-
# ==== Examples
|
|
624
|
-
# $tester.cycle
|
|
625
|
-
# $tester.call_match # Calls the match loop, or the first entry point if you have multiple
|
|
626
|
-
# $tester.cycle
|
|
627
|
-
# $tester.call_match # Calls the match loop, or the second entry point if you have multiple
|
|
628
|
-
def call_match
|
|
629
|
-
@match_counter = @match_counter || 0
|
|
630
|
-
call_subroutine("match_done_#{@match_counter}")
|
|
631
|
-
@match_counter += 1 unless @match_counter == (@match_entries || 1) - 1
|
|
632
|
-
end
|
|
633
|
-
|
|
634
|
-
# Apply a label to the pattern.
|
|
635
|
-
#
|
|
636
|
-
# No additional vector is generated.
|
|
637
|
-
# Arguments:
|
|
638
|
-
# name : label name
|
|
639
|
-
# global : (optional) whether to apply global label, default=false
|
|
640
|
-
#
|
|
641
|
-
# ==== Examples
|
|
642
|
-
# $tester.label("something_significant")
|
|
643
|
-
# $tester.label("something_significant",true) # apply global label
|
|
644
|
-
def label(name, global = false)
|
|
645
|
-
global_opt = (global) ? 'global ' : ''
|
|
646
|
-
microcode global_opt + name + ':'
|
|
647
|
-
end
|
|
648
|
-
|
|
649
|
-
# * J750 Specific *
|
|
650
|
-
#
|
|
651
|
-
# Set a readcode.
|
|
652
|
-
#
|
|
653
|
-
# Use the set an explicit readcode for communicating with the tester. This method
|
|
654
|
-
# will generate an additional vector.
|
|
655
|
-
#
|
|
656
|
-
# ==== Examples
|
|
657
|
-
# $tester.set_code(55)
|
|
658
|
-
def set_code(code)
|
|
659
|
-
cycle(microcode: "set_code #{code}")
|
|
660
|
-
end
|
|
661
|
-
|
|
662
|
-
# Branch execution to the given point.
|
|
663
|
-
#
|
|
664
|
-
# This generates a new vector with a jump instruction to a given label. This method
|
|
665
|
-
# will generate an additional vector.
|
|
666
|
-
#
|
|
667
|
-
# ==== Examples
|
|
668
|
-
# $tester.branch_to("something_significant")
|
|
669
|
-
def branch_to(label)
|
|
670
|
-
cycle(microcode: "jump #{label}")
|
|
671
|
-
end
|
|
672
|
-
alias_method :branch, :branch_to
|
|
673
|
-
|
|
674
|
-
# Add loop to the pattern.
|
|
675
|
-
#
|
|
676
|
-
# Pass in a name for the loop and the number of times to execute it, all vectors
|
|
677
|
-
# generated by the given block will be captured in the loop.
|
|
678
|
-
#
|
|
679
|
-
# Optional arguments: global - whether to apply global label (default=false)
|
|
680
|
-
# label_first - whether to apply loop label before loop vector or not
|
|
681
|
-
#
|
|
682
|
-
# ==== Examples
|
|
683
|
-
# $tester.loop_vectors("pulse_loop", 3) do # Do this 3 times...
|
|
684
|
-
# $tester.cycle
|
|
685
|
-
# some_other_method_to_generate_vectors
|
|
686
|
-
# end
|
|
687
|
-
def loop_vectors(name, number_of_loops, global = false, label_first = false)
|
|
688
|
-
if number_of_loops > 1
|
|
689
|
-
@loop_counters ||= {}
|
|
690
|
-
if @loop_counters[name]
|
|
691
|
-
@loop_counters[name] += 1
|
|
692
|
-
else
|
|
693
|
-
@loop_counters[name] = 0
|
|
694
|
-
end
|
|
695
|
-
loop_name = @loop_counters[name] == 0 ? name : "#{name}_#{@loop_counters[name]}"
|
|
696
|
-
if label_first
|
|
697
|
-
global_opt = (global) ? 'global ' : ''
|
|
698
|
-
microcode "#{global_opt}#{loop_name}: "
|
|
699
|
-
end
|
|
700
|
-
cycle(microcode: "loopA #{number_of_loops}")
|
|
701
|
-
unless label_first
|
|
702
|
-
global_opt = (global) ? 'global ' : ''
|
|
703
|
-
cycle(microcode: "#{global_opt}#{loop_name}: ")
|
|
704
|
-
end
|
|
705
|
-
yield
|
|
706
|
-
cycle(microcode: "end_loopA #{loop_name}")
|
|
707
|
-
else
|
|
708
|
-
yield
|
|
709
|
-
end
|
|
710
|
-
end
|
|
711
|
-
alias_method :loop_vector, :loop_vectors
|
|
712
|
-
|
|
713
|
-
# An internal method called by Origen to create the pattern header
|
|
714
|
-
def pattern_header(options = {})
|
|
715
|
-
options = {
|
|
716
|
-
subroutine_pat: false,
|
|
717
|
-
group: false, # If true the end pattern is intended to run within a pattern group
|
|
718
|
-
high_voltage: false, # Supply a pin name here to declare it as an HV instrument
|
|
719
|
-
freq_counter: false, # Supply a pin name here to declare it as a frequency counter
|
|
720
|
-
memory_test: false, # If true, define 2-bit MTO DGEN as instrument
|
|
721
|
-
}.merge(options)
|
|
722
|
-
|
|
723
|
-
called_timesets.each do |timeset|
|
|
724
|
-
microcode "import tset #{timeset.name};"
|
|
725
|
-
end
|
|
726
|
-
unless options[:group] # Withhold imports for pattern groups, is this correct?
|
|
727
|
-
called_subroutines.each do |sub_name|
|
|
728
|
-
# Don't import any called subroutines that are declared in the current pattern
|
|
729
|
-
microcode "import svm_subr #{sub_name};" unless local_subroutines.include?(sub_name)
|
|
730
|
-
end
|
|
731
|
-
end
|
|
732
|
-
# Should implement this more like @instruments.each...
|
|
733
|
-
if options[:memory_test]
|
|
734
|
-
microcode 'instruments = {'
|
|
735
|
-
microcode ' mto:dgen_2bit;'
|
|
736
|
-
microcode '}'
|
|
737
|
-
end
|
|
738
|
-
microcode "svm_only_file = #{options[:subroutine_pat] ? 'yes' : 'no'};"
|
|
739
|
-
microcode 'opcode_mode = extended;'
|
|
740
|
-
microcode 'compressed = yes;' # if $soc.gzip_patterns
|
|
741
|
-
options[:high_voltage] = @use_hv_pin
|
|
742
|
-
microcode "pin_setup = {#{options[:high_voltage]} high_voltage;}" if options[:high_voltage]
|
|
743
|
-
microcode "pin_setup = {#{options[:freq_counter]} freq_count;}" if options[:freq_counter]
|
|
744
|
-
microcode ''
|
|
745
|
-
|
|
746
|
-
pin_list = ordered_pins.map do |p|
|
|
747
|
-
if Origen.app.pin_pattern_order.include?(p.id)
|
|
748
|
-
p.id # specified name overrides pin name
|
|
749
|
-
else
|
|
750
|
-
p.name
|
|
751
|
-
end
|
|
752
|
-
end.join(', ')
|
|
753
|
-
|
|
754
|
-
microcode "vector ($tset, #{pin_list})"
|
|
755
|
-
microcode '{'
|
|
756
|
-
unless options[:subroutine_pat]
|
|
757
|
-
microcode 'start_label pattern_st:'
|
|
758
|
-
end
|
|
759
|
-
end
|
|
760
|
-
|
|
761
|
-
# An internal method called by Origen to generate the pattern footer
|
|
762
|
-
def pattern_footer(options = {})
|
|
763
|
-
options = {
|
|
764
|
-
subroutine_pat: false,
|
|
765
|
-
end_in_ka: false,
|
|
766
|
-
end_with_halt: false
|
|
767
|
-
}.merge(options)
|
|
768
|
-
# cycle(:microcode => "#{$soc.end_of_pattern_label}:") if $soc.end_of_pattern_label
|
|
769
|
-
if options[:end_in_ka]
|
|
770
|
-
$tester.cycle microcode: 'keep_alive'
|
|
771
|
-
else
|
|
772
|
-
if options[:end_with_halt]
|
|
773
|
-
$tester.cycle microcode: 'halt'
|
|
774
|
-
else
|
|
775
|
-
$tester.cycle microcode: 'end_module' unless options[:subroutine_pat]
|
|
776
|
-
end
|
|
777
|
-
end
|
|
778
|
-
microcode '}'
|
|
779
|
-
end
|
|
780
|
-
|
|
781
|
-
# Returns an array of subroutines called while generating the current pattern
|
|
782
|
-
def called_subroutines
|
|
783
|
-
@called_subroutines ||= []
|
|
784
|
-
end
|
|
785
|
-
|
|
786
|
-
# Returns an array of subroutines created by the current pattern
|
|
787
|
-
def local_subroutines # :nodoc:
|
|
788
|
-
@local_subroutines ||= []
|
|
789
|
-
end
|
|
790
|
-
|
|
791
|
-
# This is an internal method use by Origen which returns a fully formatted vector
|
|
792
|
-
# You can override this if you wish to change the output formatting at vector level
|
|
793
|
-
def format_vector(vec)
|
|
794
|
-
timeset = vec.timeset ? "> #{vec.timeset.name}" : ''
|
|
795
|
-
pin_vals = vec.pin_vals ? "#{vec.pin_vals} ;" : ''
|
|
796
|
-
if vec.repeat > 1
|
|
797
|
-
microcode = "repeat #{vec.repeat}"
|
|
798
|
-
else
|
|
799
|
-
microcode = vec.microcode ? vec.microcode : ''
|
|
800
|
-
end
|
|
801
|
-
# if vec.pin_vals && vec.number && vec.cycle_number
|
|
802
|
-
# comment = " // Vector #{@pattern_vectors}, Cycle #{@pattern_cycles}"
|
|
803
|
-
# else
|
|
804
|
-
comment = ''
|
|
805
|
-
# end
|
|
806
|
-
"#{microcode.ljust(65)}#{timeset.ljust(31)}#{pin_vals}#{comment}"
|
|
807
|
-
end
|
|
808
|
-
|
|
809
|
-
# Override this to force the formatting to match the v1 J750 model (easier diffs)
|
|
810
|
-
def push_microcode(code) # :nodoc:
|
|
811
|
-
stage.store(code.ljust(65) + ''.ljust(31))
|
|
812
|
-
end
|
|
813
|
-
alias_method :microcode, :push_microcode
|
|
814
|
-
|
|
815
|
-
# All vectors generated with the supplied block will have all pins set
|
|
816
|
-
# to the repeat previous state. Any pins that are changed state within
|
|
817
|
-
# the block will still update to the supplied value.
|
|
818
|
-
# ==== Example
|
|
819
|
-
# # All pins except invoke will be assigned the repeat previous code
|
|
820
|
-
# # in the generated vector. On completion of the block they will
|
|
821
|
-
# # return to their previous state, except for invoke which will
|
|
822
|
-
# # retain the value assigned within the block.
|
|
823
|
-
# $tester.repeat_previous do
|
|
824
|
-
# $top.pin(:invoke).drive(1)
|
|
825
|
-
# $tester.cycle
|
|
826
|
-
# end
|
|
827
|
-
def repeat_previous
|
|
828
|
-
pinmap = Origen.pin_bank.pins
|
|
829
|
-
pinmap.each { |_id, pin| pin.repeat_previous = true }
|
|
830
|
-
yield
|
|
831
|
-
pinmap.each { |_id, pin| pin.repeat_previous = false }
|
|
832
|
-
end
|
|
833
|
-
|
|
834
|
-
def ignore_fails(*pins)
|
|
835
|
-
pins.each(&:suspend)
|
|
836
|
-
yield
|
|
837
|
-
pins.each(&:resume)
|
|
838
|
-
end
|
|
839
|
-
|
|
840
|
-
def j750?
|
|
841
|
-
true
|
|
842
|
-
end
|
|
843
|
-
end
|
|
844
|
-
end
|
|
845
|
-
end
|