origen_arm_debug 0.10.1 → 1.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,304 +1,54 @@
1
+ require 'origen_arm_debug/mem_ap_controller'
1
2
  module OrigenARMDebug
2
- # Object that defines the API necessary to perform MEM-AP transactions. Requires
3
- # a top-level protocol be defined as well as a top-level instantiation of an
4
- # SWJ-DP object.
5
- class MemAP
3
+ # Memory Access Port (MEM-AP)
4
+ class MemAP < AP
6
5
  include Origen::Model
7
6
 
8
- # Initialize class variables
9
- #
10
- # @param [Hash] options Options to customize the operation
11
- #
12
- # @example
13
- # DUT.new.arm_debug.mem_ap
14
- #
7
+ # Latency to write a memory resource
8
+ attr_reader :latency
9
+
10
+ # Wait states for data to be transferred from Memory Resource to DRW on
11
+ # read request. Should be added to apreg_access_wait for complete transaction
12
+ # time of memory read (read data path: memory->drw->rdbuff)
13
+ attr_reader :apmem_access_wait
14
+
15
15
  def initialize(options = {})
16
- instantiate_registers
17
- end
16
+ super
17
+ @latency = options[:latency] || 0
18
+ @apmem_access_wait = options[:apmem_access_wait] || 0
18
19
 
19
- def instantiate_registers(options = {})
20
- # ARM Debug Interface v5.1
21
- reg :csw, 0x00, size: 32, reset: 0x00000000 do |reg|
20
+ reg :csw, 0x0 do |reg|
22
21
  reg.bit 31, :dbg_sw_enable
23
22
  reg.bit 30..24, :prot
24
23
  reg.bit 23, :spiden
25
24
  reg.bit 11..8, :mode
26
25
  reg.bit 7, :tr_in_prog
27
26
  reg.bit 6, :device_en
