]> sigrok.org Git - libsigrokdecode.git/blame - decoders/jtag_ejtag/pd.py
jtag_ejtag: Shorten a variable name.
[libsigrokdecode.git] / decoders / jtag_ejtag / pd.py
CommitLineData
4bfb9af7
VI
1##
2## This file is part of the libsigrokdecode project.
3##
4## Copyright (C) 2018 Vladislav Ivanov <vlad.ivanov@lab-systems.ru>
5##
6## This program is free software; you can redistribute it and/or modify
7## it under the terms of the GNU General Public License as published by
8## the Free Software Foundation; either version 2 of the License, or
9## (at your option) any later version.
10##
11## This program is distributed in the hope that it will be useful,
12## but WITHOUT ANY WARRANTY; without even the implied warranty of
13## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14## GNU General Public License for more details.
15##
16## You should have received a copy of the GNU General Public License
17## along with this program; if not, see <http://www.gnu.org/licenses/>.
18##
19
20import sigrokdecode as srd
392a5d1e 21from common.srdhelper import bin2int
4bfb9af7
VI
22
23class Instruction(object):
24 IDCODE = 0x01
25 IMPCODE = 0x03
26 ADDRESS = 0x08
27 DATA = 0x09
28 CONTROL = 0x0A
29 ALL = 0x0B
30 EJTAGBOOT = 0x0C
31 NORMALBOOT = 0x0D
32 FASTDATA = 0x0E
33 TCBCONTROLA = 0x10
34 TCBCONTROLB = 0x11
35 TCBDATA = 0x12
36 TCBCONTROLC = 0x13
37 PCSAMPLE = 0x14
38 TCBCONTROLD = 0x15
39 TCBCONTROLE = 0x16
40
41class State(object):
42 RESET = 0
43 DEVICE_ID = 1
44 IMPLEMENTATION = 2
45 DATA = 3
46 ADDRESS = 4
47 CONTROL = 5
48 FASTDATA = 6
49 PC_SAMPLE = 7
50 BYPASS = 8
51
52class ControlReg(object):
53 PRACC = (1 << 18)
54 PRNW = (1 << 19)
55
56class Ann(object):
57 INSTRUCTION = 0
58 REGISTER = 1
59 CONTROL_FIELD_IN = 10
60 CONTROL_FIELD_OUT = 11
61 PRACC = 12
62
63ejtag_insn = {
64 0x00: ['Free', 'Boundary scan'],
65 0x01: ['IDCODE', 'Select Device Identification (ID) register'],
66 0x02: ['Free', 'Boundary scan'],
67 0x03: ['IMPCODE', 'Select Implementation register'],
68 0x08: ['ADDRESS', 'Select Address register'],
69 0x09: ['DATA', 'Select Data register'],
70 0x0A: ['CONTROL', 'Select EJTAG Control register'],
71 0x0B: ['ALL', 'Select the Address, Data and EJTAG Control registers'],
72 0x0C: ['EJTAGBOOT', 'Fetch code from the debug exception vector after reset'],
73 0x0D: ['NORMALBOOT', 'Execute the reset handler after reset'],
74 0x0E: ['FASTDATA', 'Select the Data and Fastdata registers'],
75 0x0F: ['Reserved', 'Reserved'],
76 0x10: ['TCBCONTROLA', 'Select the control register TCBTraceControl'],
77 0x11: ['TCBCONTROLB', 'Selects trace control block register B'],
78 0x12: ['TCBDATA', 'Access the registers specified by TCBCONTROLB'],
79 0x13: ['TCBCONTROLC', 'Select trace control block register C'],
80 0x14: ['PCSAMPLE', 'Select the PCsample register'],
81 0x15: ['TCBCONTROLD', 'Select trace control block register D'],
82 0x16: ['TCBCONTROLE', 'Select trace control block register E'],
83 0x17: ['FDC', 'Select Fast Debug Channel'],
84 0x1C: ['Free', 'Boundary scan'],
85}
86
87ejtag_reg = {
88 0x00: 'RESET',
89 0x01: 'DEVICE_ID',
90 0x02: 'IMPLEMENTATION',
91 0x03: 'DATA',
92 0x04: 'ADDRESS',
93 0x05: 'CONTROL',
94 0x06: 'FASTDATA',
95 0x07: 'PC_SAMPLE',
96 0x08: 'BYPASS',
97}
98
99ejtag_control_reg = [
100 [31, 31, 'Rocc', [
101 # Read
102 ['No reset ocurred', 'Reset ocurred'],
103 # Write
104 ['Acknowledge reset', 'No effect'],
105 ]],
106 [30, 29, 'Psz', [
107 ['Access: byte', 'Access: halfword', 'Access: word', 'Access: triple'],
108 ]],
109 [23, 23, 'VPED', [
110 ['VPE disabled', 'VPE enabled'],
111 ]],
112 [22, 22, 'Doze', [
113 ['Processor is not in low-power mode', 'Processor is in low-power mode'],
114 ]],
115 [21, 21, 'Halt', [
116 ['Internal system bus clock is running', 'Internal system bus clock is stopped'],
117 ]],
118 [20, 20, 'Per Rst', [
119 ['No peripheral reset applied', 'Peripheral reset applied'],
120 ['Deassert peripheral reset', 'Assert peripheral reset'],
121 ]],
122 [19, 19, 'PRn W', [
123 ['Read processor access', 'Write processor access'],
124 ]],
125 [18, 18, 'Pr Acc', [
126 ['No pending processor access', 'Pending processor access'],
127 ['Finish processor access', 'Don\'t finish processor access'],
128 ]],
129 [16, 16, 'Pr Rst', [
130 ['No processor reset applied', 'Processor reset applied'],
131 ['Deassert processor reset', 'Assert system reset'],
132 ]],
133 [15, 15, 'Prob En', [
134 ['Probe will not serve processor accesses', 'Probe will service processor accesses'],
135 ]],
136 [14, 14, 'Prob Trap', [
137 ['Default location', 'DMSEG fetch'],
138 ['Set to default location', 'Set to DMSEG fetch'],
139 ]],
140 [13, 13, 'ISA On Debug', [
141 ['MIPS32/MIPS64 ISA', 'microMIPS ISA'],
142 ['Set to MIPS32/MIPS64 ISA', 'Set to microMIPS ISA'],
143 ]],
144 [12, 12, 'EJTAG Brk', [
145 ['No pending debug interrupt', 'Pending debug interrupt'],
146 ['No effect', 'Request debug interrupt'],
147 ]],
148 [3, 3, 'DM', [
149 ['Not in debug mode', 'In debug mode'],
150 ]],
151]
152
153ejtag_state_map = {
154 Instruction.IDCODE: State.DEVICE_ID,
155 Instruction.IMPCODE: State.IMPLEMENTATION,
156 Instruction.DATA: State.DATA,
157 Instruction.ADDRESS: State.ADDRESS,
158 Instruction.CONTROL: State.CONTROL,
159 Instruction.FASTDATA: State.FASTDATA,
160}
161
4bfb9af7
VI
162class RegData(object):
163 def __init__(self):
164 self.ss = None
165 self.es = None
166 self.data = None
167
168class LastData(object):
169 def __init__(self):
170 self.data_in = RegData()
171 self.data_out = RegData()
172
173class PraccState(object):
174 def reset(self):
175 self.address_in = None
176 self.address_out = None
177 self.data_in = None
178 self.data_out = None
179 self.write = False
d1b7bd1b
UH
180 self.ss = 0
181 self.es = 0
4bfb9af7
VI
182
183 def __init__(self):
184 self.reset()
185
186regs_items = {
187 'ann': tuple([tuple([s.lower(), s]) for s in list(ejtag_reg.values())]),
188 'rows_range': tuple(range(1, 1 + 9)),
189}
190
191class Decoder(srd.Decoder):
192 api_version = 3
193 id = 'jtag_ejtag'
194 name = 'JTAG / EJTAG (MIPS)'
195 longname = 'Joint Test Action Group / EJTAG (MIPS)'
196 desc = 'MIPS EJTAG protocol.'
197 license = 'gplv2+'
198 inputs = ['jtag']
199 outputs = ['jtag_ejtag']
200 annotations = (
201 ('instruction', 'Instruction'),
202 ) + regs_items['ann'] + (
203 ('control_field_in', 'Control field in'),
204 ('control_field_out', 'Control field out'),
205 ('pracc', 'PrAcc'),
206 )
207 annotation_rows = (
208 ('instructions', 'Instructions', (0,)),
209 ('regs', 'Registers', regs_items['rows_range']),
210 ('control_fields_in', 'Control fields in', (10,)),
211 ('control_fields_out', 'Control fields out', (11,)),
212 ('pracc', 'PrAcc', (12,)),
213 )
214
215 def __init__(self):
216 self.reset()
217
218 def reset(self):
219 self.state = State.RESET
220 self.pracc_state = PraccState()
221
222 def put_current(self, data):
223 self.put(self.ss, self.es, self.out_ann, data)
224
225 def put_at(self, ss: int, es: int, data):
f78b814d 226 self.put(ss, es, self.out_ann, data)
4bfb9af7
VI
227
228 def start(self):
229 self.out_ann = self.register(srd.OUTPUT_ANN)
230
231 def select_reg(self, ir_value: int):
aaaf37e1 232 self.state = ejtag_state_map.get(ir_value, State.RESET)
4bfb9af7
VI
233
234 def parse_pracc(self):
392a5d1e
UH
235 control_in = bin2int(self.last_data['in']['data'][0])
236 control_out = bin2int(self.last_data['out']['data'][0])
4bfb9af7
VI
237
238 # Check if JTAG master acknowledges a pending PrAcc.
239 if not ((not (control_in & ControlReg.PRACC)) and \
240 (control_out & ControlReg.PRACC)):
241 return
242
d1b7bd1b 243 ss, es = self.pracc_state.ss, self.pracc_state.es
4bfb9af7
VI
244 pracc_write = (control_out & ControlReg.PRNW) != 0
245
288e22b0
UH
246 s = 'PrAcc: '
247 s += 'Store' if pracc_write else 'Load/Fetch'
4bfb9af7
VI
248
249 if pracc_write:
44c2ae6e 250 if self.pracc_state.address_out is not None:
288e22b0 251 s += ', A:' + ' 0x{:08X}'.format(self.pracc_state.address_out)
44c2ae6e 252 if self.pracc_state.data_out is not None:
288e22b0 253 s += ', D:' + ' 0x{:08X}'.format(self.pracc_state.data_out)
4bfb9af7 254 else:
44c2ae6e 255 if self.pracc_state.address_out is not None:
288e22b0 256 s += ', A:' + ' 0x{:08X}'.format(self.pracc_state.address_out)
44c2ae6e 257 if self.pracc_state.data_in is not None:
288e22b0 258 s += ', D:' + ' 0x{:08X}'.format(self.pracc_state.data_in)
4bfb9af7
VI
259
260 self.pracc_state.reset()
261
288e22b0 262 self.put_at(ss, es, [Ann.PRACC, [s]])
4bfb9af7
VI
263
264 def parse_control_reg(self, ann):
265 reg_write = ann == Ann.CONTROL_FIELD_IN
266 control_bit_positions = []
aaaf37e1 267 data_select = 'in' if (reg_write) else 'out'
4bfb9af7
VI
268
269 control_bit_positions = self.last_data[data_select]['data'][1]
270 control_data = self.last_data[data_select]['data'][0]
271
272 # Annotate control register fields.
273 for field in ejtag_control_reg:
274 start_bit = 31 - field[1]
275 end_bit = 31 - field[0]
276 comment = field[2]
277 value_descriptions = []
278
279 if reg_write:
280 if len(field[3]) < 2:
281 continue
282 value_descriptions = field[3][1]
283 else:
284 value_descriptions = field[3][0]
285
d1b7bd1b
UH
286 ss = control_bit_positions[start_bit][0]
287 es = control_bit_positions[end_bit][1]
4bfb9af7
VI
288
289 value_str = control_data[end_bit : start_bit + 1]
392a5d1e 290 value_index = bin2int(value_str)
4bfb9af7
VI
291
292 short_desc = comment + ': ' + value_str
293 long_desc = value_descriptions[value_index] if len(value_descriptions) > value_index else '?'
4bfb9af7 294
288e22b0 295 self.put_at(ss, es, [ann, [long_desc, short_desc]])
4bfb9af7
VI
296
297 def check_last_data(self):
298 if not hasattr(self, 'last_data'):
299 self.last_data = {'in': {}, 'out': {}}
300
301 def handle_fastdata(self, val, ann):
302 spracc_write_desc = {
303 0: ['0', 'SPrAcc: 0', 'Request completion of Fastdata access'],
304 1: ['1', 'SPrAcc: 1', 'No effect'],
305 }
306 spracc_read_desc = {
307 0: ['0', 'SPrAcc: 0', 'Fastdata access failure'],
308 1: ['1', 'SPrAcc: 1', 'Successful completion of Fastdata access'],
309 }
310
311 bitstring = val[0]
312 bit_sample_pos = val[1]
313 fastdata_state = bitstring[32]
392a5d1e 314 data = bin2int(bitstring[0:32])
4bfb9af7
VI
315
316 fastdata_bit_pos = bit_sample_pos[32]
317 data_pos = [bit_sample_pos[31][0], bit_sample_pos[0][1]]
318
d1b7bd1b
UH
319 ss_fastdata, es_fastdata = fastdata_bit_pos
320 ss_data, es_data = data_pos
4bfb9af7
VI
321
322 display_data = [ann, ['0x{:08X}'.format(data)]]
323 spracc_display_data = []
324
325 if ann == Ann.CONTROL_FIELD_IN:
326 spracc_display_data = [ann, spracc_write_desc[int(fastdata_state)]]
327 elif ann == Ann.CONTROL_FIELD_OUT:
328 spracc_display_data = [ann, spracc_read_desc[int(fastdata_state)]]
329
d1b7bd1b
UH
330 self.put_at(ss_fastdata, es_fastdata, spracc_display_data)
331 self.put_at(ss_data, es_data, display_data)
4bfb9af7
VI
332
333 def handle_dr_tdi(self, val):
392a5d1e 334 value = bin2int(val[0])
4bfb9af7
VI
335 self.check_last_data()
336 self.last_data['in'] = {'ss': self.ss, 'es': self.es, 'data': val}
337
d1b7bd1b 338 self.pracc_state.ss, self.pracc_state.es = self.ss, self.es
4bfb9af7
VI
339
340 if self.state == State.ADDRESS:
341 self.pracc_state.address_in = value
342 elif self.state == State.DATA:
343 self.pracc_state.data_in = value
344 elif self.state == State.FASTDATA:
345 self.handle_fastdata(val, Ann.CONTROL_FIELD_IN)
346
347 def handle_dr_tdo(self, val):
392a5d1e 348 value = bin2int(val[0])
4bfb9af7
VI
349 self.check_last_data()
350 self.last_data['out'] = {'ss': self.ss, 'es': self.es, 'data': val}
351 if self.state == State.ADDRESS:
352 self.pracc_state.address_out = value
353 elif self.state == State.DATA:
354 self.pracc_state.data_out = value
355 elif self.state == State.FASTDATA:
356 self.handle_fastdata(val, Ann.CONTROL_FIELD_OUT)
357
358 def handle_ir_tdi(self, val):
392a5d1e 359 code = bin2int(val[0])
49d3e6f8 360 hexval = '0x{:02X}'.format(code)
4bfb9af7
VI
361 if code in ejtag_insn:
362 # Format instruction name.
363 insn = ejtag_insn[code]
364 s_short = insn[0]
49d3e6f8 365 s_long = insn[0] + ': ' + insn[1] + ' (' + hexval + ')'
4bfb9af7 366 # Display it and select data register.
068960b6 367 self.put_current([Ann.INSTRUCTION, [s_long, s_short]])
4bfb9af7 368 else:
49d3e6f8 369 self.put_current([Ann.INSTRUCTION, [hexval, 'IR TDI ({})'.format(hexval)]])
4bfb9af7
VI
370 self.select_reg(code)
371
372 def handle_new_state(self, new_state):
373 if new_state != 'UPDATE-DR' or not hasattr(self, 'last_data'):
374 return
375
376 if self.state == State.RESET:
377 return
378
379 reg_name = ejtag_reg[self.state]
380 ann_index = Ann.REGISTER + self.state
381 display_data = [ann_index, [reg_name]]
382 self.put_at(self.last_data['in']['ss'], self.last_data['in']['es'], display_data)
383
384 if self.state == State.CONTROL:
385 control_bit_positions = self.last_data['in']['data'][1]
386 bit_count = len(control_bit_positions)
387 # Check if control register data length is correct.
388 if bit_count != 32:
389 error_display = [Ann.REGISTER, ['Error: length != 32']]
390 self.put_at(self.last_data['in']['ss'], self.last_data['in']['es'], error_display)
391 return
392 self.parse_control_reg(Ann.CONTROL_FIELD_IN)
393 self.parse_control_reg(Ann.CONTROL_FIELD_OUT)
394 self.parse_pracc()
395
396 def decode(self, ss: int, es: int, data):
397 cmd, val = data
398 self.ss, self.es = ss, es
399
400 if cmd == 'IR TDI':
401 self.handle_ir_tdi(val)
402 elif cmd == 'DR TDI':
403 self.handle_dr_tdi(val)
404 elif cmd == 'DR TDO':
405 self.handle_dr_tdo(val)
406 elif cmd == 'NEW STATE':
407 self.handle_new_state(val)