blob: 6b3b5efa57e5de3536b10dd2b5a5a44e9014a46c [file] [log] [blame]
#!/usr/bin/env python3
"""Generate a HTML representation of the tile bit database"""
import pytrellis
import argparse
import sys
def find_bits(db):
cwords = db.get_settings_words()
for cword in cwords:
wd = db.get_data_for_setword(cword)
for bits in wd.bits:
for bit in bits.bits:
bitmap[bit.frame, bit.bit] = "word_" + str(cword)
cenums = db.get_settings_enums()
for cenum in cenums:
ed = db.get_data_for_enum(cenum)
for opt, bits in sorted(ed.options):
for bit in bits.bits:
bitmap[bit.frame, bit.bit] = "enum_" + str(cenum)
sinks = db.get_sinks()
for sink in sinks:
mux = db.get_mux_data_for_sink(sink)
for arc in mux.arcs:
for bit in arc.bits.bits:
bitmap[bit.frame, bit.bit] = "mux_" + str(sink)
def mux_html(mux, f):
bitset = set()
for arc in mux.arcs:
for bit in arc.bits.bits:
bitset.add((bit.frame, bit.bit))
bitlist = list(sorted(bitset))
print('<h3 id="mux_{}">Mux driving <span class="mux_sink">{}</span></h3>'.format(mux.sink, mux.sink), file=f)
print('<table class="mux"><tr><th>Source</th>', file=f)
for bit in bitlist:
print('<th style="padding-left: 10px; padding-right: 10px">F{}B{}</th>'.format(bit[0], bit[1]), file=f)
print('</tr>', file=f)
truthtable = []
for arc in mux.arcs:
ttrow = []
for blb in bitlist:
found = False
for ab in arc.bits.bits:
if ab.frame == blb[0] and ab.bit == blb[1]:
ttrow.append('0' if ab.inv else '1')
found = True
break
if not found:
ttrow.append("-")
truthtable.append((arc, ttrow))
trstyle = ""
for (arc, ttrow) in sorted(truthtable, key=lambda x: "".join(reversed(x[1])).replace("-", "0")):
trstyle = " bgcolor=\"#dddddd\"" if trstyle == "" else ""
print('<tr {}><td>{}</td>'.format(trstyle, arc.source), file=f)
for bit in ttrow:
print('<td style="text-align: center">{}</td>'.format(bit), file=f)
print('</td>', file=f)
print('</table>', file=f)
def setword_html(word, f):
print('<h3 id="word_{}">Configuration {} {}</h3>'.format(word.name, "bit" if len(word.bits) == 1 else "word",
word.name), file=f)
print('<p>Default value: {}\'b{}</p>'.format(len(word.defval),
"".join(reversed(["1" if _ else "0" for _ in word.defval]))), file=f)
print('<table class="setword">', file=f)
trstyle = ""
for idx in range(len(word.bits)):
cbits = " ".join(["{}F{}B{}".format("!" if b.inv else "", b.frame, b.bit) for b in word.bits[idx].bits])
trstyle = " bgcolor=\"#dddddd\"" if trstyle == "" else ""
print(
'<tr {}><td style="padding-left: 10px; padding-right: 10px">{}[{}]</td><td style="padding-left: 10px; padding-right: 10px">{}</td></tr>'.format(
trstyle, word.name, idx, cbits), file=f)
print('</table>', file=f)
def muxes_html(db, f):
sinks = db.get_sinks()
for sink in sorted(sinks):
mux = db.get_mux_data_for_sink(sink)
mux_html(mux, f)
def setwords_html(db, f):
words = db.get_settings_words()
for name in sorted(words):
word = db.get_data_for_setword(name)
setword_html(word, f)
def fixed_conns_html(db, f):
print("<h3>Fixed Connections</h3>", file=f)
print('<table class="fconn"><tr><th>Source</th><th>Sink</th></tr>', file=f)
conns = db.get_fixed_conns()
trstyle = ""
for conn in conns:
trstyle = " bgcolor=\"#dddddd\"" if trstyle == "" else ""
print(
'<tr {}><td style="padding-left: 10px; padding-right: 10px">{}</td><td style="padding-left: 10px; padding-right: 10px">{}</td></tr>'.format(
trstyle, conn.source, conn.sink), file=f)
print('</table>', file=f)
def get_bit_info(frame, bit):
if (frame, bit) in bitmap:
group = bitmap[(frame, bit)]
if group.startswith("mux"):
label = group.split("_")[-1][0]
colour = "#FF8888"
elif group.startswith("emum") or group.startswith("word"):
label = "C"
colour = "#88FF88"
else:
label = "?"
colour = "#ffffff"
return group, label, colour
else:
return "unknown", "&nbsp;", "#FFFFFF"
def bit_grid_html(tileinfo, f):
print("<table style='font-size: 8pt; border: 2px solid black; text-align: center'>", file=f)
for bit in range(tileinfo.bits_per_frame):
print("<tr style='height: 20px'>", file=f)
for frame in range(tileinfo.num_frames):
group, label, colour = get_bit_info(frame, bit)
print("<td style='height: 100%; border: 2px solid black;'>", file=f)
print("""<a href='#{}' title='F{}B{}' style='text-decoration: none; color: #000000'>
<div id='f{}b{}' style='height: 100%; background-color: {}; width: 12px' class='grp_{}'
onmouseover='mov(event);' onmouseout='mou(event);'>{}</div></a></td>""".format(
group, frame, bit, frame, bit, colour, group, label), file=f)
print("</tr>", file=f)
print("</table>", file=f)
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('family', type=str,
help="FPGA family (e.g. ECP5)")
parser.add_argument('device', type=str,
help="FPGA device (e.g. LFE5U-85F)")
parser.add_argument('tile', type=str,
help="Tile type (e.g. PLC2)")
parser.add_argument('outfile', type=argparse.FileType('w'),
help="output HTML file")
def main(argv):
global bitmap
bitmap = dict(dict())
args = parser.parse_args(argv[1:])
f = args.outfile
print(
"""<html>
<head><title>{} Bit Data</title>
""".format(args.tile), file=f)
print("""
<script type="text/javascript">
origClr = {};
origClass = "";
function mov(event) {
if (event.target.className != "unknown") {
origClass = event.target.className;
var elems = document.getElementsByClassName(origClass);
for(var i = 0; i < elems.length; i++) {
if(!(elems[i].id in origClr)) {
origClr[elems[i].id] = elems[i].style.backgroundColor;
}
elems[i].style.backgroundColor = "white";
}
}
}
function mou(event) {
var elems = document.getElementsByClassName(origClass);
for(var i = 0; i < elems.length; i++) {
elems[i].style.backgroundColor = origClr[elems[i].id] || "#ffffff";
}
}
</script>
</head>
<body>
""", file=f)
print("""<h1>{} Bit Data</h1>
""".format(args.tile), file=f)
pytrellis.load_database("../database")
tdb = pytrellis.get_tile_bitdata(
pytrellis.TileLocator(args.family, args.device, args.tile))
ch = pytrellis.Chip(args.device)
ti = ch.get_tiles_by_type(args.tile)[0].info
find_bits(tdb)
bit_grid_html(ti, f)
muxes_html(tdb, f)
setwords_html(tdb, f)
# TODO: enums
fixed_conns_html(tdb, f)
print("""</body></html>""", file=f)
if __name__ == "__main__":
main(sys.argv)