Exemplo n.º 1
0
def main(argv):
    args = parser.parse_args()

    def output_block(name, s):
        if args.verbose:
            print()
            print(name, '-' * (75 - (len(name) + 1)))
            print(s, end="")
            if s[-1] != '\n':
                print()
            print('-' * 75)

    args.width_bits = mux_lib.clog2(args.width)

    def normpath(p, to=None):
        p = os.path.realpath(os.path.abspath(p))
        if to is None:
            return p
        return os.path.relpath(p, normpath(to))

    mypath = normpath(__file__)

    if not args.outdir:
        outdir = os.path.join(".", args.name_mux.lower())
    else:
        outdir = args.outdir

    outdir = normpath(outdir)

    mydir = normpath(os.path.dirname(mypath), to=outdir)
    mux_dir = normpath(os.path.join(mydir, '..', 'vpr', 'muxes'), to=outdir)

    if args.data_width > 1 and not args.split_inputs:
        assert False, "data_width(%d) > 1 requires using split_inputs" % (
            args.data_width)

    if args.name_inputs:
        assert_eq(args.name_input, parser.get_default("name_input"))
        args.name_input = None
        args.split_inputs = True

        names = args.name_inputs.split(',')
        assert len(names) == args.width, "%s input names, but %s needed." % (
            names, args.width)
        args.name_inputs = names
    elif args.split_inputs:
        args.name_inputs = [
            args.name_input + str(i) for i in range(args.width)
        ]
        parser.name_inputs.default = args.name_inputs
        assert_eq(parser.get_default("name_inputs"), args.name_inputs)

    if args.name_selects:
        assert_eq(args.name_select, parser.get_default("name_select"))
        args.name_select = None
        args.split_selects = True

        names = args.name_selects.split(',')
        assert len(names) == args.width_bits, (
            "%s select names, but %s needed." % (names, args.width_bits))
        args.name_selects = names
    elif args.split_selects:
        args.name_selects = [
            args.name_select + str(i) for i in range(args.width_bits)
        ]
        parser.name_selects.default = args.name_selects
        assert_eq(parser.get_default("name_selects"), args.name_selects)

    os.makedirs(outdir, exist_ok=True)

    # Generated headers
    generated_with = """
Generated with %s
""" % mypath
    if args.comment:
        generated_with = "\n".join([args.comment, generated_with])

    # XML Files can't have "--" in them, so instead we use ~~
    xml_comment = generated_with.replace("--", "~~")

    if not args.outfilename:
        args.outfilename = args.name_mux.lower()

    model_xml_filename = '%s.model.xml' % args.outfilename
    pbtype_xml_filename = '%s.pb_type.xml' % args.outfilename
    sim_filename = '%s.sim.v' % args.outfilename

    # ------------------------------------------------------------------------
    # Work out the port and their names
    # ------------------------------------------------------------------------

    port_names = []
    for i in args.order:
        if i == 'i':
            if args.split_inputs:
                port_names.extend(
                    mux_lib.ModulePort(mux_lib.MuxPinType.INPUT,
                                       args.name_inputs[j], 1, '[%i]' %
                                       j, args.data_width)
                    for j in range(args.width))
            else:
                # verilog range bounds are inclusive and convention is
                # [<width-1>:0]
                port_names.append(
                    mux_lib.ModulePort(mux_lib.MuxPinType.INPUT,
                                       args.name_input, args.width,
                                       '[%i:0]' % (args.width - 1)))
        elif i == 's':
            if args.split_selects:
                port_names.extend(
                    mux_lib.ModulePort(mux_lib.MuxPinType.SELECT,
                                       args.name_selects[j], 1, '[%i]' % j)
                    for j in range(args.width_bits))
            else:
                # verilog range bounds are inclusive and convention is
                # [<width-1>:0]
                assert args.name_select is not None
                port_names.append(
                    mux_lib.ModulePort(mux_lib.MuxPinType.SELECT,
                                       args.name_select, args.width_bits,
                                       '[%i:0]' % (args.width_bits - 1)))
        elif i == 'o':
            port_names.append(
                mux_lib.ModulePort(mux_lib.MuxPinType.OUTPUT, args.name_output,
                                   1, '', args.data_width))

    # ------------------------------------------------------------------------
    # Generate the sim.v Verilog module
    # ------------------------------------------------------------------------

    sim_pathname = os.path.join(outdir, sim_filename)
    with open(sim_pathname, "w") as f:
        module_args = []
        for port in port_names:
            if args.type == 'routing' and port.pin_type == mux_lib.MuxPinType.SELECT:
                continue
            module_args.append(port.name)

        mux_class = {'logic': 'mux', 'routing': 'routing'}[args.type]

        f.write("/* ")
        f.write("\n * ".join(generated_with.splitlines()))
        f.write("\n */\n\n")
        f.write('`include "%s/%s/%smux%i/%smux%i.sim.v"\n' % (
            mux_dir,
            'logic',
            '',
            args.width,
            '',
            args.width,
        ))
        f.write("\n")
        f.write('(* whitebox *) (* CLASS="%s" *)\n' % mux_class)
        f.write("module %s(%s);\n" % (args.name_mux, ", ".join(module_args)))
        previous_type = None
        for port in port_names:
            if previous_type != port.pin_type:
                f.write("\n")
                previous_type = port.pin_type
            if args.type == 'routing' and port.pin_type == mux_lib.MuxPinType.SELECT:
                f.write(port.getParameterString())
                continue
            else:
                f.write(port.getDefinition())

        f.write("\n")
        if args.data_width > 1:
            f.write('\tgenvar\tii;\n')
            f.write('\tfor(ii=0; ii<%d; ii++) begin: bitmux\n' %
                    (args.data_width))

        f.write('\tMUX%s mux (\n' % args.width)
        for i in range(0, args.width):
            j = 0
            for port in port_names:
                if port.pin_type != mux_lib.MuxPinType.INPUT:
                    continue
                if j + port.width <= i:
                    j += port.width
                    continue
                break

            if port.width == 1:
                if args.data_width > 1:
                    f.write('\t\t.I%i(%s[ii]),\n' % (i, port.name))
                else:
                    f.write('\t\t.I%i(%s),\n' % (i, port.name))
            else:
                f.write('\t\t.I%i(%s[%i]),\n' % (i, port.name, i - j))

        for i in range(0, args.width_bits):
            j = 0
            for port in port_names:
                if port.pin_type != mux_lib.MuxPinType.SELECT:
                    continue
                if j + port.width < i:
                    j += port.width
                    continue
                break

            if port.width == 1:
                f.write('\t\t.S%i(%s),\n' % (i, port.name))
            else:
                f.write('\t\t.S%i(%s[%i]),\n' % (i, port.name, i - j))

        for port in port_names:
            if port.pin_type != mux_lib.MuxPinType.OUTPUT:
                continue
            break
        assert_eq(port.width, 1)
        if args.data_width > 1:
            f.write('\t\t.O(%s[ii])\n\t);\n' % port.name)
        else:
            f.write('\t\t.O(%s)\n\t);\n' % port.name)

        if args.data_width > 1:
            f.write('end\n')

        f.write('endmodule\n')

    output_block(sim_filename, open(sim_pathname).read())

    if args.type == 'logic':
        subckt = args.subckt or args.name_mux
        assert subckt
    elif args.type == 'routing':
        assert args.subckt is None
        subckt = None

    # ------------------------------------------------------------------------
    # Generate the Model XML form.
    # ------------------------------------------------------------------------
    def xml_comment_indent(n, s):
        return ("\n" + " " * n).join(s.splitlines() + [""])

    if args.type == 'logic':
        models_xml = ET.Element('models')
        models_xml.append(ET.Comment(xml_comment_indent(4, xml_comment)))

        model_xml = ET.SubElement(models_xml, 'model', {'name': subckt})

        input_ports = ET.SubElement(model_xml, 'input_ports')
        output_ports = ET.SubElement(model_xml, 'output_ports')
        for port in port_names:
            if port.pin_type in (mux_lib.MuxPinType.INPUT,
                                 mux_lib.MuxPinType.SELECT):
                ET.SubElement(
                    input_ports, 'port', {
                        'name':
                        port.name,
                        'combinational_sink_ports':
                        ' '.join(
                            port.name for port in port_names
                            if port.pin_type in (mux_lib.MuxPinType.OUTPUT, )),
                    })
            elif port.pin_type in (mux_lib.MuxPinType.OUTPUT, ):
                ET.SubElement(output_ports, 'port', {'name': port.name})

        models_str = ET.tostring(models_xml, pretty_print=True).decode('utf-8')
    else:
        models_str = "<models><!-- No models for routing elements.--></models>"

    output_block(model_xml_filename, models_str)
    with open(os.path.join(outdir, model_xml_filename), "w") as f:
        f.write(models_str)

    # ------------------------------------------------------------------------
    # Generate the pb_type XML form.
    # ------------------------------------------------------------------------

    pb_type_xml = mux_lib.pb_type_xml(
        mux_lib.MuxType[args.type.upper()],
        args.name_mux,
        port_names,
        subckt=subckt,
        num_pb=args.num_pb,
        comment=xml_comment_indent(4, xml_comment),
    )

    pb_type_str = ET.tostring(pb_type_xml, pretty_print=True).decode('utf-8')
    output_block(pbtype_xml_filename, pb_type_str)
    with open(os.path.join(outdir, pbtype_xml_filename), "w") as f:
        f.write(pb_type_str)

    print("Generated mux {} in {}".format(args.name_mux, outdir))
            ]
            for src_wire, index in sorted(srcs):
                if src_wire in net_dirs['inputs']:
                    src_wire_name = "%s.%s[%s]" % (tile_name, src_wire, index)
                else:
                    assert src_wire in net_dirs['outputs']
                    src_wire_name = "BEL_RX-%s%s.OUT" % (src_wire, index)

                mux_wire_name = "%s%s" % (src_wire, index)
                add_direct(src_wire_name, "%s.%s" % (mux_name, mux_wire_name))
                port_names.append(
                    mux_lib.ModulePort(mux_lib.MuxPinType.INPUT, mux_wire_name,
                                       1, 0), )

            pb_type_xml.append(
                mux_lib.pb_type_xml(mux_lib.MuxType.ROUTING, mux_name,
                                    port_names))

            add_direct("%s.OUT" % mux_name, dst_wire_name)
        else:
            assert (span_wire, pin) not in connections_map[
                'mux'] or not connections_map['mux'][(span_wire, pin)]

