|  | import json | 
|  | import csv | 
|  | import argparse | 
|  | from collections import namedtuple | 
|  |  | 
|  |  | 
|  | def get_module_ports(j, module): | 
|  | if module not in j['modules']: | 
|  | raise LookupError( | 
|  | 'module %s not in module list %s' % | 
|  | (module, ', '.join(j['modules'].keys())) | 
|  | ) | 
|  |  | 
|  | for port in j['modules'][module]['ports']: | 
|  | bits = j['modules'][module]['ports'][port]['bits'] | 
|  | if len(bits) > 1: | 
|  | for idx, _ in enumerate(bits): | 
|  | yield j['modules'][module]['ports'][port][ | 
|  | 'direction'], '%s[%d]' % (port, idx) | 
|  | else: | 
|  | yield j['modules'][module]['ports'][port]['direction'], port | 
|  |  | 
|  |  | 
|  | Pin = namedtuple('Pin', 'name is_clock is_input is_output') | 
|  |  | 
|  |  | 
|  | def get_free_pin(available_pins, direction): | 
|  | possible_pins = [] | 
|  | for pin in available_pins: | 
|  | if pin.is_input and not pin.is_clock and direction == 'input': | 
|  | possible_pins.append(pin) | 
|  | if pin.is_output and direction == 'output': | 
|  | possible_pins.append(pin) | 
|  | assert possible_pins, "Did not find any *%s* pins in:\n%s" % ( | 
|  | direction, "\n  ".join(str(x) for x in available_pins) | 
|  | ) | 
|  | return possible_pins.pop(0) | 
|  |  | 
|  |  | 
|  | def main(): | 
|  | parser = argparse.ArgumentParser( | 
|  | description='Creates a pinmap file for a module for a given package.' | 
|  | ) | 
|  |  | 
|  | parser.add_argument('--design_json', help='Yosys JSON design input.') | 
|  | parser.add_argument('--pinmap_csv', help='CSV pinmap definition.') | 
|  | parser.add_argument( | 
|  | '--module', help='Name of module to generate pindef for.' | 
|  | ) | 
|  |  | 
|  | args = parser.parse_args() | 
|  |  | 
|  | # Read in the pin map | 
|  | pins = [] | 
|  | with open(args.pinmap_csv) as f: | 
|  | for row in csv.DictReader(f): | 
|  | if 'is_clock' in row: | 
|  | is_clock = int(row['is_clock']) != 0 | 
|  | else: | 
|  | is_clock = False | 
|  |  | 
|  | if 'is_input' in row: | 
|  | is_input = int(row['is_input']) != 0 | 
|  | else: | 
|  | is_input = True | 
|  |  | 
|  | if 'is_output' in row: | 
|  | is_output = int(row['is_output']) != 0 | 
|  | else: | 
|  | is_output = True | 
|  |  | 
|  | pins.append( | 
|  | Pin( | 
|  | name=row['name'], | 
|  | is_clock=is_clock, | 
|  | is_input=is_input, | 
|  | is_output=is_output, | 
|  | ) | 
|  | ) | 
|  |  | 
|  | available_pins = list(pins) | 
|  |  | 
|  | # Read in the design and assign pins | 
|  | import sys | 
|  | with open(args.design_json) as f: | 
|  | j = json.load(f) | 
|  | for direction, port in get_module_ports(j, args.module): | 
|  | pin = get_free_pin(available_pins, direction) | 
|  | sys.stderr.write( | 
|  | "Assigned %s to %s # %s\n" % (port, pin.name, direction) | 
|  | ) | 
|  | print('set_io %s %s' % (port, pin.name)) | 
|  | available_pins.remove(pin) | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | main() |