Esempio n. 1
0
def ram_pin_offset(pin):
    """Get the offset for a given RAM pin."""
    # The pin split between top/bottom tiles is different on the 1k to all the
    # other parts.
    ram_pins_0to8 = ["WADDR[0]", "WCLKE[0]", "WCLK[0]", "WE[0]"]
    for i in range(8):
        ram_pins_0to8.extend(
            [
                "RDATA[{}]".format(i),
                "MASK[{}]".format(i),
                "WDATA[{}]".format(i),
            ]
        )
    ram_pins_0to8.extend(['WADDR[{}]'.format(i) for i in range(0, 11)])

    ram_pins_8to16 = ["RCLKE[0]", "RCLK[0]", "RE[0]"]
    for i in range(8, 16):
        ram_pins_8to16.extend(
            [
                "RDATA[{}]".format(i),
                "MASK[{}]".format(i),
                "WDATA[{}]".format(i),
            ]
        )
    ram_pins_8to16.extend(['RADDR[{}]'.format(i) for i in range(0, 11)])

    if ic.device == '384':
        assert False, "384 device doesn't have RAM!"
    elif ic.device == '1k':
        top_pins = ram_pins_8to16
        bot_pins = ram_pins_0to8
    else:
        assert ic.device in ('5k',
                             '8k'), "{} is unknown device".format(ic.device)
        top_pins = ram_pins_0to8
        bot_pins = ram_pins_8to16

    if pin.name in top_pins:
        return Offset(0, 1)
    elif pin.name in bot_pins:
        return Offset(0, 0)
    else:
        assert False, "RAM pin {} doesn't match name expected for metadata".format(
            pin.name
        )
def add_track_with_lines(g, ic, segment, lines, connections, hlc_name_f):
    """Add tracks to the rr_graph from straight lines and connections."""
    logging.debug(
        "Created track %s from sections: %s", segment.name, len(lines))
    logging.debug(
        "Created track %s from sections: %s", segment.name, lines)
    for line in lines:
        istart, iend = points.straight_ends([p.pos for p in line])
        logging.debug(
            "  %s>%s (%s)", istart, iend, line) #{n for p, n in named_positions})
    for ipos, joins in sorted(connections.items()):
        for name_a, name_b in joins:
            logging.debug(
                "  %s %s<->%s", ipos, name_a, name_b)

    for line in lines:
        istart, iend = points.straight_ends([p.pos for p in line])
        vstart, vend = pos_icebox2vpr(istart), pos_icebox2vpr(iend)

        if line.direction.value == '-':
            typeh = channel.Track.Type.X
        elif line.direction.value == '|':
            typeh = channel.Track.Type.Y
        else:
            typeh = channel.Track.Type.Y

        track, track_node = g.create_xy_track(
            vstart, vend,
            segment=segment,
            typeh=typeh,
            direction=channel.Track.Direction.BI,
        )
        track_node.set_metadata("hlc_coord", "{},{}".format(*istart), offset=Offset(0, 0))
        # FIXME: Add offset for iend

        # <metadata>
        #   <meta name="hlc_name">{PI( 0, 1): 'io_1/D_IN_0', PI( 1, 1): 'neigh_op_lft_2,neigh_op_lft_6'}</meta>
        # </metadata>
        #
        # <metadata>
        #   <meta name="hlc_name" x_offset="0" y_offset="1">io_1/D_IN_0</meta>
        #   <meta name="hlc_name" x_offset="1" y_offset="1">neigh_op_lft_2</meta>
        #   <meta name="hlc_name" x_offset="1" y_offset="1">neigh_op_lft_6</meta>
        # </metadata>

        track_fmt = format_node(g, track_node)
        logging.debug(
            " Created track %s %s from %s", track_fmt, segment.name, typeh)

        for npos in line:
            ipos = npos.pos
            vpos = pos_icebox2vpr(ipos)

            offset = Offset(npos.pos.x-line[0].pos.x, npos.pos.y-line[0].pos.y)
            hlc_name = hlc_name_f(line, ipos)
            if hlc_name is not None:
                track_node.set_metadata("hlc_name", hlc_name, offset=offset)

            for n in npos.names:
                try:
                    g.routing.localnames[(vpos, n)]

                    drv_node = g.routing.localnames[(vpos, n)]
                    drv_fmt = str(format_node(g, drv_node))
                    logging.debug(
                        "  Existing node %s with local name %s on %s",
                        drv_fmt, n, vpos)

                    g.routing.localnames.add(vpos, n+"_?", track_node)
                    if ipos in connections:
                        continue
                    connections[ipos].append((n, n+"_?"))
                except KeyError:
                    g.routing.localnames.add(vpos, n, track_node)
                    logging.debug(
                        "  Setting local name %s on %s for %s",
                        n, vpos, track_fmt)

    for ipos, joins in sorted(connections.items()):
        logging.info("pos:%s joins:%s", ipos, joins)
        for name_a, name_b in joins:
            vpos = pos_icebox2vpr(ipos)

            node_a = g.routing.localnames[(vpos, name_a)]
            node_b = g.routing.localnames[(vpos, name_b)]

            logging.debug(" Shorting at coords %s - %s -> %s\n\t%s\n ->\n\t%s",
                ipos, name_a, name_b,
                format_node(g, node_a),
                format_node(g, node_b),
            )
            create_edge_with_names(
                g,
                name_a, name_b,
                ipos, g.switches["short"],
            )
