Dick Hollenbeck <dick@softplc.com> SVF to XSVF converter and the XSVF dumper take #2
[openocd.git] / tools / xsvf_tools / svf2xsvf.py
1 #!/usr/bin/python3.0
2
3 # Copyright 2008, SoftPLC Corporation http://softplc.com
4 # Dick Hollenbeck dick@softplc.com
5
6
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, you may find one here:
19 # http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 # or you may search the http://www.gnu.org website for the version 2 license,
21 # or you may write to the Free Software Foundation, Inc.,
22 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23
24
25 # A python program to convert an SVF file to an XSVF file. There is an
26 # option to include comments containing the source file line number from the origin
27 # SVF file before each outputted XSVF statement.
28 #
29 # We deviate from the XSVF spec in that we introduce a new command called
30 # XWAITSTATE which directly flows from the SVF RUNTEST command. Unfortunately
31 # XRUNSTATE was ill conceived and is not used here. We also add support for the
32 # three Lattice extensions to SVF: LCOUNT, LDELAY, and LSDR. The xsvf file
33 # generated from this program is suitable for use with the xsvf player in
34 # OpenOCD with my modifications to xsvf.c.
35 #
36 # This program is written for python 3.0, and it is not easy to change this
37 # back to 2.x. You may find it easier to use python 3.x even if that means
38 # building it.
39
40
41 import re
42 import sys
43 import struct
44
45
46 # There are both ---<Lexer>--- and ---<Parser>--- sections to this program
47
48
49 if len( sys.argv ) < 3:
50 print("usage %s <svf_filename> <xsvf_filename>" % sys.argv[0])
51 exit(1)
52
53
54 inputFilename = sys.argv[1]
55 outputFilename = sys.argv[2]
56
57 doCOMMENTs = True # Save XCOMMENTs in the output xsvf file
58 #doCOMMENTs = False # Save XCOMMENTs in the output xsvf file
59
60 xrepeat = 0 # argument to XREPEAT, gives retry count for masked compares
61
62
63 #-----< Lexer >---------------------------------------------------------------
64
65 StateBin = (RESET,IDLE,
66 DRSELECT,DRCAPTURE,DRSHIFT,DREXIT1,DRPAUSE,DREXIT2,DRUPDATE,
67 IRSELECT,IRCAPTURE,IRSHIFT,IREXIT1,IRPAUSE,IREXIT2,IRUPDATE) = range(16)
68
69 # Any integer index into this tuple will be equal to its corresponding StateBin value
70 StateTxt = ("RESET","IDLE",
71 "DRSELECT","DRCAPTURE","DRSHIFT","DREXIT1","DRPAUSE","DREXIT2","DRUPDATE",
72 "IRSELECT","IRCAPTURE","IRSHIFT","IREXIT1","IRPAUSE","IREXIT2","IRUPDATE")
73
74
75 (XCOMPLETE,XTDOMASK,XSIR,XSDR,XRUNTEST,hole0,hole1,XREPEAT,XSDRSIZE,XSDRTDO,
76 XSETSDRMASKS,XSDRINC,XSDRB,XSDRC,XSDRE,XSDRTDOB,XSDRTDOC,
77 XSDRTDOE,XSTATE,XENDIR,XENDDR,XSIR2,XCOMMENT,XWAIT,XWAITSTATE,LCOUNT,LDELAY,LSDR) = range(28)
78
79 #Note: LCOUNT, LDELAY, and LSDR are Lattice extensions to SVF and provide a way to loop back
80 # and check a completion status, essentially waiting on a part until it signals that it is done.
81 # For example below: loop 25 times, each time through the loop do a LDELAY (same as a true RUNTEST)
82 # and exit loop when LSDR compares match.
83 """
84 LCOUNT 25;
85 ! Step to DRPAUSE give 5 clocks and wait for 1.00e+000 SEC.
86 LDELAY DRPAUSE 5 TCK 1.00E-003 SEC;
87 ! Test for the completed status. Match means pass.
88 ! Loop back to LDELAY line if not match and loop count less than 25.
89 LSDR 1 TDI (0)
90 TDO (1);
91 """
92
93 LineNumber = 1
94
95 def s_ident(scanner, token): return ("ident", token.upper(), LineNumber)
96
97 def s_hex(scanner, token):
98 global LineNumber
99 LineNumber = LineNumber + token.count('\n')
100 token = ''.join(token.split())
101 return ("hex", token[1:-1], LineNumber)
102
103 def s_int(scanner, token): return ("int", int(token), LineNumber)
104 def s_float(scanner, token): return ("float", float(token), LineNumber)
105 #def s_comment(scanner, token): return ("comment", token, LineNumber)
106 def s_semicolon(scanner, token): return ("semi", token, LineNumber)
107
108 def s_nl(scanner,token):
109 global LineNumber
110 LineNumber = LineNumber + 1
111 #print( 'LineNumber=', LineNumber, file=sys.stderr )
112 return None
113
114 #2.00E-002
115
116 scanner = re.Scanner([
117 (r"[a-zA-Z]\w*", s_ident),
118 # (r"[-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?", s_float),
119 (r"[-+]?[0-9]+(([.][0-9eE+-]*)|([eE]+[-+]?[0-9]+))", s_float),
120 (r"\d+", s_int),
121 (r"\(([0-9a-fA-F]|\s)*\)", s_hex),
122 (r"(!|//).*$", None),
123 (r";", s_semicolon),
124 (r"\n",s_nl),
125 (r"\s*", None),
126 ],
127 re.MULTILINE
128 )
129
130 # read all svf file input into string "input"
131 input = open( sys.argv[1] ).read()
132
133 # Lexer:
134 # create a list of tuples containing (tokenType, tokenValue, LineNumber)
135 tokens = scanner.scan( input )[0]
136
137 input = None # allow gc to reclaim memory holding file
138
139 #for tokenType, tokenValue, ln in tokens: print( "line %d: %s" % (ln, tokenType), tokenValue )
140
141
142 #-----<parser>-----------------------------------------------------------------
143
144 tokVal = tokType = tokLn = None
145
146 tup = iter( tokens )
147
148 def nextTok():
149 """
150 Function to read the next token from tup into tokType, tokVal, tokLn (linenumber)
151 which are globals.
152 """
153 global tokType, tokVal, tokLn, tup
154 tokType, tokVal, tokLn = tup.__next__()
155
156
157 class ParseError(Exception):
158 """A class to hold a parsing error message"""
159 def __init__(self, linenumber, token, message):
160 self.linenumber = linenumber
161 self.token = token
162 self.message = message
163 def __str__(self):
164 global inputFilename
165 return "Error in file \'%s\' at line %d near token %s\n %s" % (
166 inputFilename, self.linenumber, repr(self.token), self.message)
167
168
169 class MASKSET(object):
170 """
171 Class MASKSET holds a set of bit vectors, all of which are related, will all
172 have the same length, and are associated with one of the seven shiftOps:
173 HIR, HDR, TIR, TDR, SIR, SDR, LSDR. One of these holds a mask, smask, tdi, tdo, and a
174 size.
175 """
176 def __init__(self, name):
177 self.empty()
178 self.name = name
179
180 def empty(self):
181 self.mask = bytearray()
182 self.smask = bytearray()
183 self.tdi = bytearray()
184 self.tdo = bytearray()
185 self.size = 0
186
187 def syncLengths( self, sawTDI, sawTDO, sawMASK, sawSMASK, newSize ):
188 """
189 Set all the lengths equal in the event some of the masks were
190 not seen as part of the last change set.
191 """
192 if self.size == newSize:
193 return
194
195 if newSize == 0:
196 self.empty()
197 return
198
199 # If an SIR was given without a MASK(), then use a mask of all zeros.
200 # this is not consistent with the SVF spec, but it makes sense because
201 # it would be odd to be testing an instruction register read out of a
202 # tap without giving a mask for it. Also, lattice seems to agree and is
203 # generating SVF files that comply with this philosophy.
204 if self.name == 'SIR' and not sawMASK:
205 self.mask = bytearray( newSize )
206
207 if newSize != len(self.mask):
208 self.mask = bytearray( newSize )
209 if self.name == 'SDR': # leave mask for HIR,HDR,TIR,TDR,SIR zeros
210 for i in range( newSize ):
211 self.mask[i] = 1
212
213 if newSize != len(self.tdo):
214 self.tdo = bytearray( newSize )
215
216 if newSize != len(self.tdi):
217 self.tdi = bytearray( newSize )
218
219 if newSize != len(self.smask):
220 self.smask = bytearray( newSize )
221
222 self.size = newSize
223 #-----</MASKSET>-----
224
225
226 def makeBitArray( hexString, bitCount ):
227 """
228 Converts a packed sequence of hex ascii characters into a bytearray where
229 each element in the array holds exactly one bit. Only "bitCount" bits are
230 scanned and these must be the least significant bits in the hex number. That
231 is, it is legal to have some unused bits in the must significant hex nibble
232 of the input "hexString". The string is scanned starting from the backend,
233 then just before returning we reverse the array. This way the append()
234 method can be used, which I assume is faster than an insert.
235 """
236 global tokLn
237 a = bytearray()
238 length = bitCount
239 hexString = list(hexString)
240 hexString.reverse()
241 #print(hexString)
242 for c in hexString:
243 if length <= 0:
244 break;
245 c = int(c, 16)
246 for mask in [1,2,4,8]:
247 if length <= 0:
248 break;
249 length = length - 1
250 a.append( (c & mask) != 0 )
251 if length > 0:
252 raise ParseError( tokLn, hexString, "Insufficient hex characters for given length of %d" % bitCount )
253 a.reverse()
254 #print(a)
255 return a
256
257
258 def makeXSVFbytes( bitarray ):
259 """
260 Make a bytearray which is contains the XSVF bits which will be written
261 directly to disk. The number of bytes needed is calculated from the size
262 of the argument bitarray.
263 """
264 bitCount = len(bitarray)
265 byteCount = (bitCount+7)//8
266 ba = bytearray( byteCount )
267 firstBit = (bitCount % 8) - 1
268 if firstBit == -1:
269 firstBit = 7
270 bitNdx = 0
271 for byteNdx in range(byteCount):
272 mask = 1<<firstBit
273 byte = 0
274 while mask:
275 if bitarray[bitNdx]:
276 byte |= mask;
277 mask = mask >> 1
278 bitNdx = bitNdx + 1
279 ba[byteNdx] = byte
280 firstBit = 7
281 return ba
282
283
284 def writeComment( outputFile, shiftOp_linenum, shiftOp ):
285 """
286 Write an XCOMMENT record to outputFile
287 """
288 comment = "%s @%d\0" % (shiftOp, shiftOp_linenum) # \0 is terminating nul
289 ba = bytearray(1)
290 ba[0] = XCOMMENT
291 ba += comment.encode()
292 outputFile.write( ba )
293
294
295 def combineBitVectors( trailer, meat, header ):
296 """
297 Combine the 3 bit vectors comprizing a transmission. Since the least
298 significant bits are sent first, the header is put onto the list last so
299 they are sent first from that least significant position.
300 """
301 ret = bytearray()
302 ret.extend( trailer )
303 ret.extend( meat )
304 ret.extend( header )
305 return ret
306
307
308 def writeRUNTEST( outputFile, run_state, end_state, run_count, min_time, tokenTxt ):
309 """
310 Write the output for the SVF RUNTEST command.
311 run_count - the number of clocks
312 min_time - the number of seconds
313 tokenTxt - either RUNTEST or LDELAY
314 """
315 # convert from secs to usecs
316 min_time = int( min_time * 1000000)
317
318 # the SVF RUNTEST command does NOT map to the XSVF XRUNTEST command. Check the SVF spec, then
319 # read the XSVF command. They are not the same. Use an XSVF XWAITSTATE to
320 # implement the required behavior of the SVF RUNTEST command.
321 if doCOMMENTs:
322 writeComment( output, tokLn, tokenTxt )
323
324 if tokenTxt == 'RUNTEST':
325 obuf = bytearray(11)
326 obuf[0] = XWAITSTATE
327 obuf[1] = run_state
328 obuf[2] = end_state
329 struct.pack_into(">i", obuf, 3, run_count ) # big endian 4 byte int to obuf
330 struct.pack_into(">i", obuf, 7, min_time ) # big endian 4 byte int to obuf
331 outputFile.write( obuf )
332 else: # == 'LDELAY'
333 obuf = bytearray(10)
334 obuf[0] = LDELAY
335 obuf[1] = run_state
336 # LDELAY has no end_state
337 struct.pack_into(">i", obuf, 2, run_count ) # big endian 4 byte int to obuf
338 struct.pack_into(">i", obuf, 6, min_time ) # big endian 4 byte int to obuf
339 outputFile.write( obuf )
340
341
342 output = open( outputFilename, mode='wb' )
343
344 hir = MASKSET('HIR')
345 hdr = MASKSET('HDR')
346 tir = MASKSET('TIR')
347 tdr = MASKSET('TDR')
348 sir = MASKSET('SIR')
349 sdr = MASKSET('SDR')
350
351
352 expecting_eof = True
353
354
355 # one of the commands that take the shiftParts after the length, the parse
356 # template for all of these commands is identical
357 shiftOps = ('SDR', 'SIR', 'LSDR', 'HDR', 'HIR', 'TDR', 'TIR')
358
359 # the order must correspond to shiftOps, this holds the MASKSETS. 'LSDR' shares sdr with 'SDR'
360 shiftSets = (sdr, sir, sdr, hdr, hir, tdr, tir )
361
362 # what to expect as parameters to a shiftOp, i.e. after a SDR length or SIR length
363 shiftParts = ('TDI', 'TDO', 'MASK', 'SMASK')
364
365 # the set of legal states which can trail the RUNTEST command
366 run_state_allowed = ('IRPAUSE', 'DRPAUSE', 'RESET', 'IDLE')
367
368 enddr_state_allowed = ('DRPAUSE', 'IDLE')
369 endir_state_allowed = ('IRPAUSE', 'IDLE')
370
371 enddr_state = IDLE
372 endir_state = IDLE
373
374 frequency = 1.00e+006 # HZ;
375
376 # change detection for xsdrsize and xtdomask
377 xsdrsize = -1 # the last one sent, send only on change
378 xtdomask = bytearray() # the last one sent, send only on change
379
380
381 # we use a number of single byte writes for the XSVF command below
382 cmdbuf = bytearray(1)
383
384
385 # Save the XREPEAT setting into the file as first thing.
386 obuf = bytearray(2)
387 obuf[0] = XREPEAT
388 obuf[1] = xrepeat
389 output.write( obuf )
390
391
392 try:
393 while 1:
394 expecting_eof = True
395 nextTok()
396 expecting_eof = False
397 # print( tokType, tokVal, tokLn )
398
399 if tokVal in shiftOps:
400 shiftOp_linenum = tokLn
401 shiftOp = tokVal
402
403 set = shiftSets[shiftOps.index(shiftOp)]
404
405 # set flags false, if we see one later, set that one true later
406 sawTDI = sawTDO = sawMASK = sawSMASK = False
407
408 nextTok()
409 if tokType != 'int':
410 raise ParseError( tokLn, tokVal, "Expecting 'int' giving %s length, got '%s'" % (shiftOp, tokType) )
411 length = tokVal
412
413 nextTok()
414
415 while tokVal != ';':
416 if tokVal not in shiftParts:
417 raise ParseError( tokLn, tokVal, "Expecting TDI, TDO, MASK, SMASK, or ';'")
418 shiftPart = tokVal
419
420 nextTok()
421
422 if tokType != 'hex':
423 raise ParseError( tokLn, tokVal, "Expecting hex bits" )
424 bits = makeBitArray( tokVal, length )
425
426 if shiftPart == 'TDI':
427 sawTDI = True
428 set.tdi = bits
429
430 elif shiftPart == 'TDO':
431 sawTDO = True
432 set.tdo = bits
433
434 elif shiftPart == 'MASK':
435 sawMASK = True
436 set.mask = bits
437
438 elif shiftPart == 'SMASK':
439 sawSMASK = True
440 set.smask = bits
441
442 nextTok()
443
444 set.syncLengths( sawTDI, sawTDO, sawMASK, sawSMASK, length )
445
446 # process all the gathered parameters and generate outputs here
447 if shiftOp == 'SIR':
448 if doCOMMENTs:
449 writeComment( output, shiftOp_linenum, 'SIR' )
450
451 tdi = combineBitVectors( tir.tdi, sir.tdi, hir.tdi )
452 if len(tdi) > 255:
453 obuf = bytearray(3)
454 obuf[0] = XSIR2
455 struct.pack_into( ">h", obuf, 1, len(tdi) )
456 else:
457 obuf = bytearray(2)
458 obuf[0] = XSIR
459 obuf[1] = len(tdi)
460 output.write( obuf )
461 obuf = makeXSVFbytes( tdi )
462 output.write( obuf )
463
464 elif shiftOp == 'SDR':
465 if doCOMMENTs:
466 writeComment( output, shiftOp_linenum, shiftOp )
467
468 if not sawTDO:
469 # pass a zero filled bit vector for the sdr.mask
470 mask = combineBitVectors( tdr.mask, bytearray(sdr.size), hdr.mask )
471 tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi )
472
473 if xsdrsize != len(tdi):
474 xsdrsize = len(tdi)
475 cmdbuf[0] = XSDRSIZE
476 output.write( cmdbuf )
477 obuf = bytearray(4)
478 struct.pack_into( ">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf
479 output.write( obuf )
480
481 if xtdomask != mask:
482 xtdomask = mask
483 cmdbuf[0] = XTDOMASK
484 output.write( cmdbuf )
485 obuf = makeXSVFbytes( mask )
486 output.write( obuf )
487
488 cmdbuf[0] = XSDR
489 output.write( cmdbuf )
490 obuf = makeXSVFbytes( tdi )
491 output.write( obuf )
492
493 else:
494 mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask )
495 tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi )
496 tdo = combineBitVectors( tdr.tdo, sdr.tdo, hdr.tdo )
497
498 if xsdrsize != len(tdi):
499 xsdrsize = len(tdi)
500 cmdbuf[0] = XSDRSIZE
501 output.write( cmdbuf )
502 obuf = bytearray(4)
503 struct.pack_into(">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf
504 output.write( obuf )
505
506 if xtdomask != mask:
507 xtdomask = mask
508 cmdbuf[0] = XTDOMASK
509 output.write( cmdbuf )
510 obuf = makeXSVFbytes( mask )
511 output.write( obuf )
512
513 cmdbuf[0] = XSDRTDO
514 output.write( cmdbuf )
515 obuf = makeXSVFbytes( tdi )
516 output.write( obuf )
517 obuf = makeXSVFbytes( tdo )
518 output.write( obuf )
519 #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) )
520
521 elif shiftOp == 'LSDR':
522 if doCOMMENTs:
523 writeComment( output, shiftOp_linenum, shiftOp )
524
525 mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask )
526 tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi )
527 tdo = combineBitVectors( tdr.tdo, sdr.tdo, hdr.tdo )
528
529 if xsdrsize != len(tdi):
530 xsdrsize = len(tdi)
531 cmdbuf[0] = XSDRSIZE
532 output.write( cmdbuf )
533 obuf = bytearray(4)
534 struct.pack_into(">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf
535 output.write( obuf )
536
537 if xtdomask != mask:
538 xtdomask = mask
539 cmdbuf[0] = XTDOMASK
540 output.write( cmdbuf )
541 obuf = makeXSVFbytes( mask )
542 output.write( obuf )
543
544 cmdbuf[0] = LSDR
545 output.write( cmdbuf )
546 obuf = makeXSVFbytes( tdi )
547 output.write( obuf )
548 obuf = makeXSVFbytes( tdo )
549 output.write( obuf )
550 #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) )
551
552 elif tokVal == 'RUNTEST' or tokVal == 'LDELAY':
553 # e.g. from lattice tools:
554 # "RUNTEST IDLE 5 TCK 1.00E-003 SEC;"
555 saveTok = tokVal
556 nextTok()
557 min_time = 0
558 run_count = 0
559 max_time = 600 # ten minutes
560 if tokVal in run_state_allowed:
561 run_state = StateTxt.index(tokVal)
562 end_state = run_state # bottom of page 17 of SVF spec
563 nextTok()
564 if tokType != 'int' and tokType != 'float':
565 raise ParseError( tokLn, tokVal, "Expecting 'int' or 'float' after RUNTEST [run_state]")
566 timeval = tokVal;
567 nextTok()
568 if tokVal != 'TCK' and tokVal != 'SEC' and tokVal != 'SCK':
569 raise ParseError( tokLn, tokVal, "Expecting 'TCK' or 'SEC' or 'SCK' after RUNTEST [run_state] (run_count|min_time)")
570 if tokVal == 'TCK' or tokVal == 'SCK':
571 run_count = int( timeval )
572 else:
573 min_time = timeval
574 nextTok()
575 if tokType == 'int' or tokType == 'float':
576 min_time = tokVal
577 nextTok()
578 if tokVal != 'SEC':
579 raise ParseError( tokLn, tokVal, "Expecting 'SEC' after RUNTEST [run_state] run_count min_time")
580 nextTok()
581 if tokVal == 'MAXIMUM':
582 nextTok()
583 if tokType != 'int' and tokType != 'float':
584 raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM")
585 max_time = tokVal
586 nextTok()
587 if tokVal != 'SEC':
588 raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM max_time")
589 nextTok()
590 if tokVal == 'ENDSTATE':
591 nextTok()
592 if tokVal not in run_state_allowed:
593 raise ParseError( tokLn, tokVal, "Expecting 'run_state' after RUNTEST .... ENDSTATE")
594 end_state = StateTxt.index(tokVal)
595 nextTok()
596 if tokVal != ';':
597 raise ParseError( tokLn, tokVal, "Expecting ';' after RUNTEST ....")
598 # print( "run_count=", run_count, "min_time=", min_time,
599 # "max_time=", max_time, "run_state=", State[run_state], "end_state=", State[end_state] )
600 writeRUNTEST( output, run_state, end_state, run_count, min_time, saveTok )
601
602 elif tokVal == 'LCOUNT':
603 nextTok()
604 if tokType != 'int':
605 raise ParseError( tokLn, tokVal, "Expecting integer 'count' after LCOUNT")
606 loopCount = tokVal
607 nextTok()
608 if tokVal != ';':
609 raise ParseError( tokLn, tokVal, "Expecting ';' after LCOUNT count")
610 if doCOMMENTs:
611 writeComment( output, tokLn, 'LCOUNT' )
612 obuf = bytearray(5)
613 obuf[0] = LCOUNT
614 struct.pack_into(">i", obuf, 1, loopCount ) # big endian 4 byte int to obuf
615 output.write( obuf )
616
617 elif tokVal == 'ENDDR':
618 nextTok()
619 if tokVal not in enddr_state_allowed:
620 raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDDR. (one of: DRPAUSE, IDLE)")
621 enddr_state = StateTxt.index(tokVal)
622 nextTok()
623 if tokVal != ';':
624 raise ParseError( tokLn, tokVal, "Expecting ';' after ENDDR stable_state")
625 if doCOMMENTs:
626 writeComment( output, tokLn, 'ENDDR' )
627 obuf = bytearray(2)
628 obuf[0] = XENDDR
629 # Page 10 of the March 1999 SVF spec shows that RESET is also allowed here.
630 # Yet the XSVF spec has no provision for that, and uses a non-standard, i.e.
631 # boolean argument to XENDDR which only handles two of the 3 intended states.
632 obuf[1] = 1 if enddr_state == DRPAUSE else 0
633 output.write( obuf )
634
635 elif tokVal == 'ENDIR':
636 nextTok()
637 if tokVal not in endir_state_allowed:
638 raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDIR. (one of: IRPAUSE, IDLE)")
639 endir_state = StateTxt.index(tokVal)
640 nextTok()
641 if tokVal != ';':
642 raise ParseError( tokLn, tokVal, "Expecting ';' after ENDIR stable_state")
643 if doCOMMENTs:
644 writeComment( output, tokLn, 'ENDIR' )
645 obuf = bytearray(2)
646 obuf[0] = XENDIR
647 # Page 10 of the March 1999 SVF spec shows that RESET is also allowed here.
648 # Yet the XSVF spec has no provision for that, and uses a non-standard, i.e.
649 # boolean argument to XENDDR which only handles two of the 3 intended states.
650 obuf[1] = 1 if endir_state == IRPAUSE else 0
651 output.write( obuf )
652
653 elif tokVal == 'STATE':
654 nextTok()
655 ln = tokLn
656 while tokVal != ';':
657 if tokVal not in StateTxt:
658 raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after STATE")
659 stable_state = StateTxt.index( tokVal )
660
661 if doCOMMENTs and ln != -1:
662 writeComment( output, ln, 'STATE' )
663 ln = -1 # save comment only once
664
665 obuf = bytearray(2)
666 obuf[0] = XSTATE
667 obuf[1] = stable_state
668 output.write( obuf )
669 nextTok()
670
671 elif tokVal == 'FREQUENCY':
672 nextTok()
673 if tokVal != ';':
674 if tokType != 'int' and tokType != 'float':
675 raise ParseError( tokLn, tokVal, "Expecting 'cycles HZ' after FREQUENCY")
676 frequency = tokVal
677 nextTok()
678 if tokVal != 'HZ':
679 raise ParseError( tokLn, tokVal, "Expecting 'HZ' after FREQUENCY cycles")
680 nextTok()
681 if tokVal != ';':
682 raise ParseError( tokLn, tokVal, "Expecting ';' after FREQUENCY cycles HZ")
683
684 else:
685 raise ParseError( tokLn, tokVal, "Unknown token '%s'" % tokVal)
686
687 except StopIteration:
688 if not expecting_eof:
689 print( "Unexpected End of File at line ", tokLn )
690
691 except ParseError as pe:
692 print( "\n", pe )
693
694 finally:
695 # print( "closing file" )
696 cmdbuf[0] = XCOMPLETE
697 output.write( cmdbuf )
698 output.close()
699

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)