origen_nexus 0.8.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 +142 -0
- data/config/commands.rb +84 -0
- data/config/development.rb +16 -0
- data/config/environment.rb +32 -0
- data/config/version.rb +8 -0
- data/lib/origen_nexus.rb +11 -0
- data/lib/origen_nexus/driver.rb +545 -0
- data/lib/origen_nexus/dut.rb +85 -0
- data/pattern/read_write_block.rb +23 -0
- data/pattern/read_write_block_64bit.rb +28 -0
- data/pattern/read_write_reg.rb +63 -0
- data/pattern/subroutines.rb +30 -0
- data/templates/web/index.md.erb +173 -0
- data/templates/web/layouts/_basic.html.erb +15 -0
- data/templates/web/partials/_navbar.html.erb +22 -0
- data/templates/web/release_notes.md.erb +5 -0
- metadata +116 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8323c85ced94499f4122de4119d8cdb4e536e126
|
4
|
+
data.tar.gz: 7b47b5560e5e2d9c9e2617bcbfd5325a0436aee5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1fc4e22ebc9a4a6c0a8d90dbc57d808547f9abe201b89d9164a19b98de008e4679ace64e3d2847be1499294c943dc44cec5f7625faaaff98768c1e15e1a93185
|
7
|
+
data.tar.gz: 0fb88e1c99f27eab4974543b663f20e9f60476a3822e482ba54836a3688c3768173c881b4fc95197506a5aec745eacf2b4ef986a7053f34fff8d0a578be79ff5
|
@@ -0,0 +1,142 @@
|
|
1
|
+
class OrigenNexusApplication < 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 Nexus"
|
10
|
+
config.initials = "OrigenNexus"
|
11
|
+
config.rc_url = "git@github.com:Origen-SDK/origen_nexus.git"
|
12
|
+
config.release_externally = true
|
13
|
+
|
14
|
+
config.web_directory = "git@github.com:Origen-SDK/Origen-SDK.github.io.git/nexus"
|
15
|
+
config.web_domain = "http://origen-sdk.org/nexus"
|
16
|
+
|
17
|
+
# You can map moo numbers to targets here, this allows targets to be selected via
|
18
|
+
# origen t <moo>
|
19
|
+
#config.production_targets = {
|
20
|
+
# "1m79x" => "production",
|
21
|
+
#}
|
22
|
+
|
23
|
+
# Set up lint test
|
24
|
+
config.lint_test = {
|
25
|
+
# Require the lint tests to pass before allowing a release to proceed
|
26
|
+
:run_on_tag => true,
|
27
|
+
# Auto correct violations where possible whenever 'origen lint' is run
|
28
|
+
:auto_correct => true,
|
29
|
+
# Limit the testing for large legacy applications
|
30
|
+
#:level => :easy,
|
31
|
+
# Run on these directories/files by default
|
32
|
+
#:files => ["lib", "config/application.rb"],
|
33
|
+
}
|
34
|
+
|
35
|
+
# Versioning is based on a timestamp by default, if you would rather use semantic
|
36
|
+
# versioning, i.e. v1.0.0 format, then set this to true.
|
37
|
+
# In parallel go and edit config/version.rb to enable the semantic version code.
|
38
|
+
config.semantically_version = true
|
39
|
+
|
40
|
+
# An example of how to set application specific LSF parameters
|
41
|
+
#config.lsf.project = "msg.te"
|
42
|
+
|
43
|
+
# An exmaple of how to specify a prefix to add to all generated patterns
|
44
|
+
#config.pattern_prefix = "nvm"
|
45
|
+
|
46
|
+
# An example of how to add header comments to all generated patterns
|
47
|
+
#config.pattern_header do
|
48
|
+
# cc "This is a pattern created by the example origen application"
|
49
|
+
#end
|
50
|
+
|
51
|
+
# By default all generated output will end up in ./output.
|
52
|
+
# Here you can specify an alternative directory entirely, or make it dynamic such that
|
53
|
+
# the output ends up in a setup specific directory.
|
54
|
+
#config.output_directory do
|
55
|
+
# "#{Origen.root}/output/#{$dut.class}"
|
56
|
+
#end
|
57
|
+
|
58
|
+
# Similary for the reference files, generally you want to setup the reference directory
|
59
|
+
# structure to mirror that of your output directory structure.
|
60
|
+
#config.reference_directory do
|
61
|
+
# "#{Origen.root}/.ref/#{$dut.class}"
|
62
|
+
#end
|
63
|
+
|
64
|
+
# Run code coverage when deploying the web site
|
65
|
+
def before_deploy_site
|
66
|
+
Dir.chdir Origen.root do
|
67
|
+
system "origen examples -c"
|
68
|
+
system "origen specs -c"
|
69
|
+
dir = "#{Origen.root}/web/output/coverage"
|
70
|
+
FileUtils.remove_dir(dir, true) if File.exists?(dir)
|
71
|
+
system "mv #{Origen.root}/coverage #{dir}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# To automatically deploy your documentation after every tag use this code
|
76
|
+
def after_release_email(tag, note, type, selector, options)
|
77
|
+
command = "origen web compile --remote --api"
|
78
|
+
Dir.chdir Origen.root do
|
79
|
+
system command
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
=begin
|
84
|
+
# To enabled source-less pattern generation create a class (for example PatternDispatcher)
|
85
|
+
# to generate the pattern. This should return false if the requested pattern has been
|
86
|
+
# dispatched, otherwise Origen will proceed with looking up a pattern source as normal.
|
87
|
+
#def before_pattern_lookup(requested_pattern)
|
88
|
+
# PatternDispatcher.new.dispatch_or_return(requested_pattern)
|
89
|
+
#end
|
90
|
+
|
91
|
+
# If you use pattern iterators you may come accross the case where you request a pattern
|
92
|
+
# like this:
|
93
|
+
# origen g example_pat_b0.atp
|
94
|
+
#
|
95
|
+
# However it cannot be found by Origen since the pattern name is actually example_pat_bx.atp
|
96
|
+
# In the case where the pattern cannot be found Origen will pass the name to this translator
|
97
|
+
# if it exists, and here you can make any substitutions to help Origen find the file you
|
98
|
+
# want. In this example any instances of _b\d, where \d means a number, are replaced by
|
99
|
+
# _bx.
|
100
|
+
#config.pattern_name_translator do |name|
|
101
|
+
# name.gsub(/_b\d/, "_bx")
|
102
|
+
#end
|
103
|
+
|
104
|
+
# If you want to use pattern iterators, that is the ability to generate multiple pattern
|
105
|
+
# variants from a single source file, then you can define the required behavior here.
|
106
|
+
# The examples below implement some of the iterators that were available in Origen 1,
|
107
|
+
# you can remove them if you don't want to use them, or of course modify or add new
|
108
|
+
# iterators specific to your application logic.
|
109
|
+
|
110
|
+
# By setting iterator
|
111
|
+
config.pattern_iterator do |iterator|
|
112
|
+
# Define a key that you will use to enable this in a pattern, here the iterator
|
113
|
+
# can be enabled like this: Pattern.create(:by_setting => [1,2,3]) do
|
114
|
+
iterator.key = :by_setting
|
115
|
+
|
116
|
+
# The value passed from the pattern via the key comes in here as the first
|
117
|
+
# argument, the name applied here can be anything, but settings seem reasonable since
|
118
|
+
# an array of setting values is expected.
|
119
|
+
# The last argument &pattern is mandatory and represents the pattern block (the bit contained
|
120
|
+
# within Pattern.create do ... end)
|
121
|
+
iterator.loop do |settings, &pattern|
|
122
|
+
# Implement the loop however you like, here we loop for each value in the array
|
123
|
+
settings.each do |setting|
|
124
|
+
# Now call the pattern passing in the setting argument, this would be captured
|
125
|
+
# in the pattern like this:
|
126
|
+
# Pattern.create do |setting|
|
127
|
+
pattern.call(setting)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Each pattern iteration needs a unique name, otherwise Origen will simply overwrite
|
132
|
+
# the same output file each time.
|
133
|
+
# The base pattern name and the pattern argument, in this case the setting, will be
|
134
|
+
# passed in here and whatever is returned is what will be used as the name.
|
135
|
+
iterator.pattern_name do |name, setting|
|
136
|
+
# Substitute _x in the name with the setting, _1, _2, etc.
|
137
|
+
name.gsub("_x", "_#{setting}")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
=end
|
141
|
+
|
142
|
+
end
|
data/config/commands.rb
ADDED
@@ -0,0 +1,84 @@
|
|
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
|
+
# Now branch to the specific task code
|
21
|
+
case @command
|
22
|
+
|
23
|
+
# Here is an example of how to implement a command, the logic can go straight
|
24
|
+
# in here or you can require an external file if preferred.
|
25
|
+
#when "execute"
|
26
|
+
# puts "Executing something..."
|
27
|
+
# require "commands/execute" # Would load file lib/commands/execute.rb
|
28
|
+
# # You must always exit upon successfully capturing a command to prevent
|
29
|
+
# # control flowing back to Origen
|
30
|
+
# e it 0
|
31
|
+
when "specs"
|
32
|
+
require "rspec"
|
33
|
+
exit RSpec::Core::Runner.run(['spec'])
|
34
|
+
|
35
|
+
when "examples", "test"
|
36
|
+
Origen.load_application
|
37
|
+
status = 0
|
38
|
+
|
39
|
+
# Pattern generator tests
|
40
|
+
# (btw, %w() is ruby shorthand for making an array of strings)
|
41
|
+
ARGV = %w(regression.list -t debug_RH1 -r approved)
|
42
|
+
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
43
|
+
ARGV = %w(regression.list -t debug_RL1 -r approved)
|
44
|
+
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
45
|
+
ARGV = %w(regression.list -t debug_RH4 -r approved)
|
46
|
+
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
47
|
+
ARGV = %w(regression.list -t debug_RL4 -r approved)
|
48
|
+
load "#{Origen.top}/lib/origen/commands/generate.rb"
|
49
|
+
|
50
|
+
# check if nothing changed or nothing added
|
51
|
+
if Origen.app.stats.changed_files == 0 &&
|
52
|
+
Origen.app.stats.new_files == 0 &&
|
53
|
+
Origen.app.stats.changed_patterns == 0 &&
|
54
|
+
Origen.app.stats.new_patterns == 0
|
55
|
+
|
56
|
+
# report examples having passed
|
57
|
+
Origen.app.stats.report_pass
|
58
|
+
else
|
59
|
+
# report examples having failed
|
60
|
+
Origen.app.stats.report_fail
|
61
|
+
status = 1
|
62
|
+
end
|
63
|
+
puts
|
64
|
+
if @command == "test"
|
65
|
+
Origen.app.unload_target!
|
66
|
+
require "rspec"
|
67
|
+
result = RSpec::Core::Runner.run(['spec'])
|
68
|
+
status = status == 1 ? 1 : result
|
69
|
+
end
|
70
|
+
exit status
|
71
|
+
|
72
|
+
# Always leave an else clause to allow control to fall back through to the
|
73
|
+
# Origen command handler.
|
74
|
+
# You probably want to also add the command details to the help shown via
|
75
|
+
# origen -h, you can do this be assigning the required text to @application_commands
|
76
|
+
# before handing control back to Origen. Un-comment the example below to get started.
|
77
|
+
else
|
78
|
+
@application_commands = <<-EOT
|
79
|
+
specs Run the specs (tests), -c will enable coverage
|
80
|
+
examples Run the examples (tests), -c will enable coverage
|
81
|
+
test Run both specs and examples, -c will enable coverage
|
82
|
+
EOT
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,16 @@
|
|
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 OrigenNexus
|
14
|
+
autoload :DUT, "origen_nexus/dut"
|
15
|
+
autoload :DUTWithJTAG, "origen_nexus/dut"
|
16
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# This file will be required by Origen before your target is loaded, you
|
2
|
+
# can use this to require all of your files, which is the easiest way
|
3
|
+
# to get started. As your experience grows you may wish to require only the
|
4
|
+
# minimum files required to allow the target to be initialized and let
|
5
|
+
# each class require its own dependencies.
|
6
|
+
#
|
7
|
+
# It is recommended that you keep all of your application logic in lib/
|
8
|
+
# The lib directory has already been added to the search path and so any files
|
9
|
+
# in there can be referenced from here with a relative path.
|
10
|
+
#
|
11
|
+
# Note that pattern files do not need to be referenced from here and these
|
12
|
+
# will be located automatically by origen.
|
13
|
+
|
14
|
+
# This says load the file "lib/pioneer.rb" the first time anyone makes a
|
15
|
+
# reference to the class name 'Pioneer'.
|
16
|
+
#autoload :Pioneer, "pioneer"
|
17
|
+
# This is generally preferable to using require which will load the file
|
18
|
+
# regardless of whether it is needed by the current target or not:
|
19
|
+
#require "pioneer"
|
20
|
+
# Sometimes you have to use require however:-
|
21
|
+
# 1. When defining a test program interface:
|
22
|
+
#require "interfaces/j750"
|
23
|
+
# 2. If you want to extend a class defined by an imported application, in
|
24
|
+
# this case your must use required and supply a full path (to distinguish
|
25
|
+
# it from the one in the parent application):
|
26
|
+
#require "#{Origen.root}/c90_top_level/p2"
|
27
|
+
|
28
|
+
require 'origen_nexus'
|
29
|
+
module OrigenNexus
|
30
|
+
autoload :Driver, 'origen_nexus/driver'
|
31
|
+
end
|
32
|
+
|
data/config/version.rb
ADDED
data/lib/origen_nexus.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'origen'
|
2
|
+
require_relative '../config/application.rb'
|
3
|
+
require_relative '../config/environment.rb'
|
4
|
+
require 'origen_jtag' # required for runtime dep gems
|
5
|
+
|
6
|
+
module OrigenNexus
|
7
|
+
# Returns an instance of the Nexus::Driver
|
8
|
+
def nexus
|
9
|
+
@nexus ||= Driver.new(self)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,545 @@
|
|
1
|
+
module OrigenNexus
|
2
|
+
class Driver
|
3
|
+
# Include JTAG driver instance to fall back on (if owner doesn't have)
|
4
|
+
include OrigenJTAG
|
5
|
+
|
6
|
+
# Allow for JTAG optionality
|
7
|
+
# blank for now
|
8
|
+
JTAG_CONFIG = {}
|
9
|
+
|
10
|
+
# Include registers as Nexus has its own registers
|
11
|
+
include Origen::Registers
|
12
|
+
|
13
|
+
alias_method :local_jtag, :jtag
|
14
|
+
|
15
|
+
# Returns the underlying JTAG driver. If the owner has its own JTAG driver
|
16
|
+
# then this will be returned, otherwise it will be a fall back driver included
|
17
|
+
# by the Nexus module.
|
18
|
+
def jtag
|
19
|
+
owner.respond_to?(:jtag) ? owner.jtag : local_jtag
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the object that included the Nexus module,
|
23
|
+
# should always be the top-level model
|
24
|
+
attr_reader :owner
|
25
|
+
|
26
|
+
# OnCE Command Register (OCMD) width in bits
|
27
|
+
# OnCE (On-Chip Emulation)
|
28
|
+
attr_reader :once_ocmd_width
|
29
|
+
|
30
|
+
# The OnCE Nexus access instruction (NEXUS-ACCESS)
|
31
|
+
# OnCE command value to enable Nexus
|
32
|
+
attr_reader :once_nexus_access_instr
|
33
|
+
|
34
|
+
# The OnCE bypass instruction (BYPASS)
|
35
|
+
# OnCE command value to bypass OnCE
|
36
|
+
attr_reader :once_bypass_instr
|
37
|
+
|
38
|
+
# Nexus command width
|
39
|
+
# width of commands used in first DR pass to read/write
|
40
|
+
# a Nexus register
|
41
|
+
attr_reader :nexus_command_width
|
42
|
+
|
43
|
+
attr_reader :cpuscr_reg_width
|
44
|
+
|
45
|
+
attr_reader :once_cpuscr_go_exit_instr
|
46
|
+
|
47
|
+
def initialize(owner, options = {})
|
48
|
+
if defined?(owner.class::NEXUS_CONFIG)
|
49
|
+
options = owner.class::NEXUS_CONFIG.merge(options)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Fallback defaults
|
53
|
+
options = {
|
54
|
+
tclk_format: :rh, # format of JTAG clock used: ReturnHigh (:rh), ReturnLo (:rl)
|
55
|
+
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.
|
56
|
+
# e.g. @tclk_multiple = 2, @tclk_format = :rh, means one cycle with Tck low (non-return), one with Tck high (NR)
|
57
|
+
# @tclk_multiple = 4, @tclk_format = :rl, means 2 cycles with Tck high (NR), 2 with Tck low (NR)
|
58
|
+
tdo_strobe: :tclk_high, # when using multiple cycles for TCK, which state of TCK to strobe for TDO, :tclk_high or :tclk_low or :tclk_all
|
59
|
+
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.)
|
60
|
+
#
|
61
|
+
once_ocmd_width: 10, # Width of OnCE OCMD instruction reg in bits
|
62
|
+
once_nexus_access_instr: 0b0001111100, # Instruction used to access nexus via OnCE, default: 0x07C.
|
63
|
+
once_bypass_instr: 0b0001111111, # Instruction used to bypass OnCE, default: 0x07F.
|
64
|
+
once_cpuscr_go_exit_instr: 0b0110010000, # Instruction used to exit debug mode and kick off code execution from desired address.
|
65
|
+
nexus_command_width: 8, # Width of Nexus command data regs, default: 8.
|
66
|
+
cpuscr_reg_width: 192, # Width of cpuscr reg
|
67
|
+
}.merge(options)
|
68
|
+
|
69
|
+
# Define JTAG configs based on Nexus config
|
70
|
+
JTAG_CONFIG[:tclk_format] = options[:tclk_format]
|
71
|
+
JTAG_CONFIG[:tclk_multiple] = options[:tclk_multiple]
|
72
|
+
JTAG_CONFIG[:tdo_strobe] = options[:tdo_strobe]
|
73
|
+
JTAG_CONFIG[:tdo_store_cycle] = options[:tdo_store_cycle]
|
74
|
+
|
75
|
+
@once_ocmd_width = options[:once_ocmd_width]
|
76
|
+
@once_nexus_access_instr = options[:once_nexus_access_instr]
|
77
|
+
@once_bypass_instr = options[:once_bypass_instr]
|
78
|
+
@once_cpuscr_go_exit_instr = options[:once_cpuscr_go_exit_instr]
|
79
|
+
@nexus_command_width = options[:nexus_command_width]
|
80
|
+
@cpuscr_reg_width = options[:cpuscr_reg_width]
|
81
|
+
|
82
|
+
# Define nexus registers
|
83
|
+
define_nexus_registers
|
84
|
+
|
85
|
+
# Define CPU registers
|
86
|
+
define_cpu_registers
|
87
|
+
|
88
|
+
@owner = owner
|
89
|
+
end
|
90
|
+
|
91
|
+
def on_created
|
92
|
+
end
|
93
|
+
|
94
|
+
# This proxies all pin requests from our local JTAG driver to
|
95
|
+
# our parent DUT model
|
96
|
+
def pin(*args)
|
97
|
+
owner.pin(*args)
|
98
|
+
end
|
99
|
+
alias_method :pins, :pin
|
100
|
+
|
101
|
+
# Define Nexus registers
|
102
|
+
# For now only those related to RWA will be defined.
|
103
|
+
# RWA (read/write access) provides DMA-like access to memory-mapped resources on
|
104
|
+
# the AHB system bus either while the processor is halted or during runtime.
|
105
|
+
def define_nexus_registers
|
106
|
+
# Each register has a Nexus Opcode, which we will use as 'address' below, and
|
107
|
+
# corresponding read addresses and write addresses
|
108
|
+
|
109
|
+
# RWCS - Read/Write Access Control Register
|
110
|
+
# read addr = 0x0E, write addr = 0x0F
|
111
|
+
reg :rwcs, 0x0E, size: 32 do
|
112
|
+
bit 31, :ac
|
113
|
+
bit 30, :rw
|
114
|
+
bit 29..27, :sz
|
115
|
+
bit 26..24, :map
|
116
|
+
bit 23..22, :pr
|
117
|
+
bit 15..2, :cnt
|
118
|
+
bit 1, :err, writable: false
|
119
|
+
bit 0, :dv, writable: false
|
120
|
+
end
|
121
|
+
|
122
|
+
# RWD - Read/Write Access Data
|
123
|
+
# read addr = 0x12, write addr = 0x13
|
124
|
+
reg :rwa, 0x12, size: 32 do
|
125
|
+
bit 31..0, :addr
|
126
|
+
end
|
127
|
+
|
128
|
+
# RWD - Read/Write Access Data
|
129
|
+
# read addr = 0x14, write addr = 0x15
|
130
|
+
reg :rwd, 0x14, size: 32 do
|
131
|
+
bit 31..0, :data
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def define_cpu_registers
|
136
|
+
reg :cpuscr, 0x0, size: 192 do
|
137
|
+
bit 191..160, :ctl
|
138
|
+
bit 159..128, :ir
|
139
|
+
bit 127..96, :pc
|
140
|
+
bit 95..64, :msr
|
141
|
+
bit 63..32, :wbbrh
|
142
|
+
bit 31..0, :wbbrl
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Enable Nexus module
|
147
|
+
# Loads NEXUS-ACCESS instruction into JTAG Instruction
|
148
|
+
# Register (OnCE OCMD register).
|
149
|
+
# repeated calls will not generate vectors if the instruction
|
150
|
+
# is already loaded
|
151
|
+
#
|
152
|
+
# Optionally also accepts a block to allow temporary Nexus access
|
153
|
+
#
|
154
|
+
# nexus.enable_nexus_access do
|
155
|
+
# # Do something with nexus enabled
|
156
|
+
# end
|
157
|
+
# # Nexus access disabled
|
158
|
+
#
|
159
|
+
def enable_nexus_access
|
160
|
+
if @ir_reg_value != once_nexus_access_instr
|
161
|
+
jtag.write_ir once_nexus_access_instr, size: once_ocmd_width, msg: log2("Enable Nexus Access: OnCE_Send(#{once_ocmd_width}, 0x%02X)" % [once_nexus_access_instr])
|
162
|
+
@ir_reg_value = once_nexus_access_instr
|
163
|
+
end
|
164
|
+
if block_given?
|
165
|
+
yield
|
166
|
+
disable_once
|
167
|
+
end # whether to mark all bits in RWD for read
|
168
|
+
end
|
169
|
+
|
170
|
+
# Disable OnCE
|
171
|
+
def disable_once
|
172
|
+
if @ir_reg_value != once_bypass_instr
|
173
|
+
jtag.write_ir once_bypass_instr, size: once_ocmd_width, msg: log2("Bypass OnCE: OnCE_Send(#{once_ocmd_width}, 0x%02X)" % [once_bypass_instr])
|
174
|
+
@ir_reg_value = once_bypass_instr
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def go_exit(code_start_address = 0x4)
|
179
|
+
jtag.write_ir once_cpuscr_go_exit_instr, size: once_ocmd_width, msg: log2('Enabling CPUSCR register for read/write access')
|
180
|
+
regs(:cpuscr).bit(:wbbrl).write(0x00000000)
|
181
|
+
regs(:cpuscr).bit(:wbbrh).write(0x00000000)
|
182
|
+
regs(:cpuscr).bit(:msr).write(0x00000000)
|
183
|
+
regs(:cpuscr).bit(:pc).write(code_start_address - 4)
|
184
|
+
regs(:cpuscr).bit(:ir).write(0x7c0004ac)
|
185
|
+
regs(:cpuscr).bit(:ctl).write(0x00000000)
|
186
|
+
jtag.write_dr regs(:cpuscr).value, size: cpuscr_reg_width, msg: log2('Writing GO+EXIT to CPUSCR')
|
187
|
+
end
|
188
|
+
|
189
|
+
# Write a given Nexus register
|
190
|
+
def write_nexus_register(reg_or_val, options = {})
|
191
|
+
options = { write: true, # whether to write or read
|
192
|
+
overlay: false,
|
193
|
+
care_out: false
|
194
|
+
}.merge(options)
|
195
|
+
addr = exact_address(reg_or_val, options)
|
196
|
+
addr += 1 if options[:write] # offset address by 1 since writing
|
197
|
+
data = exact_data(reg_or_val, options)
|
198
|
+
size = exact_size(reg_or_val, options)
|
199
|
+
name = exact_name(reg_or_val, options)
|
200
|
+
|
201
|
+
if options[:write]
|
202
|
+
log "Write Nexus Reg: #{name.upcase} at 0x%04X with 0x%08X" % [addr, data]
|
203
|
+
else
|
204
|
+
log "Read Nexus Reg: #{name.upcase} at 0x%04X with 0x%08X" % [addr, data]
|
205
|
+
end
|
206
|
+
|
207
|
+
# first pass : select register via nexus command
|
208
|
+
jtag.write_dr addr, size: nexus_command_width, msg: log2("OnCE_Send(#{nexus_command_width}, 0x%02X)" % [addr])
|
209
|
+
if options[:overlay] == true
|
210
|
+
# if we want to overlay expect values, then
|
211
|
+
# put dummy data in vectors to force them to be uncompressable by pattern generator.
|
212
|
+
reg_or_val.data = 0x55555555
|
213
|
+
data = exact_data(reg_or_val, options)
|
214
|
+
end
|
215
|
+
|
216
|
+
if options[:capture]
|
217
|
+
reg(reg_or_val.name).store
|
218
|
+
end
|
219
|
+
|
220
|
+
if options[:write]
|
221
|
+
# second pass : pass data to register
|
222
|
+
jtag.write_dr reg_or_val, overlay: options[:overlay], overlay_label: options[:overlay_label], size: size, msg: log2("OnCE_Send(#{size}, 0x%08X)" % [data])
|
223
|
+
else
|
224
|
+
if options[:care_output]
|
225
|
+
reg(reg_or_val.name).read
|
226
|
+
end
|
227
|
+
# second pass : read data from register
|
228
|
+
jtag.read_dr(reg_or_val, overlay: options[:overlay], overlay_label: options[:overlay_label], size: size, msg: log2("OnCE_Read(#{size}, 0x%08X)" % [data]))
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
# Read a given Nexus register
|
233
|
+
def read_nexus_register(reg_or_val, options = {})
|
234
|
+
write_nexus_register(reg_or_val, options.merge(write: false))
|
235
|
+
end
|
236
|
+
|
237
|
+
# Write data cycles only for a Register
|
238
|
+
# Used if only want data cycles for overlay subroutines
|
239
|
+
def write_data_only(reg_or_val, options = {})
|
240
|
+
options = { write: true, # whether to write or read
|
241
|
+
}.merge(options)
|
242
|
+
|
243
|
+
data = exact_data(reg_or_val, options)
|
244
|
+
|
245
|
+
# Size of RWD register being used for output
|
246
|
+
size = reg(:rwd).size
|
247
|
+
|
248
|
+
# if reading a real register then need to handle copying over all data and flags
|
249
|
+
# undefined regs will be handled in lower function so that default is to treat
|
250
|
+
# as undefined reg (just simple accesses)
|
251
|
+
reg(:rwd).overlay(nil) # clear overlay flags if there, as sticky
|
252
|
+
if real_reg?(reg_or_val)
|
253
|
+
reg(:rwd).copy_all(reg_or_val)
|
254
|
+
end
|
255
|
+
|
256
|
+
if options[:write]
|
257
|
+
# Send command to write RWD reg
|
258
|
+
# Send data value to be written to RWD reg
|
259
|
+
reg(:rwd).write(data)
|
260
|
+
|
261
|
+
jtag.shift(reg(:rwd), options.merge(size: size, cycle_last: true, includes_last_bit: true))
|
262
|
+
|
263
|
+
else
|
264
|
+
# Mark all bits for read
|
265
|
+
reg(:rwd).read
|
266
|
+
|
267
|
+
jtag.shift(reg(:rwd), options.merge(size: size, read: true, cycle_last: true, includes_last_bit: true))
|
268
|
+
|
269
|
+
end
|
270
|
+
|
271
|
+
# Clear flags so as to not affect subsequent reg reads/writes
|
272
|
+
reg(:rwd).clear_flags
|
273
|
+
reg_or_val.clear_flags if reg_or_val.respond_to?(:clear_flags)
|
274
|
+
end
|
275
|
+
|
276
|
+
# Read data cycles only for RWD Register
|
277
|
+
def read_data_only(reg_or_val, options = {})
|
278
|
+
write_data_only(reg_or_val, options.merge(write: false))
|
279
|
+
end
|
280
|
+
|
281
|
+
# Single Write to memory-mapped resource
|
282
|
+
# for now only supports 32-bit data
|
283
|
+
def single_write_access(address, data, options = {})
|
284
|
+
options = { write: true, # whether to write or read the register
|
285
|
+
undef: true, # whether IPS being accessed is a register or undefined
|
286
|
+
count: 1, # by default use single address access mode
|
287
|
+
overlay: false, # default: assume not a real register
|
288
|
+
nexus_init: true,
|
289
|
+
width: 32, # default write width to 32 bits
|
290
|
+
}.merge(options)
|
291
|
+
if options[:width] == 8
|
292
|
+
write_width = 0b0
|
293
|
+
elsif options[:width] == 16
|
294
|
+
write_width = 0b1
|
295
|
+
elsif options[:width] == 32
|
296
|
+
write_width = 0b10
|
297
|
+
elsif options[:width] == 64
|
298
|
+
write_width = 0b11
|
299
|
+
else
|
300
|
+
Origen.log.warn 'Nexus 3 width supplied is invalid, defaulting to 32 bit width.'
|
301
|
+
end
|
302
|
+
|
303
|
+
if options[:nexus_init]
|
304
|
+
enable_nexus_access
|
305
|
+
end
|
306
|
+
# Send command to write RWA reg
|
307
|
+
# Send address value to RWA reg
|
308
|
+
reg(:rwa).write(address)
|
309
|
+
write_nexus_register(reg(:rwa))
|
310
|
+
|
311
|
+
# Send command to write RWCS reg
|
312
|
+
# Send settings to RWCS
|
313
|
+
reg(:rwcs).bits(:ac).write(1)
|
314
|
+
reg(:rwcs).bits(:rw).write(options[:write] ? 1 : 0)
|
315
|
+
reg(:rwcs).bits(:sz).write(write_width) # write_width, defaul value = 32 bits.
|
316
|
+
reg(:rwcs).bits(:map).write(0b000) # map select = primary
|
317
|
+
reg(:rwcs).bits(:pr).write(0b11) # priority = highest
|
318
|
+
reg(:rwcs).bits(:cnt).write(options[:count]) # single access
|
319
|
+
reg(:rwcs).bits(:err).write(0) # read/write access error
|
320
|
+
reg(:rwcs).bits(:dv).write(0) # read/write access data valid
|
321
|
+
write_nexus_register(reg(:rwcs))
|
322
|
+
|
323
|
+
if options[:write]
|
324
|
+
# Send command to write RWD reg
|
325
|
+
# Send data value to be written to RWD reg
|
326
|
+
reg(:rwd).write(data)
|
327
|
+
write_nexus_register(reg(:rwd), options.reject { |x| x == :address })
|
328
|
+
else
|
329
|
+
# If undefined reg, then mark all bits for read
|
330
|
+
if options[:undef]
|
331
|
+
reg(:rwd).read
|
332
|
+
end
|
333
|
+
# Send command to read RWD reg
|
334
|
+
# Read RWD reg value
|
335
|
+
reg(:rwd).write(data)
|
336
|
+
read_nexus_register(reg(:rwd), options.reject { |x| x == :address })
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
# Single Read from memory-mapped resource
|
341
|
+
# for now only supports 32-bit data
|
342
|
+
def single_read_access(address, data, options = {})
|
343
|
+
single_write_access(address, data, options.merge(write: false))
|
344
|
+
end
|
345
|
+
|
346
|
+
# Block Write to memory-mapped resources
|
347
|
+
# for now only supports 32-bit data
|
348
|
+
#
|
349
|
+
# address = address at start of block
|
350
|
+
# block_data = array of 32-bit values of block data to write
|
351
|
+
def block_write_access(address, block_data = [], options = {})
|
352
|
+
options = { write: true, # whether to write or read the block
|
353
|
+
width: 32 # width default to 32 bits
|
354
|
+
}.merge(options)
|
355
|
+
block_data.each_index do |i|
|
356
|
+
if i == 0 # first do single write access with count > 1
|
357
|
+
single_write_access(address, block_data[0], options.merge(count: block_data.count))
|
358
|
+
if options[:width] > 32
|
359
|
+
reg(:rwd).write(block_data[i = i + 1])
|
360
|
+
if options[:write]
|
361
|
+
write_nexus_register(reg(:rwd), options)
|
362
|
+
else
|
363
|
+
read_nexus_register(reg(:rwd), options)
|
364
|
+
end
|
365
|
+
end
|
366
|
+
else
|
367
|
+
next if i.odd? && options[:width] > 32
|
368
|
+
reg(:rwd).write(block_data[i])
|
369
|
+
if options[:write]
|
370
|
+
write_nexus_register(reg(:rwd), options)
|
371
|
+
else
|
372
|
+
read_nexus_register(reg(:rwd), options)
|
373
|
+
end
|
374
|
+
if options[:width] > 32
|
375
|
+
reg(:rwd).write(block_data[i = i + 1])
|
376
|
+
if options[:write]
|
377
|
+
write_nexus_register(reg(:rwd), options)
|
378
|
+
else
|
379
|
+
read_nexus_register(reg(:rwd), options)
|
380
|
+
end
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
# Block Read of memory-mapped resources
|
387
|
+
# for now only supports 32-bit data
|
388
|
+
#
|
389
|
+
# address = address at start of block
|
390
|
+
# block_data = array of 32-bit values of block data to read
|
391
|
+
def block_read_access(address, block_data = [], options = {})
|
392
|
+
block_write_access(address, block_data, options.merge(write: false))
|
393
|
+
end
|
394
|
+
|
395
|
+
# def test_read_flag(reg_to_check)
|
396
|
+
# reg_to_check.size.times do |i|
|
397
|
+
# if reg_to_check.bit(i).is_to_be_read?
|
398
|
+
# print "\t\tBIT #{i} of #{reg_to_check.name.upcase} has read flag!\n"
|
399
|
+
# else
|
400
|
+
# print "\t\tBIT #{i} of #{reg_to_check.name.upcase} DOES NOT HAVE read flag!\n"
|
401
|
+
# end
|
402
|
+
# end
|
403
|
+
# end
|
404
|
+
#
|
405
|
+
# def test_store_flag(reg_to_check)
|
406
|
+
# reg_to_check.size.times do |i|
|
407
|
+
# if reg_to_check.bit(i).is_to_be_stored?
|
408
|
+
# print "\t\tBIT #{i} of #{reg_to_check.name.upcase} has store flag!\n"
|
409
|
+
# else
|
410
|
+
# print "\t\tBIT #{i} of #{reg_to_check.name.upcase} DOES NOT HAVE store flag!\n"
|
411
|
+
# end
|
412
|
+
# end
|
413
|
+
# end
|
414
|
+
#
|
415
|
+
# def test_overlay_flag(reg_to_check, options={})
|
416
|
+
# options={:msg => ""}.merge(options)
|
417
|
+
# reg_to_check.size.times do |i|
|
418
|
+
# if reg_to_check.bit(i).has_overlay?
|
419
|
+
# print "\t\t#{options[:msg]}: BIT #{i} of #{reg_to_check.name.upcase} has overlay flag!\n"
|
420
|
+
# else
|
421
|
+
# print "\t\t#{options[:msg]}: BIT #{i} of #{reg_to_check.name.upcase} DOES NOT HAVE overlay flag!\n"
|
422
|
+
# end
|
423
|
+
# end
|
424
|
+
|
425
|
+
# determines whether real register or not
|
426
|
+
def real_reg?(reg_or_val)
|
427
|
+
reg_or_val.respond_to?(:name)
|
428
|
+
end
|
429
|
+
|
430
|
+
# Write the given register (or system memory location) or given value to a specified address
|
431
|
+
# reg_or_val := register symbol to use -- assumes register preloaded with
|
432
|
+
# required data to use, can override by using :address option
|
433
|
+
# in which case data to use provided here
|
434
|
+
#
|
435
|
+
# options[:address] := address to write to. This is mandatory in the case of the
|
436
|
+
# reg_or_val argument being a value (for data), if it is a
|
437
|
+
# Register object then this is optional and if present then
|
438
|
+
# will override the register's address.
|
439
|
+
#
|
440
|
+
def write_register(reg_or_val, options = {})
|
441
|
+
options = { write: true, # whether to write or read the register
|
442
|
+
overlay: false
|
443
|
+
}.merge(options)
|
444
|
+
address = exact_address(reg_or_val, options)
|
445
|
+
data = exact_data(reg_or_val, options)
|
446
|
+
size = exact_size(reg_or_val, options)
|
447
|
+
name = (exact_name(reg_or_val, options)).upcase
|
448
|
+
|
449
|
+
op = options[:write] ? 'Write' : 'Read'
|
450
|
+
|
451
|
+
# Set undefined register flag to override option for simple_write_access below
|
452
|
+
options[:undef] = !real_reg?(reg_or_val)
|
453
|
+
|
454
|
+
# if reading a real register then need to handle copying over all data and flags
|
455
|
+
# undefined regs will be handled in lower function so that default is to treat
|
456
|
+
# as undefined reg (just simple accesses)
|
457
|
+
reg(:rwd).overlay(nil) # clear overlay flags if there, as sticky
|
458
|
+
if real_reg?(reg_or_val)
|
459
|
+
reg(:rwd).copy_all(reg_or_val)
|
460
|
+
end
|
461
|
+
|
462
|
+
cc "**************************** NEXUS REGISTER #{op.upcase} BEGIN ****************************"
|
463
|
+
cc "- #{op} Register #{name}: addr: 0x%08X, data: 0x%08X\n" % [address, data]
|
464
|
+
single_write_access(address, data, options)
|
465
|
+
cc "**************************** NEXUS REGISTER #{op.upcase} END ****************************"
|
466
|
+
|
467
|
+
# Clear flags so as to not affect subsequent reg reads/writes
|
468
|
+
reg(:rwd).clear_flags
|
469
|
+
reg_or_val.clear_flags if reg_or_val.respond_to?(:clear_flags)
|
470
|
+
end
|
471
|
+
alias_method :write, :write_register
|
472
|
+
|
473
|
+
# Read the given register (or system memory location) or given value from a specified address
|
474
|
+
# reg_or_val := register symbol to use -- assumes register preloaded with
|
475
|
+
# required data to use, can override by using :address option
|
476
|
+
# in which case data to use provided here
|
477
|
+
#
|
478
|
+
# options[:address] := address to read from. This is mandatory in the case of the
|
479
|
+
# reg_or_val argument being a value (for data), if it is a
|
480
|
+
# Register object then this is optional and if present then
|
481
|
+
# will override the register's address.
|
482
|
+
#
|
483
|
+
def read_register(reg_or_val, options = {})
|
484
|
+
write_register(reg_or_val, options.merge(write: false))
|
485
|
+
end
|
486
|
+
alias_method :read, :read_register
|
487
|
+
|
488
|
+
# Provides exact address value either if a defined register is
|
489
|
+
# provided or if an address is provided
|
490
|
+
def exact_address(reg_or_val, options = {})
|
491
|
+
address = options[:addr] || options[:address]
|
492
|
+
unless address
|
493
|
+
# if no address provided as option then use register address
|
494
|
+
if real_reg?(reg_or_val) # if real register
|
495
|
+
address = reg_or_val.address # use register address
|
496
|
+
else
|
497
|
+
fail "An :address option must be supplied when not providing a register to Nexus!\n"
|
498
|
+
end
|
499
|
+
end
|
500
|
+
address
|
501
|
+
end
|
502
|
+
|
503
|
+
# Provides exact data value either if a defined register is
|
504
|
+
# provided or if an address is provided
|
505
|
+
def exact_data(reg_or_val, _options = {})
|
506
|
+
# if no data provided as option then use register data
|
507
|
+
if real_reg?(reg_or_val) # if real register
|
508
|
+
data = reg_or_val.data # use register value
|
509
|
+
else
|
510
|
+
data = reg_or_val # use reg_or_val passed as data
|
511
|
+
end
|
512
|
+
data
|
513
|
+
end
|
514
|
+
|
515
|
+
# Provide size of register if real register passed--
|
516
|
+
# otherwise indicate number of bits of data value
|
517
|
+
def exact_size(reg_or_val, _options = {})
|
518
|
+
if real_reg?(reg_or_val) # if real register
|
519
|
+
size = reg_or_val.size # use register size
|
520
|
+
else
|
521
|
+
size = reg_or_val.to_s(2).size # get number of bits in value
|
522
|
+
end
|
523
|
+
size
|
524
|
+
end
|
525
|
+
|
526
|
+
# Provide name of register, if real register passed
|
527
|
+
# otherwise given 'undef' as name
|
528
|
+
def exact_name(reg_or_val, _options = {})
|
529
|
+
if real_reg?(reg_or_val) # if real register
|
530
|
+
name = reg_or_val.name # use register name
|
531
|
+
else
|
532
|
+
name = 'undef' # undefined register
|
533
|
+
end
|
534
|
+
name
|
535
|
+
end
|
536
|
+
|
537
|
+
def log2(msg)
|
538
|
+
"Nexus::Driver - #{msg}"
|
539
|
+
end
|
540
|
+
|
541
|
+
def log(msg)
|
542
|
+
cc "#{log2(msg)}"
|
543
|
+
end
|
544
|
+
end
|
545
|
+
end
|