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