def parse_verilog_bitvector_to_bits(in_str): #replace x with 0 in_str = re_sub_cached('[xX]', '0', in_str) m = re_match_cached("([0-9]+)'([hdob])([0-9a-fA-F]+)", in_str) if m: num_bits = int(m.group(1)) prefix = m.group(2) val_str = m.group(3) if prefix == 'h': val = eval('0x' + val_str) elif prefix == 'd': val = eval(val_str.lstrip('0')) elif prefix == 'o' or prefix == 'b': val = eval('0' + prefix + val_str) if val.bit_length() > num_bits: raise ParseError( "Number of bits({}) given don't match expected ({})".format( val.bit_length(), num_bits)) else: val = eval('0x' + in_str) num_bits = len(in_str) * 4 bit_str = bin(val)[2:] # zero pad nz = num_bits - len(bit_str) bit_vec = nz * ['0'] + list(bit_str) return bit_vec
elif o == "-S": strip_interconn = True elif o == "-l": lookup_pins = True elif o == "-L": lookup_symbols = True elif o == "-n": modname = a elif o == "-a": pass # ignored for backward compatibility elif o in ("-p", "-P"): with open(a, "r") as f: for line in f: if o == "-P" and not re_search_cached(" # ICE_(GB_)?IO", line): continue line = re_sub_cached(r"#.*", "", line.strip()).split() if "--warn-no-port" in line: line.remove("--warn-no-port") if len(line) and line[0] == "set_io": p = line[1] if o == "-P": p = p.lower() p = re_sub_cached(r"_ibuf$", "", p) p = re_sub_cached(r"_obuft$", "", p) p = re_sub_cached(r"_obuf$", "", p) p = re_sub_cached(r"_gb_io$", "", p) p = re_sub_cached(r"_pad(_[0-9]+|)$", r"\1", p) portnames.add(p) if not re_match_cached(r"[a-zA-Z_][a-zA-Z0-9_]*$", p): p = "\\%s " % p unmatched_ports.add(p)
def print_tile(tx, ty): tile = ic.tile(tx, ty) tile_type = ic.tile_type(tx, ty) print("<title>Project IceStorm – %s %s Tile (%d %d)</title>" % (chipname, tile_type, tx, ty)) print("<h1>Project IceStorm – %s %s Tile (%d %d)</h1>" % (chipname, tile_type, tx, ty)) print( """<i><a href="http://www.clifford.at/icestorm/">Project IceStorm</a> aims at documenting the bitstream format of Lattice iCE40 FPGAs and providing simple tools for analyzing and creating bitstream files. This is work in progress.</i>""" ) print("""<p>This page describes the %s Tile (%d %d), what nets and configuration bits it has and how it is connected to its neighbourhood.</p>""" % (tile_type, tx, ty)) visible_tiles = set() print('<p><table border="1">') for y in range(ty + 2, ty - 3, -1): print("<tr>") for x in range(tx - 2, tx + 3): print( '<td style="width:100px; height:70px;" align="center" valign="center"', end="") if ic.tile_pos(x, y) == None: print('> </td>') else: if (x, y) in mktiles: if ic.tile_type(x, y) == "IO": color = "#aee" if ic.tile_type(x, y) == "LOGIC": color = "#eae" if ic.tile_type(x, y) == "RAMB": color = "#eea" if ic.tile_type(x, y) == "RAMT": color = "#eea" print( 'bgcolor="%s"><a style="color:#000; text-decoration:none" href="tile_%d_%d.html"><b>%s Tile<br/>(%d %d)</b></a></td>' % (color, x, y, ic.tile_type(x, y), x, y)) else: if ic.tile_type(x, y) == "IO": color = "#8aa" if ic.tile_type(x, y) == "LOGIC": color = "#a8a" if ic.tile_type(x, y) == "RAMB": color = "#aa8" if ic.tile_type(x, y) == "RAMT": color = "#aa8" print('bgcolor="%s">%s Tile<br/>(%d %d)</td>' % (color, ic.tile_type(x, y), x, y)) visible_tiles.add((x, y)) print("</tr>") print("</table></p>") # print_expand_all() print("<h2>Configuration Bitmap</h2>") print( "<p>A %s Tile has %d config bits in %d groups of %d bits each:<br/>" % (tile_type, len(tile) * len(tile[0]), len(tile), len(tile[0]))) print(("<tt>%s</tt></p>" % (", ".join([ '%sB%d[%d:0]' % (" " if i < 10 else "", i, len(tile[i]) - 1) for i in range(len(tile)) ]))).replace(" B8", "<br/> B8")) bitmap_cells = list() for line_nr in range(len(tile)): line = list() bitmap_cells.append(line) for bit_nr in range(len(tile[line_nr])): line.append({"bgcolor": "#aaa", "label": "?"}) for entry in ic.tile_db(tx, ty): if not ic.tile_has_entry(tx, ty, entry): continue for bit in [bit.replace("!", "") for bit in entry[0]]: match = re_match_cached(r"B(\d+)\[(\d+)\]$", bit) idx1 = int(match.group(1)) idx2 = int(match.group(2)) if entry[1] == "routing": bitmap_cells[idx1][idx2]["bgcolor"] = "#faa" bitmap_cells[idx1][idx2]["label"] = "R" bitmap_cells[idx1][idx2]["is_routing"] = True elif entry[1] == "buffer": bitmap_cells[idx1][idx2]["bgcolor"] = "#afa" bitmap_cells[idx1][idx2]["label"] = "B" bitmap_cells[idx1][idx2]["is_routing"] = True else: bitmap_cells[idx1][idx2]["bgcolor"] = "#aaf" if entry[1] == "ColBufCtrl": bitmap_cells[idx1][idx2]["label"] = "O" elif entry[1].startswith("LC_"): bitmap_cells[idx1][idx2]["label"] = "L" elif entry[1].startswith("NegClk"): bitmap_cells[idx1][idx2]["label"] = "N" elif entry[1].startswith("CarryInSet"): bitmap_cells[idx1][idx2]["label"] = "C" elif entry[1].startswith("IOB_"): bitmap_cells[idx1][idx2]["label"] = "I" elif entry[1].startswith("IoCtrl"): bitmap_cells[idx1][idx2]["label"] = "T" elif entry[1] == "Icegate": bitmap_cells[idx1][idx2]["label"] = "G" elif entry[1].startswith("Cascade"): bitmap_cells[idx1][idx2]["label"] = "A" elif entry[1].startswith("RamConfig"): bitmap_cells[idx1][idx2]["label"] = "M" elif entry[1].startswith("RamCascade"): bitmap_cells[idx1][idx2]["label"] = "M" elif entry[1].startswith("PLL"): bitmap_cells[idx1][idx2]["label"] = "P" else: assert False bitmap_cells[idx1][idx2][ "label"] = '<a style="color:#666; text-decoration:none" href="#B.%d.%d">%s</a>' % ( idx1, idx2, bitmap_cells[idx1][idx2]["label"]) print('<table style="font-size:small">') print("<tr><td></td>") for cell_nr in range(len(line)): print('<td align="center" width="15">%d</td>' % cell_nr) print("<td></td></tr>") for line_nr, line in enumerate(bitmap_cells): print("<tr>") print('<td>B%d</td>' % line_nr) for cell in line: print( '<td align="center" bgcolor="%s" style="color:#666;">%s</td>' % (cell["bgcolor"], cell["label"])) print('<td>B%d</td>' % line_nr) print("</tr>") print("<tr><td></td>") for cell_nr in range(len(line)): print('<td align="center">%d</td>' % cell_nr) print("<td></td></tr>") print("</table>") print("<h2>Nets and Connectivity</h2>") print("""<p>This section lists all nets in the tile and how this nets are connected with nets from cells in its neighbourhood.</p>""") grouped_segs = ic.group_segments(set([(tx, ty)])) groups_indexed = dict() this_tile_nets = dict() for segs in sorted(grouped_segs): this_segs = list() neighbour_segs = dict() for s in segs: if s[0] == tx and s[1] == ty: this_segs.append(s[2]) match = re_match_cached(r"(.*?_)(\d+)(.*)", s[2]) if match: this_tile_nets.setdefault( match.group(1) + "*" + match.group(3), set()).add(int(match.group(2))) else: this_tile_nets.setdefault(s[2], set()).add(-1) if (s[0], s[1]) in visible_tiles: neighbour_segs.setdefault((s[0], s[1]), list()).append(s[2]) if this_segs: this_name = ", ".join(sorted(this_segs)) assert this_name not in groups_indexed groups_indexed[this_name] = neighbour_segs print("<h3>List of nets in %s Tile (%d %d)</h3>" % (tile_type, tx, ty)) def net2cat(netname): cat = (99, "Unsorted") if netname.startswith("glb_netwk_"): cat = (10, "Global Networks") if netname.startswith("glb2local_"): cat = (10, "Global Networks") if netname.startswith("fabout"): cat = (10, "Global Networks") if netname.startswith("local_"): cat = (20, "Local Tracks") if netname.startswith("carry_in"): cat = (25, "Logic Block") if netname.startswith("io_"): cat = (25, "IO Block") if netname.startswith("ram"): cat = (25, "RAM Block") if netname.startswith("lutff_"): cat = (25, "Logic Block") if netname.startswith("lutff_0"): cat = (30, "Logic Unit 0") if netname.startswith("lutff_1"): cat = (30, "Logic Unit 1") if netname.startswith("lutff_2"): cat = (30, "Logic Unit 2") if netname.startswith("lutff_3"): cat = (30, "Logic Unit 3") if netname.startswith("lutff_4"): cat = (30, "Logic Unit 4") if netname.startswith("lutff_5"): cat = (30, "Logic Unit 5") if netname.startswith("lutff_6"): cat = (30, "Logic Unit 6") if netname.startswith("lutff_7"): cat = (30, "Logic Unit 7") if netname.startswith("neigh_op_"): cat = (40, "Neighbourhood") if netname.startswith("logic_op_"): cat = (40, "Neighbourhood") if netname.startswith("sp4_v_"): cat = (50, "Span-4 Vertical") if netname.startswith("span4_vert_"): cat = (50, "Span-4 Vertical") if netname.startswith("sp4_r_v_"): cat = (55, "Span-4 Right Vertical") if netname.startswith("sp4_h_"): cat = (60, "Span-4 Horizontal") if netname.startswith("span4_horz_"): cat = (60, "Span-4 Horizontal") if netname.startswith("sp12_v_"): cat = (70, "Span-12 Vertical") if netname.startswith("span12_vert_"): cat = (70, "Span-12 Vertical") if netname.startswith("sp12_h_"): cat = (80, "Span-12 Horizontal") if netname.startswith("span12_horz_"): cat = (80, "Span-12 Horizontal") return cat nets_in_cats = dict() for this_name in sorted(this_tile_nets): nets_in_cats.setdefault(net2cat(this_name), list()).append(this_name) for cat in sorted(nets_in_cats): print('<h4>%s</h4>' % cat[1]) print('<p><ul style="margin:0">') for this_name in sorted(nets_in_cats[cat]): indices = [i for i in this_tile_nets[this_name] if i >= 0] if -1 in this_tile_nets[this_name]: print("<li><tt>%s</tt></li>" % this_name) if len(indices) == 1: print("<li><tt>%s</tt></li>" % this_name.replace("*", "%d" % indices[0])) elif len(indices) > 0: print("<li><tt>%s</tt></li>" % this_name.replace( "*", "{" + ",".join(["%d" % i for i in sorted(indices)]) + "}")) print("</ul></p>") print( "<h3>Nets and their permanent connections to nets in neighbour tiles</h3>" ) # print_expand_div("connection details") all_cats = set() for this_name in sorted(groups_indexed): all_cats.add(net2cat(this_name)) for cat in sorted(all_cats): print('<h4>%s</h4>' % cat[1]) print( '<p><div style="-webkit-column-count: 3; -moz-column-count: 3; column-count: 3;"><ul style="margin:0">' ) for this_name in sorted(groups_indexed): if net2cat(this_name) == cat: neighbour_segs = groups_indexed[this_name] print("<li><tt><b>%s</b></tt>" % this_name) if neighbour_segs: print("<ul>") for nidx in sorted(neighbour_segs): if nidx == (tx, ty): print("<li><tt><b>(%d %d)</b> %s</tt></li>" % (nidx[0], nidx[1], ", ".join( sorted(neighbour_segs[nidx])))) else: print("<li><tt>(%d %d) %s</tt></li>" % (nidx[0], nidx[1], ", ".join( sorted(neighbour_segs[nidx])))) print("</ul>") print("</li>") print("</ul></div></p>") # print_expand_end() print("<h2>Routing Configuration</h2>") print("""<p>This section lists the routing configuration bits in the tile. All routing resources are directional tristate buffers that are in tristate mode in the all-zeros configuration.</p>""") grpgrp = dict() config_groups = dict() other_config_groups = dict() for entry in ic.tile_db(tx, ty): if not ic.tile_has_entry(tx, ty, entry): continue if entry[1] in ("routing", "buffer"): cfggrp = entry[1] + " " + entry[3] + "," + ",".join( sorted([bit.replace("!", "") for bit in entry[0]])) config_groups.setdefault(cfggrp, list()).append(entry) grpgrp.setdefault(net2cat(entry[3]), set()).add(cfggrp) else: grp = other_config_groups.setdefault(" ".join(entry[1:]), set()) for bit in entry[0]: grp.add(bit) for cat in sorted(grpgrp): print('<h4>%s</h4>' % cat[1]) bits_in_cat = set() for cfggrp in sorted(grpgrp[cat]): grp = config_groups[cfggrp] for bit in cfggrp.split(",")[1:]: match = re_match_cached(r"B(\d+)\[(\d+)\]", bit) bits_in_cat.add((int(match.group(1)), int(match.group(2)))) print('<table style="font-size:x-small">') print("<tr><td></td>") for cell_nr in range(len(bitmap_cells[0])): print('<td align="center" width="15">%d</td>' % cell_nr) print("<td></td></tr>") for line_nr, line in enumerate(bitmap_cells): print("<tr>") print('<td>B%d</td>' % line_nr) for cell_nr, cell in enumerate(line): color = cell["bgcolor"] if (line_nr, cell_nr) not in bits_in_cat: color = "#aaa" print( '<td align="center" bgcolor="%s" style="color:#666;">%s</td>' % (color, cell["label"])) print('<td>B%d</td>' % line_nr) print("</tr>") print("<tr><td></td>") for cell_nr in range(len(line)): print('<td align="center">%d</td>' % cell_nr) print("<td></td></tr>") print("</table>") # print_expand_div("details") src_nets = set() dst_nets = set() links = dict() for cfggrp in sorted(grpgrp[cat]): grp = config_groups[cfggrp] for entry in grp: src_nets.add(entry[2]) dst_nets.add(entry[3]) if entry[1] == "buffer": assert (entry[2], entry[3]) not in links links[( entry[2], entry[3] )] = '<td align="center" bgcolor="#afa" style="color:#666;">B</td>' else: assert (entry[2], entry[3]) not in links links[( entry[2], entry[3] )] = '<td align="center" bgcolor="#faa" style="color:#666;">R</td>' print('<h5>Connectivity Matrix</h5>') print('<table style="font-size:x-small">') dst_net_prefix = "" dst_net_list = sorted(dst_nets, key=icebox.key_netname) if len(dst_net_list) > 1: while len(set([n[0] for n in dst_net_list])) == 1: dst_net_prefix += dst_net_list[0][0] for i in range(len(dst_net_list)): dst_net_list[i] = dst_net_list[i][1:] while dst_net_prefix != "" and dst_net_prefix[-1] != "_": for i in range(len(dst_net_list)): dst_net_list[i] = dst_net_prefix[-1] + dst_net_list[i] dst_net_prefix = dst_net_prefix[0:-1] print('<tr><td></td><td colspan="%d" align="center">%s</td></tr>' % (len(dst_net_list), dst_net_prefix)) print('<tr><td></td>') for dn in dst_net_list: print('<td>%s</td>' % dn) print("</tr>") for sn in sorted(src_nets, key=icebox.key_netname): print("<tr>") print('<td>%s</td>' % sn) for dn in sorted(dst_nets, key=icebox.key_netname): if (sn, dn) in links: print(links[(sn, dn)]) else: print( '<td align="center" bgcolor="#aaa" style="color:#666;"> </td>' ) print("</tr>") print("</table>") print('<h5>Configuration Stamps</h5>') for cfggrp in sorted(grpgrp[cat]): grp = config_groups[cfggrp] bits = cfggrp.split(",")[1:] print('<p><table style="font-size:small" border><tr>') for bit in bits: print( '<th style="width:5em"><a name="%s">%s</a></th>' % (re_sub_cached(r"B(\d+)\[(\d+)\]", r"B.\1.\2", bit), bit)) group_lines = list() is_buffer = True for entry in grp: line = '<tr>' for bit in bits: if bit in entry[0]: line += '<td align="center">1</td>' else: line += '<td align="center">0</td>' is_buffer = entry[1] == "buffer" line += '<td align="center">%s</td><td><tt>%s</tt></td><td><tt>%s</tt></td></tr>' % ( entry[1], entry[2], entry[3]) group_lines.append(line) if is_buffer: print( '<th style="width:5em">Function</th><th style="width:15em">Source-Net</th><th style="width:15em">Destination-Net</th></tr>' ) else: print( '<th style="width:5em">Function</th><th style="width:15em">Net</th><th style="width:15em">Net</th></tr>' ) for line in sorted(group_lines): print(line) print('</table></p>') # print_expand_end() print("<h2>Non-routing Configuration</h2>") print( "<p>This section lists the non-routing configuration bits in the tile.</p>" ) print('<table style="font-size:x-small">') print("<tr><td></td>") for cell_nr in range(len(bitmap_cells[0])): print('<td align="center" width="15">%d</td>' % cell_nr) print("<td></td></tr>") for line_nr, line in enumerate(bitmap_cells): print("<tr>") print('<td>B%d</td>' % line_nr) for cell_nr, cell in enumerate(line): color = cell["bgcolor"] if "is_routing" in cell: color = "#aaa" print( '<td align="center" bgcolor="%s" style="color:#666;">%s</td>' % (color, cell["label"])) print('<td>B%d</td>' % line_nr) print("</tr>") print("<tr><td></td>") for cell_nr in range(len(line)): print('<td align="center">%d</td>' % cell_nr) print("<td></td></tr>") print("</table>") print( '<p><table style="font-size:small" border><tr><th>Function</th><th>Bits</th></tr>' ) for cfggrp in sorted(other_config_groups): bits = " ".join([ '<a name="%s">%s</a>' % (re_sub_cached(r"B(\d+)\[(\d+)\]", r"B.\1.\2", bit), bit) for bit in sorted(other_config_groups[cfggrp]) ]) cfggrp = cfggrp.replace( " " + list(other_config_groups[cfggrp])[0], "") print('<tr><td>%s</td><td>%s</td></tr>' % (cfggrp, bits)) print('</table></p>')