origen_nexus 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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
@@ -0,0 +1,8 @@
1
+ module OrigenNexus
2
+ MAJOR = 0
3
+ MINOR = 8
4
+ BUGFIX = 0
5
+ DEV = nil
6
+
7
+ VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
8
+ end
@@ -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