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)