def create_edge_with_names(g, src_name, dst_name, ipos, switch, skip=None, bidir=None):
    """Create an edge at a given icebox position from two local names."""
    assert_type(src_name, str)
    assert_type(dst_name, str)
    assert_type(ipos, PositionIcebox)
    assert_type(switch, graph.Switch)

    if skip is None:
        def skip(fmt, *a, **k):
            raise AssertionError(fmt % a)

    if switch.type in (graph.SwitchType.SHORT, graph.SwitchType.PASS_GATE):
        if bidir is None:
            bidir = True
        else:
            assert bidir is True, "Switch {} must be bidir ({})".format(
                switch, (ipos, src_name, dst_name, bidir))
    elif bidir is None:
        bidir = False

    src_hlc_name = group_hlc_name([NP(ipos, [src_name])])
    dst_hlc_name = group_hlc_name([NP(ipos, [dst_name])])

    vpos = pos_icebox2vpr(ipos)
    src_node = g.routing.get_by_name(src_name, vpos, None)
    dst_node = g.routing.get_by_name(dst_name, vpos, None)

    if src_node is None:
        skip(
            "src missing *%s:%s* (%s) node %s => %s:%s (%s) node %s",
            vpos,
            src_name,
            src_hlc_name,
            format_node(g, src_node),
            vpos,
            dst_name,
            dst_hlc_name,
            format_node(g, dst_node),
            level=logging.WARNING,
        )
        return
    if dst_node is None:
        skip(
            "dst missing %s:%s (%s) node %s => *%s:%s* (%s) node %s",
            vpos,
            src_name,
            src_hlc_name,
            format_node(g, src_node),
            vpos,
            dst_name,
            dst_hlc_name,
            format_node(g, dst_node),
        )
        return

    logging.debug(
        "On %s add %-8s edge %s - %s:%s (%s) node %s => %s:%s (%s) node %s",
        ipos,
        switch.name,
        len(g.routing.id2element[graph.RoutingEdge]),
        vpos,
        src_name,
        src_hlc_name,
        format_node(g, src_node),
        vpos,
        dst_name,
        dst_hlc_name,
        format_node(g, dst_node),
    )

    g.routing.create_edge_with_nodes(
        src_node, dst_node,
        switch=switch,
        bidir=bidir,
        metadata={Offset(0,0):{"hlc_coord": "{},{}".format(*ipos)}},
    )
