origen_jtag 0.13.0 → 0.14.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/boot.rb +24 -0
- data/config/commands.rb +23 -10
- data/config/version.rb +1 -1
- data/lib/origen_jtag/driver.rb +148 -95
- data/lib/{origen_jtag/dut.rb → origen_jtag_dev/top_level.rb} +42 -16
- data/pattern/jtag_workout.rb +161 -153
- data/templates/web/index.md.erb +12 -2
- metadata +10 -5
- data/config/environment.rb +0 -1
- data/config/users.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02b837da449c42cd29928bf58d3f793a1e9f7e45
|
4
|
+
data.tar.gz: 671bab411d61f7b7b14e1a9bc52c88b4f27345f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c8b11e4b45bf3d52e6c2044c5e92c13b2b5bce3e7a97d0a27d97dc613fedbdca7fd403c23e614bc2d4a326a480c7e5766ab8c10b1f8cfb69890a6d4fc8db5b81
|
7
|
+
data.tar.gz: eceb297fc81700389c1edef3f99b5574a4019240c934366bf5b25eb918824b9daf0ce3dc909cff4da95e51c3d8bb0a59b1fe7ac9a0b246834b0457247cc0a89f
|
data/config/boot.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# This file is used to boot your plugin when it is running in standalone mode
|
2
|
+
# from its own workspace - i.e. when the plugin is being developed.
|
3
|
+
#
|
4
|
+
# It will not be loaded when the plugin is imported by a 3rd party app - in that
|
5
|
+
# case only lib/origen_jtag.rb is loaded.
|
6
|
+
#
|
7
|
+
# Therefore this file can be used to load anything extra that you need to boot
|
8
|
+
# the development environment for this app. For example this is typically used
|
9
|
+
# to load some additional test classes to use your plugin APIs so that they can
|
10
|
+
# be tested and/or interacted with in the console.
|
11
|
+
require 'origen_jtag'
|
12
|
+
|
13
|
+
module OrigenJTAGDev
|
14
|
+
# Example of how to explicitly require a file
|
15
|
+
# require "origen_jtag_dev/my_file"
|
16
|
+
|
17
|
+
# Load all files in the lib/origen_jtag_dev directory.
|
18
|
+
# Note that there is no problem from requiring a file twice (Ruby will ignore
|
19
|
+
# the second require), so if you have a file that must be required first, then
|
20
|
+
# explicitly require it up above and then let this take care of the rest.
|
21
|
+
Dir.glob("#{File.dirname(__FILE__)}/../lib/origen_jtag_dev/**/*.rb").sort.each do |file|
|
22
|
+
require file
|
23
|
+
end
|
24
|
+
end
|
data/config/commands.rb
CHANGED
@@ -18,27 +18,32 @@ aliases ={
|
|
18
18
|
case @command
|
19
19
|
|
20
20
|
## Run the unit tests
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
when "specs"
|
22
|
+
require "rspec"
|
23
|
+
exit RSpec::Core::Runner.run(['spec'])
|
24
24
|
|
25
|
-
when "examples"
|
25
|
+
when "examples", "test"
|
26
26
|
Origen.load_application
|
27
27
|
status = 0
|
28
28
|
|
29
29
|
# Pattern generator tests
|
30
|
-
ARGV = %w(jtag_workout -t v93k
|
30
|
+
ARGV = %w(jtag_workout -t debug_RH1 -e v93k -r approved)
|
31
31
|
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
32
|
-
ARGV = %w(jtag_workout -t debug_RH1 -r approved)
|
32
|
+
ARGV = %w(jtag_workout -t debug_RH1 -e j750.rb -r approved)
|
33
33
|
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
34
|
-
ARGV = %w(jtag_workout -t debug_RL1 -r approved)
|
34
|
+
ARGV = %w(jtag_workout -t debug_RL1 -e j750.rb -r approved)
|
35
35
|
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
36
36
|
|
37
|
-
ARGV = %w(jtag_workout -t
|
37
|
+
ARGV = %w(jtag_workout -t debug_RH2.rb -e j750.rb -r approved)
|
38
38
|
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
39
|
-
ARGV = %w(jtag_workout -t
|
39
|
+
ARGV = %w(jtag_workout -t debug_RH2_1.rb -e j750.rb -r approved)
|
40
40
|
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
41
|
-
|
41
|
+
|
42
|
+
ARGV = %w(jtag_workout -t debug_RH4 -e v93k -r approved)
|
43
|
+
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
44
|
+
ARGV = %w(jtag_workout -t debug_RH4 -e j750.rb -r approved)
|
45
|
+
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
46
|
+
ARGV = %w(jtag_workout -t debug_RL4 -e j750.rb -r approved)
|
42
47
|
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
43
48
|
|
44
49
|
if Origen.app.stats.changed_files == 0 &&
|
@@ -52,6 +57,12 @@ when "examples"
|
|
52
57
|
status = 1
|
53
58
|
end
|
54
59
|
puts
|
60
|
+
if @command == "test"
|
61
|
+
Origen.app.unload_target!
|
62
|
+
require "rspec"
|
63
|
+
result = RSpec::Core::Runner.run(['spec'])
|
64
|
+
status = status == 1 ? 1 : result
|
65
|
+
end
|
55
66
|
exit status
|
56
67
|
|
57
68
|
# Always leave an else clause to allow control to fall back through to the
|
@@ -61,7 +72,9 @@ when "examples"
|
|
61
72
|
# before handing control back to Origen. Un-comment the example below to get started.
|
62
73
|
else
|
63
74
|
@application_commands = <<-EOT
|
75
|
+
specs Run the specs (tests), -c will enable coverage
|
64
76
|
examples Run the examples (tests), -c will enable coverage
|
77
|
+
test Run both specs and examples, -c will enable coverage
|
65
78
|
EOT
|
66
79
|
|
67
80
|
end
|
data/config/version.rb
CHANGED
data/lib/origen_jtag/driver.rb
CHANGED
@@ -42,7 +42,7 @@ module OrigenJTAG
|
|
42
42
|
# Fallback defaults
|
43
43
|
options = {
|
44
44
|
verbose: false,
|
45
|
-
tclk_format: :rh,
|
45
|
+
tclk_format: :rh, # format of JTAG clock used: ReturnHigh (:rh), ReturnLo (:rl)
|
46
46
|
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.
|
47
47
|
# e.g. @tclk_multiple = 2, @tclk_format = :rh, means one cycle with Tck low (non-return), one with Tck high (NR)
|
48
48
|
# @tclk_multiple = 4, @tclk_format = :rl, means 2 cycles with Tck high (NR), 2 with Tck low (NR)
|
@@ -108,111 +108,91 @@ module OrigenJTAG
|
|
108
108
|
includes_last_bit: true,
|
109
109
|
no_subr: false # do not use subroutine for any overlay
|
110
110
|
}.merge(options)
|
111
|
+
|
112
|
+
# save compression state for restoring afterwards
|
113
|
+
compression_on = !Origen.tester.dont_compress
|
114
|
+
|
115
|
+
# clean incoming data
|
111
116
|
size = extract_size(reg_or_val, options)
|
117
|
+
tdi_reg = extract_shift_in_data(reg_or_val, size, options)
|
118
|
+
tdo_reg = extract_shift_out_data(reg_or_val, size, options)
|
119
|
+
global_ovl, ovl_reg = extract_overlay_data(reg_or_val, size, options)
|
120
|
+
|
121
|
+
# tester does not support direct labels, so can't do
|
112
122
|
if options[:no_subr] && !$tester.respond_to?('label')
|
113
|
-
# tester does not support direct labels, so can't do
|
114
123
|
cc 'This tester does not support use of labels, cannot do no_subr option as requested'
|
115
124
|
cc ' going with subroutine overlay instead'
|
116
125
|
options[:no_subr] = false
|
117
126
|
end
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
127
|
+
|
128
|
+
# insert global label if specified
|
129
|
+
if global_ovl
|
130
|
+
if $tester.respond_to?('label')
|
131
|
+
$tester.label(global_ovl, true)
|
132
|
+
else
|
133
|
+
cc "Unsupported global label: #{global_ovl}"
|
134
|
+
end
|
123
135
|
end
|
124
|
-
|
125
|
-
|
126
|
-
owner.pin(:tdi).drive(0) # Drive state when reading out
|
127
|
-
owner.pin(:tms).drive(0)
|
136
|
+
|
137
|
+
# loop through each data bit
|
128
138
|
last_overlay_label = ''
|
129
139
|
size.times do |i|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
if reg_or_val[i].overlay_str != last_overlay_label
|
146
|
-
$tester.label(reg_or_val[i].overlay_str)
|
147
|
-
last_overlay_label = reg_or_val[i].overlay_str
|
148
|
-
end
|
149
|
-
owner.pin(:tdo).assert(reg_or_val[i] ? reg_or_val[i] : 0)
|
150
|
-
else
|
151
|
-
call_subroutine = reg_or_val[i].overlay_str
|
152
|
-
end
|
153
|
-
end
|
154
|
-
elsif reg_or_val[i].is_to_be_read?
|
155
|
-
owner.pin(:tdo).assert(reg_or_val[i] ? reg_or_val[i] : 0)
|
156
|
-
elsif options.key?(:compare_data)
|
157
|
-
if i.eql?(0) || i.eql?(1) || i.eql?(2)
|
158
|
-
# Skip comparing first three status bits
|
159
|
-
owner.pin(:tdo).dont_care
|
160
|
-
else
|
161
|
-
owner.pin(:tdo).assert(reg_or_val[i] ? reg_or_val[i] : 0)
|
162
|
-
end
|
163
|
-
else
|
164
|
-
owner.pin(:tdo).dont_care
|
165
|
-
end
|
166
|
-
# If the read width extends beyond the register boundary, don't care
|
167
|
-
# the extra bits
|
168
|
-
else
|
169
|
-
owner.pin(:tdo).dont_care
|
170
|
-
end
|
171
|
-
# Otherwise read the whole thing
|
172
|
-
else
|
173
|
-
Origen.tester.dont_compress = false
|
174
|
-
owner.pin(:tdo).assert(reg_or_val[i] ? reg_or_val[i] : 0)
|
140
|
+
store_tdo_this_tclk = false
|
141
|
+
|
142
|
+
# Set up pin actions for bit transaction (tclk cycle)
|
143
|
+
|
144
|
+
# TDI
|
145
|
+
owner.pin(:tdi).drive(tdi_reg[i])
|
146
|
+
|
147
|
+
# TDO
|
148
|
+
owner.pin(:tdo).dont_care # default setting
|
149
|
+
if tdo_reg[i]
|
150
|
+
if tdo_reg[i].is_to_be_stored? # store
|
151
|
+
store_tdo_this_tclk = true
|
152
|
+
owner.pin(:tdo).dont_care if Origen.tester.j750?
|
153
|
+
elsif tdo_reg[i].is_to_be_read? # compare/assert
|
154
|
+
owner.pin(:tdo).assert(tdo_reg[i])
|
175
155
|
end
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
else
|
189
|
-
call_subroutine = reg_or_val[i].overlay_str
|
190
|
-
end
|
191
|
-
end
|
192
|
-
elsif options.key?(:arm_debug_overlay)
|
193
|
-
if Origen.mode.simulation?
|
194
|
-
owner.pin(:tdi).drive(reg_or_val[i] ? reg_or_val[i] : 0)
|
195
|
-
else
|
196
|
-
$tester.label('// JTAG DATA Pin: ' + i.to_s)
|
197
|
-
owner.pin(:tdi).drive(reg_or_val[i] ? reg_or_val[i] : 0)
|
156
|
+
end
|
157
|
+
|
158
|
+
# TMS
|
159
|
+
owner.pin(:tms).drive(0)
|
160
|
+
|
161
|
+
# Overlay - reconfigure pin action for overlay if necessary
|
162
|
+
if ovl_reg[i] && ovl_reg[i].has_overlay? && !Origen.mode.simulation?
|
163
|
+
if options[:no_subr]
|
164
|
+
Origen.tester.dont_compress = true
|
165
|
+
if ovl_reg[i].overlay_str != last_overlay_label
|
166
|
+
$tester.label(ovl_reg[i].overlay_str)
|
167
|
+
last_overlay_label = ovl_reg[i].overlay_str
|
198
168
|
end
|
169
|
+
owner.pin(:tdo).assert(tdo_reg[i]) if options[:read]
|
199
170
|
else
|
200
|
-
|
201
|
-
|
171
|
+
owner.pin(:tdi).drive(0)
|
172
|
+
call_subroutine = ovl_reg[i].overlay_str
|
202
173
|
end
|
203
174
|
end
|
175
|
+
|
176
|
+
# With JTAG pin actions queued up, use block call to tclk_cycle to
|
177
|
+
# execute a single TCLK period. Special handling of subroutines,
|
178
|
+
# case of last bit in shift, and store vector (within a multi-cycle
|
179
|
+
# tclk config).
|
204
180
|
if call_subroutine
|
205
181
|
Origen.tester.call_subroutine(call_subroutine)
|
206
182
|
@last_data_vector_shifted = true
|
207
183
|
else
|
208
184
|
@last_data_vector_shifted = false
|
209
|
-
|
210
|
-
|
185
|
+
@next_data_vector_to_be_stored = false
|
186
|
+
|
187
|
+
# Don't latch the last bit, that will be done when leaving the state.
|
211
188
|
if i != size - 1 || options[:cycle_last]
|
212
189
|
if i == size - 1 && options[:includes_last_bit]
|
213
190
|
owner.pin(:tms).drive(1)
|
214
191
|
end
|
215
192
|
tclk_cycle do
|
193
|
+
if store_tdo_this_tclk && @next_data_vector_to_be_stored
|
194
|
+
Origen.tester.store_next_cycle(owner.pin(:tdo))
|
195
|
+
end
|
216
196
|
Origen.tester.cycle
|
217
197
|
end
|
218
198
|
owner.pin(:tdo).dont_care
|
@@ -221,11 +201,12 @@ module OrigenJTAG
|
|
221
201
|
end
|
222
202
|
end
|
223
203
|
end
|
224
|
-
|
225
|
-
# been fulfilled
|
204
|
+
|
205
|
+
# Clear read and similar flags to reflect that the request has just been fulfilled
|
226
206
|
reg_or_val.clear_flags if reg_or_val.respond_to?(:clear_flags)
|
207
|
+
|
227
208
|
# put back compression if turned on above
|
228
|
-
Origen.tester.dont_compress = false
|
209
|
+
Origen.tester.dont_compress = false if compression_on
|
229
210
|
end
|
230
211
|
|
231
212
|
# Cycles the tester through one TCLK cycle
|
@@ -250,7 +231,7 @@ module OrigenJTAG
|
|
250
231
|
mask_tdo_half1 = ((@tclk_format == :rl) && (@tdo_strobe == :tclk_high) && (@tclk_multiple > 1)) ||
|
251
232
|
((@tclk_format == :rh) && (@tdo_strobe == :tclk_low) && (@tclk_multiple > 1))
|
252
233
|
|
253
|
-
# determine whether TDO is set to capture for this
|
234
|
+
# determine whether TDO is set to capture for this TCLK cycle
|
254
235
|
tdo_to_be_captured = owner.pin(:tdo).to_be_captured?
|
255
236
|
|
256
237
|
# If TDO is already suspended (by an application) then don't do the
|
@@ -260,9 +241,7 @@ module OrigenJTAG
|
|
260
241
|
@tclk_multiple.times do |i|
|
261
242
|
# 50% duty cycle if @tclk_multiple is even, otherwise slightly off
|
262
243
|
|
263
|
-
|
264
|
-
owner.pin(:tdo).state = @tdo_store_cycle == i ? :capture : :dont_care
|
265
|
-
end
|
244
|
+
@next_data_vector_to_be_stored = @tdo_store_cycle == i ? true : false
|
266
245
|
|
267
246
|
if i < (@tclk_multiple + 1) / 2
|
268
247
|
# first half of cycle
|
@@ -340,9 +319,6 @@ module OrigenJTAG
|
|
340
319
|
end
|
341
320
|
val = reg_or_val.respond_to?(:data) ? reg_or_val.data : reg_or_val
|
342
321
|
shift_dr(write: val.to_hex) do
|
343
|
-
if options[:overlay] == true
|
344
|
-
$tester.label(options[:overlay_label], true) # apply global label
|
345
|
-
end
|
346
322
|
shift(reg_or_val, options)
|
347
323
|
end
|
348
324
|
end
|
@@ -376,9 +352,6 @@ module OrigenJTAG
|
|
376
352
|
cc "#{options[:msg]}\n"
|
377
353
|
end
|
378
354
|
shift_dr(read: Origen::Utility.read_hex(reg_or_val)) do
|
379
|
-
if options[:overlay] == true
|
380
|
-
$tester.label(options[:overlay_label], true) # apply global label
|
381
|
-
end
|
382
355
|
shift(reg_or_val, options)
|
383
356
|
end
|
384
357
|
end
|
@@ -456,6 +429,8 @@ module OrigenJTAG
|
|
456
429
|
|
457
430
|
private
|
458
431
|
|
432
|
+
# Return size of transaction. Options[:size] has priority and need not match the
|
433
|
+
# register size. Any mismatch will be handled by the api.
|
459
434
|
def extract_size(reg_or_val, options = {})
|
460
435
|
size = options[:size]
|
461
436
|
unless size
|
@@ -468,6 +443,84 @@ module OrigenJTAG
|
|
468
443
|
size
|
469
444
|
end
|
470
445
|
|
446
|
+
# Combine any legacy options into a single global overlay and create
|
447
|
+
# new bit collection to track any bit-wise overlays.
|
448
|
+
def extract_overlay_data(reg_or_val, size, options = {})
|
449
|
+
if reg_or_val.respond_to?(:data)
|
450
|
+
ovl = reg_or_val.dup
|
451
|
+
else
|
452
|
+
ovl = Reg.dummy(size)
|
453
|
+
end
|
454
|
+
|
455
|
+
if options[:overlay]
|
456
|
+
global = options[:overlay_label]
|
457
|
+
elsif options.key?(:arm_debug_overlay) # prob don't need this anymore
|
458
|
+
global = options[:arm_debug_overlay] # prob don't need this anymore
|
459
|
+
else
|
460
|
+
global = nil
|
461
|
+
end
|
462
|
+
|
463
|
+
[global, ovl]
|
464
|
+
end
|
465
|
+
|
466
|
+
# Create data that will be shifted in on TDI, create new bit collection
|
467
|
+
# on the fly if reg_or_val arg is data only. Consider read operation
|
468
|
+
# where caller has requested (specific) shift in data to be used.
|
469
|
+
def extract_shift_in_data(reg_or_val, size, options = {})
|
470
|
+
if reg_or_val.respond_to?(:data)
|
471
|
+
if options[:read]
|
472
|
+
data = options[:shift_in_data] || 0
|
473
|
+
tdi = Reg.dummy(size)
|
474
|
+
tdi.write(data)
|
475
|
+
else
|
476
|
+
tdi = reg_or_val.dup
|
477
|
+
end
|
478
|
+
else
|
479
|
+
# Not a register model, so can't support bit-wise overlay
|
480
|
+
tdi = Reg.dummy(size)
|
481
|
+
if options[:read]
|
482
|
+
data = options[:shift_in_data] || 0
|
483
|
+
tdi.write(data)
|
484
|
+
else
|
485
|
+
tdi.write(reg_or_val)
|
486
|
+
end
|
487
|
+
end
|
488
|
+
tdi
|
489
|
+
end
|
490
|
+
|
491
|
+
# Create data that will be shifted out on TDO, create new bit collection
|
492
|
+
# on the fly if reg_or_val arg is data only. Consider write operation
|
493
|
+
# where caller has requested (specific) shift out data to be compared.
|
494
|
+
def extract_shift_out_data(reg_or_val, size, options = {})
|
495
|
+
if reg_or_val.respond_to?(:data)
|
496
|
+
if options[:read]
|
497
|
+
tdo = reg_or_val.dup
|
498
|
+
else
|
499
|
+
tdo = Reg.dummy(size)
|
500
|
+
if options[:shift_out_data]
|
501
|
+
tdo.write(options[:shift_out_data])
|
502
|
+
tdo.read
|
503
|
+
else
|
504
|
+
tdo.write(0)
|
505
|
+
end
|
506
|
+
end
|
507
|
+
else
|
508
|
+
tdo = Reg.dummy(size)
|
509
|
+
if options[:read]
|
510
|
+
tdo.write(reg_or_val)
|
511
|
+
tdo.read
|
512
|
+
else
|
513
|
+
if options[:shift_out_data]
|
514
|
+
tdo.write(options[:shift_out_data])
|
515
|
+
tdo.read
|
516
|
+
else
|
517
|
+
tdo.write(0)
|
518
|
+
end
|
519
|
+
end
|
520
|
+
end
|
521
|
+
tdo
|
522
|
+
end
|
523
|
+
|
471
524
|
# Validates that the parent object (the owner) has defined the necessary
|
472
525
|
# pins to implement the JTAG
|
473
526
|
def validate_pins
|
@@ -1,14 +1,14 @@
|
|
1
|
-
module
|
1
|
+
module OrigenJTAGDev
|
2
2
|
# This is a dummy DUT model which is used
|
3
3
|
# to instantiate and test the JTAG locally
|
4
4
|
# during development.
|
5
5
|
#
|
6
6
|
# It is not included when this library is imported.
|
7
7
|
class DUT
|
8
|
+
include Origen::TopLevel
|
8
9
|
include OrigenJTAG
|
9
|
-
|
10
|
-
|
11
|
-
include Origen::Pins
|
10
|
+
|
11
|
+
attr_reader :jtag_config
|
12
12
|
|
13
13
|
JTAG_CONFIG = {
|
14
14
|
verbose: true,
|
@@ -25,40 +25,66 @@ module OrigenJTAG
|
|
25
25
|
JTAG_CONFIG[:tdo_strobe] = options[:tdo_strobe] if options[:tdo_strobe]
|
26
26
|
JTAG_CONFIG[:tdo_store_cycle] = options[:tdo_store_cycle] if options[:tdo_store_cycle]
|
27
27
|
JTAG_CONFIG[:init_state] = options[:init_state] if options[:init_state]
|
28
|
+
|
29
|
+
instantiate_registers(options)
|
30
|
+
instantiate_pins(options)
|
31
|
+
end
|
32
|
+
|
33
|
+
def instantiate_registers(options = {})
|
34
|
+
reg :test16, 0x0012, size: 16 do |reg|
|
35
|
+
reg.bit 15..8, :bus
|
36
|
+
reg.bit 0, :bit
|
37
|
+
end
|
38
|
+
|
39
|
+
reg :test32, 0x0014, size: 32 do |reg|
|
40
|
+
reg.bit 31..16, :bus
|
41
|
+
reg.bit 0, :bit
|
42
|
+
end
|
28
43
|
end
|
29
44
|
|
45
|
+
def instantiate_pins(options = {})
|
46
|
+
add_pin :tclk
|
47
|
+
add_pin :tdi
|
48
|
+
add_pin :tdo
|
49
|
+
add_pin :tms
|
50
|
+
end
|
51
|
+
|
52
|
+
def startup(options = {})
|
53
|
+
tester.set_timeset('nvmbist', 40)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Getter for top-level tclk_format setting
|
30
57
|
def tclk_format
|
31
58
|
JTAG_CONFIG[:tclk_format]
|
32
59
|
end
|
33
60
|
|
61
|
+
# Getter for top-level tclk_multiple setting
|
34
62
|
def tclk_multiple
|
35
63
|
JTAG_CONFIG[:tclk_multiple]
|
36
64
|
end
|
37
65
|
|
66
|
+
# Getter for top-level tdo_strobe setting
|
38
67
|
def tdo_strobe
|
39
68
|
JTAG_CONFIG[:tdo_strobe]
|
40
69
|
end
|
41
70
|
|
71
|
+
# Getter for top-level tdo_store_cycle setting
|
42
72
|
def tdo_store_cycle
|
43
73
|
JTAG_CONFIG[:tdo_store_cycle]
|
44
74
|
end
|
45
75
|
|
76
|
+
# Getter for top-level init_state setting
|
46
77
|
def init_state
|
47
78
|
JTAG_CONFIG[:init_state]
|
48
79
|
end
|
49
80
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
$tester.set_timeset('nvmbist', 40)
|
58
|
-
add_pin :tclk
|
59
|
-
add_pin :tdi
|
60
|
-
add_pin :tdo
|
61
|
-
add_pin :tms
|
81
|
+
# Wouldn't want to do this in reality, but allows some flexibility duing gem testing
|
82
|
+
def update_jtag_config(cfg, val)
|
83
|
+
if JTAG_CONFIG.key?(cfg)
|
84
|
+
JTAG_CONFIG[cfg] = val
|
85
|
+
else
|
86
|
+
fail "#{cfg} not a part of JTAG_CONFIG"
|
87
|
+
end
|
62
88
|
end
|
63
89
|
end
|
64
90
|
end
|
data/pattern/jtag_workout.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
pat_name = "jtag_workout_#{$dut.tclk_format.upcase}#{$dut.tclk_multiple}"
|
2
|
+
pat_name = pat_name + "_#{dut.tdo_store_cycle}" if dut.tdo_store_cycle != 0
|
3
|
+
|
4
|
+
Pattern.create(options = { name: pat_name }) do
|
2
5
|
def test(msg)
|
3
6
|
ss "Test - #{msg}"
|
4
7
|
end
|
@@ -8,185 +11,190 @@ Pattern.create(options={:name => "jtag_workout_#{$dut.tclk_format.upcase}#{$dut.
|
|
8
11
|
|
9
12
|
# First tests of the TAP Controller
|
10
13
|
|
11
|
-
test
|
12
|
-
jtag.shift_dr {
|
14
|
+
test 'Transition TAP controller in and out of Shift-DR'
|
15
|
+
jtag.shift_dr {}
|
13
16
|
|
14
|
-
test
|
15
|
-
jtag.pause_dr {
|
17
|
+
test 'Transition TAP controller in and out of Pause-DR'
|
18
|
+
jtag.pause_dr {}
|
16
19
|
|
17
|
-
test
|
18
|
-
jtag.shift_ir {
|
20
|
+
test 'Transition TAP controller in and out of Shift-IR'
|
21
|
+
jtag.shift_ir {}
|
19
22
|
|
20
|
-
test
|
21
|
-
jtag.pause_ir {
|
23
|
+
test 'Transition TAP controller in and out of Pause-IR'
|
24
|
+
jtag.pause_ir {}
|
22
25
|
|
23
|
-
test
|
26
|
+
test 'Transition into Shift-DR, then back and forth into Pause-DR'
|
24
27
|
jtag.shift_dr do
|
25
|
-
jtag.pause_dr {
|
26
|
-
jtag.pause_dr {
|
28
|
+
jtag.pause_dr {}
|
29
|
+
jtag.pause_dr {}
|
27
30
|
end
|
28
31
|
|
29
|
-
test
|
32
|
+
test 'Transition into Pause-DR, then back and forth into Shift-DR'
|
30
33
|
jtag.pause_dr do
|
31
|
-
jtag.shift_dr {
|
32
|
-
jtag.shift_dr {
|
34
|
+
jtag.shift_dr {}
|
35
|
+
jtag.shift_dr {}
|
33
36
|
end
|
34
|
-
|
35
|
-
test
|
37
|
+
|
38
|
+
test 'Transition into Shift-IR, then back and forth into Pause-IR'
|
36
39
|
jtag.shift_ir do
|
37
|
-
jtag.pause_ir {
|
38
|
-
jtag.pause_ir {
|
40
|
+
jtag.pause_ir {}
|
41
|
+
jtag.pause_ir {}
|
39
42
|
end
|
40
43
|
|
41
|
-
test
|
44
|
+
test 'Transition into Pause-IR, then back and forth into Shift-IR'
|
42
45
|
jtag.pause_ir do
|
43
|
-
jtag.shift_ir {
|
44
|
-
jtag.shift_ir {
|
46
|
+
jtag.shift_ir {}
|
47
|
+
jtag.shift_ir {}
|
45
48
|
end
|
46
49
|
|
47
50
|
# Tests of the shift method, make sure it handles registers with
|
48
51
|
# bit-level flags set in additional to dumb values
|
49
52
|
|
50
|
-
test
|
51
|
-
jtag.shift 0x1234, :
|
52
|
-
|
53
|
-
test
|
54
|
-
jtag.shift 0x1234, :
|
55
|
-
|
56
|
-
test
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
test
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
test
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
test
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
test
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
test
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
test
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
test
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
test
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
test
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
53
|
+
test 'Shifting an explicit value into TDI'
|
54
|
+
jtag.shift 0x1234, size: 16, cycle_last: true
|
55
|
+
|
56
|
+
test 'Shifting an explicit value out of TDO'
|
57
|
+
jtag.shift 0x1234, size: 16, cycle_last: true, read: true
|
58
|
+
|
59
|
+
test 'Shift register into TDI'
|
60
|
+
reg.write(0xFF01)
|
61
|
+
cc 'Full register (16 bits)'
|
62
|
+
jtag.shift reg, cycle_last: true
|
63
|
+
cc 'Full register with additional size (32 bits)'
|
64
|
+
jtag.shift reg, cycle_last: true, size: 32
|
65
|
+
cc 'Full register with reduced size (8 bits)'
|
66
|
+
jtag.shift reg, cycle_last: true, size: 8, includes_last_bit: false
|
67
|
+
|
68
|
+
test 'Shift register into TDI with overlay'
|
69
|
+
reg.overlay('write_overlay')
|
70
|
+
cc 'Full register (16 bits)'
|
71
|
+
tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
72
|
+
jtag.shift reg, cycle_last: true
|
73
|
+
cc 'Full register with additional size (32 bits)'
|
74
|
+
tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
75
|
+
jtag.shift reg, cycle_last: true, size: 32
|
76
|
+
cc 'Full register with reduced size (8 bits)'
|
77
|
+
tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
78
|
+
jtag.shift reg, cycle_last: true, size: 8, includes_last_bit: false
|
79
|
+
cc 'It should in-line overlays when running in simulation mode'
|
80
|
+
Origen.mode = :simulation
|
81
|
+
tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
82
|
+
jtag.shift reg, cycle_last: true
|
83
|
+
Origen.mode = :debug
|
84
|
+
if tester.respond_to?('label')
|
85
|
+
cc 'Full register overlay without using subroutine'
|
86
|
+
jtag.shift reg, cycle_last: true, no_subr: true
|
87
|
+
end
|
88
|
+
|
89
|
+
test 'Shift register into TDI with single bit overlay'
|
90
|
+
reg.overlay(nil)
|
91
|
+
reg.bit(:bit).overlay('write_overlay2')
|
92
|
+
tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
93
|
+
jtag.shift reg, cycle_last: true
|
94
|
+
reg.overlay(nil)
|
95
|
+
|
96
|
+
test 'Read register out of TDO'
|
97
|
+
cc 'Full register (16 bits)'
|
98
|
+
reg.read
|
99
|
+
jtag.shift reg, cycle_last: true, read: true
|
100
|
+
cc 'Full register with additional size (32 bits)'
|
101
|
+
reg.read
|
102
|
+
jtag.shift reg, cycle_last: true, size: 32, read: true
|
103
|
+
cc 'Full register with reduced size (8 bits)'
|
104
|
+
reg.read
|
105
|
+
jtag.shift reg, cycle_last: true, size: 8, read: true, includes_last_bit: false
|
106
|
+
|
107
|
+
test 'Read single bit out of TDO'
|
108
|
+
reg.bit(:bit).read
|
109
|
+
jtag.shift reg, cycle_last: true, read: true
|
110
|
+
|
111
|
+
test 'Store register out of TDO'
|
112
|
+
cc 'Full register (16 bits)'
|
113
|
+
reg.store
|
114
|
+
jtag.shift reg, cycle_last: true, read: true
|
115
|
+
cc 'Full register with additional size (32 bits)'
|
116
|
+
reg.store
|
117
|
+
jtag.shift reg, cycle_last: true, size: 32, read: true
|
118
|
+
cc 'Full register with reduced size (8 bits)'
|
119
|
+
reg.store
|
120
|
+
jtag.shift reg, cycle_last: true, size: 8, read: true, includes_last_bit: false
|
121
|
+
|
122
|
+
test 'Store single bit out of TDO'
|
123
|
+
reg.bit(:bit).store
|
124
|
+
jtag.shift reg, cycle_last: true, read: true
|
125
|
+
|
126
|
+
test 'Test flag clear, bit 0 should be read, but not stored'
|
127
|
+
reg.bit(:bit).read
|
128
|
+
jtag.shift reg, cycle_last: true, read: true
|
129
|
+
|
130
|
+
test 'Shift register out of TDO with overlay'
|
131
|
+
reg.overlay('read_overlay')
|
132
|
+
cc 'Full register (16 bits)'
|
133
|
+
tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
134
|
+
jtag.shift reg, cycle_last: true, read: true
|
135
|
+
cc 'Full register with additional size (32 bits)'
|
136
|
+
tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
137
|
+
jtag.shift reg, cycle_last: true, size: 32, read: true
|
138
|
+
cc 'Full register with reduced size (8 bits)'
|
139
|
+
tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
140
|
+
jtag.shift reg, cycle_last: true, size: 8, read: true, includes_last_bit: false
|
141
|
+
cc 'It should in-line overlays when running in simulation mode'
|
142
|
+
Origen.mode = :simulation
|
143
|
+
tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
144
|
+
jtag.shift reg, cycle_last: true, read: true
|
145
|
+
Origen.mode = :debug
|
146
|
+
if tester.respond_to?('label')
|
147
|
+
cc 'Full register overlay without using subroutine'
|
148
|
+
jtag.shift reg, cycle_last: true, read: true, no_subr: true
|
149
|
+
end
|
150
|
+
|
151
|
+
test 'Shift register out of TDO with single bit overlay'
|
152
|
+
reg.overlay(nil)
|
153
|
+
reg.bit(:bit).overlay('read_overlay2')
|
154
|
+
tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
155
|
+
jtag.shift reg, cycle_last: true
|
156
|
+
reg.overlay(nil)
|
154
157
|
|
155
158
|
# Finally integration tests of the TAPController + shift
|
156
159
|
|
157
|
-
test
|
158
|
-
|
160
|
+
test 'Write value into DR'
|
161
|
+
jtag.write_dr 0xFFFF, size: 16, msg: 'Write value into DR'
|
159
162
|
|
160
|
-
test
|
161
|
-
|
162
|
-
jtag.write_dr r
|
163
|
+
test 'Write value into DR, with compare on TDO'
|
164
|
+
jtag.write_dr 0xFFFF, size: 16, shift_out_data: 0xAAAA, msg: 'Write value into DR'
|
163
165
|
|
164
|
-
|
165
|
-
|
166
|
+
test 'Write register into DR with full-width overlay'
|
167
|
+
r = $dut.reg(:test32).overlay('write_overlay')
|
168
|
+
jtag.write_dr r
|
166
169
|
|
167
|
-
test
|
168
|
-
|
170
|
+
test 'Read value out of DR'
|
171
|
+
jtag.read_dr 0xFFFF, size: 16, msg: 'Read value out of DR'
|
169
172
|
|
170
|
-
test
|
171
|
-
|
173
|
+
test 'Read value out of DR, with specified shift in data into TDI'
|
174
|
+
jtag.read_dr 0xFFFF, size: 16, shift_in_data: 0x5555, msg: 'Read value out of DR'
|
172
175
|
|
173
|
-
|
174
|
-
|
176
|
+
test 'Write value into IR'
|
177
|
+
jtag.write_ir 0xF, size: 4, msg: 'Write value into IR'
|
175
178
|
|
176
|
-
test
|
177
|
-
|
179
|
+
test 'Read value out of IR'
|
180
|
+
jtag.read_ir 0xF, size: 4, msg: 'Read value out of IR'
|
178
181
|
|
179
|
-
test
|
180
|
-
|
182
|
+
test 'The IR value is tracked and duplicate writes are inhibited'
|
183
|
+
jtag.write_ir 0xF, size: 4
|
181
184
|
|
182
|
-
test
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
185
|
+
test 'Unless forced'
|
186
|
+
jtag.write_ir 0xF, size: 4, force: true
|
187
|
+
|
188
|
+
test 'Reset'
|
189
|
+
jtag.reset
|
190
|
+
|
191
|
+
test 'Suspend of compare on TDO works'
|
192
|
+
cc 'TDO should be H'
|
193
|
+
jtag.read_dr 0xFFFF, size: 16, msg: 'Read value out of DR'
|
194
|
+
tester.ignore_fails($dut.pin(:tdo)) do
|
195
|
+
cc 'TDO should be X'
|
196
|
+
jtag.read_dr 0xFFFF, size: 16, msg: 'Read value out of DR'
|
197
|
+
end
|
198
|
+
cc 'TDO should be H'
|
199
|
+
jtag.read_dr 0xFFFF, size: 16, msg: 'Read value out of DR'
|
192
200
|
end
|
data/templates/web/index.md.erb
CHANGED
@@ -82,14 +82,24 @@ These accept either an absolute data value or an Origen register/bit collection.
|
|
82
82
|
|
83
83
|
~~~ruby
|
84
84
|
jtag.write_dr 0x1234, :size => 16
|
85
|
+
|
85
86
|
# The size option is not required when a register is supplied
|
86
87
|
jtag.write_dr $dut.reg(:clkdiv)
|
88
|
+
|
87
89
|
# Although it can still be added if the register is not the full data width
|
88
90
|
jtag.write_dr $dut.reg(:clkdiv), :size => 32
|
89
|
-
|
90
|
-
# overlay operations
|
91
|
+
|
92
|
+
# A rich read method is available which supports bit-level read, store and overlay operations
|
91
93
|
$dut.reg(:clkdiv).bits(:div).read(0x55)
|
92
94
|
jtag.read $dut.reg(:clkdiv)
|
95
|
+
|
96
|
+
# In cases where both shift in (TDI) and shift out data (TDO) are critical, (e.g. compare shift
|
97
|
+
# out data on a write, or shfit in specific data on a read) the shift_in_data and
|
98
|
+
# shift_out_data options can be specified. By default, TDO will be dont care on writes
|
99
|
+
# and TDI will be 0 on reads.
|
100
|
+
jtag.write_dr $dut.reg(:clkdiv), :shift_out_data => 0x4321
|
101
|
+
jtag.read_dr $udt.reg(:clkdiv), :shift_in_data => 0x5678
|
102
|
+
|
93
103
|
# Similar methods exist for the instruction register
|
94
104
|
jtag.write_ir 0x1F, :size => 5
|
95
105
|
jtag.read_ir 0x1F, :size => 5
|
metadata
CHANGED
@@ -1,19 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: origen_jtag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen McGinty
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-03-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: origen
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.7'
|
17
20
|
- - ">="
|
18
21
|
- !ruby/object:Gem::Version
|
19
22
|
version: 0.7.35
|
@@ -21,6 +24,9 @@ dependencies:
|
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.7'
|
24
30
|
- - ">="
|
25
31
|
- !ruby/object:Gem::Version
|
26
32
|
version: 0.7.35
|
@@ -32,15 +38,14 @@ extensions: []
|
|
32
38
|
extra_rdoc_files: []
|
33
39
|
files:
|
34
40
|
- config/application.rb
|
41
|
+
- config/boot.rb
|
35
42
|
- config/commands.rb
|
36
43
|
- config/development.rb
|
37
|
-
- config/environment.rb
|
38
|
-
- config/users.rb
|
39
44
|
- config/version.rb
|
40
45
|
- lib/origen_jtag.rb
|
41
46
|
- lib/origen_jtag/driver.rb
|
42
|
-
- lib/origen_jtag/dut.rb
|
43
47
|
- lib/origen_jtag/tap_controller.rb
|
48
|
+
- lib/origen_jtag_dev/top_level.rb
|
44
49
|
- pattern/jtag_workout.rb
|
45
50
|
- templates/web/index.md.erb
|
46
51
|
- templates/web/layouts/_basic.html.erb
|
data/config/environment.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require "origen_jtag"
|
data/config/users.rb
DELETED
@@ -1,19 +0,0 @@
|
|
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
|