origen_arm_debug 0.8.4 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,121 +3,98 @@ module OrigenARMDebug
3
3
  # a top-level protocol be defined as well as a top-level instantiation of an
4
4
  # SWJ-DP object.
5
5
  class MemAP
6
- # ARM Debug Interface v5.1
7
- MEM_ADDR_CSW = 0x00000000
8
- MEM_ADDR_TAR = 0x00000004
9
- MEM_ADDR_DRW = 0x0000000C
10
- MEM_ADDR_BD0 = 0x00000010
11
- MEM_ADDR_BD1 = 0x00000014
12
- MEM_ADDR_BD2 = 0x00000018
13
- MEM_ADDR_BD3 = 0x0000001C
14
- MEM_ADDR_CFG = 0x000000F4
15
- MEM_ADDR_BASE = 0x000000F8
16
- MEM_ADDR_IDR = 0x000000FC
17
-
18
- # Returns the parent object that instantiated the driver
19
- attr_reader :owner
6
+ include Origen::Model
20
7
 
21
8
  # Initialize class variables
22
9
  #
23
- # @param [Object] owner Parent object
24
10
  # @param [Hash] options Options to customize the operation
25
11
  #
26
12
  # @example
27
13
  # DUT.new.arm_debug.mem_ap
28
14
  #
29
- def initialize(owner, options = {})
30
- @owner = owner
31
- @name = options[:name].nil? ? 'default' : options[:name]
32
- @base_address = options[:base_address].nil? ? 0x00000000 : options[:base_address]
15
+ def initialize(options = {})
16
+ instantiate_registers
17
+ end
18
+
19
+ def instantiate_registers(options = {})
20
+ # ARM Debug Interface v5.1
21
+ reg :csw, 0x00, size: 32, reset: 0x00000000 do |reg|
22
+ reg.bit 31, :dbg_sw_enable
23
+ reg.bit 30..24, :prot
24
+ reg.bit 23, :spiden
25
+ reg.bit 11..8, :mode
26
+ reg.bit 7, :tr_in_prog
27
+ reg.bit 6, :device_en
28
+ reg.bit 5..4, :addr_inc, reset: 0b00
29
+ reg.bit 2..0, :size, reset: 0b000
30
+ end
33
31
 
34
- # reset values for MEM-AP registers
35
- @current_csw = 0x00000000
36
- @current_tar = 0xffffffff
37
- @current_dsw = 0x00000000
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
38
34
  end
39
35
 
40
36
  # Shortcut name to SWJ-DP Debug Port
41
37
  def debug_port
42
- owner.swj_dp
38
+ parent.swj_dp
43
39
  end
44
40
  alias_method :dp, :debug_port
45
41
 
46
- # Output some instance-specific information
47
- def inspect
48
- Origen.log.info '=' * 30
49
- Origen.log.info ' MEM-AP INFO'
50
- Origen.log.info " name: #{@name}"
51
- Origen.log.info " base address: 0x#{@base_address.to_hex}"
52
- Origen.log.info ''
53
- Origen.log.debug " csw_reg_addr = 0x#{csw_reg_addr.to_hex}"
54
- Origen.log.debug " tar_reg_addr = 0x#{tar_reg_addr.to_hex}"
55
- Origen.log.debug " drw_reg_addr = 0x#{drw_reg_addr.to_hex}"
56
- Origen.log.debug " bd0_reg_addr = 0x#{bd0_reg_addr.to_hex}"
57
- Origen.log.debug " bd1_reg_addr = 0x#{bd1_reg_addr.to_hex}"
58
- Origen.log.debug " bd2_reg_addr = 0x#{bd2_reg_addr.to_hex}"
59
- Origen.log.debug " bd3_reg_addr = 0x#{bd3_reg_addr.to_hex}"
60
- Origen.log.debug " cfg_reg_addr = 0x#{cfg_reg_addr.to_hex}"
61
- Origen.log.debug " base_reg_addr = 0x#{base_reg_addr.to_hex}"
62
- Origen.log.debug " idr_reg_addr = 0x#{idr_reg_addr.to_hex}"
63
- end
64
-
65
42
  # -----------------------------------------------------------------------------
66
43
  # User API
67
44
  # -----------------------------------------------------------------------------
