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 +7 -0
- data/config/application.rb +64 -0
- data/config/commands.rb +90 -0
- data/config/development.rb +15 -0
- data/config/environment.rb +1 -0
- data/config/users.rb +19 -0
- data/config/version.rb +8 -0
- data/lib/origen_jtag/driver.rb +449 -0
- data/lib/origen_jtag/dut.rb +64 -0
- data/lib/origen_jtag/tap_controller.rb +299 -0
- data/lib/origen_jtag.rb +13 -0
- data/pattern/jtag_workout.rb +184 -0
- data/templates/web/index.md.erb +139 -0
- data/templates/web/layouts/_basic.html.erb +13 -0
- data/templates/web/partials/_navbar.html.erb +22 -0
- data/templates/web/release_notes.md.erb +5 -0
- metadata +73 -0
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
|
data/config/commands.rb
ADDED
@@ -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,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
|