|  | #!/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() |