28
- reg.bit 5..4, :addr_inc, reset: 0b00
29
- reg.bit 2..0, :size, reset: 0b000
30
- end
31
-
32
- add_reg :tar, 0x04, 32, data: { pos: 0, bits: 32 }, reset: 0xffffffff
33
- add_reg :drw, 0x0C, 32, data: { pos: 0, bits: 32 }, reset: 0x00000000
34
- end
35
-
36
- # Shortcut name to SWJ-DP Debug Port
37
- def debug_port
38
- parent.swj_dp
39
- end
40
- alias_method :dp, :debug_port
41
-
42
- # -----------------------------------------------------------------------------
43
- # User API
44
- # -----------------------------------------------------------------------------
45
- def write_register(reg_or_val, options = {})
46
- if reg_or_val.respond_to?(:data)
47
- addr = reg_or_val.addr
48
- data = reg_or_val.data
49
- else
50
- addr = options[:address]
51
- data = reg_or_val
52
- end
53
- size = options[:size] || 32
54
-
55
- msg = "Arm Debug: Shift in data to write: #{data.to_hex}"
56
- options = { arm_debug_comment: msg }.merge(options)
57
-
58
- set_size(size)
59
- set_addr(addr)
60
- reg(:drw).data = get_wdata(size, addr, data)
61
- debug_port.write_ap(reg(:drw).address, reg(:drw).data, options)
62
- increment_addr
63
-
64
- cc "MEM-AP(#{@name}): WR-#{size.to_s(10)}: "\
65
- "addr=0x#{addr.to_s(16).rjust(size / 4, '0')}, "\
66
- "data=0x#{reg(:drw).data.to_s(16).rjust(size / 4, '0')}"
67
-
68
- apply_latency
69
- end
70
-
71
- def read_register(reg_or_val, options = {})
72
- if reg_or_val.respond_to?(:data)
73
- addr = reg_or_val.addr
74
- data = reg_or_val.data
75
- options[:mask] = reg_or_val.enable_mask(:read)
76
- options[:store] = reg_or_val.enable_mask(:store)
77
- else
78
- addr = options[:address]
79
- data = reg_or_val
80
- end
81
- size = options[:size] || 32
82
-
83
- msg = 'Arm Debug: Shift out data for reading'
84
- options = { arm_debug_comment: msg }.merge(options)
85
- set_size(size)
86
- set_addr(addr)
87
- reg(:drw).data = get_rdata(size, addr, data)
88
- debug_port.read_ap(reg(:drw).address, reg(:drw).data, options)
89
- increment_addr
90
-
91
- cc "MEM-AP(#{@name}): R-#{size.to_s(10)}: "\
92
- "addr=0x#{addr.to_s(16).rjust(size / 4, '0')}"
93
-
94
- apply_latency
95
- end
96
-
97
- # -----------------------------------------------------------------------------
98
- # Legacy Support (to be phased out)
99
- # -----------------------------------------------------------------------------
100
-
101
- # Method to read from a mem_ap register (DEPRECATED)
102
- #
103
- # @param [Integer] addr Address of register to be read from
104
- # @param [Hash] options Options to customize the operation
105
- #
106
- # @example
107
- # # don't care what data actually is
108
- # mem_ap.read(0x2000000, size: 32)
109
- #
110
- # # expect read data to be = 0x5a5a5a5a
111
- # mem_ap.read(0x2000000, size: 32, edata: 0x5a5a5a5a)
112
- #
113
- # # expect read data to be = 0xXXXXXX5a (mask out all bits except [7:0])
114
- # mem_ap.read(0x2000000, size: 32, edata: 0x5a5a5a5a, r_mask: 0x000000ff)
115
- #
116
- # Returns nothing.
117
- def read(addr, options = {})
118
- # Warn caller that this method is being deprecated
119
- msg = 'Use mem_ap.read_register(reg_or_val, options) instead of read(addr, options)'
120
- Origen.deprecate msg
121
-
122
- # Convert old style (addr, options) to (data, options) before passing on to new method
123
- data = options.delete(:edata) || 0x00000000
124
- mask = options.delete(:r_mask) || 0xFFFFFFFF
125
- options = { address: addr, mask: mask }.merge(options)
126
- if mask == 'store'
127
- options = { store: 0xFFFFFFFF }.merge(options)
128
- read_register(data, options)
129
- else
130
- read_register(data, options)
131
- end
132
- end
133
-
134
- # Method to write to a mem_ap register (DEPRECATED)
135
- #
136
- # @param [Integer] addr Address of register to be read from
137
- # @param [Integer] wdata Data to be written
138
- # @param [Hash] options Options to customize the operation
139
- #
140
- # @example
141
- # mem_ap.write(0x2000000, 0xc3c3a5a5, size: 32)
142
- #
143
- # Returns nothing.
144
- def write(addr, wdata, options = {});
145
- # Warn caller that this method is being deprecated
146
- msg = 'Use mem_ap.write_register(reg_or_val, options) instead of write(addr, wdata, options)'
147
- Origen.deprecate msg
148
-
149
- # Convert old style (addr, wdata, options) to (data, options) before passing on to new method
150
- data = wdata
151
- options = { address: addr }.merge(options)
152
- write_register(data, options)
153
- end
154
-
155
- # Method to write and then read from a mem_ap register (DEPRECATED)
156
- #
157
- # @param [Integer] addr Address of register to be read from
158
- # @param [Integer] wdata Data to be written
159
- # @param [Hash] options Options to customize the operation
160
- #
161
- # @example
162
- # # don't care what read-back data actually is
163
- # mem_ap.write_read(0x2000000, 0xc3c3a5a5, size: 32)
164
- #
165
- # # expect read-back data to be same as write data = 0xc3c3a5a5
166
- # mem_ap.read(0x2000000, 0xc3c3a5a5, size: 32, edata: 0xc3c3a5a5)
167
- #
168
- # # expect read-back data to be = 0xXXXXXXa5 (mask out all bits except [7:0])
169
- # mem_ap.read(0x2000000, 0xc3c3a5a5, size: 32, edata: 0xc3c3a5a5, r_mask: 0x000000ff)
170
- #
171
- # Returns nothing.
172
- def write_read(addr, wdata, options = {})
173
- # Warn caller that this method is being deprecated
174
- msg = 'Use mem_ap.write_read_register(reg_or_val, options) instead of write_read(addr, options)'
175
- Origen.deprecate msg
176
-
177
- # Convert old style (addr, wdata, options) to (data, options) before passing on to new method
178
- data = wdata
179
- mask = options.delete(:r_mask) || 0xFFFFFFFF
180
- options = { address: addr, mask: mask }.merge(options)
181
- write_register(data, options)
182
- data = options[:edata] || wdata
183
- read_register(data, options)
184
- end
185
-
186
- # -----------------------------------------------------------------------------
187
- # Support Code
188
- # -----------------------------------------------------------------------------
189
-
190
- private
191
-
192
- # Sets the size of the data (by writing to the CSW size bits). It will only
193
- # write to the size if the size from the previous transaction has changed
194
- #
195
- # @param [Integer] size Size of data, supports 8-bit, 16-bit, and 32-bit
196
- def set_size(size)
197
- case size
198
- when 8 then new_size = 0b00
199
- when 16 then new_size = 0b01
200
- when 32 then new_size = 0b10
27
+ reg.bit 5..4, :addr_inc
28
+ reg.bit 2..0, :size
201
29
  end
