diff --git a/tools/fasm2frame.py b/tools/fasm2frame.py index 27c2e255..622b85cc 100644 --- a/tools/fasm2frame.py +++ b/tools/fasm2frame.py @@ -231,8 +231,16 @@ if __name__ == '__main__': '--sparse', action='store_true', help="Don't zero fill all frames") parser.add_argument( '--debug', action='store_true', help="Print debug dump") - parser.add_argument('fn_in', help='Input FPGA assembly (.fasm) file') - parser.add_argument('fn_out', help='Output FPGA frame (.frm) file') + parser.add_argument( + 'fn_in', + default='/dev/stdin', + nargs='?', + help='Input FPGA assembly (.fasm) file') + parser.add_argument( + 'fn_out', + default='/dev/stdout', + nargs='?', + help='Output FPGA frame (.frm) file') args = parser.parse_args() run( diff --git a/tools/segprint2fasm.py b/tools/segprint2fasm.py new file mode 100644 index 00000000..198f795b --- /dev/null +++ b/tools/segprint2fasm.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 + +import os +import re +import sys +import json + + +def tag2fasm(grid, seg, tag): + '''Given tilegrid, segment name and tag, return fasm directive''' + segj = grid['segments'][seg] + + def clbf(seg, tile, tag_post): + # seg: SEG_CLBLM_L_X10Y102 + # tile_type: CLBLM_L + # tag_post: SLICEM_X0.ALUT.INIT[43] + # To: CLBLM_L_X10Y102.SLICE_X12Y102.ALUT.INIT[43] 1 + m = re.match(r'(SLICE[LM])_X([01])[.](.*)', tag_post) + slicelm = m.group(1) + off01 = int(m.group(2)) + post = m.group(3) + + # xxx: actually this might not work on decimal overflow (9 => 10) + for site in grid['tiles'][tile]['sites'].keys(): + m = re.match(r'SLICE_X(.*)Y.*', site) + sitex = int(m.group(1)) + if sitex % 2 == off01: + break + else: + raise Exception("Failed to match site") + + return '%s.%s.%s 1' % (tile, site, post) + + def intf(seg, tile, tag_post): + # Make the selection an argument of the configruation + m = re.match(r'(.*)[.]([A-Za-z0-9_]+)', tag_post) + which = m.group(1) + value = m.group(2) + site = { + 'clblm_l': 'CENTER_INTER_L', + 'clblm_r': 'CENTER_INTER_R', + 'hclk_l': 'HCLK_L', + 'hclk_r': 'HCLK_R', + }[segj['type']] + return '%s.%s.%s %s' % (tile, site, which, value) + + m = re.match(r'([A-Za-z0-9_]+)[.](.*)', tag) + tile_type = m.group(1) + tag_post = m.group(2) + + # Find associated tile + for tile in segj['tiles']: + if grid['tiles'][tile]['type'] == tile_type: + break + else: + raise Exception("Couldn't find tile type %s" % tile_type) + + tag2asm = { + 'CLBLM_L': clbf, + 'CLBLM_R': clbf, + 'INT_L': intf, + 'INT_R': intf, + 'HCLK_L': intf, + } + f = tag2asm.get(tile_type, None) + if f is None: + raise Exception("Unhandled segment type %s" % tilej['type']) + return f(seg, tile, tag_post) + + +def run(f_in, f_out, sparse=False): + with open("%s/%s/tilegrid.json" % (os.getenv("XRAY_DATABASE_DIR"), + os.getenv("XRAY_DATABASE")), "r") as f: + grid = json.load(f) + + seg = None + for l in f_in: + l = l.strip() + if not l: + continue + # seg SEG_CLBLM_L_X10Y102 + # tag CLBLM_L.SLICEM_X0.ALUT.INIT[00] + m = re.match('(seg|tag) (.*)', l) + if not m: + raise Exception("Invalid line %s" % l) + type = m.group(1) + if type == 'seg': + seg = m.group(2) + elif type == 'tag': + f_out.write(tag2fasm(grid, seg, m.group(2)) + '\n') + else: + raise Exception("Invalid type %s" % type) + + +if __name__ == '__main__': + import argparse + + parser = argparse.ArgumentParser( + description='Convert segprint -d output to .fasm file (FPGA assembly)') + + parser.add_argument( + 'fn_in', default='/dev/stdin', nargs='?', help='Input segment file') + parser.add_argument( + 'fn_out', default='/dev/stdout', nargs='?', help='Output .fasm file') + + args = parser.parse_args() + run(open(args.fn_in, 'r'), open(args.fn_out, 'w')) diff --git a/tools/test_data/clb_ff/design.segp b/tools/test_data/clb_ff/design.segp new file mode 100644 index 00000000..2e0bd01d --- /dev/null +++ b/tools/test_data/clb_ff/design.segp @@ -0,0 +1,17 @@ + +seg SEG_HCLK_L_X31Y130 +tag HCLK_L.ENABLE_BUFFER.HCLK_CK_BUFHCLK8 +tag HCLK_L.HCLK_LEAF_CLK_B_BOTL5.HCLK_CK_BUFHCLK8 + +seg SEG_CLBLM_L_X10Y102 +tag CLBLM_L.SLICEM_X0.AFF.DMUX.AX +tag CLBLM_L.SLICEM_X0.AFF.ZINI +tag CLBLM_L.SLICEM_X0.AFF.ZRST +tag CLBLM_L.SLICEM_X0.CEUSEDMUX +tag CLBLM_L.SLICEM_X0.SRUSEDMUX +tag INT_L.BYP_ALT0.EE2END0 +tag INT_L.BYP_ALT1.EL1END1 +tag INT_L.CLK_L1.GCLK_L_B11_WEST +tag INT_L.CTRL_L1.ER1END2 +tag INT_L.FAN_ALT7.BYP_BOUNCE0 +tag INT_L.WW2BEG0.LOGIC_OUTS_L4 diff --git a/tools/test_data/clb_lut/design.segp b/tools/test_data/clb_lut/design.segp new file mode 100644 index 00000000..371afecd --- /dev/null +++ b/tools/test_data/clb_lut/design.segp @@ -0,0 +1,22 @@ + +seg SEG_CLBLM_L_X10Y102 +tag CLBLM_L.SLICEM_X0.ALUT.INIT[00] +tag CLBLM_L.SLICEM_X0.ALUT.INIT[08] +tag CLBLM_L.SLICEM_X0.ALUT.INIT[10] +tag CLBLM_L.SLICEM_X0.ALUT.INIT[11] +tag CLBLM_L.SLICEM_X0.ALUT.INIT[13] +tag CLBLM_L.SLICEM_X0.ALUT.INIT[14] +tag CLBLM_L.SLICEM_X0.ALUT.INIT[15] +tag CLBLM_L.SLICEM_X0.ALUT.INIT[41] +tag CLBLM_L.SLICEM_X0.ALUT.INIT[43] +tag CLBLM_L.SLICEM_X0.ALUT.INIT[44] +tag CLBLM_L.SLICEM_X0.ALUT.INIT[46] +tag CLBLM_L.SLICEM_X0.ALUT.INIT[47] +tag CLBLM_L.SLICEM_X0.ALUT.INIT[63] +tag INT_L.IMUX_L1.EE2END0 +tag INT_L.IMUX_L11.EL1END1 +tag INT_L.IMUX_L2.EE2END1 +tag INT_L.IMUX_L4.EE2END2 +tag INT_L.IMUX_L7.EE2END3 +tag INT_L.IMUX_L8.EL1END0 +tag INT_L.WW2BEG0.LOGIC_OUTS_L12 diff --git a/tools/test_segprint2fasm.py b/tools/test_segprint2fasm.py new file mode 100644 index 00000000..14b3b401 --- /dev/null +++ b/tools/test_segprint2fasm.py @@ -0,0 +1,44 @@ +import segprint2fasm + +import unittest +import StringIO +import re + + +class TestStringMethods(unittest.TestCase): + def check_segprint_fasm_equiv(self, segp_fn, fasm_fn): + fout = StringIO.StringIO() + segprint2fasm.run(open(segp_fn, 'r'), fout) + fasm_out = fout.getvalue() + + fasm_ref = open(fasm_fn, 'r').read() + + def normalize(fasm): + '''Remove all comments and sort''' + ret = [] + for l in fasm.split('\n'): + # Remove comments + i = l.rfind('#') + if i >= 0: + l = l[0:i] + l = l.strip() + if not l: + continue + ret.append(l) + return sorted(ret) + + fasm_out = normalize(fasm_out) + fasm_ref = normalize(fasm_ref) + self.assertEquals(fasm_ref, fasm_out) + + def test_lut_int(self): + self.check_segprint_fasm_equiv( + 'test_data/clb_lut/design.segp', 'test_data/lut_int.fasm') + + def test_ff_int(self): + self.check_segprint_fasm_equiv( + 'test_data/clb_ff/design.segp', 'test_data/ff_int.fasm') + + +if __name__ == '__main__': + unittest.main()