68
- def read_register(reg_or_val, options = {})
45
+ def write_register(reg_or_val, options = {})
69
46
  if reg_or_val.respond_to?(:data)
70
47
  addr = reg_or_val.addr
71
- rdata = reg_or_val.data
72
- options = { reg: reg_or_val }.merge(options)
48
+ data = reg_or_val.data
73
49
  else
74
- addr = reg_or_val # if not a register, use the 'val' as target addr
75
- rdata = 0
50
+ addr = options[:address]
51
+ data = reg_or_val
76
52
  end
53
+ size = options[:size] || 32
77
54
 
78
- options = { size: 32 }.merge(options)
79
- options = { r_mask: 'mask', r_attempts: 1 }.merge(options)
80
- msg = 'Arm Debug: Shift out data for reading'
55
+ msg = "Arm Debug: Shift in data to write: #{data.to_hex}"
81
56
  options = { arm_debug_comment: msg }.merge(options)
82
- size = options[:size]
83
57
 
84
58
  set_size(size)
85
59
  set_addr(addr)
86
- debug_port.read_ap(drw_reg_addr, options)
87
- rdata = get_rdata(size, addr, rdata)
60
+ reg(:drw).data = get_wdata(size, addr, data)
61
+ debug_port.write_ap(reg(:drw).address, reg(:drw).data, options)
88
62
  increment_addr
89
63
 
90
- cc "MEM-AP(#{@name}): R-#{size.to_s(10)}: "\
91
- "addr=0x#{addr.to_s(16).rjust(size / 4, '0')}"
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')}"
92
67
  end
93
68
 
94
- def write_register(reg_or_val, options = {});
69
+ def read_register(reg_or_val, options = {})
95
70
  if reg_or_val.respond_to?(:data)
96
71
  addr = reg_or_val.addr
97
- wdata = reg_or_val.data
98
- options = { reg: reg_or_val }.merge(options)
72
+ data = reg_or_val.data
73
+ options[:mask] = reg_or_val.enable_mask(:read)
74
+ options[:store] = reg_or_val.enable_mask(:store)
99
75
  else
100
- addr = reg_or_val # if not a register, use the 'val' as target addr
101
- wdata = options[:wdata]
76
+ addr = options[:address]
77
+ data = reg_or_val
102
78
  end
103
- options = { size: 32 }.merge(options)
104
- options = { w_attempts: 1 }.merge(options)
105
- msg = "Arm Debug: Shift in data to write: #{wdata.to_hex}"
106
- options = { arm_debug_comment: msg }.merge(options)
107
- size = options[:size]
79
+ size = options[:size] || 32
108
80
 
81
+ msg = 'Arm Debug: Shift out data for reading'
82
+ options = { arm_debug_comment: msg }.merge(options)
109
83
  set_size(size)
110
84
  set_addr(addr)
111
- wdata = get_wdata(size, addr, wdata)
112
- debug_port.write_ap(drw_reg_addr, wdata, options)
85
+ reg(:drw).data = get_rdata(size, addr, data)
86
+ debug_port.read_ap(reg(:drw).address, reg(:drw).data, options)
113
87
  increment_addr
114
88
 
115
- cc "MEM-AP(#{@name}): WR-#{size.to_s(10)}: "\
116
- "addr=0x#{addr.to_s(16).rjust(size / 4, '0')}, "\
117
- "data=0x#{wdata.to_s(16).rjust(size / 4, '0')}"
89
+ cc "MEM-AP(#{@name}): R-#{size.to_s(10)}: "\
90
+ "addr=0x#{addr.to_s(16).rjust(size / 4, '0')}"
118
91
  end
119
92
 
120
- # Method to read from a mem_ap register
93
+ # -----------------------------------------------------------------------------
94
+ # Legacy Support (to be phased out)
95
+ # -----------------------------------------------------------------------------
96
+
97
+ # Method to read from a mem_ap register (DEPRECATED)
121
98
  #
122
99
  # @param [Integer] addr Address of register to be read from
123
100
  # @param [Hash] options Options to customize the operation
@@ -134,23 +111,23 @@ module OrigenARMDebug
134
111
  #
135
112
  # Returns nothing.
136
113
  def read(addr, options = {})
