| #!/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 |
| |
| import json |
| import argparse |
| |
| from prjxray.util import OpenSafeFile |
| |
| def get_elems_count(timings, slice, site, bel_type): |
| combinational = 0 |
| sequential = 0 |
| for delay in timings[slice][site][bel_type]: |
| if 'sequential' in timings[slice][site][bel_type][delay]: |
| sequential += 1 |
| else: |
| combinational += 1 |
| return combinational, sequential |
| |
| |
| def produce_sdf(timings, outdir): |
| |
| for slice in timings: |
| sdf = \ |
| """ |
| (DELAYFILE |
| (SDFVERSION \"3.0\") |
| (TIMESCALE 1ns) |
| """ |
| for site in sorted(timings[slice]): |
| for bel_type in sorted(timings[slice][site]): |
| combinational, sequential = get_elems_count( |
| timings, slice, site, bel_type) |
| #define CELL |
| cell= \ |
| """ |
| (CELL |
| (CELLTYPE \"{name}\") |
| (INSTANCE {location})""".format(name=bel_type.upper(), location=site) |
| sdf += cell |
| |
| #define delay header (if needed) |
| if combinational > 0: |
| delay_hdr = \ |
| """ |
| (DELAY |
| (ABSOLUTE""" |
| sdf += delay_hdr |
| # add all delays definitions |
| for delay in sorted(timings[slice][site][bel_type]): |
| if 'sequential' in timings[slice][site][bel_type][ |
| delay]: |
| continue |
| dly = \ |
| """ |
| (IOPATH {input} {output} ({FAST_MIN}::{FAST_MAX})({SLOW_MIN}::{SLOW_MAX}))""".format(**timings[slice][site][bel_type][delay]) |
| if 'extra_ports' in timings[slice][site][bel_type][ |
| delay] is not None: |
| dly += \ |
| """ #extra ports {}""".format(timings[slice][site][bel_type][delay]['extra_ports']) |
| |
| sdf += dly |
| |
| # close DELAY definition |
| enddelay = \ |
| """ |
| ) |
| )""" |
| sdf += enddelay |
| |
| # define TIMINGCHECK header (if needed) |
| if sequential > 0: |
| timingcheck_hdr = \ |
| """ |
| (TIMINGCHECK""" |
| sdf += timingcheck_hdr |
| |
| for delay in sorted(timings[slice][site][bel_type]): |
| if 'sequential' not in timings[slice][site][bel_type][ |
| delay]: |
| continue |
| timingcheck = \ |
| """ |
| ({prop} {input} (posedge {clock}) ({SLOW_MIN}::{SLOW_MAX}))""".format( |
| prop=timings[slice][site][bel_type][delay]['sequential'].upper(), |
| **timings[slice][site][bel_type][delay]) |
| |
| if 'extra_ports' in timings[slice][site][bel_type][ |
| delay] is not None: |
| timingcheck += \ |
| """ #extra ports {}""".format(timings[slice][site][bel_type][delay]['extra_ports']) |
| |
| sdf += timingcheck |
| |
| # close TIMINGCHECK definition |
| endtimingcheck = \ |
| """ |
| )""" |
| sdf += endtimingcheck |
| |
| endcell = \ |
| """ |
| )""" |
| sdf += endcell |
| # end of SDF |
| sdf += \ |
| """ |
| )""" |
| |
| with OpenSafeFile(outdir + '/' + slice + '.sdf', "w") as fp: |
| fp.write(sdf) |
| |
| |
| def main(): |
| |
| parser = argparse.ArgumentParser() |
| parser.add_argument('--json', type=str, help="Input JSON file") |
| parser.add_argument('--sdf', type=str, help="SDF files output directory") |
| |
| args = parser.parse_args() |
| |
| with OpenSafeFile(args.json, 'r') as fp: |
| timings = json.load(fp) |
| |
| produce_sdf(timings, args.sdf) |
| |
| |
| if __name__ == '__main__': |
| main() |