origen_jtag 0.12.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e06b3dca12b20579f6fbfbc389dac204e960a93b
4
+ data.tar.gz: dc97efa495078334d68ce6ac8bd43fcea8b2467d
5
+ SHA512:
6
+ metadata.gz: 43f03422ef2359a8e10a527300824d84e29f92cd97934b535d69f12e73aa480163790a06041b991bb25d5c05a76c491dcef9428db0cdaed7b5f3b7c33359e134
7
+ data.tar.gz: b84f766c5f4dd19cc111fad60e4f55c2162f2b09c4abff4c2d4016b5a97b0ff036e75393517e8488b87af9da552d26b0fc28a0e8fe48d1f9765f449bf15e0433
@@ -0,0 +1,64 @@
1
+ class OrigenJTAGApplication < Origen::Application
2
+
3
+ # This file contains examples of some of the most common configuration options,
4
+ # to see a real production example from a large application have a look at:
5
+ # sync://sync-15088:15088/Projects/common_tester_blocks/blocks/C90TFS_NVM_tester/tool_data/origen_v2/config/application.rb
6
+
7
+ # This information is used in headers and email templates, set it specific
8
+ # to your application
9
+ config.name = "Origen JTAG"
10
+ config.initials = "OrigenJTAG"
11
+ # Force naming for gem, done here because JTAG will not automatically convert to
12
+ # 'jtag' when OrigenJTAG is snakecased
13
+ self.name = "origen_jtag"
14
+ self.namespace = "OrigenJTAG"
15
+ config.rc_url = "git@github.com:Origen-SDK/origen_jtag.git"
16
+ config.release_externally = true
17
+
18
+ # To enable deployment of your documentation to a web server (via the 'origen web'
19
+ # command) fill in these attributes.
20
+ config.web_directory = "git@github.com:Origen-SDK/Origen-SDK.github.io.git/jtag"
21
+ config.web_domain = "http://origen-sdk.org/jtag"
22
+
23
+ config.semantically_version = true
24
+
25
+ config.lint_test = {
26
+ # Require the lint tests to pass before allowing a release to proceed
27
+ run_on_tag: true,
28
+ # Auto correct violations where possible whenever 'origen lint' is run
29
+ auto_correct: true,
30
+ # Limit the testing for large legacy applications
31
+ #level: :easy,
32
+ # Run on these directories/files by default
33
+ #files: ["lib", "config/application.rb"],
34
+ }
35
+
36
+ # Ensure that all tests pass before allowing a release to continue
37
+ def validate_release
38
+ if !system("origen examples") #|| !system("origen specs")
39
+ puts "Sorry but you can't release with failing tests, please fix them and try again."
40
+ exit 1
41
+ else
42
+ puts "All tests passing, proceeding with release process!"
43
+ end
44
+ end
45
+
46
+ # Run code coverage when deploying the web site
47
+ def before_deploy_site
48
+ Dir.chdir Origen.root do
49
+ system "origen examples -c"
50
+ dir = "#{Origen.root}/web/output/coverage"
51
+ FileUtils.remove_dir(dir, true) if File.exists?(dir)
52
+ system "mv #{Origen.root}/coverage #{dir}"
53
+ end
54
+ end
55
+
56
+ # Deploy the website automatically after a production tag
57
+ def after_release_email(tag, note, type, selector, options)
58
+ command = "origen web compile --remote --api"
59
+ Dir.chdir Origen.root do
60
+ system command
61
+ end
62
+ end
63
+
64
+ end
@@ -0,0 +1,90 @@
1
+ # This file should be used to extend the origen command line tool with tasks
2
+ # specific to your application.
3
+ # The comments below should help to get started and you can also refer to
4
+ # lib/origen/commands.rb in your Origen core workspace for more examples and
5
+ # inspiration.
6
+ #
7
+ # Also see the official docs on adding commands:
8
+ # http://origen.freescale.net/origen/latest/guides/custom/commands/
9
+
10
+ # Map any command aliases here, for example to allow origen -x to refer to a
11
+ # command called execute you would add a reference as shown below:
12
+ aliases ={
13
+ # "-x" => "execute",
14
+ }
15
+
16
+ # The requested command is passed in here as @command, this checks it against
17
+ # the above alias table and should not be removed.
18
+ @command = aliases[@command] || @command
19
+
20
+ def path_to_coverage_report
21
+ require 'pathname'
22
+ Pathname.new("#{Origen.root}/coverage/index.html").relative_path_from(Pathname.pwd)
23
+ end
24
+
25
+ def enable_coverage(name, merge=true)
26
+ if ARGV.delete("-c") || ARGV.delete("--coverage")
27
+ require 'simplecov'
28
+ SimpleCov.start do
29
+ command_name name
30
+
31
+ at_exit do
32
+ SimpleCov.result.format!
33
+ puts ""
34
+ puts "To view coverage report:"
35
+ puts " firefox #{path_to_coverage_report} &"
36
+ puts ""
37
+ end
38
+ end
39
+ yield
40
+ else
41
+ yield
42
+ end
43
+ end
44
+
45
+ # Now branch to the specific task code
46
+ case @command
47
+
48
+ when "examples"
49
+ Origen.load_application
50
+ enable_coverage("examples") do
51
+
52
+ # Pattern generator tests
53
+ ARGV = %w(jtag_workout -t v93k.rb -r approved)
54
+ load "#{Origen.top}/lib/origen/commands/generate.rb"
55
+ ARGV = %w(jtag_workout -t debug_RH1 -r approved)
56
+ load "#{Origen.top}/lib/origen/commands/generate.rb"
57
+ ARGV = %w(jtag_workout -t debug_RL1 -r approved)
58
+ load "#{Origen.top}/lib/origen/commands/generate.rb"
59
+
60
+ ARGV = %w(jtag_workout -t v93k_RH4.rb -r approved)
61
+ load "#{Origen.top}/lib/origen/commands/generate.rb"
62
+ ARGV = %w(jtag_workout -t debug_RH4 -r approved)
63
+ load "#{Origen.top}/lib/origen/commands/generate.rb"
64
+ ARGV = %w(jtag_workout -t debug_RL4 -r approved)
65
+ load "#{Origen.top}/lib/origen/commands/generate.rb"
66
+
67
+ if Origen.app.stats.changed_files == 0 &&
68
+ Origen.app.stats.new_files == 0 &&
69
+ Origen.app.stats.changed_patterns == 0 &&
70
+ Origen.app.stats.new_patterns == 0
71
+
72
+ Origen.app.stats.report_pass
73
+ else
74
+ Origen.app.stats.report_fail
75
+ end
76
+ puts ""
77
+ end
78
+ exit 0
79
+
80
+ # Always leave an else clause to allow control to fall back through to the
81
+ # Origen command handler.
82
+ # You probably want to also add the command details to the help shown via
83
+ # origen -h, you can do this be assigning the required text to @application_commands
84
+ # before handing control back to Origen. Un-comment the example below to get started.
85
+ else
86
+ @application_commands = <<-EOT
87
+ examples Run the examples (tests), -c will enable coverage
88
+ EOT
89
+
90
+ end
@@ -0,0 +1,15 @@
1
+ # This file is similar to environment.rb and will be loaded
2
+ # automatically at the start of each invocation of Origen.
3
+ #
4
+ # However the major difference is that it will not be loaded
5
+ # if the application is imported by a 3rd party app - in that
6
+ # case only environment.rb is loaded.
7
+ #
8
+ # Therefore this file should be used to load anything you need
9
+ # to setup a development environment for this app, normally
10
+ # this would be used to define some dummy classes to instantiate
11
+ # your objects so that they can be tested and/or interacted with
12
+ # in the console.
13
+ module OrigenJTAG
14
+ autoload :DUT, "origen_jtag/dut"
15
+ end
@@ -0,0 +1 @@
1
+ require "origen_jtag"
data/config/users.rb ADDED
@@ -0,0 +1,19 @@
1
+ # This file defines the users associated with your project, it is basically the
2
+ # mailing list for release notes.
3
+ #
4
+ # You can split your users into "admin" and "user" groups, the main difference
5
+ # between the two is that admin users will get all tag emails, users will get
6
+ # emails on external/official releases only.
7
+ #
8
+ # Users are also prohibited from running the "origen tag" task, but this is
9
+ # really just to prevent a casual user from executing it inadvertently and is
10
+ # not intended to be a serious security gate.
11
+ module Origen
12
+ module Users
13
+ def users
14
+ @users ||= [
15
+
16
+ ]
17
+ end
18
+ end
19
+ end
data/config/version.rb ADDED
@@ -0,0 +1,8 @@
1
+ module OrigenJTAG
2
+ MAJOR = 0
3
+ MINOR = 12
4
+ BUGFIX = 0
5
+ DEV = nil
6
+
7
+ VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
8
+ end
@@ -0,0 +1,449 @@
1
+ module OrigenJTAG
2
+ # This driver provides methods to read and write from a JTAG instruction
3
+ # and data registers.
4
+ #
5
+ # Low level methods are also provided for fine control of the TAP Controller
6
+ # state machine via the TAPController module.
7
+ #
8
+ # To use this driver the parent model must define the following pins (an alias is fine):
9
+ # :tclk
10
+ # :tdi
11
+ # :tdo
12
+ # :tms
13
+ class Driver
14
+ REQUIRED_PINS = [:tclk, :tdi, :tdo, :tms]
15
+
16
+ include TAPController
17
+ include Origen::Registers
18
+
19
+ # Returns the object that instantiated the JTAG
20
+ attr_reader :owner
21
+
22
+ # Returns the current value in the instruction register
23
+ attr_reader :ir_value
24
+
25
+ attr_accessor :tclk_format
26
+ # Set true to print out debug comments about all state transitions
27
+ attr_accessor :verbose
28
+ alias_method :verbose?, :verbose
29
+
30
+ def initialize(owner, options = {})
31
+ @owner = owner
32
+ validate_pins
33
+
34
+ # The parent can configure JTAG settings by defining this constant
35
+ if defined?(owner.class::JTAG_CONFIG)
36
+ options = owner.class::JTAG_CONFIG.merge(options)
37
+ end
38
+
39
+ # Fallback defaults
40
+ options = {
41
+ verbose: false,
42
+ tclk_format: :rh, # format of JTAG clock used: ReturnHigh (:rh), ReturnLo (:rl)
43
+ tclk_multiple: 1, # number of cycles for one clock pulse, assumes 50% duty cycle. Uses tester non-return format to spread TCK across multiple cycles.
44
+ # e.g. @tclk_multiple = 2, @tclk_format = :rh, means one cycle with Tck low (non-return), one with Tck high (NR)
45
+ # @tclk_multiple = 4, @tclk_format = :rl, means 2 cycles with Tck high (NR), 2 with Tck low (NR)
46
+ tdo_strobe: :tclk_high, # when using multiple cycles for TCK, when to strobe for TDO, options include:
47
+ # :tclk_high - strobe TDO only when TCK is high
48
+ # :tclk_low - strobe TDO only when TCK is low
49
+ # :tclk_all - strobe TDO throughout TCK cycle
50
+ tdo_store_cycle: 0, # store vector cycle within TCK (i.e. when to indicate to tester to store vector within TCK cycle. 0 is first vector, 1 is second, etc.)
51
+ # NOTE: only when user indicates to store TDO, which will mean we don't care the 1 or 0 value on TDO (overriding effectively :tdo_strobe option above)
52
+ init_state: :unknown
53
+ }.merge(options)
54
+
55
+ init_tap_controller(options)
56
+
57
+ @verbose = options[:verbose]
58
+ @ir_value = :unknown
59
+ @tclk_format = options[:tclk_format]
60
+ @tclk_multiple = options[:tclk_multiple]
61
+ @tdo_strobe = options[:tdo_strobe]
62
+ @tdo_store_cycle = options[:tdo_store_cycle]
63
+ @state = options[:init_state]
64
+ end
65
+
66
+ # Shift data into the TDI pin or out of the TDO pin.
67
+ #
68
+ # There is no TAP controller state checking or handling here, it just
69
+ # shifts some data directly into the pattern, so it is assumed that some
70
+ # higher level logic is co-ordinating the TAP Controller.
71
+ #
72
+ # Most applications should not call this method directly and should instead
73
+ # use the pre-packaged read/write_dr/ir methods.
74
+ # However it is provided as a public API for the corner cases like generating
75
+ # an overlay subroutine pattern where it would be necessary to generate some JTAG
76
+ # vectors outwith the normal state controller wrapper.
77
+ #
78
+ # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
79
+ # Value to be shifted. If a reg/bit collection is supplied this can be pre-marked for
80
+ # read, store or overlay and which will result in the requested action being applied to
81
+ # the cycles corresponding to those bits only (don't care cycles will be generated for the others).
82
+ # @param [Hash] options Options to customize the operation
83
+ # @option options [Integer] :size The number of bits to shift. This is optional
84
+ # when supplying a register or bit collection in which case the size will be derived from
85
+ # the number of bits supplied. If this option is supplied then it will override
86
+ # the size derived from the bits. If the size is greater than the number of bits
87
+ # provided then the additional space will be padded by 0s or don't cares as appropriate.
88
+ # @option options [Boolean] :read (false) When true the given value will be compared on the TDO pin
89
+ # instead of being shifted into the TDI pin. In the case of a register object being provided
90
+ # only those bits that are actually marked for read will be compared.
91
+ # @option options [Boolean] :cycle_last (false) Normally the last data bit is applied to the
92
+ # pins but not cycled, this is to integrate with the TAPController which usually
93
+ # requires that the TMS value is also changed on the last data bit. To override this
94
+ # default behavior and force a cycle for the last data bit set this to true.
95
+ # @option options [Boolean] :includes_last_bit (true) When true the TMS pin will be driven
96
+ # to 1 on the last cycle of the shift if :cycle_last has been specified. To override this
97
+ # and keep TMS low on the last cycle set this to false. One reason for doing this would be
98
+ # if generating some subroutine vectors which only represented a partial section of a shift
99
+ # operation.
100
+ def shift(reg_or_val, options = {})
101
+ options = {
102
+ read: false,
103
+ cycle_last: false,
104
+ includes_last_bit: true
105
+ }.merge(options)
106
+ size = extract_size(reg_or_val, options)
107
+ if options.key?(:arm_debug_comment)
108
+ cc options[:arm_debug_comment]
109
+ end
110
+ if options.key?(:arm_debug_overlay)
111
+ $tester.label(options[:arm_debug_overlay])
112
+ end
113
+ size = extract_size(reg_or_val, options)
114
+ contains_bits = (contains_bits?(reg_or_val) || is_a_bit?(reg_or_val))
115
+ owner.pin(:tdi).drive(0) # Drive state when reading out
116
+ owner.pin(:tms).drive(0)
117
+ size.times do |i|
118
+ call_subroutine = false
119
+ if options[:read]
120
+ # If it's a register support bit-wise reads
121
+ if contains_bits
122
+ if reg_or_val[i]
123
+ if reg_or_val[i].is_to_be_stored?
124
+ Origen.tester.store_next_cycle(owner.pin(:tdo))
125
+ owner.pin(:tdo).dont_care if Origen.tester.j750?
126
+ elsif reg_or_val[i].has_overlay?
127
+ if Origen.mode.simulation?
128
+ owner.pin(:tdo).dont_care
129
+ else
130
+ call_subroutine = reg_or_val[i].overlay_str
131
+ end
132
+ elsif reg_or_val[i].is_to_be_read?
133
+ owner.pin(:tdo).assert(reg_or_val[i] ? reg_or_val[i] : 0)
134
+ elsif options.key?(:compare_data)
135
+ if i.eql?(0) || i.eql?(1) || i.eql?(2)
136
+ # Skip comparing first three status bits
137
+ owner.pin(:tdo).dont_care
138
+ else
139
+ owner.pin(:tdo).assert(reg_or_val[i] ? reg_or_val[i] : 0)
140
+ end
141
+ else
142
+ owner.pin(:tdo).dont_care
143
+ end
144
+ # If the read width extends beyond the register boundary, don't care
145
+ # the extra bits
146
+ else
147
+ owner.pin(:tdo).dont_care
148
+ end
149
+ # Otherwise read the whole thing
150
+ else
151
+ owner.pin(:tdo).assert(reg_or_val[i] ? reg_or_val[i] : 0)
152
+ end
153
+ else
154
+ if contains_bits && reg_or_val[i] && reg_or_val[i].has_overlay?
155
+ if Origen.mode.simulation?
156
+ owner.pin(:tdi).drive(reg_or_val[i] ? reg_or_val[i] : 0)
157
+ else
158
+ call_subroutine = reg_or_val[i].overlay_str
159
+ end
160
+ elsif options.key?(:arm_debug_overlay)
161
+ if Origen.mode.simulation?
162
+ owner.pin(:tdi).drive(reg_or_val[i] ? reg_or_val[i] : 0)
163
+ else
164
+ $tester.label('// JTAG DATA Pin: ' + i.to_s)
165
+ owner.pin(:tdi).drive(reg_or_val[i] ? reg_or_val[i] : 0)
166
+ end
167
+ else
168
+ owner.pin(:tdi).drive(reg_or_val[i] ? reg_or_val[i] : 0)
169
+ end
170
+ end
171
+ if call_subroutine
172
+ Origen.tester.call_subroutine(call_subroutine)
173
+ @last_data_vector_shifted = true
174
+ else
175
+ @last_data_vector_shifted = false
176
+ # Don't latch the last bit, that will be done when
177
+ # leaving the state.
178
+ if i != size - 1 || options[:cycle_last]
179
+ if i == size - 1 && options[:includes_last_bit]
180
+ owner.pin(:tms).drive(1)
181
+ end
182
+ tclk_cycle do
183
+ Origen.tester.cycle
184
+ end
185
+ owner.pin(:tdo).dont_care
186
+ else
187
+ @deferred_compare = true
188
+ end
189
+ end
190
+ end
191
+ # Clear read and similar flags to reflect that the request has just
192
+ # been fulfilled
193
+ reg_or_val.clear_flags if reg_or_val.respond_to?(:clear_flags)
194
+ end
195
+
196
+ # Cycles the tester through one TCLK cycle
197
+ # Adjusts for the TCLK format and cycle span
198
+ # Assumes caller will drive pattern to tester
199
+ # via .drive or similar
200
+ def tclk_cycle
201
+ case @tclk_format
202
+ when :rh
203
+ tclk_val = 0
204
+ when :rl
205
+ tclk_val = 1
206
+ else
207
+ fail 'ERROR: Invalid Tclk timing format!'
208
+ end
209
+
210
+ # determine whether to mask TDO on first half cycle
211
+ mask_tdo_half0 = ((@tclk_format == :rl) && (@tdo_strobe == :tclk_low) && (@tclk_multiple > 1)) ||
212
+ ((@tclk_format == :rh) && (@tdo_strobe == :tclk_high) && (@tclk_multiple > 1))
213
+
214
+ # determine whether to mask TDO on second half cycle
215
+ mask_tdo_half1 = ((@tclk_format == :rl) && (@tdo_strobe == :tclk_high) && (@tclk_multiple > 1)) ||
216
+ ((@tclk_format == :rh) && (@tdo_strobe == :tclk_low) && (@tclk_multiple > 1))
217
+
218
+ # determine whether TDO is set to capture for this TCK cycle
219
+ tdo_to_be_captured = owner.pin(:tdo).to_be_captured?
220
+
221
+ # If TDO is already suspended (by an application) then don't do the
222
+ # suspends below since the resume will clear the application's suspend
223
+ tdo_already_suspended = owner.pin(:tdo).suspended? && !@tdo_suspended_by_driver
224
+
225
+ @tclk_multiple.times do |i|
226
+ # 50% duty cycle if @tclk_multiple is even, otherwise slightly off
227
+
228
+ if tdo_to_be_captured
229
+ owner.pin(:tdo).state = @tdo_store_cycle == i ? :capture : :dont_care
230
+ end
231
+
232
+ if i < (@tclk_multiple + 1) / 2
233
+ # first half of cycle
234
+ owner.pin(:tclk).drive(tclk_val)
235
+ unless tdo_already_suspended
236
+ unless tdo_to_be_captured
237
+ if mask_tdo_half0
238
+ @tdo_suspended_by_driver = true
239
+ owner.pin(:tdo).suspend
240
+ else
241
+ @tdo_suspended_by_driver = false
242
+ owner.pin(:tdo).resume
243
+ end
244
+ end
245
+ end
246
+ else
247
+ # second half of cycle
248
+ owner.pin(:tclk).drive(1 - tclk_val)
249
+ unless tdo_already_suspended
250
+ unless tdo_to_be_captured
251
+ if mask_tdo_half1
252
+ @tdo_suspended_by_driver = true
253
+ owner.pin(:tdo).suspend
254
+ else
255
+ @tdo_suspended_by_driver = false
256
+ owner.pin(:tdo).resume
257
+ end
258
+ end
259
+ end
260
+ end
261
+ yield
262
+ end
263
+ if @tdo_suspended_by_driver
264
+ owner.pin(:tdo).resume
265
+ @tdo_suspended_by_driver = false
266
+ end
267
+ end
268
+
269
+ # Applies the given value to the TMS pin and then
270
+ # cycles the tester for one TCLK
271
+ #
272
+ # @param [Integer] val Value to drive on the TMS pin, 0 or 1
273
+ def tms!(val)
274
+ if @deferred_compare
275
+ @deferred_compare = nil
276
+ else
277
+ owner.pin(:tdo).dont_care
278
+ end
279
+
280
+ tclk_cycle do
281
+ owner.pin(:tms).drive!(val)
282
+ end
283
+ end
284
+
285
+ # Write the given value, register or bit collection to the data register.
286
+ # This is a self contained method that will take care of the TAP controller
287
+ # state transitions, exiting with the TAP controller in Run-Test/Idle.
288
+ #
289
+ # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
290
+ # Value to be written. If a reg/bit collection is supplied this can be pre-marked for overlay.
291
+ # @param [Hash] options Options to customize the operation
292
+ # @option options [Integer] :size The number of bits to write. This is optional
293
+ # when supplying a register or bit collection in which case the size will be derived from
294
+ # the number of bits supplied. If this option is supplied then it will override
295
+ # the size derived from the bits. If the size is greater than the number of bits
296
+ # provided then the additional space will be padded by 0s.
297
+ # @option options [String] :msg By default will not make any comments directly here. Can pass
298
+ # a msg to be written out prior to shifting data.
299
+ def write_dr(reg_or_val, options = {})
300
+ if Origen.tester.respond_to?(:write_dr)
301
+ Origen.tester.write_dr(reg_or_val, options)
302
+ else
303
+ if options[:msg]
304
+ cc "#{options[:msg]}\n"
305
+ end
306
+ shift_dr do
307
+ if options[:overlay] == true
308
+ $tester.label(options[:overlay_label], true) # apply global label
309
+ end
310
+ shift(reg_or_val, options)
311
+ end
312
+ end
313
+ end
314
+
315
+ # Read the given value, register or bit collection from the data register.
316
+ # This is a self contained method that will take care of the TAP controller
317
+ # state transitions, exiting with the TAP controller in Run-Test/Idle.
318
+ #
319
+ # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
320
+ # Value to be read. If a reg/bit collection is supplied this can be pre-marked for read in which
321
+ # case only the marked bits will be read and the vectors corresponding to the data from the non-read
322
+ # bits will be set to don't care. Similarly the bits can be pre-marked for store (capture) or
323
+ # overlay.
324
+ # @param [Hash] options Options to customize the operation
325
+ # @option options [Integer] :size The number of bits to read. This is optional
326
+ # when supplying a register or bit collection in which case the size will be derived from
327
+ # the number of bits supplied. If the size is supplied then it will override
328
+ # the size derived from the bits. If the size is greater than the number of bits
329
+ # provided then the additional space will be padded by don't care cycles.
330
+ # @option options [String] :msg By default will not make any comments directly here. Can pass
331
+ # a msg to be written out prior to shifting data.
332
+ def read_dr(reg_or_val, options = {})
333
+ if Origen.tester.respond_to?(:read_dr)
334
+ Origen.tester.read_dr(reg_or_val, options)
335
+ else
336
+ options = {
337
+ read: true
338
+ }.merge(options)
339
+ if options[:msg]
340
+ cc "#{options[:msg]}\n"
341
+ end
342
+ shift_dr do
343
+ if options[:overlay] == true
344
+ $tester.label(options[:overlay_label], true) # apply global label
345
+ end
346
+ shift(reg_or_val, options)
347
+ end
348
+ end
349
+ end
350
+
351
+ # Write the given value, register or bit collection to the instruction register.
352
+ # This is a self contained method that will take care of the TAP controller
353
+ # state transitions, exiting with the TAP controller in Run-Test/Idle.
354
+ #
355
+ # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
356
+ # Value to be written. If a reg/bit collection is supplied this can be pre-marked for overlay.
357
+ # @param [Hash] options Options to customize the operation
358
+ # @option options [Integer] :size The number of bits to write. This is optional
359
+ # when supplying a register or bit collection in which case the size will be derived from
360
+ # the number of bits supplied. If this option is supplied then it will override
361
+ # the size derived from the bits. If the size is greater than the number of bits
362
+ # provided then the additional space will be padded by 0s.
363
+ # @option options [Boolean] :force By default multiple calls to this method will not generate
364
+ # multiple writes. This is to allow wrapper algorithms to remain efficient yet not have to
365
+ # manually track the IR state (and in many cases this may be impossible due to multiple
366
+ # protocols using the same JTAG). To force a write regardless of what the driver thinks the IR
367
+ # contains set this to true.
368
+ # @option options [String] :msg By default will not make any comments directly here. Can pass
369
+ # a msg to be written out prior to shifting in IR data. Will not write comment only if write
370
+ # occurs.
371
+ def write_ir(reg_or_val, options = {})
372
+ if Origen.tester.respond_to?(:write_ir)
373
+ Origen.tester.write_ir(reg_or_val, options)
374
+ else
375
+ val = reg_or_val.respond_to?(:data) ? reg_or_val.data : reg_or_val
376
+ if val != ir_value || options[:force]
377
+ if options[:msg]
378
+ cc "#{options[:msg]}\n"
379
+ end
380
+ shift_ir do
381
+ shift(reg_or_val, options)
382
+ end
383
+ @ir_value = val
384
+ end
385
+ end
386
+ end
387
+
388
+ # Read the given value, register or bit collection from the instruction register.
389
+ # This is a self contained method that will take care of the TAP controller
390
+ # state transitions, exiting with the TAP controller in Run-Test/Idle.
391
+ #
392
+ # @param [Integer, Origen::Register::Reg, Origen::Register::BitCollection, Origen::Register::Bit] reg_or_val
393
+ # Value to be read. If a reg/bit collection is supplied this can be pre-marked for read in which
394
+ # case only the marked bits will be read and the vectors corresponding to the data from the non-read
395
+ # bits will be set to don't care. Similarly the bits can be pre-marked for store (capture) or
396
+ # overlay.
397
+ # @param [Hash] options Options to customize the operation
398
+ # @option options [Integer] :size The number of bits to read. This is optional
399
+ # when supplying a register or bit collection in which case the size will be derived from
400
+ # the number of bits supplied. If the size is supplied then it will override
401
+ # the size derived from the bits. If the size is greater than the number of bits
402
+ # provided then the additional space will be padded by don't care cycles.
403
+ # @option options [String] :msg By default will not make any comments directly here. Can pass
404
+ # a msg to be written out prior to shifting data.
405
+ def read_ir(reg_or_val, options = {})
406
+ if Origen.tester.respond_to?(:read_ir)
407
+ Origen.tester.read_ir(reg_or_val, options)
408
+ else
409
+ options = {
410
+ read: true
411
+ }.merge(options)
412
+ if options[:msg]
413
+ cc "#{options[:msg]}\n"
414
+ end
415
+ shift_ir do
416
+ shift(reg_or_val, options)
417
+ end
418
+ end
419
+ end
420
+
421
+ private
422
+
423
+ def extract_size(reg_or_val, options = {})
424
+ size = options[:size]
425
+ unless size
426
+ if reg_or_val.is_a?(Fixnum) || !reg_or_val.respond_to?(:size)
427
+ fail 'When suppling a value to JTAG::Driver#shift you must supply a :size in the options!'
428
+ else
429
+ size = reg_or_val.size
430
+ end
431
+ end
432
+ size
433
+ end
434
+
435
+ # Validates that the parent object (the owner) has defined the necessary
436
+ # pins to implement the JTAG
437
+ def validate_pins
438
+ REQUIRED_PINS.each do |name|
439
+ owner.pin(name)
440
+ end
441
+ rescue
442
+ puts 'Missing JTAG pins!'
443
+ puts "In order to use the JTAG driver your #{owner.class} class must define"
444
+ puts 'the following pins (an alias is fine):'
445
+ puts REQUIRED_PINS
446
+ raise 'JTAG driver error!'
447
+ end
448
+ end
449
+ end