30
+ reg(:csw).write(options[:csw_reset]) if options[:csw_reset]
202
31
 
203
- if (reg(:csw).data == 0x00000000)
204
- debug_port.read_ap(reg(:csw).address, reg(:csw).data, mask: 0x00000000)
205
- reg(:csw).data = 0x23000040
206
- end
32
+ # Doesn't really reset to all 1's, but just to make sure the address
33
+ # optimization logic does not kick in on the first transaction
34
+ add_reg :tar, 0x04, reset: 0xFFFFFFFF
35
+ add_reg :drw, 0x0C, reset: :undefined
36
+ add_reg :bd0, 0x10, reset: :undefined
37
+ add_reg :bd1, 0x14, reset: :undefined
38
+ add_reg :bd2, 0x18, reset: :undefined
39
+ add_reg :bd3, 0x1C, reset: :undefined
207
40
 
208
- if (reg(:csw).bits(:size).data != new_size)
209
- reg(:csw).bits(:size).data = new_size
210
- debug_port.write_ap(reg(:csw).address, reg(:csw).data)
41
+ reg :cfg, 0xF4, access: :ro do |reg|
42
+ reg.bit 0, :big_endian
211
43
  end
212
- end
213
-
214
- # Sets the addr of the transaction.
215
- #
216
- # @param [Integer] addr Address of data to be read from or written to
217
- def set_addr(addr)
218
- arm_debug_comment = "Arm Debug: Shift in read/write address: #{addr.to_hex}"
219
- options = { arm_debug_comment: arm_debug_comment }
220
44
 
221
- if (reg(:tar).data != addr)
222
- debug_port.write_ap(reg(:tar).address, addr, options)
45
+ reg :base, 0xF8, access: :ro do |reg|
46
+ reg.bit 31..12, :baseaddr
47
+ reg.bit 1, :format, reset: 1
48
+ reg.bit 0, :entry_present
223
49
  end