137
- options = { size: 32 }.merge(options)
138
- options = { r_mask: 'mask', r_attempts: 1 }.merge(options)
139
- msg = 'Arm Debug: Shift out data for reading'
140
- options = { arm_debug_comment: msg }.merge(options)
141
- size = options[:size]
142
-
143
- set_size(size)
144
- set_addr(addr)
145
- debug_port.read_ap(drw_reg_addr, options)
146
- rdata = get_rdata(size, addr, 0)
147
- increment_addr
114
+ # Warn caller that this method is being deprecated
115
+ msg = 'Use mem_ap.read_register(reg_or_val, options) instead of read(addr, options)'
116
+ Origen.deprecate msg
148
117
 
149
- cc "MEM-AP(#{@name}): R-#{size.to_s(10)}: "\
150
- "addr=0x#{addr.to_s(16).rjust(size / 4, '0')}"
118
+ # Convert old style (addr, options) to (data, options) before passing on to new method
119
+ data = options.delete(:edata) || 0x00000000
120
+ mask = options.delete(:r_mask) || 0xFFFFFFFF
121
+ options = { address: addr, mask: mask }.merge(options)
122
+ if mask == 'store'
123
+ options = { store: 0xFFFFFFFF }.merge(options)
124
+ read_register(data, options)
125
+ else
126
+ read_register(data, options)
127
+ end
151
128
  end
152
129
 
153
- # Method to write to a mem_ap register
130
+ # Method to write to a mem_ap register (DEPRECATED)
154
131
  #
155
132
  # @param [Integer] addr Address of register to be read from
156
133
  # @param [Integer] wdata Data to be written
@@ -161,24 +138,17 @@ module OrigenARMDebug
161
138
  #
162
139
  # Returns nothing.
163
140
  def write(addr, wdata, options = {});
164
- options = { size: 32 }.merge(options)
165
- options = { w_attempts: 1 }.merge(options)
166
- msg = "Arm Debug: Shift in data to write: #{wdata.to_hex}"
167
- options = { arm_debug_comment: msg }.merge(options)
168
- size = options[:size]
169
-
170
- set_size(size)
171
- set_addr(addr)
172
- wdata = get_wdata(size, addr, wdata)
173
- debug_port.write_ap(drw_reg_addr, wdata, options)
174
- increment_addr
141
+ # Warn caller that this method is being deprecated
142
+ msg = 'Use mem_ap.write_register(reg_or_val, options) instead of write(addr, wdata, options)'
143
+ Origen.deprecate msg
175
144
 
176
- cc "MEM-AP(#{@name}): WR-#{size.to_s(10)}: "\
177
- "addr=0x#{addr.to_s(16).rjust(size / 4, '0')}, "\
178
- "data=0x#{wdata.to_s(16).rjust(size / 4, '0')}"
145
+ # Convert old style (addr, wdata, options) to (data, options) before passing on to new method
146
+ data = wdata
147
+ options = { address: addr }.merge(options)
148
+ write_register(data, options)
179
149
  end
180
150
 
181
- # Method to write and then read from a mem_ap register (legacy)
151
+ # Method to write and then read from a mem_ap register (DEPRECATED)
182
152
  #
183
153
  # @param [Integer] addr Address of register to be read from
184
154
  # @param [Integer] wdata Data to be written
@@ -196,77 +166,18 @@ module OrigenARMDebug
196
166
  #
197
167
  # Returns nothing.
198
168
  def write_read(addr, wdata, options = {})
199
- options = { size: 32 }.merge(options)
200
- options = { edata: 0x00000000, r_mask: 0xffffffff, actual: 0x00000000 }.merge(options)
201
- options = { w_attempts: 1, r_attempts: 1 }.merge(options)
202
- size = options[:size]
203
-
204
- write(addr, wdata, options)
205
- options[:edata] = wdata & options[:r_mask] if options[:edata] == 0x00000000
206
- read(addr, options)
207
- actual = wdata & options[:r_mask]
208
-
209
- cc "MEM-AP(#{@name}): WR-#{size.to_s(10)}: "\
210
- "addr=0x#{addr.to_s(16).rjust(size / 4, '0')}, "\
211
- "wdata=0x#{wdata.to_s(16).rjust(size / 4, '0')}, "\
212
- "read=0x#{actual.to_s(16).rjust(size / 4, '0')}, "\
213
- "expect=0x#{options[:edata].to_s(16).rjust(size / 4, '0')}, "\
214
- "mask=0x#{options[:r_mask].to_s(16).rjust(size / 4, '0')}"
215
- end
216
-
217
- # -----------------------------------------------------------------------------
218
- # Legacy Support (to be phased out)
219
- # -----------------------------------------------------------------------------
220
-
221
- # Method to read from a mem_ap register (legacy)
222
- #
223
- # @param [Integer] addr Address of register to be read from
224
- # @param [Integer] rdata This really does nothing since only care about value
225
- # of options[:edata]
226
- # @param [Hash] options Options to customize the operation
227
- # Returns nothing.
228
- def r(addr, rdata, options = {})
229
169
  # Warn caller that this method is being deprecated
