origen_arm_debug 0.4.0

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.
@@ -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