| """ Utility for generating TCL script to generate bitstream, project and | 
 | checkpoint from fasm2v output. | 
 | """ | 
 | import argparse | 
 |  | 
 |  | 
 | def create_runme(f_out, args): | 
 |     print( | 
 |         """ | 
 | create_project -force -part {part} design design | 
 |  | 
 | read_verilog {bit_v} | 
 | synth_design -top {top} -bufg 0 | 
 |  | 
 | write_checkpoint -force design_{name}_pre_source.dcp | 
 |  | 
 | read_xdc -no_add {bit_xdc} | 
 | """.format( | 
 |             name=args.name, | 
 |             bit_v=args.verilog, | 
 |             top=args.top, | 
 |             bit_xdc=args.routing_xdc, | 
 |             part=args.part | 
 |         ), | 
 |         file=f_out | 
 |     ) | 
 |  | 
 |     if args.clock_pins or args.clock_periods: | 
 |         clock_pins = args.clock_pins.split(';') | 
 |         clock_periods = args.clock_periods.split(';') | 
 |         assert len(clock_pins) == len(clock_periods) | 
 |         for clock_pin, clock_period in zip(clock_pins, map(float, | 
 |                                                            clock_periods)): | 
 |             print( | 
 |                 """ | 
 | create_clock -period {period} -name {pin} -waveform {{0.000 {half_period}}} [get_ports {pin}] | 
 | """.format( | 
 |                     period=clock_period, | 
 |                     pin=clock_pin, | 
 |                     half_period=clock_period / 2, | 
 |                 ), | 
 |                 file=f_out | 
 |             ) | 
 |  | 
 |     if args.additional_xdc: | 
 |         print("source {}".format(args.additional_xdc), file=f_out) | 
 |  | 
 |     if args.place_and_route: | 
 |         print( | 
 |             """ | 
 | write_checkpoint -force design_{name}_pre_route.dcp | 
 |  | 
 | place_design | 
 | route_design | 
 |  | 
 | set_property IS_ENABLED 1 [get_drc_checks *] | 
 | set_property CFGBVS VCCO [current_design] | 
 | set_property CONFIG_VOLTAGE 3.3 [current_design] | 
 | set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design] | 
 | set_property IS_ENABLED 0 [get_drc_checks {{LUTLP-1}}] | 
 | set_property IS_ENABLED 0 [get_drc_checks {{RTRES-2}}] | 
 |  | 
 | report_utilization -file design_{name}_utilization.rpt | 
 | report_clock_utilization -file design_{name}_clock_utilization.rpt | 
 | report_timing_summary -datasheet -max_paths 10 -file design_{name}_timing_summary.rpt | 
 | report_power -file design_{name}_power.rpt | 
 | report_route_status -file design_{name}_route_status.rpt | 
 |  | 
 | write_checkpoint -force design_{name}.dcp | 
 | write_bitstream -force design_{name}.bit | 
 | save_project_as -force design_{name}.xpr | 
 |  | 
 | report_timing_summary | 
 | """.format(name=args.name), | 
 |             file=f_out | 
 |         ) | 
 |     else: | 
 |         print( | 
 |             """ | 
 |  | 
 | write_checkpoint -force design_{name}_pre_route.dcp | 
 | save_project_as -force design_{name}.xpr | 
 | close_project | 
 |  | 
 | open_checkpoint design_{name}_pre_route.dcp | 
 |  | 
 | set conflict_nets [get_nets -filter {{ ROUTE_STATUS == "CONFLICTS" }}] | 
 | if {{$conflict_nets != ""}} {{ | 
 |     puts "There are conflicting nets!" | 
 |  | 
 |     foreach net $conflict_nets {{ | 
 |         puts $net | 
 |     }} | 
 |     error "Exiting!" | 
 | }} | 
 |  | 
 | set unrouted_nets [get_nets -filter {{ ROUTE_STATUS == "UNROUTED" }}] | 
 |  | 
 | set antenna_nets [get_nets -filter {{ ROUTE_STATUS == "ANTENNAS" }}] | 
 |  | 
 | set partial_nets [get_nets -filter {{ ROUTE_STATUS == "PARTIAL" }}] | 
 |  | 
 | set nets_to_route "$unrouted_nets $antenna_nets $partial_nets" | 
 |  | 
 | set_property IS_ENABLED 0 [get_drc_checks *] | 
 |  | 
 | report_route_status | 
 | foreach net $nets_to_route {{ | 
 |     route_design -nets [get_nets $net] | 
 | }} | 
 |  | 
 | set_property IS_ENABLED 1 [get_drc_checks *] | 
 | set_property CFGBVS VCCO [current_design] | 
 | set_property CONFIG_VOLTAGE 3.3 [current_design] | 
 | set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design] | 
 | set_property IS_ENABLED 0 [get_drc_checks {{LUTLP-1}}] | 
 | set_property IS_ENABLED 0 [get_drc_checks {{RTRES-2}}] | 
 |  | 
 | report_utilization -file design_{name}_utilization.rpt | 
 | report_clock_utilization -file design_{name}_clock_utilization.rpt | 
 | report_timing_summary -datasheet -max_paths 10 -file design_{name}_timing_summary.rpt | 
 | report_power -file design_{name}_power.rpt | 
 | report_route_status -file design_{name}_route_status.rpt | 
 |  | 
 | write_checkpoint -force design_{name}.dcp | 
 | write_bitstream -force design_{name}.bit | 
 | save_project_as -force design_{name}.xpr | 
 |  | 
 | report_timing_summary | 
 | """.format(name=args.name), | 
 |             file=f_out | 
 |         ) | 
 |  | 
 |  | 
 | def main(): | 
 |     parser = argparse.ArgumentParser(description=__doc__) | 
 |  | 
 |     parser.add_argument( | 
 |         '--name', help="Name to postfix outputs.", required=True | 
 |     ) | 
 |     parser.add_argument( | 
 |         '--verilog', help="Input verilog file to build.", required=True | 
 |     ) | 
 |     parser.add_argument( | 
 |         '--routing_xdc', | 
 |         help="TCL script to run after synthesis to add static routing.", | 
 |         required=True | 
 |     ) | 
 |     parser.add_argument('--top', help="Top-level module name.", required=True) | 
 |     parser.add_argument( | 
 |         '--part', help="Part number to build for.", required=True | 
 |     ) | 
 |     parser.add_argument( | 
 |         '--clock_pins', | 
 |         help="Semi-colon seperated list of clock pins.", | 
 |         required=False | 
 |     ) | 
 |     parser.add_argument( | 
 |         '--clock_periods', | 
 |         help="Semi-colon seperated list of clock periods (in ns).", | 
 |         required=False | 
 |     ) | 
 |     parser.add_argument( | 
 |         '--output_tcl', help="Filename of output TCL file.", required=True | 
 |     ) | 
 |     parser.add_argument( | 
 |         '--additional_xdc', | 
 |         help="Filename of additional XDC file.", | 
 |     ) | 
 |     parser.add_argument( | 
 |         '--place_and_route', | 
 |         help="Run full place and route flow, rather than an incremental route.", | 
 |         action="store_true", | 
 |     ) | 
 |  | 
 |     args = parser.parse_args() | 
 |     with open(args.output_tcl, 'w') as f: | 
 |         create_runme(f, args) | 
 |  | 
 |  | 
 | if __name__ == "__main__": | 
 |     main() |