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