def add_pin_aliases(g, ic):
    """Create icebox local names from the architecture pin names."""
    name_rr2local = {}

    # BLK_TL-PLB - http://www.clifford.at/icestorm/logic_tile.html
    name_rr2local['BLK_TL-PLB.lutff_global/s_r[0]'] = 'lutff_global/s_r'
    name_rr2local['BLK_TL-PLB.lutff_global/clk[0]'] = 'lutff_global/clk'
    name_rr2local['BLK_TL-PLB.lutff_global/cen[0]'] = 'lutff_global/cen'
    # FIXME: these two are wrong I think, but don't worry about carry for now
    #name_rr2local['BLK_TL-PLB.FCIN[0]'] = 'lutff_0/cin'
    #name_rr2local['BLK_TL-PLB.FCOUT[0]'] = 'lutff_7/cout'
    #name_rr2local['BLK_TL-PLB.lutff_0_cin[0]'] = 'lutff_0/cin'
    #name_rr2local['BLK_TL-PLB.lutff_7_cout[0]'] = 'lutff_7/cout'
    for luti in range(8):
        name_rr2local['BLK_TL-PLB.lutff_{}/out[0]'.format(
            luti)] = 'lutff_{}/out'.format(luti)
        for lut_input in range(4):
            name_rr2local['BLK_TL-PLB.lutff_{}/in[{}]'.format(
                luti, lut_input)] = 'lutff_{}/in_{}'.format(
                    luti, lut_input)

    name_rr2local['BLK_TL-PLB.FCOUT[0]'] = 'lutff_0/cout'

    # BLK_TL-PIO - http://www.clifford.at/icestorm/io_tile.html
    for blocki in range(2):
        name_rr2local['BLK_TL-PIO.[{}]LATCH[0]'.format(
            blocki)] = 'io_{}/latch'.format(blocki)
        name_rr2local['BLK_TL-PIO.[{}]OUTCLK[0]'.format(
            blocki)] = 'io_{}/outclk'.format(blocki)
        name_rr2local['BLK_TL-PIO.[{}]CEN[0]'.format(
            blocki)] = 'io_{}/cen'.format(blocki)
        name_rr2local['BLK_TL-PIO.[{}]INCLK[0]'.format(
            blocki)] = 'io_{}/inclk'.format(blocki)
        name_rr2local['BLK_TL-PIO.[{}]D_IN[0]'.format(
            blocki)] = 'io_{}/D_IN_0'.format(blocki)
        name_rr2local['BLK_TL-PIO.[{}]D_IN[1]'.format(
            blocki)] = 'io_{}/D_IN_1'.format(blocki)
        name_rr2local['BLK_TL-PIO.[{}]D_OUT[0]'.format(
            blocki)] = 'io_{}/D_OUT_0'.format(blocki)
        name_rr2local['BLK_TL-PIO.[{}]D_OUT[1]'.format(
            blocki)] = 'io_{}/D_OUT_1'.format(blocki)
        name_rr2local['BLK_TL-PIO.[{}]OUT_ENB[0]'.format(
            blocki)] = 'io_{}/OUT_ENB'.format(blocki)
        name_rr2local['BLK_TL-PIO.[{}]PACKAGE_PIN[0]'.format(
            blocki)] = 'io_{}/pin'.format(blocki)

    # BLK_TL-RAM - http://www.clifford.at/icestorm/ram_tile.html
    for top_bottom in 'BT':
        # rdata, wdata, and mask ranges are the same based on Top/Bottom
        if top_bottom == 'T':
            data_range = range(8,16)
            # top has Read clock and enable and address
            rw = 'R'
        else:
            data_range = range(0,8)
            # top has Read clock and enable and address
            rw = 'W'

        def add_ram_pin(rw, sig, ind=None):
            if ind is None:
                name_rr2local['BLK_TL-RAM.{}{}[{}]'.format(rw, sig, 0)] = 'ram/{}{}'.format(rw, sig)
            else:
                name_rr2local['BLK_TL-RAM.{}{}[{}]'.format(rw, sig, ind)] = 'ram/{}{}_{}'.format(rw, sig, ind)

        add_ram_pin(rw, 'CLK')
        add_ram_pin(rw, 'CLKE')
        add_ram_pin(rw, 'E')

        for ind in range(11):
            add_ram_pin(rw, 'ADDR', ind)

        for ind in data_range:
            add_ram_pin('R', 'DATA', ind)
            add_ram_pin('W', 'DATA', ind)
            add_ram_pin('', 'MASK', ind)

    # BLK_TL-RAM
    for top_bottom in 'BT':
        # rdata, wdata, and mask ranges are the same based on Top/Bottom
        if top_bottom == 'T':
            data_range = range(8,16)
            # top has Read clock and enbable and address
            rw = 'R'
        else:
            data_range = range(0,8)
            # top has Read clock and enbable and address
            rw = 'W'

        def add_ram_pin(rw, sig, ind=None):
            if ind is None:
                name_rr2local['BLK_TL-RAM.{}{}[{}]'.format(rw, sig, 0)] = 'ram/{}{}'.format(rw, sig)
            else:
                name_rr2local['BLK_TL-RAM.{}{}[{}]'.format(rw, sig, ind)] = 'ram/{}{}_{}'.format(rw, sig, ind)

        add_ram_pin(rw, 'CLK')
        add_ram_pin(rw, 'CLKE')
        add_ram_pin(rw, 'E')

        for ind in range(11):
            add_ram_pin(rw, 'ADDR', ind)

        for ind in data_range:
            add_ram_pin('R', 'DATA', ind)
            add_ram_pin('W', 'DATA', ind)
            add_ram_pin('', 'MASK', ind)

    for block in g.block_grid:
        for pin in block.pins:
            if "RAM" in block.block_type.name:
                pin_offset = ram_pin_offset(pin)
            elif "DSP" in block.block_type.name:
                pin_offset = dsp_pin_offset(pin)
            else:
                pin_offset = Offset(0, 0)
            pin_pos = block.position + pin_offset

            vpos = PositionVPR(*pin_pos)
            ipos = pos_vpr2icebox(vpos)

            node = g.routing.localnames[(pin_pos, pin.name)]
            node.set_metadata("hlc_coord", "{},{}".format(*ipos))

            logging.debug("On %s for %s", vpos, format_node(g, node))

            hlc_name = name_rr2local.get(
                pin.xmlname, group_hlc_name([NP(ipos, [pin.name])]))
            logging.debug(
                " Setting local name %s on %s for %s",
                hlc_name, vpos, format_node(g, node))
            g.routing.localnames.add(vpos, hlc_name, node)
            node.set_metadata("hlc_name", hlc_name)

            rr_name = pin.xmlname
            try:
                localname = name_rr2local[rr_name]
            except KeyError:
                logging.warn(
                    "On %s - %s doesn't have a translation",
                    ipos, rr_name)
                continue

            # FIXME: only add for actual position instead for all
            if localname == hlc_name:
                logging.debug(
                    " Local name %s same as hlc_name on %s for %s",
                    localname, vpos, format_node(g, node))
            else:
                assert False, "{} != {}".format(localname, hlc_name)
                logging.debug(
                    " Setting local name %s on %s for %s",
                    localname, vpos, format_node(g, node))
                g.routing.localnames.add(vpos, localname, node)