for clock_wire, pins in sorted(wires_by_type['clock'].items()):
    ET.SubElement(
        pb_type_xml,
        'clock',
        {
            'name': clock_wire,
            'num_pins': str(len(pins))
        },
    )
Exemplo n.º 3
0
def main(argv):
    call_args = list(argv)

    args = parser.parse_args()

    def output_block(name, s):
        if args.verbose:
            print()
            print(name, '-' * (75 - (len(name) + 1)))
            print(s, end="")
            if s[-1] != '\n':
                print()
            print('-' * 75)

    args.width_bits = mux_lib.clog2(args.width)

    def normpath(p, to=None):
        p = os.path.realpath(os.path.abspath(p))
        if to is None:
            return p
        return os.path.relpath(p, normpath(to))

    mypath = normpath(__file__)

    if not args.outdir:
        outdir = os.path.join(".", args.name_mux.lower())
    else:
        outdir = args.outdir

    outdir = normpath(outdir)

    mydir = normpath(os.path.dirname(mypath), to=outdir)
    mypath = normpath(mypath, to=outdir)
    mux_dir = normpath(os.path.join(mydir, '..', 'vpr', 'muxes'), to=outdir)
    buf_dir = normpath(os.path.join(mydir, '..', 'vpr', 'buf'), to=outdir)
    mux_mk = normpath(os.path.join(mydir, '..', 'common', 'make', 'mux.mk'),
                      to=outdir)

    if args.name_inputs:
        assert_eq(args.name_input, parser.get_default("name_input"))
        args.name_input = None
        args.split_inputs = True

        names = args.name_inputs.split(',')
        assert len(names) == args.width, "%s input names, but %s needed." % (
            names, args.width)
        args.name_inputs = names
    elif args.split_inputs:
        args.name_inputs = [
            args.name_input + str(i) for i in range(args.width)
        ]
        parser.name_inputs.default = args.name_inputs
        assert_eq(parser.get_default("name_inputs"), args.name_inputs)

    if args.name_selects:
        assert_eq(args.name_select, parser.get_default("name_select"))
        args.name_select = None
        args.split_selects = True

        names = args.name_selects.split(',')
        assert len(
            names) == args.width_bits, "%s select names, but %s needed." % (
                names, args.width_bits)
        args.name_selects = names
    elif args.split_selects:
        args.name_selects = [
            args.name_select + str(i) for i in range(args.width_bits)
        ]
        parser.name_selects.default = args.name_selects
        assert_eq(parser.get_default("name_selects"), args.name_selects)

    os.makedirs(outdir, exist_ok=True)

    # Generated headers
    generated_with = """
Generated with %s
""" % mypath
    if args.comment:
        generated_with = "\n".join([args.comment, generated_with])

    # XML Files can't have "--" in them, so instead we use ~~
    xml_comment = generated_with.replace("--", "~~")

    # ------------------------------------------------------------------------
    # Create a makefile to regenerate files.
    # ------------------------------------------------------------------------
    makefile_file = os.path.join(outdir, "Makefile.mux")

    if not args.outfilename:
        args.outfilename = args.name_mux.lower()

    model_xml_filename = '%s.model.xml' % args.outfilename
    pbtype_xml_filename = '%s.pb_type.xml' % args.outfilename
    sim_filename = '%s.sim.v' % args.outfilename

    output_files = [
        model_xml_filename, pbtype_xml_filename, sim_filename, 'Makefile.mux'
    ]
    commit_files = ["Makefile.mux"]
    remove_files = [f for f in output_files if f not in commit_files]

    new_makefile_contents = io.StringIO()
    if True:
        f = new_makefile_contents
        # Comment goes first so it is the first thing people see.
        if args.comment:
            print("MUX_COMMENT = {}".format(args.comment), file=f)

        # Required values
        print("MUX_TYPE = {}".format(args.type.lower()), file=f)
        print("MUX_OUTFILE = {}".format(args.outfilename), file=f)
        print("MUX_NAME = {}".format(args.name_mux), file=f)
        print("MUX_WIDTH = {}".format(args.width), file=f)

        # Optional values
        if args.split_inputs:
            print("MUX_SPLIT_INPUTS = 1", file=f)
            if args.name_inputs != parser.get_default('name_inputs'):
                print("MUX_INPUTS = {}".format(",".join(args.name_inputs)),
                      file=f)
        else:
            if args.name_input != parser.get_default('name_input'):
                print("MUX_INPUT = {}".format(args.name_input), file=f)

        if args.split_selects:
            print("MUX_SPLIT_SELECTS = 1", file=f)
            if args.name_selects != parser.get_default('name_selects'):
                print("MUX_SELECTS = {}".format(",".join(args.name_selects)),
                      file=f)
        else:
            if args.name_select != parser.get_default('name_select'):
                print("MUX_SELECT = {}".format(args.name_select), file=f)

        if args.name_output != parser.get_default('name_output'):
            print("MUX_OUTPUT = {}".format(args.name_output), file=f)

        if args.order != parser.get_default('order'):
            print("MUX_ORDER = {}".format(args.order), file=f)

        if args.subckt != parser.get_default('subckt'):
            print("MUX_SUBCKT = {}".format(args.subckt), file=f)

    new_makefile_contents = new_makefile_contents.getvalue()
    if not os.path.exists(makefile_file):
        current_makefile_contents = ""
    else:
        current_makefile_contents = open(makefile_file, "r").read()

    if current_makefile_contents != new_makefile_contents:
        open(makefile_file, "w").write(new_makefile_contents)

    output_block("Makefile.mux", open(makefile_file).read())

    # ------------------------------------------------------------------------
    # Work out the port and their names
    # ------------------------------------------------------------------------

    port_names = []
    for i in args.order:
        if i == 'i':
            if args.split_inputs:
                port_names.extend((mux_lib.MuxPinType.INPUT,
                                   args.name_inputs[j], 1, '[%i]' % j)
                                  for j in range(args.width))
            else:
                # verilog range bounds are inclusive and convention is [<width-1>:0]
                port_names.append((mux_lib.MuxPinType.INPUT, args.name_input,
                                   args.width, '[%i:0]' % (args.width - 1)))
        elif i == 's':
            if args.split_selects:
                port_names.extend((mux_lib.MuxPinType.SELECT,
                                   args.name_selects[j], 1, '[%i]' % j)
                                  for j in range(args.width_bits))
            else:
                assert args.name_select is not None
                # verilog array range bounds are inclusive and convention is [<width-1>:0]
                port_names.append(
                    (mux_lib.MuxPinType.SELECT, args.name_select,
                     args.width_bits, '[%i:0]' % (args.width_bits - 1)))
        elif i == 'o':
            port_names.append(
                (mux_lib.MuxPinType.OUTPUT, args.name_output, 1, ''))

    # ------------------------------------------------------------------------
    # Generate the sim.v Verilog module
    # ------------------------------------------------------------------------

    defs = {'i': 'input wire', 's': 'input wire', 'o': 'output wire'}

    sim_pathname = os.path.join(outdir, sim_filename)
    with open(sim_pathname, "w") as f:
        module_args = []
        for type, name, _, _ in port_names:
            if args.type == 'routing' and type == mux_lib.MuxPinType.SELECT:
                continue
            module_args.append(name)

        mux_prefix = {'logic': '', 'routing': 'r'}[args.type]
        mux_class = {'logic': 'mux', 'routing': 'routing'}[args.type]

        f.write("/* ")
        f.write("\n * ".join(generated_with.splitlines()))
        f.write("\n */\n\n")
        f.write('`include "%s/%s/%smux%i/%smux%i.sim.v"\n' % (
            mux_dir,
            'logic',
            '',
            args.width,
            '',
            args.width,
        ))
        f.write("\n")
        f.write('(* blackbox *) (* CLASS="%s" *)\n' % mux_class)
        f.write("module %s(%s);\n" % (args.name_mux, ", ".join(module_args)))
        previous_type = None
        for type, name, width, index in port_names:
            if previous_type != type:
                f.write("\n")
                previous_type = type
            if args.type == 'routing' and type == mux_lib.MuxPinType.SELECT:
                if width == 1:
                    f.write('\tparameter [0:0] %s = 0;\n' % (name))
                else:
                    f.write('\tparameter %s %s = 0;\n' % (index, name))
                continue

            if width == 1:
                f.write('\t%s %s;\n' % (type.verilog(), name))
            else:
                f.write('\t%s %s %s;\n' % (type.verilog(), index, name))

        f.write("\n")
        f.write('\tMUX%s mux (\n' % args.width)
        for i in range(0, args.width):
            j = 0
            for type, name, width, index in port_names:
                if type != mux_lib.MuxPinType.INPUT:
                    continue
                if j + width <= i:
                    j += width
                    continue
                break

            if width == 1:
                f.write('\t\t.I%i(%s),\n' % (i, name))
            else:
                f.write('\t\t.I%i(%s[%i]),\n' % (i, name, i - j))

        for i in range(0, args.width_bits):
            j = 0
            for type, name, width, index in port_names:
                if type != mux_lib.MuxPinType.SELECT:
                    continue
                if j + width < i:
                    j += width
                    continue
                break

            if width == 1:
                f.write('\t\t.S%i(%s),\n' % (i, name))
            else:
                f.write('\t\t.S%i(%s[%i]),\n' % (i, name, i - j))

        for type, name, width, index in port_names:
            if type != mux_lib.MuxPinType.OUTPUT:
                continue
            break
        assert_eq(width, 1)
        f.write('\t\t.O(%s)\n\t);\n' % name)

        f.write('endmodule\n')

    output_block(sim_filename, open(sim_pathname).read())

    if args.type == 'logic':
        subckt = args.subckt or args.name_mux
        assert subckt
    elif args.type == 'routing':
        assert args.subckt is None
        subckt = None

    # ------------------------------------------------------------------------
    # Generate the Model XML form.
    # ------------------------------------------------------------------------
    def xml_comment_indent(n, s):
        return ("\n" + " " * n).join(s.splitlines() + [""])

    if args.type == 'logic':
        models_xml = ET.Element('models')
        models_xml.append(ET.Comment(xml_comment_indent(4, xml_comment)))

        model_xml = ET.SubElement(models_xml, 'model', {'name': subckt})

        input_ports = ET.SubElement(model_xml, 'input_ports')
        output_ports = ET.SubElement(model_xml, 'output_ports')
        for type, name, width, index in port_names:
            if type in (mux_lib.MuxPinType.INPUT, mux_lib.MuxPinType.SELECT):
                ET.SubElement(
                    input_ports, 'port', {
                        'name':
                        name,
                        'combinational_sink_ports':
                        ','.join(n for t, n, w, i in port_names
                                 if t in (mux_lib.MuxPinType.OUTPUT, )),
                    })
            elif type in (mux_lib.MuxPinType.OUTPUT, ):
                ET.SubElement(output_ports, 'port', {'name': args.name_output})

        models_str = ET.tostring(models_xml, pretty_print=True).decode('utf-8')
    else:
        models_str = "<models><!-- No models for routing elements.--></models>"

    output_block(model_xml_filename, models_str)
    with open(os.path.join(outdir, model_xml_filename), "w") as f:
        f.write(models_str)

    # ------------------------------------------------------------------------
    # Generate the pb_type XML form.
    # ------------------------------------------------------------------------

    pb_type_xml = mux_lib.pb_type_xml(
        mux_lib.MuxType[args.type.upper()],
        args.name_mux,
        port_names,
        subckt=subckt,
        num_pb=args.num_pb,
        comment=xml_comment_indent(4, xml_comment),
    )

    pb_type_str = ET.tostring(pb_type_xml, pretty_print=True).decode('utf-8')
    output_block(pbtype_xml_filename, pb_type_str)
    with open(os.path.join(outdir, pbtype_xml_filename), "w") as f:
        f.write(pb_type_str)

    print("Generated mux {} in {}".format(args.name_mux, outdir))