| #!/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 | |
| ''' | |
| FDCE Primitive: D Flip-Flop with Clock Enable and Asynchronous Clear | |
| FDPE Primitive: D Flip-Flop with Clock Enable and Asynchronous Preset | |
| FDRE Primitive: D Flip-Flop with Clock Enable and Synchronous Reset | |
| FDSE Primitive: D Flip-Flop with Clock Enable and Synchronous Set | |
| LDCE Primitive: Transparent Data Latch with Asynchronous Clear and Gate Enable | |
| LDPE Primitive: Transparent Data Latch with Asynchronous Preset and Gate Enable | |
| ''' | |
| from prims import * | |
| from prjxray.segmaker import Segmaker | |
| segmk = Segmaker("design.bits") | |
| def ones(l): | |
| #return l + [x + '_1' for x in l] | |
| #return sorted(l + [x + '_1' for x in l]) | |
| ret = [] | |
| for x in l: | |
| ret.append(x) | |
| ret.append(x + '_1') | |
| return ret | |
| def loadtop(): | |
| ''' | |
| i,prim,loc,bel | |
| 0,FDPE,SLICE_X12Y100,C5FF | |
| 1,FDPE,SLICE_X15Y100,A5FF | |
| 2,FDPE_1,SLICE_X16Y100,B5FF | |
| 3,LDCE_1,SLICE_X17Y100,BFF | |
| ''' | |
| f = open('top.txt', 'r') | |
| f.readline() | |
| ret = {} | |
| for l in f: | |
| i, prim, loc, bel, init = l.split(",") | |
| i = int(i) | |
| init = int(init) | |
| ret[loc] = (i, prim, loc, bel, init) | |
| return ret | |
| top = loadtop() | |
| def vs2i(s): | |
| return {"1'b0": 0, "1'b1": 1}[s] | |
| print("Loading tags from design.txt") | |
| with open("design.txt", "r") as f: | |
| for line in f: | |
| ''' | |
| puts $fp "$type $tile $grid_x $grid_y $ff $bel_type $used $usedstr" | |
| CLBLM_L CLBLM_L_X10Y137 30 13 SLICE_X13Y137/AFF REG_INIT 1 FDRE | |
| CLBLM_L CLBLM_L_X10Y137 30 13 SLICE_X12Y137/D5FF FF_INIT 0 | |
| ''' | |
| line = line.split() | |
| tile_type = line[0] | |
| tile_name = line[1] | |
| grid_x = line[2] | |
| grid_y = line[3] | |
| # Other code uses BEL name | |
| # SLICE_X12Y137/D5FF | |
| site_ff_name = line[4] | |
| site, ff_name = site_ff_name.split('/') | |
| ff_type = line[5] | |
| used = int(line[6]) | |
| cel_prim = None | |
| cel_name = None | |
| if used: | |
| cel_name = line[7] | |
| # ex: FDCE | |
| cel_prim = line[8] | |
| # 1'b1 | |
| # cinv = int(line[9][-1]) | |
| cinv = int(line[9]) | |
| init = vs2i(line[10]) | |
| #init = int(line[10]) | |
| # A B C D | |
| which = ff_name[0] | |
| # LUT6 vs LUT5 FF | |
| is5 = '5' in ff_name | |
| if used: | |
| segmk.add_site_tag(site, "%s.ZINI" % ff_name, 1 ^ init) | |
| # CLKINV turns out to be more complicated than origianlly thought | |
| if isff(cel_prim): | |
| segmk.add_site_tag(site, "CLKINV", cinv) | |
| segmk.add_site_tag(site, "NOCLKINV", 1 ^ cinv) | |
| else: | |
| segmk.add_site_tag(site, "CLKINV", 1 ^ cinv) | |
| segmk.add_site_tag(site, "NOCLKINV", cinv) | |
| # Synchronous vs asynchronous FF | |
| # Unlike most bits, shared between all CLB FFs | |
| segmk.add_site_tag(site, "FFSYNC", cel_prim in ('FDSE', 'FDRE')) | |
| # Latch bit | |
| # Only applies to LUT6 (non-5) FF's | |
| if not is5: | |
| segmk.add_site_tag(site, "LATCH", isl(cel_prim)) | |
| ''' | |
| On name: | |
| The primitives you listed have a control input to set the FF value to zero (clear/reset), | |
| the other three primitives have a control input that sets the FF value to one. | |
| Z => inversion | |
| ''' | |
| segmk.add_site_tag( | |
| site, "%s.ZRST" % ff_name, | |
| cel_prim in ('FDRE', 'FDCE', 'LDCE')) | |
| segmk.compile() | |
| segmk.write() |