230
- msg = 'Use mem_ap.read(addr, options) instead of R(addr, rdata, options)'
170
+ msg = 'Use mem_ap.write_read_register(reg_or_val, options) instead of write_read(addr, options)'
231
171
  Origen.deprecate msg
232
172
 
233
- # Patch arguments and send to new method
234
- options = { rdata: rdata }.merge(options)
235
- read(addr, options)
173
+ # Convert old style (addr, wdata, options) to (data, options) before passing on to new method
174
+ data = wdata
175
+ mask = options.delete(:r_mask) || 0xFFFFFFFF
176
+ options = { address: addr, mask: mask }.merge(options)
177
+ write_register(data, options)
178
+ data = options[:edata] || wdata
179
+ read_register(data, options)
236
180
  end
237
- alias_method :R, :r
238
-
239
- # Method to write to a mem_ap register (legacy)
240
- #
241
- # @param [Integer] addr Address of register to be written to
242
- # @param [Integer] wdata Data to be written
243
- # @param [Hash] options Options to customize the operation
244
- # Returns nothing.
245
- def w(addr, wdata, options = {})
246
- # Warn caller that this method is being deprecated
247
- msg = 'Use mem_ap.write(addr, wdata, options) instead of W(addr, wdata, options)'
248
- Origen.deprecate msg
249
-
250
- # Patch arguments and send to new method
251
- write(addr, wdata, options)
252
- end
253
- alias_method :W, :w
254
-
255
- # Method to write and then read from a mem_ap register (legacy)
256
- #
257
- # @param [Integer] addr Address of register to be read from
258
- # @param [Integer] wdata Data to be written
259
- # @param [Hash] options Options to customize the operation
260
- # Returns nothing.
261
- def wr(addr, wdata, options = {})
262
- # Warn caller that this method is being deprecated
263
- msg = 'Use mem_ap.write_read(addr, wdata, options) instead of WR(addr, wdata, options)'
264
- Origen.deprecate msg
265
-
266
- # Patch arguments and send to new method
267
- write_read(addr, wdata, options)
268
- end
269
- alias_method :WR, :wr
270
181
 
271
182
  # -----------------------------------------------------------------------------
272
183
  # Support Code
@@ -280,22 +191,19 @@ module OrigenARMDebug
280
191
  # @param [Integer] size Size of data, supports 8-bit, 16-bit, and 32-bit
281
192
  def set_size(size)
282
193
  case size
283
- when 8 then new_size = 0x00000000
284
- when 16 then new_size = 0x00000001
285
- when 32 then new_size = 0x00000002
286
- else new_size = 0x00000002
194
+ when 8 then new_size = 0b00
195
+ when 16 then new_size = 0b01
196
+ when 32 then new_size = 0b10
287
197
  end
288
198
 
289
- if (@current_csw == 0x00000000)
290
- debug_port.read_ap(csw_reg_addr)
291
- @current_csw = 0x23000040
199
+ if (reg(:csw).data == 0x00000000)
200
+ debug_port.read_ap(reg(:csw).address, reg(:csw).data, mask: 0x00000000)
201
+ reg(:csw).data = 0x23000040
292
202
  end
293
203
 
294
- csw_size = @current_csw & 0x00000003
295
- if (csw_size != new_size)
296
- new_csw = (@current_csw & 0xfffffffc) | new_size
297
- debug_port.write_ap(csw_reg_addr, new_csw)
298
- @current_csw = new_csw
204
+ if (reg(:csw).bits(:size).data != new_size)
205
+ reg(:csw).bits(:size).data = new_size
206
+ debug_port.write_ap(reg(:csw).address, reg(:csw).data)
299
207
  end
