origen_arm_debug 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,269 @@
1
+ # To use this driver the $soc model must define the following pins (an alias is fine):
2
+ # :swd_clk
3
+ # :swd_dio
4
+ #
5
+ # API methods:
6
+ # R_dp - debug register read - just a dummy function in origen
7
+ # RE_dp - debug register read/expect - expect compares not implemented
8
+ # R_ap - read a specific address - just a dummy function in origen
9
+ # W_dp - debug register write
10
+ # W_ap - write a specific address
11
+ # WR_ap - write a specific address, then read back
12
+
13
+ module OrigenARMDebug
14
+ class ABSIF_SWD
15
+ attr_reader :owner
16
+ include Origen::Registers
17
+
18
+ def initialize(owner, options = {})
19
+ @current_apaddr = 0
20
+ @orundetect = 0
21
+ @owner = owner
22
+ end
23
+
24
+ # Highest level implementation of API - abstracted from 'read' and 'write' for future merging with JTAG debug
25
+ def R_dp(name, rdata, options = {})
26
+ cc 'Reading ' + name
27
+ read_dp(name, options)
28
+ end
29
+
30
+ def RE_dp(name, edata, options = {})
31
+ R_dp(name, edata, options)
32
+ end
33
+
34
+ def R_ap(addr, rdata, options = {})
35
+ cc 'Reading address ' + addr.to_s(16)
36
+ read_ap(addr, options)
37
+ end
38
+
39
+ def WAIT_RE_ap(addr, edata, options = {})
40
+ options = { mask: 0xffffffff, r_attempts: 1 }.merge(options)
41
+
42
+ # just assume that it always passes
43
+ actual = edata
44
+
45
+ R_ap(addr, actual, options)
46
+
47
+ cc "ABS-IF: WAIT_RE-AP: addr = 0x#{addr.to_s(16)}, "\
48
+ "actual = 0x#{actual.to_s(16)}, "\
49
+ "expected = 0x#{edata.to_s(16)}, "\
50
+ "mask = 0x#{options[:mask].to_s(16)}"
51
+ end
52
+
53
+ def W_dp(name, wdata, options = {})
54
+ cc 'Writing 0x' + wdata.to_s(16) + ' to ' + name
55
+ write_dp(name, wdata, options)
56
+ end
57
+
58
+ def WR_dp(name, wdata, options = {})
59
+ options = { edata: 0x00000000, mask: 0xffffffff,
60
+ w_attempts: 1, r_attempts: 1
61
+ }.merge(options)
62
+
63
+ # just assume that it always passes
64
+ actual = options[:edata] & options[:mask]
65
+
66
+ W_dp(name, wdata, options)
67
+ R_dp(name, actual, options)
68
+
69
+ cc "ABS-IF: WR-DP: #{name} write = 0x#{wdata.to_s(16)}, "\
70
+ "read = 0x#{actual.to_s(16)}, "\
71
+ "expected = 0x#{options[:edata].to_s(16)}, "\
72
+ "mask = 0x#{options[:mask].to_s(16)}"
73
+ end
74
+
75
+ def W_ap(addr, wdata, options = {})
76
+ options = { w_attempts: 1 }.merge(options)
77
+ cc 'Writing 0x' + wdata.to_s(16) + ' to address 0x' + addr.to_s(16)
78
+ write_ap(addr, wdata, options)
79
+ end
80
+
81
+ def WR_ap(addr, wdata, options = {})
82
+ options = { edata: 0x00000000, mask: 0xffffffff,
83
+ w_attempts: 1, r_attempts: 1
84
+ }.merge(options)
85
+
86
+ # just assume that it always passes
87
+ actual = wdata & options[:mask]
88
+ W_ap(addr, wdata, options)
89
+ options.delete(:w_delay) if options.key?(:w_delay)
90
+ R_ap(addr, actual, options)
91
+
92
+ cc "ABS-IF: WR-AP: addr = 0x#{addr.to_s(16)}, "\
93
+ "write = 0x#{wdata.to_s(16)}, "\
94
+ "read = 0x#{actual.to_s(16)}, "\
95
+ "expected = 0x#{options[:edata].to_s(16)}, "\
96
+ "mask = 0x#{options[:mask].to_s(16)}"
97
+ end
98
+
99
+ # SWD-specific functions
100
+ def read_dp(name, options = {})
101
+ case name
102
+ when 'IDCODE' then dpacc_access(name, 1, 0x55555555, options)
103
+ when 'ABORT' then cc 'Write only register!'
104
+ when 'CTRL/STAT' then dpacc_access(name, 1, 0x55555555, options)
105
+ when 'SELECT' then cc 'Write only register!'
106
+ when 'RDBUFF' then dpacc_access(name, 1, 0x55555555, options)
107
+ when 'WCR' then dpacc_access(name, 1, 0x55555555, options)
108
+ when 'RESEND' then dpacc_access(name, 1, 0x55555555, options)
109
+ else cc 'Unknown SW-DP register name'
110
+ end
111
+ end
112
+
113
+ def write_dp(name, wdata, options = {})
114
+ case name
115
+ when 'IDCODE' then cc 'SW-DP register is read-only'
116
+ when 'ABORT' then dpacc_access(name, 0, wdata, options)
117
+ when 'CTRL/STAT' then dpacc_access(name, 0, wdata, options)
118
+ when 'SELECT' then dpacc_access(name, 0, wdata, options)
119
+ when 'RDBUFF' then cc 'SW-DP register is read-only'
120
+ when 'WCR' then dpacc_access(name, 0, wdata, options)
121
+ when 'RESEND' then cc 'SW-DP register is read-only'
122
+ else cc 'Unknown SW-DP register name'
123
+ end
124
+ end
125
+
126
+ def write_ap(addr, wdata, options = {})
127
+ apacc_access(addr, 0, wdata, options)
128
+ end
129
+
130
+ def read_ap(addr, options = {})
131
+ # Create another copy of options with select keys removed. This first read is junk so we do not want to
132
+ # store it or compare it.
133
+ junk_options = options.clone.delete_if do |key, val|
134
+ (key.eql?(:r_mask) && val.eql?('store')) || key.eql?(:compare_data)
135
+ end
136
+ # pass junk options onto the first apacc access
137
+ apacc_access(addr, 1, 0x55555555, junk_options)
138
+ read_dp('RDBUFF', options) # This is the real data
139
+ end
140
+
141
+ # Low-level access functions
142
+ def dpacc_access(name, rwb, wdata, options = {})
143
+ addr = get_dp_addr(name)
144
+ if (name == 'CTRL/STAT')
145
+ cc 'CTRL/STAT'
146
+ set_apselect(@current_apaddr & 0xFFFFFFFE, options)
147
+ end
148
+ if (name == 'WCR')
149
+ cc 'NOT IMPLEMENTED'
150
+ end
151
+
152
+ acc_access(addr, rwb, 0, wdata, options)
153
+
154
+ if (name == 'WCR')
155
+ cc 'NOT IMPLEMENTED'
156
+ end
157
+ if (name == 'CTRL/STAT')
158
+ @orundetect = wdata & 0x1
159
+ end
160
+ end
161
+
162
+ def apacc_access(addr, rwb, wdata, options = {})
163
+ set_apselect((addr & 0xFFFFFFFE) | (@current_apaddr & 1), options)
164
+ options.delete(:w_delay) if options.key?(:w_delay)
165
+ acc_access((addr & 0xC), rwb, 1, wdata, options)
166
+ end
167
+
168
+ def get_dp_addr(name)
169
+ case name
170
+ when 'IDCODE' then return 0x0
171
+ when 'ABORT' then return 0x0
172
+ when 'CTRL/STAT' then return 0x4
173
+ when 'WCR' then return 0x4
174
+ when 'RESEND' then return 0x8
175
+ when 'SELECT' then return 0x8
176
+ when 'RDBUFF' then return 0xC
177
+ else cc 'Unknown SW-DP register name'
178
+ end
179
+ end
180
+
181
+ def acc_access(address, rwb, ap_dp, wdata, options = {})
182
+ start = 1
183
+ apndp = ap_dp
184
+ rnw = rwb
185
+ addr = address >> 2
186
+ parity_pr = ap_dp ^ rwb ^ (addr >> 3) ^ (addr >> 2) & (0x01) ^ (addr >> 1) & (0x01) ^ addr & 0x01
187
+ trn = 0
188
+ data = wdata
189
+ require_dp = @orundetect
190
+ line_reset = 0
191
+ stop = 0
192
+ park = 1
193
+
194
+ cc 'SWD transaction'
195
+ cc 'Packet Request Phase'
196
+
197
+ annotate 'Send Start Bit'
198
+ owner.owner.swd.send_data(start, 1)
199
+ cc('Send APnDP Bit (DP or AP Access Register Bit)', prefix: true)
200
+ owner.owner.swd.send_data(apndp, 1)
201
+ c2 'Send RnW Bit (read or write bit)'
202
+ owner.owner.swd.send_data(rnw, 1)
203
+ c2 'Send Address Bits (2 bits)'
204
+ owner.owner.swd.send_data(addr, 2)
205
+ c2 'Send Parity Bit'
206
+ owner.owner.swd.send_data(parity_pr, 1)
207
+ c2 'Send Stop Bit'
208
+ owner.owner.swd.send_data(stop, 1)
209
+ c2 'Send Park Bit'
210
+ owner.owner.swd.send_data(park, 1)
211
+
212
+ cc 'Acknowledge Response phase'
213
+ owner.owner.swd.send_data(0xf, trn + 1)
214
+ owner.owner.swd.get_data (3)
215
+ cc 'Read/Write Data Phase'
216
+ if (rwb == 1)
217
+ cc 'Read'
218
+ if options[:r_mask] == 'store'
219
+ owner.owner.pin(:swd_dio).store
220
+ end
221
+ cc 'SWD 32-Bit Read Data Start'
222
+ owner.owner.swd.get_data(32, options)
223
+ cc 'SWD 32-Bit Read Data End'
224
+ cc 'Get Read Parity Bit'
225
+ owner.owner.swd.get_data(1)
226
+ cc 'Send Read ACK bits'
227
+ owner.owner.swd.send_data(0xf, trn + 1)
228
+ else
229
+ cc 'Write'
230
+ cc 'Send ACK Bits'
231
+ owner.owner.swd.send_data(0xf, trn + 1)
232
+ cc 'SWD 32-Bit Write Start'
233
+ owner.owner.swd.send_data(data, 32, options)
234
+ cc 'SWD 32-Bit Write End'
235
+ cc 'Send Write Parity Bit'
236
+ owner.owner.swd.send_data(swd_xor_calc(32, data), 1)
237
+ end
238
+
239
+ if options.key?(:w_delay)
240
+ cc "SWD DIO to 0 for #{options[:w_delay]} cycles"
241
+ owner.owner.swd.swd_dio_to_0(options[:w_delay])
242
+ else
243
+ cc 'SWD DIO to 0 for 10 cycles'
244
+ owner.owner.swd.swd_dio_to_0(10)
245
+ end
246
+ end
247
+
248
+ def set_apselect(addr, options = {})
249
+ addr &= 0xff0000f1
250
+ cc "SET_APSelect: addr = 0x#{addr.to_s(16)} "
251
+
252
+ if (addr != @current_apaddr)
253
+ cc 'SET_APSelect: write_dp SELECT'
254
+ write_dp('SELECT', addr & 0xff0000ff, options)
255
+ end
256
+
257
+ @current_apaddr = addr
258
+ end
259
+
260
+ # Calculate exclusive OR
261
+ def swd_xor_calc(size, number)
262
+ xor = 0
263
+ size.times do |bit|
264
+ xor ^= (number >> bit) & 0x01
265
+ end
266
+ xor
267
+ end
268
+ end
269
+ end
File without changes
@@ -0,0 +1,67 @@
1
+ module OrigenARMDebug
2
+ class Driver
3
+ # Returns the parent object that instantiated the driver, could be
4
+ # either a DUT object or a protocol abstraction
5
+ attr_reader :owner
6
+
7
+ # Initialize class variables
8
+ #
9
+ # @param [Object] owner Parent object
10
+ # @param [Hash] options Options to customize the operation
11
+ #
12
+ # @example
13
+ # DUT.new.arm_debug
14
+ #
15
+ def initialize(owner, options = {})
16
+ @owner = owner
17
+ end
18
+
19
+ def swj_dp
20
+ if owner.respond_to?(:swd)
21
+ @swj_dp ||= SWJ_DP.new(self, :swd)
22
+ elsif owner.respond_to?(:jtag)
23
+ @swj_dp ||= SWJ_DP.new(self, :jtag)
24
+ end
25
+ end
26
+
27
+ # Returns an instance of the OrigenARMDebug::MemAP
28
+ def mem_ap
29
+ @mem_ap ||= MemAP.new(self)
30
+ end
31
+
32
+ # Method to add additional Memory Access Ports (MEM-AP) with specified base address
33
+ # name - short name for mem_ap that is being created
34
+ # base_address - base address
35
+ def add_mem_ap(name, base_address)
36
+ instance_variable_set("@#{name}", MemAP.new(self, name: name, base_address: base_address))
37
+ self.class.send(:attr_accessor, name)
38
+ end
39
+
40
+ def read_register(reg_or_val, options = {})
41
+ mem_ap.read(reg_or_val.address, size: reg_or_val.size, compare_data: reg_or_val.data)
42
+ end
43
+
44
+ def write_register(reg_or_val, options = {})
45
+ mem_ap.write(reg_or_val.address, reg_or_val.data, size: reg_or_val.size)
46
+ end
47
+
48
+ private
49
+
50
+ def arm_debug_driver
51
+ return @arm_debug_driver if @arm_debug_driver
52
+ if owner.respond_to?(:jtag)
53
+ @arm_debug_driver = owner.jtag
54
+ elsif owner.respond_to?(:swd)
55
+ @arm_debug_driver = owner.swd
56
+ else
57
+ puts 'Cannot find a compatible physical driver!'
58
+ puts 'The ARM debug protocol supports the following phyiscal drivers:'
59
+ puts ' JTAG - http://origen-sdk.org/origen_jtag'
60
+ puts ' Single Wire Debug - http://origen-sdk.org/origen_swd'
61
+ puts ' Background Debug - http://origen-sdk.org/origen_bdm'
62
+ puts "Add one to your #{owner.class} to resolve this error."
63
+ fail 'ARM Debug error!'
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,51 @@
1
+ module OrigenARMDebug
2
+ # This is a dummy DUT model which is used
3
+ # to instantiate and test the ARMDebug locally
4
+ # during development.
5
+ #
6
+ # It is not included when this library is imported.
7
+ class DUT
8
+ include OrigenARMDebug
9
+ include Origen::Callbacks
10
+ include Origen::Registers
11
+
12
+ # Initializes simple dut model with test register and required jtag/swd pins
13
+ #
14
+ # @example
15
+ # $dut = OrigenARMDebug::DUT.new
16
+ #
17
+ def initialize
18
+ add_reg :dap, 0x0, 35, data: { pos: 0, bits: 35 }
19
+
20
+ add_reg :test, 0x0, 32, data: { pos: 0, bits: 32 },
21
+ bit: { pos: 0 }
22
+
23
+ arm_debug.add_mem_ap('mem_ap', 0x00000000)
24
+ arm_debug.add_mem_ap('mdm_ap', 0x01000000)
25
+ arm_debug.add_mem_ap('alt_ahbapi', 0x02000000)
26
+ end
27
+
28
+ # Add any custom startup business here.
29
+ #
30
+ # @param [Hash] options Options to customize the operation
31
+ def startup(options)
32
+ $tester.set_timeset('arm_debug', 40)
33
+ end
34
+
35
+ # Read data from a register
36
+ #
37
+ # @param [Register] reg Register name or address value
38
+ # @param [Hash] options Options to customize the operation
39
+ def read_register(reg, options = {})
40
+ arm_debug.read_register(reg, options)
41
+ end
42
+
43
+ # Write data to a register
44
+ #
45
+ # @param [Register] reg Register name or address value
46
+ # @param [Hash] options Options to customize the operation
47
+ def write_register(reg, options = {})
48
+ arm_debug.write_register(reg, options)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,17 @@
1
+ module OrigenARMDebug
2
+ class JTAG_DUT < DUT
3
+ include OrigenJTAG
4
+ include Origen::Pins
5
+
6
+ # Adds jtag-required pins to the simple dut model
7
+ # Returns nothing.
8
+ def initialize
9
+ super
10
+ add_pin :tclk
11
+ add_pin :tdi
12
+ add_pin :tdo
13
+ add_pin :tms
14
+ add_pin :trst
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module OrigenARMDebug
2
+ class SWD_DUT < DUT
3
+ include OrigenSWD
4
+ include Origen::Pins
5
+
6
+ # Adds swd-required pins to the simple dut model
7
+ # Returns nothing.
8
+ def initialize
9
+ super
10
+ add_pin :swd_clk
11
+ add_pin :swd_dio
12
+ end
13
+ end
14
+ end
File without changes
File without changes
@@ -0,0 +1,387 @@
1
+ module OrigenARMDebug
2
+ class MemAP
3
+ # ARM Debug Interface v5.1
4
+ MEM_ADDR_CSW = 0x00000000
5
+ MEM_ADDR_TAR = 0x00000004
6
+ MEM_ADDR_DRW = 0x0000000C
7
+ MEM_ADDR_BD0 = 0x00000010
8
+ MEM_ADDR_BD1 = 0x00000014
9
+ MEM_ADDR_BD2 = 0x00000018
10
+ MEM_ADDR_BD3 = 0x0000001C
11
+ MEM_ADDR_CFG = 0x000000F4
12
+ MEM_ADDR_BASE = 0x000000F8
13
+ MEM_ADDR_IDR = 0x000000FC
14
+
15
+ # Returns the parent object that instantiated the driver
16
+ attr_reader :owner
17
+
18
+ # Initialize class variables
19
+ #
20
+ # @param [Object] owner Parent object
21
+ # @param [Hash] options Options to customize the operation
22
+ #
23
+ # @example
24
+ # DUT.new.arm_debug.mem_ap
25
+ #
26
+ def initialize(owner, options = {})
27
+ @owner = owner
28
+ @name = options[:name].nil? ? 'default' : options[:name]
29
+ @base_address = options[:base_address].nil? ? 0x00000000 : options[:base_address]
30
+
31
+ # reset values for MEM-AP registers
32
+ @current_csw = 0x00000000
33
+ @current_tar = 0xffffffff
34
+ @current_dsw = 0x00000000
35
+ end
36
+
37
+ # Shortcut name to SWJ-DP Debug Port
38
+ def debug_port
39
+ owner.swj_dp
40
+ end
41
+ alias_method :dp, :debug_port
42
+
43
+ # -----------------------------------------------------------------------------
44
+ # User API
45
+ # -----------------------------------------------------------------------------
46
+
47
+ # Method to read from a mem_ap register
48
+ #
49
+ # @param [Integer] addr Address of register to be read from
50
+ # @param [Hash] options Options to customize the operation
51
+ #
52
+ # @example
53
+ # # don't care what data actually is
54
+ # mem_ap.read(0x2000000, size: 32)
55
+ #
56
+ # # expect read data to be = 0x5a5a5a5a
57
+ # mem_ap.read(0x2000000, size: 32, edata: 0x5a5a5a5a)
58
+ #
59
+ # # expect read data to be = 0xXXXXXX5a (mask out all bits except [7:0])
60
+ # mem_ap.read(0x2000000, size: 32, edata: 0x5a5a5a5a, r_mask: 0x000000ff)
61
+ #
62
+ # Returns nothing.
63
+ def read(addr, options = {})
64
+ options = { size: 32 }.merge(options)
65
+ options = { r_mask: 'mask', r_attempts: 1 }.merge(options)
66
+ msg = 'Arm Debug: Shift out data for reading'
67
+ options = { arm_debug_comment: msg }.merge(options)
68
+ size = options[:size]
69
+
70
+ set_size(size)
71
+ set_addr(addr)
72
+ debug_port.read_ap(drw_reg_addr, options)
73
+ rdata = get_rdata(size, addr, rdata)
74
+ increment_addr
75
+
76
+ cc "MEM-AP(#{@name}): R-#{size.to_s(10)}: "\
77
+ "addr=0x#{addr.to_s(16).rjust(size / 4, '0')}"
78
+ end
79
+
80
+ # Method to write to a mem_ap register
81
+ #
82
+ # @param [Integer] addr Address of register to be read from
83
+ # @param [Integer] wdata Data to be written
84
+ # @param [Hash] options Options to customize the operation
85
+ #
86
+ # @example
87
+ # mem_ap.write(0x2000000, 0xc3c3a5a5, size: 32)
88
+ #
89
+ # Returns nothing.
90
+ def write(addr, wdata, options = {});
91
+ options = { size: 32 }.merge(options)
92
+ options = { w_attempts: 1 }.merge(options)
93
+ msg = "Arm Debug: Shift in data to write: #{wdata.to_hex}"
94
+ options = { arm_debug_comment: msg }.merge(options)
95
+ size = options[:size]
96
+
97
+ set_size(size)
98
+ set_addr(addr)
99
+ wdata = get_wdata(size, addr, wdata)
100
+ debug_port.write_ap(drw_reg_addr, wdata, options)
101
+ increment_addr
102
+
103
+ cc "MEM-AP(#{@name}): WR-#{size.to_s(10)}: "\
104
+ "addr=0x#{addr.to_s(16).rjust(size / 4, '0')}, "\
105
+ "data=0x#{wdata.to_s(16).rjust(size / 4, '0')}"
106
+ end
107
+
108
+ # Method to write and then read from a mem_ap register (legacy)
109
+ #
110
+ # @param [Integer] addr Address of register to be read from
111
+ # @param [Integer] wdata Data to be written
112
+ # @param [Hash] options Options to customize the operation
113
+ #
114
+ # @example
115
+ # # don't care what read-back data actually is
116
+ # mem_ap.write_read(0x2000000, 0xc3c3a5a5, size: 32)
117
+ #
118
+ # # expect read-back data to be same as write data = 0xc3c3a5a5
119
+ # mem_ap.read(0x2000000, 0xc3c3a5a5, size: 32, edata: 0xc3c3a5a5)
120
+ #
121
+ # # expect read-back data to be = 0xXXXXXXa5 (mask out all bits except [7:0])
122
+ # mem_ap.read(0x2000000, 0xc3c3a5a5, size: 32, edata: 0xc3c3a5a5, r_mask: 0x000000ff)
123
+ #
124
+ # Returns nothing.
125
+ def write_read(addr, wdata, options = {})
126
+ options = { size: 32 }.merge(options)
127
+ options = { edata: 0x00000000, r_mask: 0xffffffff, actual: 0x00000000 }.merge(options)
128
+ options = { w_attempts: 1, r_attempts: 2 }.merge(options)
129
+ size = options[:size]
130
+
131
+ write(addr, wdata, options)
132
+ options[:edata] = wdata & options[:r_mask] if options[:edata] == 0x00000000
133
+ read(addr, options)
134
+ actual = wdata & options[:r_mask]
135
+
136
+ cc "MEM-AP(#{@name}): WR-#{size.to_s(10)}: "\
137
+ "addr=0x#{addr.to_s(16).rjust(size / 4, '0')}, "\
138
+ "wdata=0x#{wdata.to_s(16).rjust(size / 4, '0')}, "\
139
+ "read=0x#{actual.to_s(16).rjust(size / 4, '0')}, "\
140
+ "expect=0x#{options[:edata].to_s(16).rjust(size / 4, '0')}, "\
141
+ "mask=0x#{options[:r_mask].to_s(16).rjust(size / 4, '0')}"
142
+ end
143
+
144
+ # -----------------------------------------------------------------------------
145
+ # Legacy Support (to be phased out)
146
+ # -----------------------------------------------------------------------------
147
+
148
+ # Method to read from a mem_ap register (legacy)
149
+ #
150
+ # @param [Integer] addr Address of register to be read from
151
+ # @param [Integer] rdata This really does nothing since only care about value
152
+ # of options[:edata]
153
+ # @param [Hash] options Options to customize the operation
154
+ # Returns nothing.
155
+ def R(addr, rdata, options = {})
156
+ # Warn caller that this method is being deprecated
157
+ msg = 'Use mem_ap.read(addr, options) instead of R(addr, rdata, options)'
158
+ Origen.deprecate msg
159
+
160
+ # Patch arguments and send to new method
161
+ options = { rdata: rdata }.merge(options)
162
+ read(addr, options)
163
+ end
164
+
165
+ # Method to write to a mem_ap register (legacy)
166
+ #
167
+ # @param [Integer] addr Address of register to be written to
168
+ # @param [Integer] wdata Data to be written
169
+ # @param [Hash] options Options to customize the operation
170
+ # Returns nothing.
171
+ def W(addr, wdata, options = {})
172
+ # Warn caller that this method is being deprecated
173
+ msg = 'Use mem_ap.write(addr, wdata, options) instead of W(addr, wdata, options)'
174
+ Origen.deprecate msg
175
+
176
+ # Patch arguments and send to new method
177
+ write(addr, wdata, options)
178
+ end
179
+
180
+ # Method to write and then read from a mem_ap register (legacy)
181
+ #
182
+ # @param [Integer] addr Address of register to be read from
183
+ # @param [Integer] wdata Data to be written
184
+ # @param [Hash] options Options to customize the operation
185
+ # Returns nothing.
186
+ def WR(addr, wdata, options = {})
187
+ # Warn caller that this method is being deprecated
188
+ msg = 'Use mem_ap.write_read(addr, wdata, options) instead of WR(addr, wdata, options)'
189
+ Origen.deprecate msg
190
+
191
+ # Patch arguments and send to new method
192
+ write_read(addr, wdata, options)
193
+ end
194
+
195
+ # -----------------------------------------------------------------------------
196
+ # Support Code
197
+ # -----------------------------------------------------------------------------
198
+
199
+ private
200
+
201
+ # Sets the size of the data (by writing to the CSW size bits). It will only
202
+ # write to the size if the size from the previous transaction has changed
203
+ #
204
+ # @param [Integer] size Size of data, supports 8-bit, 16-bit, and 32-bit
205
+ def set_size(size)
206
+ case size
207
+ when 8 then new_size = 0x00000000
208
+ when 16 then new_size = 0x00000001
209
+ when 32 then new_size = 0x00000002
210
+ else new_size = 0x00000002
211
+ end
212
+
213
+ if (@current_csw == 0x00000000)
214
+ debug_port.read_ap(csw_reg_addr)
215
+ @current_csw = 0x23000040
216
+ end
217
+
218
+ csw_size = @current_csw & 0x00000003
219
+ if (csw_size != new_size)
220
+ new_csw = (@current_csw & 0xfffffffc) | new_size
221
+ debug_port.write_ap(csw_reg_addr, new_csw)
222
+ @current_csw = new_csw
223
+ end
224
+ end
225
+
226
+ # Sets the addr of the transaction.
227
+ #
228
+ # @param [Integer] addr Address of data to be read from or written to
229
+ def set_addr(addr)
230
+ arm_debug_comment = "Arm Debug: Shift in read/write address: #{addr.to_hex}"
231
+ options = { arm_debug_comment: arm_debug_comment }
232
+
233
+ if (@current_tar != addr)
234
+ debug_port.write_ap(tar_reg_addr, addr, options)
235
+ end
236
+ @current_tar = addr;
237
+ end
238
+
239
+ # Increment the address for the next transaction.
240
+ def increment_addr
241
+ current_csw_5_4 = (@current_csw & 0x00000030) >> 4
242
+ current_csw_2_0 = @current_csw & 0x00000007
243
+ if (current_csw_5_4 == 0b01)
244
+ case current_csw_2_0
245
+ when 0b000 then @current_tar += 1 # Increment single
246
+ when 0b001 then @current_tar += 2 # Increment single
247
+ when 0b010 then @current_tar += 4 # Increment single
248
+ end
249
+ elsif (current_csw_5_4 == 0b10)
250
+ @current_tar += 4 # Increment packed
251
+ end
252
+
253
+ if current_csw_5_4 && ((@current_tar & 0xfffffc00) == 0xffffffff)
254
+ # reset tar when attempting to increment past 1kB boundary
255
+ @current_tar = 0xffffffff
256
+ end
257
+ end
258
+
259
+ # Create a bit-wise mask based on size, address and mask parameters.
260
+ #
261
+ # @param [Integer] size Size of data, supports 8-bit, 16-bit, and 32-bit
262
+ # @param [Integer] addr Address of data to be read from or written to
263
+ # @param [Integer] mask Mask for full data, used to create nibble mask
264
+ def get_mask(size, addr, mask)
265
+ addr_1_0 &= 0x00000003
266
+ case size
267
+ when 8
268
+ case addr_1_0
269
+ when 0b00 then mask &= 0x000000ff
270
+ when 0b01 then mask &= 0x0000ff00
271
+ when 0b10 then mask &= 0x00ff0000
272
+ when 0b11 then mask &= 0xff000000
273
+ end
274
+ when 16
275
+ case addr_1_0
276
+ when 0b00 then mask &= 0x0000ffff
277
+ when 0b10 then mask &= 0xffff0000
278
+ end
279
+ when 32
280
+ mask &= 0xffffffff
281
+ end
282
+ mask
283
+ end
284
+
285
+ # Create a bit-wise read-data based on size, address and rdata parameters.
286
+ #
287
+ # @param [Integer] size Size of data, supports 8-bit, 16-bit, and 32-bit
288
+ # @param [Integer] addr Address of data to be read from or written to
289
+ # @param [Integer] rdata Full data for read, used to create nibble read data
290
+ def get_rdata(size, addr, rdata)
291
+ addr_1_0 &= 0x00000003
292
+ case size
293
+ when 8
294
+ case addr_1_0
295
+ when 0b00 then rdata = 0x000000ff & rdata
296
+ when 0b01 then rdata = 0x000000ff & (rdata >> 8)
297
+ when 0b10 then rdata = 0x000000ff & (rdata >> 16)
298
+ when 0b11 then rdata = 0x000000ff & (rdata >> 24)
299
+ end
300
+ when 16
301
+ case addr_1_0
302
+ when 0b00 then rdata = 0x0000ffff & rdata
303
+ when 0b10 then rdata = 0x0000ffff & (rdata >> 16)
304
+ end
305
+ when 32
306
+ rdata = rdata
307
+ end
308
+ rdata
309
+ end
310
+
311
+ # Create a bit-wise read-data based on size, address and wdata parameters.
312
+ #
313
+ # @param [Integer] size Size of data, supports 8-bit, 16-bit, and 32-bit
314
+ # @param [Integer] addr Address of data to be read from or written to
315
+ # @param [Integer] wdata Full data for write, used to create nibble write data
316
+ def get_wdata(size, addr, wdata);
317
+ addr_1_0 &= 0x00000003
318
+ case size
319
+ when 8
320
+ case addr_1_0
321
+ when 0b00 then wdata = 0x000000ff & wdata
322
+ when 0b01 then wdata = 0x0000ff00 & (wdata << 8)
323
+ when 0b10 then wdata = 0x00ff0000 & (wdata << 16)
324
+ when 0b11 then wdata = 0xff000000 & (wdata << 24)
325
+ end
326
+ when 16
327
+ case addr_1_0
328
+ when 0b00 then wdata = 0x0000ffff & wdata
329
+ when 0b10 then wdata = 0xffff0000 & (wdata << 16)
330
+ end
331
+ when 32
332
+ wdata = wdata
333
+ end
334
+ wdata
335
+ end
336
+
337
+ # Returns address of CSW register for this mem-ap instance
338
+ def csw_reg_addr
339
+ MEM_ADDR_CSW + @base_address
340
+ end
341
+
342
+ # Returns address of TAR register for this mem-ap instance
343
+ def tar_reg_addr
344
+ MEM_ADDR_TAR + @base_address
345
+ end
346
+
347
+ # Returns address of DRW register for this mem-ap instance
348
+ def drw_reg_addr
349
+ MEM_ADDR_DRW + @base_address
350
+ end
351
+
352
+ # Returns address of BD0 register for this mem-ap instance
353
+ def bdo_reg_addr
354
+ MEM_ADDR_BD0 + @base_address
355
+ end
356
+
357
+ # Returns address of BD1 register for this mem-ap instance
358
+ def bd1_reg_addr
359
+ MEM_ADDR_BD1 + @base_address
360
+ end
361
+
362
+ # Returns address of BD2 register for this mem-ap instance
363
+ def bd2_reg_addr
364
+ MEM_ADDR_BD2 + @base_address
365
+ end
366
+
367
+ # Returns address of BD3 register for this mem-ap instance
368
+ def bd3_reg_addr
369
+ MEM_ADDR_BD3 + @base_address
370
+ end
371
+
372
+ # Returns address of CFG register for this mem-ap instance
373
+ def cfg_reg_addr
374
+ MEM_ADDR_CFG + @base_address
375
+ end
376
+
377
+ # Returns address of BASE register for this mem-ap instance
378
+ def base_reg_addr
379
+ MEM_ADDR_BASE + @base_address
380
+ end
381
+
382
+ # Returns address of IDR register for this mem-ap instance
383
+ def idr_reg_addr
384
+ MEM_ADDR_IDR + @base_address
385
+ end
386
+ end
387
+ end