| #!/usr/bin/env python3 | 
 | # -*- coding: utf-8 -*- | 
 | # | 
 | # Copyright (C) 2017-2020  The Project X-Ray Authors. | 
 | # | 
 | # Use of this source code is governed by a ISC-style | 
 | # license that can be found in the LICENSE file or at | 
 | # https://opensource.org/licenses/ISC | 
 | # | 
 | # SPDX-License-Identifier: ISC | 
 |  | 
 | from prjxray.segmaker import Segmaker | 
 |  | 
 | verbose = False | 
 |  | 
 | segmk = Segmaker("design.bits") | 
 |  | 
 | # Can fit 4 per CLB | 
 | # BELable | 
 | multi_bels_by = [ | 
 |     'SRL16E', | 
 |     'SRLC32E', | 
 | ] | 
 | # Not BELable | 
 | multi_bels_bn = [ | 
 |     'RAM32X1S', | 
 |     'RAM64X1S', | 
 | ] | 
 |  | 
 |  | 
 | def load_tcl(): | 
 |     f = open('design.csv', 'r') | 
 |     f.readline() | 
 |     ret = {} | 
 |     for l in f: | 
 |         l = l.strip() | 
 |         tile, site, bel, cell, ref_name, prim_type = l.split(',') | 
 |         ret[bel] = ref_name | 
 |     return ret | 
 |  | 
 |  | 
 | design = load_tcl() | 
 |  | 
 | print("Loading tags") | 
 | ''' | 
 | module,loc,bela,belb,belc,beld | 
 | my_ram_N,SLICE_X12Y100,SRLC32E,SRL16E,SRLC32E,LUT6 | 
 | my_ram_N,SLICE_X12Y101,SRLC32E,SRLC32E,SRLC32E,SRLC32E | 
 | my_RAM256X1S,SLICE_X12Y102,None,0,, | 
 | ''' | 
 | f = open('params.csv', 'r') | 
 | f.readline() | 
 | for l in f: | 
 |     l = l.strip() | 
 |     module, loc, p0, p1, p2, p3 = l.split(',') | 
 |  | 
 |     segmk.add_site_tag( | 
 |         loc, "WA7USED", | 
 |         module in ('my_RAM128X1D', 'my_RAM128X1S_N', 'my_RAM256X1S')) | 
 |     segmk.add_site_tag(loc, "WA8USED", module == 'my_RAM256X1S') | 
 |  | 
 |     bels_tcl = [design.get("%s/%c6LUT" % (loc, bel), None) for bel in "ABCD"] | 
 |  | 
 |     # (a, b, c, d) | 
 |     # Size set for RAM32X1S, RAM32X1D, and SRL16E | 
 |     size = [0, 0, 0, 0] | 
 |     # SRL set for SRL* primitives | 
 |     srl = [0, 0, 0, 0] | 
 |     # RAM set for RAM* primitives | 
 |     ram = [0, 0, 0, 0] | 
 |  | 
 |     verbose and print('%s' % loc) | 
 |     verbose and print('  %s %s %s %s' % tuple(bels_tcl)) | 
 |  | 
 |     if module == 'my_ram_N': | 
 |         # Each one of: SRL16E, SRLC32E, LUT6 | 
 |         bels = [p0, p1, p2, p3] | 
 |         verbose and print('  %s %s %s %s' % tuple(bels)) | 
 |         assert bels == bels_tcl | 
 |  | 
 |         # Clock Enable (CE) clock gate only enabled if we have clocked elements | 
 |         # A pure LUT6 does not, but everything else should | 
 |         segmk.add_site_tag( | 
 |             loc, "WEMUX.CE", bels != ['LUT6', 'LUT6', 'LUT6', 'LUT6']) | 
 |  | 
 |         beli = 0 | 
 |         for which, bel in zip('ABCD', bels): | 
 |             if bel == 'SRL16E': | 
 |                 size[beli] = 1 | 
 |             if bel in ('SRL16E', 'SRLC32E'): | 
 |                 srl[beli] = 1 | 
 |             beli += 1 | 
 |     else: | 
 |         n = p0 | 
 |         if n: | 
 |             n = int(n) | 
 |         # Unused. Just to un-alias mux | 
 |         #_ff = int(p1) | 
 |  | 
 |         # Can pack 4 into a CLB | 
 |         # D is always occupied first (due to WA/A sharing on D) | 
 |         # TODO: maybe investigate ROM primitive for completeness | 
 |         pack4 = [ | 
 |             # (a, b, c, d) | 
 |             (0, 0, 0, 1), | 
 |             (1, 0, 0, 1), | 
 |             (1, 1, 0, 1), | 
 |             (1, 1, 1, 1), | 
 |         ] | 
 |         # Uses CD first | 
 |         pack2 = [ | 
 |             (0, 0, 1, 1), | 
 |             (1, 1, 1, 1), | 
 |         ] | 
 |         has_bel_tcl = tuple([int(bool(x)) for x in bels_tcl]) | 
 |  | 
 |         # Always use all 4 sites | 
 |         if module in ('my_RAM32M', 'my_RAM64M', 'my_RAM128X1D', | 
 |                       'my_RAM256X1S'): | 
 |             ram = (1, 1, 1, 1) | 
 |         # Only can occupy CD I guess | 
 |         elif module == 'my_RAM32X1D': | 
 |             ram = (0, 0, 1, 1) | 
 |         # Uses 2 sites at a time | 
 |         elif module in ('my_RAM64X1D_N', 'my_RAM128X1S_N'): | 
 |             ram = pack2[n - 1] | 
 |         # Uses 1 site at a time | 
 |         elif module in ('my_RAM32X1S_N', 'my_RAM64X1S_N'): | 
 |             ram = pack4[n - 1] | 
 |         else: | 
 |             assert (0) | 
 |         verbose and print('  %s %s %s %s' % tuple(ram)) | 
 |         verbose and print('  %s %s %s %s' % tuple(has_bel_tcl)) | 
 |         # assert ram == ram_tcl | 
 |         # Hack: reject if something unexpected got packed in | 
 |         # TODO: place dummy LUTs to exclude placement? | 
 |         if ram != has_bel_tcl: | 
 |             continue | 
 |  | 
 |         # All entries here require D | 
 |         assert (ram[3]) | 
 |  | 
 |         if module == 'my_RAM32X1D': | 
 |             # Occupies CD | 
 |             size[2] = 1 | 
 |             size[3] = 1 | 
 |         elif module == 'my_RAM32M': | 
 |             size = [1, 1, 1, 1] | 
 |         elif module == 'my_RAM32X1S_N': | 
 |             size = pack4[n - 1] | 
 |             if size != has_bel_tcl: | 
 |                 continue | 
 |         else: | 
 |             assert (not module.startswith('my_RAM32')) | 
 |  | 
 |     # Now commit bits after marking 1's | 
 |     for beli, bel in enumerate('ABCD'): | 
 |         segmk.add_site_tag(loc, "%sLUT.RAM" % bel, ram[beli]) | 
 |         # FIXME: quick fix | 
 |         segmk.add_site_tag(loc, "%sLUT.SRL" % bel, srl[beli]) | 
 |         segmk.add_site_tag(loc, "%sLUT.SMALL" % bel, size[beli]) | 
 |  | 
 |  | 
 | def bitfilter(frame_idx, bit_idx): | 
 |     # Hack to remove aliased PIP bits on CE | 
 |     # We should either mix up routing more or exclude previous DB entries | 
 |     return (frame_idx, bit_idx) not in [(0, 27), (1, 25), (1, 26), (1, 29)] | 
 |  | 
 |  | 
 | segmk.compile(bitfilter=bitfilter) | 
 | segmk.write() |