|  | """ 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() |