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