origen_arm_debug 0.10.1 → 1.0.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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