300
208
  end
301
209
 
@@ -306,29 +214,27 @@ module OrigenARMDebug
306
214
  arm_debug_comment = "Arm Debug: Shift in read/write address: #{addr.to_hex}"
307
215
  options = { arm_debug_comment: arm_debug_comment }
308
216
 
309
- if (@current_tar != addr)
310
- debug_port.write_ap(tar_reg_addr, addr, options)
217
+ if (reg(:tar).data != addr)
218
+ debug_port.write_ap(reg(:tar).address, addr, options)
311
219
  end
312
- @current_tar = addr;
220
+ reg(:tar).data = addr;
313
221
  end
314
222
 
315
223
  # Increment the address for the next transaction.
316
224
  def increment_addr
317
- current_csw_5_4 = (@current_csw & 0x00000030) >> 4
318
- current_csw_2_0 = @current_csw & 0x00000007
319
- if (current_csw_5_4 == 0b01)
320
- case current_csw_2_0
321
- when 0 then @current_tar += 1 # Increment single
322
- when 1 then @current_tar += 2 # Increment single
323
- when 2 then @current_tar += 4 # Increment single
225
+ if reg(:csw).bits(:addr_inc).data == 1
226
+ case reg(:csw).bits(:size)
227
+ when 0 then reg(:tar).data += 1 # Increment single
228
+ when 1 then reg(:tar).data += 2 # Increment single
229
+ when 2 then reg(:tar).data += 4 # Increment single
324
230
  end
325
- elsif (current_csw_5_4 == 2)
326
- @current_tar += 4 # Increment packed
231
+ elsif reg(:csw).bits(:addr_inc).data == 2
232
+ reg(:tar).data += 4 # Increment packed
327
233
  end
328
234
 
329
- if current_csw_5_4 && ((@current_tar & 0xfffffc00) == 0xffffffff)
235
+ if reg(:csw).bits(:addr_inc) && ((reg(:tar).data & 0xfffffc00) == 0xffffffff)
330
236
  # reset tar when attempting to increment past 1kB boundary
331
- @current_tar = 0xffffffff
237
+ reg(:tar).data = 0xffffffff
332
238
  end
333
239
  end
334
240
 
@@ -383,55 +289,5 @@ module OrigenARMDebug
383
289
  end
384
290
  wdata
385
291
  end
386
-
387
- # Returns address of CSW register for this mem-ap instance
388
- def csw_reg_addr
389
- MEM_ADDR_CSW + @base_address
390
- end
391
-
392
- # Returns address of TAR register for this mem-ap instance
393
- def tar_reg_addr
394
- MEM_ADDR_TAR + @base_address
395
- end
396
-
397
- # Returns address of DRW register for this mem-ap instance
398
- def drw_reg_addr
399
- MEM_ADDR_DRW + @base_address
400
- end
401
-
402
- # Returns address of BD0 register for this mem-ap instance
403
- def bd0_reg_addr
404
- MEM_ADDR_BD0 + @base_address
405
- end
406
-
407
- # Returns address of BD1 register for this mem-ap instance
408
- def bd1_reg_addr
409
- MEM_ADDR_BD1 + @base_address
410
- end
411
-
412
- # Returns address of BD2 register for this mem-ap instance
413
- def bd2_reg_addr
414
- MEM_ADDR_BD2 + @base_address
415
- end
416
-
417
- # Returns address of BD3 register for this mem-ap instance
418
- def bd3_reg_addr
419
- MEM_ADDR_BD3 + @base_address
420
- end
421
-
422
- # Returns address of CFG register for this mem-ap instance
423
- def cfg_reg_addr
424
- MEM_ADDR_CFG + @base_address
425
- end
426
-
427
- # Returns address of BASE register for this mem-ap instance
428
- def base_reg_addr
429
- MEM_ADDR_BASE + @base_address
430
- end
431
-
432
- # Returns address of IDR register for this mem-ap instance
433
- def idr_reg_addr
434
- MEM_ADDR_IDR + @base_address
435
- end
436
292
  end
437
293
  end