| 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() |