224
- reg(:tar).data = addr;
225
- end
226
-
227
- # Increment the address for the next transaction.
228
- def increment_addr
229
- if reg(:csw).bits(:addr_inc).data == 1
230
- case reg(:csw).bits(:size)
231
- when 0 then reg(:tar).data += 1 # Increment single
232
- when 1 then reg(:tar).data += 2 # Increment single
233
- when 2 then reg(:tar).data += 4 # Increment single
234
- end
235
- elsif reg(:csw).bits(:addr_inc).data == 2
236
- reg(:tar).data += 4 # Increment packed
237
- end
238
-
239
- if reg(:csw).bits(:addr_inc) && ((reg(:tar).data & 0xfffffc00) == 0xffffffff)
240
- # reset tar when attempting to increment past 1kB boundary
241
- reg(:tar).data = 0xffffffff
242
- end
243
- end
244
-
245
- # Create a bit-wise read-data based on size, address and rdata parameters.
246
- #
247
- # @param [Integer] size Size of data, supports 8-bit, 16-bit, and 32-bit
248
- # @param [Integer] addr Address of data to be read from or written to
249
- # @param [Integer] rdata Full data for read, used to create nibble read data
250
- def get_rdata(size, addr, rdata)
251
- addr_1_0 = addr & 0x00000003
252
- case size
253
- when 8
254
- case addr_1_0
255
- when 0 then rdata = 0x000000ff & rdata
256
- when 1 then rdata = 0x000000ff & (rdata >> 8)
257
- when 2 then rdata = 0x000000ff & (rdata >> 16)
258
- when 3 then rdata = 0x000000ff & (rdata >> 24)
259
- end
260
- when 16
261
- case addr_1_0
262
- when 0 then rdata = 0x0000ffff & rdata
263
- when 2 then rdata = 0x0000ffff & (rdata >> 16)
264
- end
265
- when 32
266
- rdata = rdata
267
- end
268
- rdata
269
- end
270
-
271
- # Create a bit-wise read-data based on size, address and wdata parameters.
272
- #
273
- # @param [Integer] size Size of data, supports 8-bit, 16-bit, and 32-bit
274
- # @param [Integer] addr Address of data to be read from or written to
275
- # @param [Integer] wdata Full data for write, used to create nibble write data
276
- def get_wdata(size, addr, wdata);
277
- addr_1_0 = addr & 0x00000003
278
- case size
279
- when 8
280
- case addr_1_0
281
- when 0 then wdata = 0x000000ff & wdata
282
- when 1 then wdata = 0x0000ff00 & (wdata << 8)
283
- when 2 then wdata = 0x00ff0000 & (wdata << 16)
284
- when 3 then wdata = 0xff000000 & (wdata << 24)
285
- end
286
- when 16
287
- case addr_1_0
288
- when 0 then wdata = 0x0000ffff & wdata
289
- when 2 then wdata = 0xffff0000 & (wdata << 16)
290
- end
291
- when 32
292
- wdata = wdata
293
- end
294
- wdata
295
- end
296
50
 
297
- # Apply delay as specified by the top-level attribute 'latency' (defaults to 0).
298
- #
299
- # @param [Hash] options Options to customize the operation
300
- def apply_latency(options = {})
301
- Origen.tester.cycle(repeat: parent.latency)
51
+ add_reg :idr, 0xFC, access: :ro
302
52
  end
303
53
  end
304
54
  end
