From a470ee524e3fbbbbcbfc80879f656202bc0a6034 Mon Sep 17 00:00:00 2001 From: Graeme Smecher Date: Mon, 5 Sep 2022 10:52:53 -0700 Subject: [PATCH 1/3] Remove deprecated comma form for catching multiple exceptions. Since opbasm already requires Python 2.7+ (per the README), we are improving forwards compatibility at no cost. --- opbasm/__main__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/opbasm/__main__.py b/opbasm/__main__.py index b22fe65..fa6ab79 100644 --- a/opbasm/__main__.py +++ b/opbasm/__main__.py @@ -289,9 +289,9 @@ def printq(*args, **keys): try: templates = find_templates(options.template_file) - except StatementError, e: + except StatementError as e: asm_error(*e.args, exit=1) - except FatalError, e: + except FatalError as e: asm_error(str(e), exit=1) # Make sure the extension of the generated VHDL file matches the template extension @@ -334,9 +334,9 @@ def printq(*args, **keys): try: assembled_code = asm.assemble_file(options.input_file) - except StatementError, e: + except StatementError as e: asm_error(*e.args, exit=1, statement=e.statement) - except FatalError, e: + except FatalError as e: asm_error(str(e), exit=1) @@ -386,9 +386,9 @@ def printq(*args, **keys): template_file, target_file = templates[hdl_name] asm.write_template_file(template_file, target_file, longest_name) - except StatementError, e: + except StatementError as e: asm_error(*e.args, exit=1, statement=e.statement) - except FatalError, e: + except FatalError as e: asm_error(str(e), exit=1) asm.write_formatted_source(config.output_dir) From 8bc14d4fc4cfa2eb702859dc73770d643138815a Mon Sep 17 00:00:00 2001 From: Graeme Smecher Date: Tue, 6 Sep 2022 14:55:35 -0700 Subject: [PATCH 2/3] Python 3-ize. Bulk conversions: - dict.iteritems() -> dict.items() - dict.iterkeys() -> just dict - dict.itervalues() -> dict.values() - xrange -> range - unicode() to str() --- AUTHORS | 1 + opbasm/__main__.py | 8 ++--- opbasm/opbasm.py | 84 ++++++++++++++++++++++------------------------ setup.py | 2 -- 4 files changed, 46 insertions(+), 49 deletions(-) diff --git a/AUTHORS b/AUTHORS index ec8cc42..b0a4fbd 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,4 +4,5 @@ Contributors to Opbasm Kevin Thibedeau Patrick Lehmann +Graeme Smecher diff --git a/opbasm/__main__.py b/opbasm/__main__.py index fa6ab79..d486dc1 100644 --- a/opbasm/__main__.py +++ b/opbasm/__main__.py @@ -304,7 +304,7 @@ def printq(*args, **keys): vhdl_file = build_path(config.output_dir, options.module_name + vhdl_ext) verilog_file = build_path(config.output_dir, options.module_name + '.v') - for hdl in templates.iterkeys(): + for hdl in templates: templates[hdl] = (templates[hdl], vhdl_file if hdl == 'vhdl' else verilog_file) log_file = build_path(config.output_dir, options.module_name + '.log') @@ -350,7 +350,7 @@ def printq(*args, **keys): if len(templates) > 0: printq(_('\n Found {}:').format(_('templates') if len(templates) > 1 else _('template'))) - for f in templates.itervalues(): + for f in templates.values(): printq(' ', f[0]) @@ -378,11 +378,11 @@ def printq(*args, **keys): # Find longest template file name so we can align the warning messages # about unmapped INIT fields. if len(templates) > 0: - longest_name = max(len(v[1]) for v in templates.itervalues()) + longest_name = max(len(v[1]) for v in templates.values()) else: longest_name = 0 - for hdl_name in templates.iterkeys(): + for hdl_name in templates: template_file, target_file = templates[hdl_name] asm.write_template_file(template_file, target_file, longest_name) diff --git a/opbasm/opbasm.py b/opbasm/opbasm.py index ffec894..34f1549 100644 --- a/opbasm/opbasm.py +++ b/opbasm/opbasm.py @@ -273,7 +273,7 @@ def format_inst(self): if self.arg2 is not None: if self.indirect_reg: inst += ', (' + self.arg2 + ')' - elif self.table_def or not isinstance(self.arg2, basestring): + elif self.table_def or not isinstance(self.arg2, str): inst += ', [' + ', '.join(self.arg2[:-1]) + self.arg2[-1] else: inst += ', ' + str(self.arg2) @@ -485,7 +485,7 @@ def reset(self, config=None, timestamp=None): self.sources = {} self.default_jump = None - self.upper_env_names = dict(((k.upper(), k) for k in os.environ.iterkeys())) + self.upper_env_names = dict(((k.upper(), k) for k in os.environ)) self.line_index = {} @@ -539,7 +539,7 @@ def stats(self): @property def optimizer_sequence(self): '''Return list of active optimizers sorted by priority''' - return sorted(self.optimizers.itervalues(), key=lambda o: o.priority) + return sorted(self.optimizers.values(), key=lambda o: o.priority) def add_optimizer(self, opt): '''Register a new optimizer''' @@ -548,7 +548,7 @@ def add_optimizer(self, opt): def _init_registers(self): '''Initialize table of register names''' - hex_digits = [hex(d)[-1] for d in xrange(16)] + hex_digits = [hex(d)[-1] for d in range(16)] return dict(('s' + h, i) for i, h in enumerate(hex_digits)) def _init_constants(self): @@ -577,7 +577,7 @@ def _init_constants(self): 'ST' : Symbol('ST', 0x9c) } - for c in constants.itervalues(): + for c in constants.values(): c.in_use = True return constants @@ -594,7 +594,7 @@ def _init_strings(self): 'Opbasm_version$' : Symbol('Opbasm_version$', ver, '"{}"'.format(ver)), } - for s in strings.itervalues(): + for s in strings.values(): s.in_use = True return strings @@ -652,7 +652,7 @@ def _preprocess_with_m4(self, source_file, source_code): # Build argument string for defines fed into m4 m4_def_args = \ - ' '.join('-D{}={}'.format(k,v) if v else '-D{}'.format(k) for k,v in m4_defines.iteritems()) + ' '.join('-D{}={}'.format(k,v) if v else '-D{}'.format(k) for k,v in m4_defines.items()) m4_cmd = get_m4_path() cmd = '"{}" {} {} "{}" -'.format(m4_cmd, m4_options, m4_def_args, macro_defs) @@ -1509,7 +1509,7 @@ def code_stats(self): def instruction_usage(self): '''Analyze assembled code to determine instruction histogram''' - usage = dict((k, 0) for k in self.config.target_arch.opcodes.iterkeys()) + usage = dict((k, 0) for k in self.config.target_arch.opcodes) del usage['inst'] # Not a real opcode for s in self.assembled_code: @@ -1576,7 +1576,7 @@ def write_mif_file(self, fname): print('CONTENT', file=fh) print('BEGIN', file=fh) # Write data lines -> 'Address : Content' in multiples of 8 - for a in xrange(len(self.mmap) // 8): + for a in range(len(self.mmap) // 8): d = ' '.join('{:05X}'.format(w) for w in self.mmap[a*8:(a+1)*8]) print('{:04X} : {};'.format(a*8, d), file=fh) @@ -1597,9 +1597,7 @@ def write_log_file(self, log_file, colorize=False, refline_cols=8, use_unicode=T with io.open(log_file, 'w', encoding='utf-8') as fh: def printf(*args): - # For Python 2.x we have to ensure all args are unicode strings - # before passing them to print(). - return print(*[unicode(a) for a in args], file=fh) + return print(*[str(a) for a in args], file=fh) printf(_('Open PicoBlaze Assembler log for program "{}"').format(self.top_source_name())) printf(_('Generated by opbasm v{}').format(__version__)) @@ -1644,18 +1642,18 @@ def printf(*args): printf(_('\nAll unused memory locations contain a DEFAULT_JUMP to {:03X}').format(self.default_jump & 0xFFF)) printf('\n\n' + underline(_('PSM files that have been assembled'))) - for f in self.sources.iterkeys(): + for f in self.sources: printf(' ', os.path.abspath(f)) printf('\n\n' + underline(_('List of defined constants'))) headings = [_(' CONSTANT name'), _('Value'), _('Source PSM file')] rows = [((' ' if self.constants[c].in_use else '* ') + c, \ self.constants[c].val_text, self.constants[c].source_file) \ - for c in sorted(self.constants.iterkeys())] + for c in self.constants] for r in format_table(rows, headings, indent=1): printf(r) - if not all(c.in_use for c in self.constants.itervalues()): # Show caption + if not all(c.in_use for c in self.constants.values()): # Show caption printf(_('\n * Unreferenced constant(s)')) @@ -1666,11 +1664,11 @@ def printf(*args): headings = [_(' TABLE name'), _('Value'), _('Source PSM file')] rows = [((' ' if self.tables[t].in_use else '* ') + t, \ self.tables[t].val_text, self.tables[t].source_file) \ - for t in sorted(self.tables.iterkeys())] + for t in self.tables] for r in format_table(rows, headings, indent=1): printf(r) - if not all(t.in_use for t in self.tables.itervalues()): # Show caption + if not all(t.in_use for t in self.tables.values()): # Show caption printf(_('\n * Unreferenced table(s)')) @@ -1678,11 +1676,11 @@ def printf(*args): headings = [_(' STRING name'), _('Value'), _('Source PSM file')] rows = [((' ' if self.strings[s].in_use else '* ') + s, \ self.strings[s].val_text, self.strings[s].source_file) \ - for s in sorted(self.strings.iterkeys())] + for s in self.strings] for r in format_table(rows, headings, indent=1): printf(r) - if not all(s.in_use for s in self.strings.itervalues()): # Show caption + if not all(s.in_use for s in self.strings.values()): # Show caption printf(_('\n * Unreferenced string(s)')) @@ -1690,11 +1688,11 @@ def printf(*args): headings = [_(' Label'), _('Addr'), _('Source PSM file')] rows = [((' ' if self.labels[l].in_use else '* ') + l, \ '{:03X}'.format(self.labels[l].value), self.labels[l].source_file) \ - for l in sorted(self.labels.iterkeys())] + for l in self.labels] for r in format_table(rows, headings, indent=1): printf(r) - if not all(l.in_use for l in self.labels.itervalues()): # Show caption + if not all(l.in_use for l in self.labels.values()): # Show caption printf(_('\n * Unreferenced label(s)')) @@ -1702,7 +1700,7 @@ def printf(*args): all_blocks = extract_pragma_blocks(self.assembled_code) headings = [_('Name'), _('Addr range'), _('Value')] rows = [(b.name, '({:03X} - {:03X})'.format(b.start, b.end), \ - ' '.join([unicode(a) for a in b.args])) for b in all_blocks] + ' '.join(str(a) for a in b.args)) for b in all_blocks] for r in format_table(rows, headings, indent=3): printf(r) @@ -1710,7 +1708,7 @@ def printf(*args): inst_usage = self.instruction_usage() headings = [_('Instruction'), _('Instances')] rows = [(i.upper(), inst_usage[i] if inst_usage[i] > 0 else '-') \ - for i in sorted(inst_usage.iterkeys())] + for i in inst_usage] for r in format_table(rows, headings, indent=3): printf(r) @@ -1748,7 +1746,7 @@ def write_formatted_source(self, output_dir): '''Write source for all included files''' self._print(_('\n Formatted source:')) self.create_output_dir(output_dir) - for fname, source in self.sources.iteritems(): + for fname, source in self.sources.items(): if fname == '-': fname = 'stdin' fname = os.path.splitext(os.path.basename(fname))[0] + '.fmt' fname = build_path(output_dir, fname) @@ -1886,7 +1884,7 @@ def overlaps(self, j): # Build char matrix for ASCII arcs total_cols = min(max(min_cols, len(columns)), max_cols) - graph = [[' ']*total_cols for x in xrange(len(self.assembled_code))] + graph = [[' ']*total_cols for x in range(len(self.assembled_code))] for j in jumps: j_min = j.min j_max = j.max @@ -1895,7 +1893,7 @@ def overlaps(self, j): graph[j_max][total_cols - 2 - j.column] = chars['bot_corner'] # Draw horizontal lines - for c in xrange(total_cols - 1 - j.column, total_cols): + for c in range(total_cols - 1 - j.column, total_cols): min_cell = graph[j_min][c] if min_cell == chars['top_corner']: graph[j_min][c] = chars['top_tee'] # Add tee to merge with existing arc @@ -1917,7 +1915,7 @@ def overlaps(self, j): graph[j.target][total_cols-1] = chars['earrow'] # Draw vertical connections within a column - for v in xrange(j_min+1, j_max): + for v in range(j_min+1, j_max): if graph[v][total_cols - 2 - j.column] == ' ': graph[v][total_cols - 2 - j.column] = chars['vline'] @@ -2038,7 +2036,7 @@ def _annotate_pragmas(slist): print('\n' + warn(_('WARNING:')) + _(' Unrecognized pragma at {}').format(s.error_line)) if s.is_instruction(): - for p, a in active_tags.iteritems(): + for p, a in active_tags.items(): s.tags[p] = a if del_pragma: @@ -2063,7 +2061,7 @@ def extract_pragma_blocks(slist): for s in slist: if s.tags: - for p, a in s.tags.iteritems(): + for p, a in s.tags.items(): if p in open_blocks: if s.tags[p] == open_blocks[p].args: open_blocks[p].end = s.address @@ -2090,7 +2088,7 @@ def extract_pragma_blocks(slist): # Move any remaining unclosed blocks to the list - all_blocks.extend(open_blocks.itervalues()) + all_blocks.extend(open_blocks.values()) # Remove empty blocks containing no instructions all_blocks = [b for b in all_blocks if b.has_inst] @@ -2118,14 +2116,14 @@ def format_table(rows, col_names, indent=0): Returns a list of strings ''' cols = zip(col_names, *rows) - col_size = [max(len(unicode(i)) for i in col) for col in cols] + col_size = [max([len(str(i)) for i in col]) for col in cols] fmt = ' ' * indent + ' '.join('{{:{}}}'.format(w) for w in col_size) tbl = [fmt.format(*col_names), fmt.format(*['-'*len(c) for c in col_names]) ] for r in rows: - tbl.append(fmt.format(*['' if i is None else unicode(i) for i in r]).rstrip()) + tbl.append(fmt.format(*[str(i) for i in r]).rstrip()) return tbl @@ -2136,16 +2134,16 @@ def build_xilinx_mem_init(mmap, split_data=False): if not split_data: # Map to 18-bit BRAMs # Lower 16-bits are put in INIT - for a in xrange(len(mmap) // 16): + for a in range(len(mmap) // 16): mline = mmap[a*16:(a+1)*16] init = ''.join('{:04X}'.format(w & 0xFFFF) for w in reversed(mline)) minit['INIT_{:02X}'.format(a)] = init # Upper 2-bits are put in INITP - for a in xrange(len(mmap) // 128): + for a in range(len(mmap) // 128): mline = mmap[a*128:(a+1)*128] nibbles = [] - for i in xrange(0, len(mline), 2): + for i in range(0, len(mline), 2): nibbles.append((mline[i] >> 16) + ((mline[i+1] >> 14) & 0xC)) init = ''.join('{:01X}'.format(n & 0xF) for n in reversed(nibbles)) @@ -2170,16 +2168,16 @@ def build_xilinx_mem_init(mmap, split_data=False): def build_9_bit_mem_init(mmap, minit, bit_range): '''Compute Xilinx BRAM INIT and INITP strings for 9-bit split memories''' # Lower 8-bits are put in INIT - for a in xrange(len(mmap) // 32): + for a in range(len(mmap) // 32): mline = mmap[a*32:(a+1)*32] init = ''.join('{:02X}'.format(w & 0xFF) for w in reversed(mline)) minit['[{}]_INIT_{:02X}'.format(bit_range, a)] = init # Upper 1-bits are put in INITP - for a in xrange(len(mmap) // 256): + for a in range(len(mmap) // 256): mline = mmap[a*256:(a+1)*256] nibbles = [] - for i in xrange(0, len(mline), 4): + for i in range(0, len(mline), 4): nibbles.append((mline[i] >> 8) + ((mline[i+1] >> 7) & 0x02) + \ ((mline[i+2] >> 6) & 0x04) + ((mline[i+3] >> 5) & 0x08)) @@ -2196,7 +2194,7 @@ def build_xilinx_ecc_mem_init(mmap): folded = [(z << 40) + (y << 20) + x for x,y,z in zip(mmap[0:0x200], mmap[0x200:0x400], mmap[0x400:0x600])] # Merge every 4 folded words into an init word - for a in xrange(len(folded) // 4): + for a in range(len(folded) // 4): mline = folded[a*4:(a+1)*4] init = ''.join('{:016X}'.format(w) for w in reversed(mline)) minit['ECC_7S_1K5_INIT_{:02X}'.format(a)] = init @@ -2204,7 +2202,7 @@ def build_xilinx_ecc_mem_init(mmap): # Compute Hamming ECC (72,64) and store in INITPs hamming = [secded_encode_num(w, 64) for w in folded] - for a in xrange(len(folded) // 32): + for a in range(len(folded) // 32): mline = hamming[a*32:(a+1)*32] init = ''.join('{:02X}'.format(w) for w in reversed(mline)) minit['ECC_7S_1K5_INITP_{:02X}'.format(a)] = init @@ -2249,7 +2247,7 @@ def write_hdl_file(input_file, hdl_file, hdl_template, minit, timestamp, default hdl = ''.join(template) # Substitute template tags - for k, v in minit.iteritems(): + for k, v in minit.items(): hdl = hdl.replace('{{{}}}'.format(k), v) # When using the -m option with the KCPSM6 ROM_form.vhd/v files there will @@ -2263,7 +2261,7 @@ def write_hdl_file(input_file, hdl_file, hdl_template, minit, timestamp, default all_inits_replaced = False # Substitute default jump instructions into the unused INIT fields dj_inits = build_default_jump_inits(default_jump) - for k, v in dj_inits.iteritems(): + for k, v in dj_inits.items(): hdl = re.sub(r'{{{}_..}}'.format(k), v, hdl) hdl = hdl.replace('{source file}', input_file) # Extension not used by KCPSM3.exe @@ -2340,7 +2338,7 @@ def template_data_size(template_file): # Search for a line containing each possible signature with io.open(template_file, 'r', encoding='latin1') as fh: for l in fh: - for name, sig in signatures.iteritems(): + for name, sig in signatures.items(): if sig in l: found_sigs.add(name) break diff --git a/setup.py b/setup.py index 0da9ad7..c127139 100755 --- a/setup.py +++ b/setup.py @@ -41,8 +41,6 @@ }, include_package_data = True, - use_2to3 = True, - keywords='Picoblaze assembler', license='MIT', classifiers=['Development Status :: 5 - Production/Stable', From 43a1600588479bb7b6d8a2ec12f1b635da029157 Mon Sep 17 00:00:00 2001 From: Graeme Smecher Date: Tue, 6 Sep 2022 14:57:44 -0700 Subject: [PATCH 3/3] Remove Python 2.x-specific notes from documentation. --- doc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index 6e6f600..431f85a 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -49,7 +49,7 @@ If you are unfamiliar with the PicoBlaze architecture you can review the :doc:`r Requirements ------------ -Opbasm requires either Python 2.7 or Python 3.x and no additional libraries. The installation script depends on setuptools which will be installed if it isn't currently present in your Python distribution. Optional macro support is provided when m4 is installed. You can get optional colorized output from the scripts by installing the Python colorama package. The source is written in Python 2.7 syntax but will convert cleanly to Python 3 when the installer passes it through ``2to3``. +Opbasm requires Python 3.x and no additional libraries. The installation script depends on setuptools which will be installed if it isn't currently present in your Python distribution. Optional macro support is provided when m4 is installed. You can get optional colorized output from the scripts by installing the Python colorama package. Download