def get_pin_meta(block, pin):
    """Get the offset and edge for a given pin."""
    grid_sz = PositionVPR(ic.max_x+1+4, ic.max_y+1+4)
    if "PIN" in block.block_type.name:
        if block.position.x == 1:
            return (graph.RoutingNodeSide.RIGHT, Offset(0, 0))
        elif block.position.y == 1:
            return (graph.RoutingNodeSide.TOP, Offset(0, 0))
        elif block.position.y == grid_sz.y-2:
            return (graph.RoutingNodeSide.BOTTOM, Offset(0, 0))
        elif block.position.x == grid_sz.x-2:
            return (graph.RoutingNodeSide.LEFT, Offset(0, 0))

    if "RAM" in block.block_type.name:
        return (graph.RoutingNodeSide.RIGHT, ram_pin_offset(pin))

    if "DSP" in block.block_type.name:
        return (graph.RoutingNodeSide.RIGHT, dsp_pin_offset(pin))

    if "PIO" in block.block_type.name:
        if pin.name.startswith("O[") or pin.name.startswith("I["):
            if block.position.x == 2:
                return (graph.RoutingNodeSide.LEFT, Offset(0, 0))
            elif block.position.y == 2:
                return (graph.RoutingNodeSide.BOTTOM, Offset(0, 0))
            elif block.position.y == grid_sz.y-3:
                return (graph.RoutingNodeSide.TOP, Offset(0, 0))
            elif block.position.x == grid_sz.x-3:
                return (graph.RoutingNodeSide.RIGHT, Offset(0, 0))
        return (graph.RoutingNodeSide.RIGHT, Offset(0, 0))

    if "PLB" in block.block_type.name:
        if "FCIN" in pin.port_name:
            return (graph.RoutingNodeSide.BOTTOM, Offset(0, 0))
        elif "FCOUT" in pin.port_name:
            return (graph.RoutingNodeSide.TOP, Offset(0, 0))

        return (graph.RoutingNodeSide.RIGHT, Offset(0, 0))

    assert False, (block, pin)
def dsp_pin_offset(pin):
    return Offset(0, pin.port_index)