@@ -0,0 +1,81 @@
1
+ module OrigenARMDebug
2
+ class MemAPController < APController
3
+ def write_register(reg_or_val, options = {})
4
+ if reg_or_val.try(:owner) == model
5
+ log "Write MEM-AP (#{model.name}) register #{reg_or_val.name.to_s.upcase}: #{reg_or_val.data.to_hex}" do
6
+ parent.dp.write_register(reg_or_val, options)
7
+ apreg_access_wait.cycles
8
+ end
9
+ else
10
+
11
+ addr = extract_address(reg_or_val, options)
12
+ data = extract_data(reg_or_val, options)
13
+ ovl = options.delete(:overlay)
14
+ unless ovl.nil?
15
+ Origen.log.warn '[ARM Debug] Overlays only supported through register model'
16
+ end
17
+
18
+ log "Write MEM-AP (#{model.name}) address #{addr.to_hex}: #{data.to_hex}" do
19
+ csw.bits(:size).write!(0b010) if csw.bits(:size).data != 0b010
20
+ tar.write!(addr) unless tar.data == addr
21
+ drw.reset
22
+ drw.overlay(nil)
23
+ drw.copy_all(reg_or_val)
24
+ drw.write!(options)
25
+ latency.cycles
26
+ end
27
+ increment_addr
28
+ end
29
+ end
30
+
31
+ def read_register(reg_or_val, options = {})
32
+ if reg_or_val.try(:owner) == model
33
+ apacc_wait_states = reg_or_val.name == :drw ? (apmem_access_wait + apreg_access_wait) : apreg_access_wait
34
+ log "Read MEM-AP (#{model.name}) register #{reg_or_val.name.to_s.upcase}: #{Origen::Utility.read_hex(reg_or_val)}" do
35
+ parent.dp.read_register(reg_or_val, options.merge(apacc_wait_states: apacc_wait_states))
36
+ end
37
+
38
+ else
39
+
40
+ addr = extract_address(reg_or_val, options)
41
+
42
+ log "Read MEM-AP (#{model.name}) address #{addr.to_hex}: #{Origen::Utility.read_hex(reg_or_val)}" do
43
+ csw.bits(:size).write!(0b010) if csw.bits(:size).data != 0b010
44
+ unless tar.data == addr
45
+ tar.write!(addr)
46
+ end
47
+ drw.reset
48
+ drw.overlay(nil)
49
+ drw.copy_all(reg_or_val)
50
+ parent.dp.read_register(drw, options.merge(apacc_wait_states: (apmem_access_wait + apreg_access_wait)))
51
+ end
52
+ increment_addr
53
+ end
54
+ end
55
+
56
+ def address_increment_enabled?
57
+ d = csw.addr_inc.data
58
+ d == 1 || d == 2
59
+ end
60
+
61
+ private
62
+
63
+ # Update the model if the address is auto-incrementing on chip
64
+ def increment_addr
65
+ if address_increment_enabled?
66
+ case csw.bits(:size).data
67
+ when 0 then tar.data += 1 # Increment single
68
+ when 1 then tar.data += 2 # Increment single
69
+ when 2 then tar.data += 4 # Increment single
70
+ end
71
+ elsif csw.addr_inc.data == 2
72
+ tar.data += 4 # Increment packed
73
+ end
74
+
75
+ # Reset tar if just crossed a 1kB boundary
76
+ if address_increment_enabled? && (tar[9..0].data == 0)
77
+ tar.reset
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,65 @@
1
+ require 'origen_arm_debug/sw_dp_controller'
2
+ module OrigenARMDebug
3
+ class SW_DP
4
+ include Origen::Model
5
+
6
+ def initialize(options = {})
7
+ reg :idcode, 0, access: :ro do |reg|
8
+ reg.bit 31..28, :version
9
+ reg.bit 27..12, :partno
10
+ reg.bit 11..1, :designer
11
+ reg.bit 0, :bit0, reset: 1
12
+ end
13
+
14
+ reg :abort, 0, access: :wo do |reg|
15
+ reg.bit 4, :orunerrclr
16
+ reg.bit 3, :wderrclr
17
+ reg.bit 2, :stkerrclr
18
+ reg.bit 1, :stkcmpclr
19
+ reg.bit 0, :dapabort
20
+ end
21
+
22
+ reg :ctrlstat, 0x4 do |reg|
23
+ reg.bit 31, :csyspwrupack
24
+ reg.bit 30, :csyspwrupreq
25
+ reg.bit 29, :cdbgpwrupack
26
+ reg.bit 28, :cdbgpwrupreq
27
+ reg.bit 27, :cdbgrstack
28
+ reg.bit 26, :cdbgrstreq
29
+ reg.bit 23..12, :trncnt
30
+ reg.bit 11..8, :masklane
31
+ reg.bit 7, :wdataerr
32
+ reg.bit 6, :readok
33
+ reg.bit 5, :stickyerr
34
+ reg.bit 4, :stickycmp
35
+ reg.bit 3..2, :trnmode
36
+ reg.bit 1, :stickyorun
37
+ reg.bit 0, :orundetect
38
+ end
39
+
40
+ reg :wcr, 0x4 do |reg|
41
+ reg.bit 9..8, :turnround
42
+ reg.bit 7..6, :wiremode
43
+ reg.bit 2..0, :prescaler
44
+ end
45
+
46
+ add_reg :resend, 0x8, access: :ro
47
+
48
+ reg :select, 0x8, access: :wo do |reg|
49
+ reg.bit 31..24, :apsel
50
+ reg.bit 7..4, :apbanksel
51
+ reg.bit 0, :ctrlsel
52
+ end
53
+
54
+ add_reg :rdbuff, 0xC, access: :ro
55
+ end
56
+
57
+ def select
58
+ reg(:select)
59
+ end
60
+
61
+ def abort
62
+ reg(:abort)
63
+ end
64
+ end
65
+ end