diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/remote_bitbang/remote_bitbang_sysfsgpio.c | 408 | ||||
-rw-r--r-- | tools/xsvf_tools/svf2xsvf.py | 729 | ||||
-rw-r--r-- | tools/xsvf_tools/xsvfdump.py | 268 |
3 files changed, 0 insertions, 1405 deletions
diff --git a/tools/remote_bitbang/remote_bitbang_sysfsgpio.c b/tools/remote_bitbang/remote_bitbang_sysfsgpio.c deleted file mode 100644 index e59a1bd..0000000 --- a/tools/remote_bitbang/remote_bitbang_sysfsgpio.c +++ /dev/null @@ -1,408 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2013 Paul Fertser <fercerpav@gmail.com> * - * Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - ***************************************************************************/ - -/* - This is a test application to be used as a remote bitbang server for - the OpenOCD remote_bitbang interface driver. - - To compile run: - gcc -Wall -ansi -pedantic -std=c99 -o remote_bitbang_sysfsgpio remote_bitbang_sysfsgpio.c - - - Usage example: - - On Raspberry Pi run: - socat TCP6-LISTEN:7777,fork EXEC:"sudo ./remote_bitbang_sysfsgpio tck 11 tms 25 tdo 9 tdi 10" - - On host run: - openocd -c "interface remote_bitbang; remote_bitbang_host raspberrypi; remote_bitbang_port 7777" \ - -f target/stm32f1x.cfg - - Or if you want to test UNIX sockets, run both on Raspberry Pi: - socat UNIX-LISTEN:/tmp/remotebitbang-socket,fork EXEC:"sudo ./remote_bitbang_sysfsgpio tck 11 tms 25 tdo 9 tdi 10" - openocd -c "interface remote_bitbang; remote_bitbang_host /tmp/remotebitbang-socket" -f target/stm32f1x.cfg -*/ - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#define LOG_ERROR(...) do { \ - fprintf(stderr, __VA_ARGS__); \ - fputc('\n', stderr); \ - } while (0) -#define LOG_WARNING(...) LOG_ERROR(__VA_ARGS__) - -#define ERROR_OK (-1) -#define ERROR_FAIL (-2) -#define ERROR_JTAG_INIT_FAILED ERROR_FAIL - -/* - * Helper func to determine if gpio number valid - * - * Assume here that there will be less than 1000 gpios on a system - */ -static int is_gpio_valid(int gpio) -{ - return gpio >= 0 && gpio < 1000; -} - -/* - * Helper func to open, write to and close a file - * name and valstr must be null terminated. - * - * Returns negative on failure. - */ -static int open_write_close(const char *name, const char *valstr) -{ - int ret; - int fd = open(name, O_WRONLY); - if (fd < 0) - return fd; - - ret = write(fd, valstr, strlen(valstr)); - close(fd); - - return ret; -} - -/* - * Helper func to unexport gpio from sysfs - */ -static void unexport_sysfs_gpio(int gpio) -{ - char gpiostr[4]; - - if (!is_gpio_valid(gpio)) - return; - - snprintf(gpiostr, sizeof(gpiostr), "%d", gpio); - if (open_write_close("/sys/class/gpio/unexport", gpiostr) < 0) - LOG_ERROR("Couldn't unexport gpio %d", gpio); - - return; -} - -/* - * Exports and sets up direction for gpio. - * If the gpio is an output, it is initialized according to init_high, - * otherwise it is ignored. - * - * If the gpio is already exported we just show a warning and continue; if - * openocd happened to crash (or was killed by user) then the gpios will not - * have been cleaned up. - */ -static int setup_sysfs_gpio(int gpio, int is_output, int init_high) -{ - char buf[40]; - char gpiostr[4]; - int ret; - - if (!is_gpio_valid(gpio)) - return ERROR_OK; - - snprintf(gpiostr, sizeof(gpiostr), "%d", gpio); - ret = open_write_close("/sys/class/gpio/export", gpiostr); - if (ret < 0) { - if (errno == EBUSY) { - LOG_WARNING("gpio %d is already exported", gpio); - } else { - LOG_ERROR("Couldn't export gpio %d", gpio); - perror("sysfsgpio: "); - return ERROR_FAIL; - } - } - - snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio); - ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in"); - if (ret < 0) { - LOG_ERROR("Couldn't set direction for gpio %d", gpio); - perror("sysfsgpio: "); - unexport_sysfs_gpio(gpio); - return ERROR_FAIL; - } - - snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio); - if (is_output) - ret = open(buf, O_WRONLY | O_NONBLOCK | O_SYNC); - else - ret = open(buf, O_RDONLY | O_NONBLOCK | O_SYNC); - - if (ret < 0) - unexport_sysfs_gpio(gpio); - - return ret; -} - -/* - * file descriptors for /sys/class/gpio/gpioXX/value - * Set up during init. - */ -static int tck_fd = -1; -static int tms_fd = -1; -static int tdi_fd = -1; -static int tdo_fd = -1; -static int trst_fd = -1; -static int srst_fd = -1; - -/* - * Bitbang interface read of TDO - * - * The sysfs value will read back either '0' or '1'. The trick here is to call - * lseek to bypass buffering in the sysfs kernel driver. - */ -static int sysfsgpio_read(void) -{ - char buf[1]; - - /* important to seek to signal sysfs of new read */ - lseek(tdo_fd, 0, SEEK_SET); - int ret = read(tdo_fd, &buf, sizeof(buf)); - - if (ret < 0) { - LOG_WARNING("reading tdo failed"); - return 0; - } - - return buf[0]; -} - -/* - * Bitbang interface write of TCK, TMS, TDI - * - * Seeing as this is the only function where the outputs are changed, - * we can cache the old value to avoid needlessly writing it. - */ -static void sysfsgpio_write(int tck, int tms, int tdi) -{ - const char one[] = "1"; - const char zero[] = "0"; - - static int last_tck; - static int last_tms; - static int last_tdi; - - static int first_time; - size_t bytes_written; - - if (!first_time) { - last_tck = !tck; - last_tms = !tms; - last_tdi = !tdi; - first_time = 1; - } - - if (tdi != last_tdi) { - bytes_written = write(tdi_fd, tdi ? &one : &zero, 1); - if (bytes_written != 1) - LOG_WARNING("writing tdi failed"); - } - - if (tms != last_tms) { - bytes_written = write(tms_fd, tms ? &one : &zero, 1); - if (bytes_written != 1) - LOG_WARNING("writing tms failed"); - } - - /* write clk last */ - if (tck != last_tck) { - bytes_written = write(tck_fd, tck ? &one : &zero, 1); - if (bytes_written != 1) - LOG_WARNING("writing tck failed"); - } - - last_tdi = tdi; - last_tms = tms; - last_tck = tck; -} - -/* - * Bitbang interface to manipulate reset lines SRST and TRST - * - * (1) assert or (0) deassert reset lines - */ -static void sysfsgpio_reset(int trst, int srst) -{ - const char one[] = "1"; - const char zero[] = "0"; - size_t bytes_written; - - /* assume active low */ - if (srst_fd >= 0) { - bytes_written = write(srst_fd, srst ? &zero : &one, 1); - if (bytes_written != 1) - LOG_WARNING("writing srst failed"); - } - - /* assume active low */ - if (trst_fd >= 0) { - bytes_written = write(trst_fd, trst ? &zero : &one, 1); - if (bytes_written != 1) - LOG_WARNING("writing trst failed"); - } -} - -/* gpio numbers for each gpio. Negative values are invalid */ -static int tck_gpio = -1; -static int tms_gpio = -1; -static int tdi_gpio = -1; -static int tdo_gpio = -1; -static int trst_gpio = -1; -static int srst_gpio = -1; - -/* helper func to close and cleanup files only if they were valid/ used */ -static void cleanup_fd(int fd, int gpio) -{ - if (gpio >= 0) { - if (fd >= 0) - close(fd); - - unexport_sysfs_gpio(gpio); - } -} - -static void cleanup_all_fds(void) -{ - cleanup_fd(tck_fd, tck_gpio); - cleanup_fd(tms_fd, tms_gpio); - cleanup_fd(tdi_fd, tdi_gpio); - cleanup_fd(tdo_fd, tdo_gpio); - cleanup_fd(trst_fd, trst_gpio); - cleanup_fd(srst_fd, srst_gpio); -} - -static void process_remote_protocol(void) -{ - int c; - while (1) { - c = getchar(); - if (c == EOF || c == 'Q') /* Quit */ - break; - else if (c == 'b' || c == 'B') /* Blink */ - continue; - else if (c >= 'r' && c <= 'r' + 2) { /* Reset */ - char d = c - 'r'; - sysfsgpio_reset(!!(d & 2), - (d & 1)); - } else if (c >= '0' && c <= '0' + 7) {/* Write */ - char d = c - '0'; - sysfsgpio_write(!!(d & 4), - !!(d & 2), - (d & 1)); - } else if (c == 'R') - putchar(sysfsgpio_read()); - else - LOG_ERROR("Unknown command '%c' received", c); - } -} - -int main(int argc, char *argv[]) -{ - LOG_WARNING("SysfsGPIO remote_bitbang JTAG driver\n"); - - for (int i = 1; i < argc; i++) { - if (!strcmp(argv[i], "tck")) - tck_gpio = atoi(argv[++i]); - else if (!strcmp(argv[i], "tms")) - tms_gpio = atoi(argv[++i]); - else if (!strcmp(argv[i], "tdo")) - tdo_gpio = atoi(argv[++i]); - else if (!strcmp(argv[i], "tdi")) - tdi_gpio = atoi(argv[++i]); - else if (!strcmp(argv[i], "trst")) - trst_gpio = atoi(argv[++i]); - else if (!strcmp(argv[i], "srst")) - srst_gpio = atoi(argv[++i]); - else { - LOG_ERROR("Usage:\n%s ((tck|tms|tdo|tdi|trst|srst) num)*", argv[0]); - return -1; - } - } - - if (!(is_gpio_valid(tck_gpio) - && is_gpio_valid(tms_gpio) - && is_gpio_valid(tdi_gpio) - && is_gpio_valid(tdo_gpio))) { - if (!is_gpio_valid(tck_gpio)) - LOG_ERROR("gpio num for tck is invalid"); - if (!is_gpio_valid(tms_gpio)) - LOG_ERROR("gpio num for tms is invalid"); - if (!is_gpio_valid(tdo_gpio)) - LOG_ERROR("gpio num for tdo is invalid"); - if (!is_gpio_valid(tdi_gpio)) - LOG_ERROR("gpio num for tdi is invalid"); - - LOG_ERROR("Require tck, tms, tdi and tdo gpios to all be specified"); - return ERROR_JTAG_INIT_FAILED; - } - - /* - * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST - * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high. - */ - tck_fd = setup_sysfs_gpio(tck_gpio, 1, 0); - if (tck_fd < 0) - goto out_error; - - tms_fd = setup_sysfs_gpio(tms_gpio, 1, 1); - if (tms_fd < 0) - goto out_error; - - tdi_fd = setup_sysfs_gpio(tdi_gpio, 1, 0); - if (tdi_fd < 0) - goto out_error; - - tdo_fd = setup_sysfs_gpio(tdo_gpio, 0, 0); - if (tdo_fd < 0) - goto out_error; - - /* assume active low */ - if (trst_gpio > 0) { - trst_fd = setup_sysfs_gpio(trst_gpio, 1, 1); - if (trst_fd < 0) - goto out_error; - } - - /* assume active low */ - if (srst_gpio > 0) { - srst_fd = setup_sysfs_gpio(srst_gpio, 1, 1); - if (srst_fd < 0) - goto out_error; - } - - LOG_WARNING("SysfsGPIO nums: tck = %d, tms = %d, tdi = %d, tdo = %d", - tck_gpio, tms_gpio, tdi_gpio, tdo_gpio); - LOG_WARNING("SysfsGPIO num: srst = %d", srst_gpio); - LOG_WARNING("SysfsGPIO num: trst = %d", trst_gpio); - - setvbuf(stdout, NULL, _IONBF, 0); - process_remote_protocol(); - - cleanup_all_fds(); - return 0; -out_error: - cleanup_all_fds(); - return ERROR_JTAG_INIT_FAILED; -} diff --git a/tools/xsvf_tools/svf2xsvf.py b/tools/xsvf_tools/svf2xsvf.py deleted file mode 100644 index 113e0a6..0000000 --- a/tools/xsvf_tools/svf2xsvf.py +++ /dev/null @@ -1,729 +0,0 @@ -#!/usr/bin/python3.0 - -# Copyright 2008, SoftPLC Corporation http://softplc.com -# Dick Hollenbeck dick@softplc.com - - -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, you may find one here: -# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# or you may search the http://www.gnu.org website for the version 2 license, -# or you may write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - - -# A python program to convert an SVF file to an XSVF file. There is an -# option to include comments containing the source file line number from the origin -# SVF file before each outputted XSVF statement. -# -# We deviate from the XSVF spec in that we introduce a new command called -# XWAITSTATE which directly flows from the SVF RUNTEST command. Unfortunately -# XRUNSTATE was ill conceived and is not used here. We also add support for the -# three Lattice extensions to SVF: LCOUNT, LDELAY, and LSDR. The xsvf file -# generated from this program is suitable for use with the xsvf player in -# OpenOCD with my modifications to xsvf.c. -# -# This program is written for python 3.0, and it is not easy to change this -# back to 2.x. You may find it easier to use python 3.x even if that means -# building it. - - -import re -import sys -import struct - - -# There are both ---<Lexer>--- and ---<Parser>--- sections to this program - - -if len( sys.argv ) < 3: - print("usage %s <svf_filename> <xsvf_filename>" % sys.argv[0]) - exit(1) - - -inputFilename = sys.argv[1] -outputFilename = sys.argv[2] - -doCOMMENTs = True # Save XCOMMENTs in the output xsvf file -#doCOMMENTs = False # Save XCOMMENTs in the output xsvf file - -# pick your file encoding -file_encoding = 'ISO-8859-1' -#file_encoding = 'utf-8' - - -xrepeat = 0 # argument to XREPEAT, gives retry count for masked compares - - -#-----< Lexer >--------------------------------------------------------------- - -StateBin = (RESET,IDLE, - DRSELECT,DRCAPTURE,DRSHIFT,DREXIT1,DRPAUSE,DREXIT2,DRUPDATE, - IRSELECT,IRCAPTURE,IRSHIFT,IREXIT1,IRPAUSE,IREXIT2,IRUPDATE) = range(16) - -# Any integer index into this tuple will be equal to its corresponding StateBin value -StateTxt = ("RESET","IDLE", - "DRSELECT","DRCAPTURE","DRSHIFT","DREXIT1","DRPAUSE","DREXIT2","DRUPDATE", - "IRSELECT","IRCAPTURE","IRSHIFT","IREXIT1","IRPAUSE","IREXIT2","IRUPDATE") - - -(XCOMPLETE,XTDOMASK,XSIR,XSDR,XRUNTEST,hole0,hole1,XREPEAT,XSDRSIZE,XSDRTDO, - XSETSDRMASKS,XSDRINC,XSDRB,XSDRC,XSDRE,XSDRTDOB,XSDRTDOC, - XSDRTDOE,XSTATE,XENDIR,XENDDR,XSIR2,XCOMMENT,XWAIT,XWAITSTATE, - LCOUNT,LDELAY,LSDR,XTRST) = range(29) - -#Note: LCOUNT, LDELAY, and LSDR are Lattice extensions to SVF and provide a way to loop back -# and check a completion status, essentially waiting on a part until it signals that it is done. -# For example below: loop 25 times, each time through the loop do a LDELAY (same as a true RUNTEST) -# and exit loop when LSDR compares match. -""" -LCOUNT 25; -! Step to DRPAUSE give 5 clocks and wait for 1.00e+000 SEC. -LDELAY DRPAUSE 5 TCK 1.00E-003 SEC; -! Test for the completed status. Match means pass. -! Loop back to LDELAY line if not match and loop count less than 25. -LSDR 1 TDI (0) - TDO (1); -""" - -#XTRST is an opcode Xilinx seemed to have missed and it comes from the SVF TRST statement. - -LineNumber = 1 - -def s_ident(scanner, token): return ("ident", token.upper(), LineNumber) - -def s_hex(scanner, token): - global LineNumber - LineNumber = LineNumber + token.count('\n') - token = ''.join(token.split()) - return ("hex", token[1:-1], LineNumber) - -def s_int(scanner, token): return ("int", int(token), LineNumber) -def s_float(scanner, token): return ("float", float(token), LineNumber) -#def s_comment(scanner, token): return ("comment", token, LineNumber) -def s_semicolon(scanner, token): return ("semi", token, LineNumber) - -def s_nl(scanner,token): - global LineNumber - LineNumber = LineNumber + 1 - #print( 'LineNumber=', LineNumber, file=sys.stderr ) - return None - -#2.00E-002 - -scanner = re.Scanner([ - (r"[a-zA-Z]\w*", s_ident), -# (r"[-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?", s_float), - (r"[-+]?[0-9]+(([.][0-9eE+-]*)|([eE]+[-+]?[0-9]+))", s_float), - (r"\d+", s_int), - (r"\(([0-9a-fA-F]|\s)*\)", s_hex), - (r"(!|//).*$", None), - (r";", s_semicolon), - (r"\n",s_nl), - (r"\s*", None), - ], - re.MULTILINE - ) - -# open the file using the given encoding -file = open( sys.argv[1], encoding=file_encoding ) - -# read all svf file input into string "input" -input = file.read() - -file.close() - -# Lexer: -# create a list of tuples containing (tokenType, tokenValue, LineNumber) -tokens = scanner.scan( input )[0] - -input = None # allow gc to reclaim memory holding file - -#for tokenType, tokenValue, ln in tokens: print( "line %d: %s" % (ln, tokenType), tokenValue ) - - -#-----<parser>----------------------------------------------------------------- - -tokVal = tokType = tokLn = None - -tup = iter( tokens ) - -def nextTok(): - """ - Function to read the next token from tup into tokType, tokVal, tokLn (linenumber) - which are globals. - """ - global tokType, tokVal, tokLn, tup - tokType, tokVal, tokLn = tup.__next__() - - -class ParseError(Exception): - """A class to hold a parsing error message""" - def __init__(self, linenumber, token, message): - self.linenumber = linenumber - self.token = token - self.message = message - def __str__(self): - global inputFilename - return "Error in file \'%s\' at line %d near token %s\n %s" % ( - inputFilename, self.linenumber, repr(self.token), self.message) - - -class MASKSET(object): - """ - Class MASKSET holds a set of bit vectors, all of which are related, will all - have the same length, and are associated with one of the seven shiftOps: - HIR, HDR, TIR, TDR, SIR, SDR, LSDR. One of these holds a mask, smask, tdi, tdo, and a - size. - """ - def __init__(self, name): - self.empty() - self.name = name - - def empty(self): - self.mask = bytearray() - self.smask = bytearray() - self.tdi = bytearray() - self.tdo = bytearray() - self.size = 0 - - def syncLengths( self, sawTDI, sawTDO, sawMASK, sawSMASK, newSize ): - """ - Set all the lengths equal in the event some of the masks were - not seen as part of the last change set. - """ - if self.size == newSize: - return - - if newSize == 0: - self.empty() - return - - # If an SIR was given without a MASK(), then use a mask of all zeros. - # this is not consistent with the SVF spec, but it makes sense because - # it would be odd to be testing an instruction register read out of a - # tap without giving a mask for it. Also, lattice seems to agree and is - # generating SVF files that comply with this philosophy. - if self.name == 'SIR' and not sawMASK: - self.mask = bytearray( newSize ) - - if newSize != len(self.mask): - self.mask = bytearray( newSize ) - if self.name == 'SDR': # leave mask for HIR,HDR,TIR,TDR,SIR zeros - for i in range( newSize ): - self.mask[i] = 1 - - if newSize != len(self.tdo): - self.tdo = bytearray( newSize ) - - if newSize != len(self.tdi): - self.tdi = bytearray( newSize ) - - if newSize != len(self.smask): - self.smask = bytearray( newSize ) - - self.size = newSize -#-----</MASKSET>----- - - -def makeBitArray( hexString, bitCount ): - """ - Converts a packed sequence of hex ascii characters into a bytearray where - each element in the array holds exactly one bit. Only "bitCount" bits are - scanned and these must be the least significant bits in the hex number. That - is, it is legal to have some unused bits in the must significant hex nibble - of the input "hexString". The string is scanned starting from the backend, - then just before returning we reverse the array. This way the append() - method can be used, which I assume is faster than an insert. - """ - global tokLn - a = bytearray() - length = bitCount - hexString = list(hexString) - hexString.reverse() - #print(hexString) - for c in hexString: - if length <= 0: - break; - c = int(c, 16) - for mask in [1,2,4,8]: - if length <= 0: - break; - length = length - 1 - a.append( (c & mask) != 0 ) - if length > 0: - raise ParseError( tokLn, hexString, "Insufficient hex characters for given length of %d" % bitCount ) - a.reverse() - #print(a) - return a - - -def makeXSVFbytes( bitarray ): - """ - Make a bytearray which is contains the XSVF bits which will be written - directly to disk. The number of bytes needed is calculated from the size - of the argument bitarray. - """ - bitCount = len(bitarray) - byteCount = (bitCount+7)//8 - ba = bytearray( byteCount ) - firstBit = (bitCount % 8) - 1 - if firstBit == -1: - firstBit = 7 - bitNdx = 0 - for byteNdx in range(byteCount): - mask = 1<<firstBit - byte = 0 - while mask: - if bitarray[bitNdx]: - byte |= mask; - mask = mask >> 1 - bitNdx = bitNdx + 1 - ba[byteNdx] = byte - firstBit = 7 - return ba - - -def writeComment( outputFile, shiftOp_linenum, shiftOp ): - """ - Write an XCOMMENT record to outputFile - """ - comment = "%s @%d\0" % (shiftOp, shiftOp_linenum) # \0 is terminating nul - ba = bytearray(1) - ba[0] = XCOMMENT - ba += comment.encode() - outputFile.write( ba ) - - -def combineBitVectors( trailer, meat, header ): - """ - Combine the 3 bit vectors comprizing a transmission. Since the least - significant bits are sent first, the header is put onto the list last so - they are sent first from that least significant position. - """ - ret = bytearray() - ret.extend( trailer ) - ret.extend( meat ) - ret.extend( header ) - return ret - - -def writeRUNTEST( outputFile, run_state, end_state, run_count, min_time, tokenTxt ): - """ - Write the output for the SVF RUNTEST command. - run_count - the number of clocks - min_time - the number of seconds - tokenTxt - either RUNTEST or LDELAY - """ - # convert from secs to usecs - min_time = int( min_time * 1000000) - - # the SVF RUNTEST command does NOT map to the XSVF XRUNTEST command. Check the SVF spec, then - # read the XSVF command. They are not the same. Use an XSVF XWAITSTATE to - # implement the required behavior of the SVF RUNTEST command. - if doCOMMENTs: - writeComment( output, tokLn, tokenTxt ) - - if tokenTxt == 'RUNTEST': - obuf = bytearray(11) - obuf[0] = XWAITSTATE - obuf[1] = run_state - obuf[2] = end_state - struct.pack_into(">i", obuf, 3, run_count ) # big endian 4 byte int to obuf - struct.pack_into(">i", obuf, 7, min_time ) # big endian 4 byte int to obuf - outputFile.write( obuf ) - else: # == 'LDELAY' - obuf = bytearray(10) - obuf[0] = LDELAY - obuf[1] = run_state - # LDELAY has no end_state - struct.pack_into(">i", obuf, 2, run_count ) # big endian 4 byte int to obuf - struct.pack_into(">i", obuf, 6, min_time ) # big endian 4 byte int to obuf - outputFile.write( obuf ) - - -output = open( outputFilename, mode='wb' ) - -hir = MASKSET('HIR') -hdr = MASKSET('HDR') -tir = MASKSET('TIR') -tdr = MASKSET('TDR') -sir = MASKSET('SIR') -sdr = MASKSET('SDR') - - -expecting_eof = True - - -# one of the commands that take the shiftParts after the length, the parse -# template for all of these commands is identical -shiftOps = ('SDR', 'SIR', 'LSDR', 'HDR', 'HIR', 'TDR', 'TIR') - -# the order must correspond to shiftOps, this holds the MASKSETS. 'LSDR' shares sdr with 'SDR' -shiftSets = (sdr, sir, sdr, hdr, hir, tdr, tir ) - -# what to expect as parameters to a shiftOp, i.e. after a SDR length or SIR length -shiftParts = ('TDI', 'TDO', 'MASK', 'SMASK') - -# the set of legal states which can trail the RUNTEST command -run_state_allowed = ('IRPAUSE', 'DRPAUSE', 'RESET', 'IDLE') - -enddr_state_allowed = ('DRPAUSE', 'IDLE') -endir_state_allowed = ('IRPAUSE', 'IDLE') - -trst_mode_allowed = ('ON', 'OFF', 'Z', 'ABSENT') - -enddr_state = IDLE -endir_state = IDLE - -frequency = 1.00e+006 # HZ; - -# change detection for xsdrsize and xtdomask -xsdrsize = -1 # the last one sent, send only on change -xtdomask = bytearray() # the last one sent, send only on change - - -# we use a number of single byte writes for the XSVF command below -cmdbuf = bytearray(1) - - -# Save the XREPEAT setting into the file as first thing. -obuf = bytearray(2) -obuf[0] = XREPEAT -obuf[1] = xrepeat -output.write( obuf ) - - -try: - while 1: - expecting_eof = True - nextTok() - expecting_eof = False - # print( tokType, tokVal, tokLn ) - - if tokVal in shiftOps: - shiftOp_linenum = tokLn - shiftOp = tokVal - - set = shiftSets[shiftOps.index(shiftOp)] - - # set flags false, if we see one later, set that one true later - sawTDI = sawTDO = sawMASK = sawSMASK = False - - nextTok() - if tokType != 'int': - raise ParseError( tokLn, tokVal, "Expecting 'int' giving %s length, got '%s'" % (shiftOp, tokType) ) - length = tokVal - - nextTok() - - while tokVal != ';': - if tokVal not in shiftParts: - raise ParseError( tokLn, tokVal, "Expecting TDI, TDO, MASK, SMASK, or ';'") - shiftPart = tokVal - - nextTok() - - if tokType != 'hex': - raise ParseError( tokLn, tokVal, "Expecting hex bits" ) - bits = makeBitArray( tokVal, length ) - - if shiftPart == 'TDI': - sawTDI = True - set.tdi = bits - - elif shiftPart == 'TDO': - sawTDO = True - set.tdo = bits - - elif shiftPart == 'MASK': - sawMASK = True - set.mask = bits - - elif shiftPart == 'SMASK': - sawSMASK = True - set.smask = bits - - nextTok() - - set.syncLengths( sawTDI, sawTDO, sawMASK, sawSMASK, length ) - - # process all the gathered parameters and generate outputs here - if shiftOp == 'SIR': - if doCOMMENTs: - writeComment( output, shiftOp_linenum, 'SIR' ) - - tdi = combineBitVectors( tir.tdi, sir.tdi, hir.tdi ) - if len(tdi) > 255: - obuf = bytearray(3) - obuf[0] = XSIR2 - struct.pack_into( ">h", obuf, 1, len(tdi) ) - else: - obuf = bytearray(2) - obuf[0] = XSIR - obuf[1] = len(tdi) - output.write( obuf ) - obuf = makeXSVFbytes( tdi ) - output.write( obuf ) - - elif shiftOp == 'SDR': - if doCOMMENTs: - writeComment( output, shiftOp_linenum, shiftOp ) - - if not sawTDO: - # pass a zero filled bit vector for the sdr.mask - mask = combineBitVectors( tdr.mask, bytearray(sdr.size), hdr.mask ) - tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) - - if xsdrsize != len(tdi): - xsdrsize = len(tdi) - cmdbuf[0] = XSDRSIZE - output.write( cmdbuf ) - obuf = bytearray(4) - struct.pack_into( ">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf - output.write( obuf ) - - if xtdomask != mask: - xtdomask = mask - cmdbuf[0] = XTDOMASK - output.write( cmdbuf ) - obuf = makeXSVFbytes( mask ) - output.write( obuf ) - - cmdbuf[0] = XSDR - output.write( cmdbuf ) - obuf = makeXSVFbytes( tdi ) - output.write( obuf ) - - else: - mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask ) - tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) - tdo = combineBitVectors( tdr.tdo, sdr.tdo, hdr.tdo ) - - if xsdrsize != len(tdi): - xsdrsize = len(tdi) - cmdbuf[0] = XSDRSIZE - output.write( cmdbuf ) - obuf = bytearray(4) - struct.pack_into(">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf - output.write( obuf ) - - if xtdomask != mask: - xtdomask = mask - cmdbuf[0] = XTDOMASK - output.write( cmdbuf ) - obuf = makeXSVFbytes( mask ) - output.write( obuf ) - - cmdbuf[0] = XSDRTDO - output.write( cmdbuf ) - obuf = makeXSVFbytes( tdi ) - output.write( obuf ) - obuf = makeXSVFbytes( tdo ) - output.write( obuf ) - #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) ) - - elif shiftOp == 'LSDR': - if doCOMMENTs: - writeComment( output, shiftOp_linenum, shiftOp ) - - mask = combineBitVectors( tdr.mask, sdr.mask, hdr.mask ) - tdi = combineBitVectors( tdr.tdi, sdr.tdi, hdr.tdi ) - tdo = combineBitVectors( tdr.tdo, sdr.tdo, hdr.tdo ) - - if xsdrsize != len(tdi): - xsdrsize = len(tdi) - cmdbuf[0] = XSDRSIZE - output.write( cmdbuf ) - obuf = bytearray(4) - struct.pack_into(">i", obuf, 0, xsdrsize ) # big endian 4 byte int to obuf - output.write( obuf ) - - if xtdomask != mask: - xtdomask = mask - cmdbuf[0] = XTDOMASK - output.write( cmdbuf ) - obuf = makeXSVFbytes( mask ) - output.write( obuf ) - - cmdbuf[0] = LSDR - output.write( cmdbuf ) - obuf = makeXSVFbytes( tdi ) - output.write( obuf ) - obuf = makeXSVFbytes( tdo ) - output.write( obuf ) - #print( "len(tdo)=", len(tdo), "len(tdr.tdo)=", len(tdr.tdo), "len(sdr.tdo)=", len(sdr.tdo), "len(hdr.tdo)=", len(hdr.tdo) ) - - elif tokVal == 'RUNTEST' or tokVal == 'LDELAY': - # e.g. from lattice tools: - # "RUNTEST IDLE 5 TCK 1.00E-003 SEC;" - saveTok = tokVal - nextTok() - min_time = 0 - run_count = 0 - max_time = 600 # ten minutes - if tokVal in run_state_allowed: - run_state = StateTxt.index(tokVal) - end_state = run_state # bottom of page 17 of SVF spec - nextTok() - if tokType != 'int' and tokType != 'float': - raise ParseError( tokLn, tokVal, "Expecting 'int' or 'float' after RUNTEST [run_state]") - timeval = tokVal; - nextTok() - if tokVal != 'TCK' and tokVal != 'SEC' and tokVal != 'SCK': - raise ParseError( tokLn, tokVal, "Expecting 'TCK' or 'SEC' or 'SCK' after RUNTEST [run_state] (run_count|min_time)") - if tokVal == 'TCK' or tokVal == 'SCK': - run_count = int( timeval ) - else: - min_time = timeval - nextTok() - if tokType == 'int' or tokType == 'float': - min_time = tokVal - nextTok() - if tokVal != 'SEC': - raise ParseError( tokLn, tokVal, "Expecting 'SEC' after RUNTEST [run_state] run_count min_time") - nextTok() - if tokVal == 'MAXIMUM': - nextTok() - if tokType != 'int' and tokType != 'float': - raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM") - max_time = tokVal - nextTok() - if tokVal != 'SEC': - raise ParseError( tokLn, tokVal, "Expecting 'max_time' after RUNTEST [run_state] min_time SEC MAXIMUM max_time") - nextTok() - if tokVal == 'ENDSTATE': - nextTok() - if tokVal not in run_state_allowed: - raise ParseError( tokLn, tokVal, "Expecting 'run_state' after RUNTEST .... ENDSTATE") - end_state = StateTxt.index(tokVal) - nextTok() - if tokVal != ';': - raise ParseError( tokLn, tokVal, "Expecting ';' after RUNTEST ....") - # print( "run_count=", run_count, "min_time=", min_time, - # "max_time=", max_time, "run_state=", State[run_state], "end_state=", State[end_state] ) - writeRUNTEST( output, run_state, end_state, run_count, min_time, saveTok ) - - elif tokVal == 'LCOUNT': - nextTok() - if tokType != 'int': - raise ParseError( tokLn, tokVal, "Expecting integer 'count' after LCOUNT") - loopCount = tokVal - nextTok() - if tokVal != ';': - raise ParseError( tokLn, tokVal, "Expecting ';' after LCOUNT count") - if doCOMMENTs: - writeComment( output, tokLn, 'LCOUNT' ) - obuf = bytearray(5) - obuf[0] = LCOUNT - struct.pack_into(">i", obuf, 1, loopCount ) # big endian 4 byte int to obuf - output.write( obuf ) - - elif tokVal == 'ENDDR': - nextTok() - if tokVal not in enddr_state_allowed: - raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDDR. (one of: DRPAUSE, IDLE)") - enddr_state = StateTxt.index(tokVal) - nextTok() - if tokVal != ';': - raise ParseError( tokLn, tokVal, "Expecting ';' after ENDDR stable_state") - if doCOMMENTs: - writeComment( output, tokLn, 'ENDDR' ) - obuf = bytearray(2) - obuf[0] = XENDDR - # Page 10 of the March 1999 SVF spec shows that RESET is also allowed here. - # Yet the XSVF spec has no provision for that, and uses a non-standard, i.e. - # boolean argument to XENDDR which only handles two of the 3 intended states. - obuf[1] = 1 if enddr_state == DRPAUSE else 0 - output.write( obuf ) - - elif tokVal == 'ENDIR': - nextTok() - if tokVal not in endir_state_allowed: - raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after ENDIR. (one of: IRPAUSE, IDLE)") - endir_state = StateTxt.index(tokVal) - nextTok() - if tokVal != ';': - raise ParseError( tokLn, tokVal, "Expecting ';' after ENDIR stable_state") - if doCOMMENTs: - writeComment( output, tokLn, 'ENDIR' ) - obuf = bytearray(2) - obuf[0] = XENDIR - # Page 10 of the March 1999 SVF spec shows that RESET is also allowed here. - # Yet the XSVF spec has no provision for that, and uses a non-standard, i.e. - # boolean argument to XENDDR which only handles two of the 3 intended states. - obuf[1] = 1 if endir_state == IRPAUSE else 0 - output.write( obuf ) - - elif tokVal == 'STATE': - nextTok() - ln = tokLn - while tokVal != ';': - if tokVal not in StateTxt: - raise ParseError( tokLn, tokVal, "Expecting 'stable_state' after STATE") - stable_state = StateTxt.index( tokVal ) - - if doCOMMENTs and ln != -1: - writeComment( output, ln, 'STATE' ) - ln = -1 # save comment only once - - obuf = bytearray(2) - obuf[0] = XSTATE - obuf[1] = stable_state - output.write( obuf ) - nextTok() - - elif tokVal == 'FREQUENCY': - nextTok() - if tokVal != ';': - if tokType != 'int' and tokType != 'float': - raise ParseError( tokLn, tokVal, "Expecting 'cycles HZ' after FREQUENCY") - frequency = tokVal - nextTok() - if tokVal != 'HZ': - raise ParseError( tokLn, tokVal, "Expecting 'HZ' after FREQUENCY cycles") - nextTok() - if tokVal != ';': - raise ParseError( tokLn, tokVal, "Expecting ';' after FREQUENCY cycles HZ") - - elif tokVal == 'TRST': - nextTok() - if tokVal not in trst_mode_allowed: - raise ParseError( tokLn, tokVal, "Expecting 'ON|OFF|Z|ABSENT' after TRST") - trst_mode = tokVal - nextTok() - if tokVal != ';': - raise ParseError( tokLn, tokVal, "Expecting ';' after TRST trst_mode") - if doCOMMENTs: - writeComment( output, tokLn, 'TRST %s' % trst_mode ) - obuf = bytearray( 2 ) - obuf[0] = XTRST - obuf[1] = trst_mode_allowed.index( trst_mode ) # use the index as the binary argument to XTRST opcode - output.write( obuf ) - - else: - raise ParseError( tokLn, tokVal, "Unknown token '%s'" % tokVal) - -except StopIteration: - if not expecting_eof: - print( "Unexpected End of File at line ", tokLn ) - -except ParseError as pe: - print( "\n", pe ) - -finally: - # print( "closing file" ) - cmdbuf[0] = XCOMPLETE - output.write( cmdbuf ) - output.close() - diff --git a/tools/xsvf_tools/xsvfdump.py b/tools/xsvf_tools/xsvfdump.py deleted file mode 100644 index e65f8d5..0000000 --- a/tools/xsvf_tools/xsvfdump.py +++ /dev/null @@ -1,268 +0,0 @@ -#!/usr/bin/python3.0 - -# Copyright 2008, SoftPLC Corporation http://softplc.com -# Dick Hollenbeck dick@softplc.com - -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, you may find one here: -# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html -# or you may search the http://www.gnu.org website for the version 2 license, -# or you may write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - -# Dump an Xilinx XSVF file to stdout - -# This program is written for python 3.0, and it is not easy to change this -# back to 2.x. You may find it easier to use python 3.x even if that means -# building it. - - -import sys -import struct - - -LABEL = "A script to dump an XSVF file to stdout" - - -Xsdrsize = 0 - - -(XCOMPLETE,XTDOMASK,XSIR,XSDR,XRUNTEST,hole0,hole1,XREPEAT,XSDRSIZE,XSDRTDO, - XSETSDRMASKS,XSDRINC,XSDRB,XSDRC,XSDRE,XSDRTDOB,XSDRTDOC, - XSDRTDOE,XSTATE,XENDIR,XENDDR,XSIR2,XCOMMENT,XWAIT,XWAITSTATE, - LCOUNT,LDELAY,LSDR,XTRST) = range(29) - - -(RESET,IDLE, - DRSELECT,DRCAPTURE,DRSHIFT,DREXIT1,DRPAUSE,DREXIT2,DRUPDATE, - IRSELECT,IRCAPTURE,IRSHIFT,IREXIT1,IRPAUSE,IREXIT2,IRUPDATE) = range(16) - - -State = ("RESET","IDLE", - "DRSELECT","DRCAPTURE","DRSHIFT","DREXIT1","DRPAUSE","DREXIT2","DRUPDATE", - "IRSELECT","IRCAPTURE","IRSHIFT","IREXIT1","IRPAUSE","IREXIT2","IRUPDATE") - - -trst_mode_allowed = ('ON', 'OFF', 'Z', 'ABSENT') - - -Setsdrmasks = 0 -SetsdrmasksOnesCount = 0 - -def ReadSDRMASKS( f, len ): - global Setsdrmasks, SetsdrmasksOnesCount - byteCount = (len+7)//8 - Setsdrmasks = f.read( byteCount ) - ls = [] - SetsdrmasksOnesCount = 0 - for b in Setsdrmasks: - ls.append( "%x" % ((b & 0xf0) >> 4) ) - ls.append( "%x" % ( b & 0x0f ) ) - for i in range(8): - if b & (1<<i): - SetsdrmasksOnesCount = SetsdrmasksOnesCount +1 - return ''.join(ls) - - -def bytes2hexString( f, len ): - byteCount = (len+7)//8 - bytebuf = f.read( byteCount ) - ls = [] - for b in bytebuf: - ls.append( "%x" % ((b & 0xf0) >> 4) ) - ls.append( "%x" % ( b & 0x0f ) ) - return ''.join(ls) - - -def ReadByte( f ): - """Read a byte from a file and return it as an int in least significant 8 bits""" - b = f.read(1) - if b: - return 0xff & b[0]; - else: - return -1 - - -def ShowState( state ): - """return the given state int as a state string""" - #return "0x%02x" % state # comment this out to get textual state form - global State - if 0 <= state <= IRUPDATE: - return State[state] - else: - return "Unknown state 0x%02x" % state - - -def ShowOpcode( op, f ): - """return the given byte as an opcode string""" - global Xsdrsize - if op == XCOMPLETE: - print("XCOMPLETE") - - elif op == XTDOMASK: - buf = bytes2hexString( f, Xsdrsize ) - print("XTDOMASK 0x%s" % buf) - - elif op == XSIR: - len = ReadByte( f ) - buf = bytes2hexString( f, len ) - print("XSIR 0x%02X 0x%s" % (len, buf)) - - elif op == XSDR: - tdi = bytes2hexString( f, Xsdrsize ) - print("XSDR 0x%s" % tdi) - - elif op == XRUNTEST: - len = struct.unpack( '>i', f.read(4) )[0] - print("XRUNTEST 0x%08X" % len) - - elif op == XREPEAT: - len = ReadByte( f ) - print("XREPEAT 0x%02X" % len) - - elif op == XSDRSIZE: - Xsdrsize = struct.unpack( '>i', f.read(4) )[0] - #print("XSDRSIZE 0x%08X" % Xsdrsize, file=sys.stderr ) - print("XSDRSIZE 0x%08X %d" % (Xsdrsize, Xsdrsize) ) - - elif op == XSDRTDO: - tdi = bytes2hexString( f, Xsdrsize ) - tdo = bytes2hexString( f, Xsdrsize ) - print("XSDRTDO 0x%s 0x%s" % (tdi, tdo) ) - - elif op == XSETSDRMASKS: - addrmask = bytes2hexString( f, Xsdrsize ) - datamask = ReadSDRMASKS( f, Xsdrsize ) - print("XSETSDRMASKS 0x%s 0x%s" % (addrmask, datamask) ) - - elif op == XSDRINC: - startaddr = bytes2hexString( f, Xsdrsize ) - len = ReadByte(f) - print("XSDRINC 0x%s 0x%02X" % (startaddr, len), end='' ) - for numTimes in range(len): - data = bytes2hexString( f, SetsdrmasksOnesCount) - print(" 0x%s" % data ) - print() # newline - - elif op == XSDRB: - tdi = bytes2hexString( f, Xsdrsize ) - print("XSDRB 0x%s" % tdi ) - - elif op == XSDRC: - tdi = bytes2hexString( f, Xsdrsize ) - print("XSDRC 0x%s" % tdi ) - - elif op == XSDRE: - tdi = bytes2hexString( f, Xsdrsize ) - print("XSDRE 0x%s" % tdi ) - - elif op == XSDRTDOB: - tdo = bytes2hexString( f, Xsdrsize ) - print("XSDRTDOB 0x%s" % tdo ) - - elif op == XSDRTDOC: - tdi = bytes2hexString( f, Xsdrsize ) - tdo = bytes2hexString( f, Xsdrsize ) - print("XSDRTDOC 0x%s 0x%s" % (tdi, tdo) ) - - elif op == XSDRTDOE: - tdi = bytes2hexString( f, Xsdrsize ) - tdo = bytes2hexString( f, Xsdrsize ) - print("XSDRTDOE 0x%s 0x%s" % (tdi, tdo) ) - - elif op == XSTATE: - b = ReadByte(f) - print("XSTATE %s" % ShowState(b)) - - elif op == XENDIR: - b = ReadByte( f ) - print("XENDIR %s" % 'IRPAUSE' if b==1 else 'IDLE') - - elif op == XENDDR: - b = ReadByte( f ) - print("XENDDR %s" % 'DRPAUSE' if b==1 else 'IDLE') - - elif op == XSIR2: - len = struct.unpack( '>H', f.read(2) )[0] - buf = bytes2hexString( f, len ) - print("XSIR2 0x%04X 0x%s" % (len, buf)) - - elif op == XCOMMENT: - cmt = [] - while 1: - b = ReadByte(f) - if b == 0: # terminating nul - break; - cmt.append( chr(b) ) - print("XCOMMENT \"%s\"" % ''.join(cmt) ) - - elif op == XWAIT: - run_state = ReadByte(f) - end_state = ReadByte(f) - useconds = struct.unpack( '>i', f.read(4) )[0] - print("XWAIT %s %s" % (ShowState(run_state), ShowState(end_state)), useconds) - - elif op == XWAITSTATE: - run_state = ReadByte(f) - end_state = ReadByte(f) - clocks = struct.unpack( '>i', f.read(4) )[0] - useconds = struct.unpack( '>i', f.read(4) )[0] - print("XWAITSTATE %s %s CLOCKS=%d USECS=%d" % (ShowState(run_state), ShowState(end_state), clocks, useconds) ) - - elif op == LCOUNT: - loop_count = struct.unpack( '>i', f.read(4) )[0] - print("LCOUNT", loop_count ) - - elif op == LDELAY: - run_state = ReadByte(f) - clocks = struct.unpack( '>i', f.read(4) )[0] - useconds = struct.unpack( '>i', f.read(4) )[0] - print("LDELAY %s CLOCKS=%d USECS=%d" % (ShowState(run_state), clocks, useconds) ) - - elif op == LSDR: - tdi = bytes2hexString( f, Xsdrsize ) - tdo = bytes2hexString( f, Xsdrsize ) - print("LSDR 0x%s 0x%s" % (tdi, tdo) ) - - elif op == XTRST: - # the argument is a single byte and it is the index into "trst_mode_allowed" - trst_mode = ReadByte(f) - if trst_mode <= 3: - print("TRST %s" % trst_mode_allowed[trst_mode] ) - else: - print("TRST 0x%02X" % trst_mode ); - - else: - print("UNKNOWN op 0x%02X %d" % (op, op)) - exit(1) - - -def main(): - - if len( sys.argv ) < 2: - print("usage %s <xsvf_filename>" % sys.argv[0]) - exit(1) - - f = open( sys.argv[1], 'rb' ) - - opcode = ReadByte( f ) - while opcode != -1: - # print the position within the file, then the command - print( "%d: " % f.tell(), end='' ) - ShowOpcode( opcode, f ) - opcode = ReadByte(f) - - -if __name__ == "__main__": - main() - |