origen_jtag 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|