From 751fb9944b80fc00ec4d43002f98292c20fa2bac Mon Sep 17 00:00:00 2001 From: Stephen More Date: Tue, 18 Oct 2022 19:35:53 -0400 Subject: [PATCH 01/10] checkpoint of innovus changes --- coffe/hardblock_functions.py | 324 +++++++++++++++++++++-------------- coffe/utils.py | 15 +- 2 files changed, 209 insertions(+), 130 deletions(-) diff --git a/coffe/hardblock_functions.py b/coffe/hardblock_functions.py index 48c76ee..54b10e3 100644 --- a/coffe/hardblock_functions.py +++ b/coffe/hardblock_functions.py @@ -17,6 +17,7 @@ def write_synth_tcl(flow_settings,clock_period,wire_selection): """ file = open("dc_script.tcl","w") file.write("cd " + flow_settings['synth_folder'] + "\n") + #search path should have all directories which contain source , std cell libs, DesignCompiler libs file.write("set search_path " + flow_settings["search_path"] + " \n") if len(flow_settings["design_files"]) == 1: file.write("set my_files " + flow_settings["design_files"][0] + "\n") @@ -156,134 +157,195 @@ def run_synth(flow_settings,clock_period,wire_selection): exit() return synth_report_str + +def write_innovus_view_file(flow_settings): + """Write .view file for innovus place and route, this is used for for creating the delay corners from timing libs and importings constraints""" + view_fname = flow_settings["top_level"] + file = open(flow_settings["top_level"]+".view","w") + file.write("# Version:1.0 MMMC View Definition File\n# Do Not Remove Above Line") + #I created a typical delay corner but I don't think its being used as its not called in create_analysis_view command, however, may be useful? not sure but its here + #One could put RC values (maybe temperature in here) later for now they will all be the same + file.write("create_rc_corner -name RC_BEST -preRoute_res {1.0} -preRoute_cap {1.0} -preRoute_clkres {0.0} -preRoute_clkcap {0.0} -postRoute_res {1.0} -postRoute_cap {1.0} -postRoute_xcap {1.0} -postRoute_clkres {0.0} -postRoute_clkcap {0.0}"+ "\n") + file.write("create_rc_corner -name RC_TYP -preRoute_res {1.0} -preRoute_cap {1.0} -preRoute_clkres {0.0} -preRoute_clkcap {0.0} -postRoute_res {1.0} -postRoute_cap {1.0} -postRoute_xcap {1.0} -postRoute_clkres {0.0} -postRoute_clkcap {0.0}" + "\n") + file.write("create_rc_corner -name RC_WORST -preRoute_res {1.0} -preRoute_cap {1.0} -preRoute_clkres {0.0} -preRoute_clkcap {0.0} -postRoute_res {1.0} -postRoute_cap {1.0} -postRoute_xcap {1.0} -postRoute_clkres {0.0} -postRoute_clkcap {0.0}" + "\n") + #create libraries for each timing corner + file.write("create_library_set -name MIN_TIMING -timing {" + flow_settings["best_case_libs"] + "}" + "\n") + file.write("create_library_set -name TYP_TIMING -timing {" + flow_settings["standard_libs"] + "}" + "\n") + file.write("create_library_set -name MAX_TIMING -timing {" + flow_settings["worst_case_libs"] + "}" + "\n") + #import constraints from synthesis generated sdc + file.write("create_constraint_mode -name CONSTRAINTS -sdc_files {" + flow_settings['synth_folder'] + "/synthesized.sdc" + "}" + "\n") + file.write("create_delay_corner -name MIN_DELAY -library_set {MIN_TIMING} -rc_corner {RC_BEST}" + "\n") + file.write("create_delay_corner -name TYP_DELAY -library_set {TYP_TIMING} -rc_corner {RC_TYP}" + "\n") + file.write("create_delay_corner -name MAX_DELAY -library_set {MAX_TIMING} -rc_corner {RC_WORST}" + "\n") + file.write("create_analysis_view -name BEST_CASE -constraint_mode {CONSTRAINTS} -delay_corner {MIN_DELAY}" + "\n") + file.write("create_analysis_view -name TYP_CASE -constraint_mode {CONSTRAINTS} -delay_corner {TYP_DELAY}" + "\n") + file.write("create_analysis_view -name WORST_CASE -constraint_mode {CONSTRAINTS} -delay_corner {MAX_DELAY}" + "\n") + #This sets our analysis view to be using our worst case analysis view for setup and best for timing, + #This makes sense as the BC libs would have the most severe hold violations and vice versa for setup + file.write("set_analysis_view -setup {WORST_CASE} -hold {BEST_CASE}" + "\n") + +def write_innovus_globals(flow_settings): + print('tes') + def write_pnr_script(flow_settings,metal_layer,core_utilization): """" writes the tcl script for place and route using Cadence Encounter, tested under 2009 version """ - # generate the EDI (encounter) configuration - file = open("edi.conf", "w") - file.write("global rda_Input \n") - file.write("set cwd .\n\n") - file.write("set rda_Input(ui_leffile) " + flow_settings['lef_files'] + "\n") - file.write("set rda_Input(ui_timelib,min) " + flow_settings['best_case_libs'] + "\n") - file.write("set rda_Input(ui_timelib) " + flow_settings['standard_libs'] + "\n") - file.write("set rda_Input(ui_timelib,max) " + flow_settings['worst_case_libs'] + "\n") - file.write("set rda_Input(ui_netlist) " + os.path.expanduser(flow_settings['synth_folder']) + "/synthesized.v" + "\n") - file.write("set rda_Input(ui_netlisttype) {Verilog} \n") - file.write("set rda_Input(import_mode) {-treatUndefinedCellAsBbox 0 -keepEmptyModule 1}\n") - file.write("set rda_Input(ui_timingcon_file) " + os.path.expanduser(flow_settings['synth_folder']) + "/synthesized.sdc" + "\n") - file.write("set rda_Input(ui_topcell) " + flow_settings['top_level'] + "\n\n") - gnd_pin = flow_settings['gnd_pin'] - gnd_net = flow_settings['gnd_net'] - pwr_pin = flow_settings['pwr_pin'] - pwr_net = flow_settings['pwr_net'] - file.write("set rda_Input(ui_gndnet) {" + gnd_net + "} \n") - file.write("set rda_Input(ui_pwrnet) {" + pwr_net + "} \n") - if flow_settings['tilehi_tielo_cells_between_power_gnd'] is True: - file.write("set rda_Input(ui_pg_connections) [list {PIN:" + gnd_pin + ":}" + " {TIEL::} " + "{NET:" + gnd_net + ":} {NET:" + pwr_net + ":}" + " {TIEH::} " + "{PIN:" + pwr_pin + ":} ] \n") - else: - file.write("set rda_Input(ui_pg_connections) [list {PIN:" + gnd_pin + ":} {NET:" + gnd_net + ":} {NET:" + pwr_net + ":} {PIN:" + pwr_pin + ":} ] \n") - file.write("set rda_Input(PIN:" + gnd_pin + ":) {" + gnd_pin + "} \n") - file.write("set rda_Input(TIEL::) {" + gnd_pin + "} \n") - file.write("set rda_Input(NET:" + gnd_net + ":) {" + gnd_net + "} \n") - file.write("set rda_Input(PIN:" + pwr_pin + ":) {" + pwr_pin + "} \n") - file.write("set rda_Input(TIEH::) {" + pwr_pin + "} \n") - file.write("set rda_Input(NET:" + pwr_net + ":) {" + pwr_net + "} \n\n") - if (flow_settings['inv_footprint'] != "None"): - file.write("set rda_Input(ui_inv_footprint) {" + flow_settings['inv_footprint'] + "}\n") - if (flow_settings['buf_footprint'] != "None"): - file.write("set rda_Input(ui_buf_footprint) {" + flow_settings['buf_footprint'] + "}\n") - if (flow_settings['delay_footprint'] != "None"): - file.write("set rda_Input(ui_delay_footprint) {" + flow_settings['delay_footprint'] + "}\n") - file.close() - metal_layer_bottom = flow_settings["metal_layer_names"][0] - metal_layer_second = flow_settings["metal_layer_names"][1] - metal_layer_top = flow_settings["metal_layer_names"][int(metal_layer)-1] - power_ring_metal_top = flow_settings["power_ring_metal_layer_names"][0] - power_ring_metal_bottom = flow_settings["power_ring_metal_layer_names"][1] - power_ring_metal_left = flow_settings["power_ring_metal_layer_names"][2] - power_ring_metal_right = flow_settings["power_ring_metal_layer_names"][3] - # generate the EDI (encounter) script - file = open("edi.tcl", "w") - file.write("loadConfig edi.conf \n") - file.write("floorPlan -site " + flow_settings['core_site_name'] \ - + " -r " + str(flow_settings['height_to_width_ratio']) \ - + " " + str(core_utilization) \ - + " " + str(flow_settings['space_around_core']) \ - + " " + str(flow_settings['space_around_core']) + " ") - file.write(str(flow_settings['space_around_core']) + " " + str(flow_settings['space_around_core']) + "\n") - file.write("setMaxRouteLayer " + str(metal_layer) + " \n") - file.write("fit \n") - file.write("addRing -spacing_bottom " + str(flow_settings['power_ring_spacing']) \ - + " -spacing_right " + str(flow_settings['power_ring_spacing']) \ - + " -spacing_top " + str(flow_settings['power_ring_spacing']) \ - + " -spacing_left " + str(flow_settings['power_ring_spacing']) \ - + " -width_right " + str(flow_settings['power_ring_width']) \ - + " -width_left " + str(flow_settings['power_ring_width']) \ - + " -width_bottom " + str(flow_settings['power_ring_width']) \ - + " -width_top " + str(flow_settings['power_ring_width']) \ - + " -center 1" \ - + " -around core" \ - + " -layer_top " + power_ring_metal_top \ - + " -layer_bottom " + power_ring_metal_bottom \ - + " -layer_left " + power_ring_metal_left \ - + " -layer_right " + power_ring_metal_right \ - + " -nets { " + gnd_net + " " + pwr_net + " }" \ - + " -stacked_via_top_layer "+ metal_layer_top \ - + " -stacked_via_bottom_layer " + metal_layer_bottom + " \n") - file.write("setPlaceMode -fp false -maxRouteLayer " + str(metal_layer) + "\n") - file.write("placeDesign -inPlaceOpt -noPrePlaceOpt \n") - file.write("checkPlace " + flow_settings['top_level'] +" \n") - file.write("trialroute \n") - file.write("buildTimingGraph \n") - file.write("timeDesign -preCTS -idealClock -numPaths 10 -prefix preCTS -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/timeDesignpreCTSReports" + "\n") - file.write("optDesign -preCTS -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/optDesignpreCTSReports" + "\n") - # I won't do a CTS anyway as the blocks are small. - file.write("addFiller -cell {" + " ".join([str(item) for item in flow_settings['filler_cell_names']]) + "} -prefix FILL -merge true \n") - file.write("clearGlobalNets \n") - file.write("globalNetConnect " + gnd_net + " -type pgpin -pin " + gnd_pin + " -inst {} \n") - file.write("globalNetConnect " + pwr_net + " -type pgpin -pin " + pwr_pin + " -inst {} \n") - file.write("globalNetConnect " + gnd_net + " -type net -net " + gnd_net + " \n") - file.write("globalNetConnect " + pwr_net + " -type net -net " + pwr_net + " \n") - file.write("globalNetConnect " + pwr_net + " -type pgpin -pin " + pwr_pin + " -inst * \n") - file.write("globalNetConnect " + gnd_net + " -type pgpin -pin " + gnd_pin + " -inst * \n") - file.write("globalNetConnect " + pwr_net + " -type tiehi -inst * \n") - file.write("globalNetConnect " + gnd_net + " -type tielo -inst * \n") - file.write("sroute -connect { blockPin padPin padRing corePin floatingStripe }" \ - + " -layerChangeRange { " + metal_layer_bottom + " " + metal_layer_top + " }" \ - + " -blockPinTarget { nearestRingStripe nearestTarget }" \ - + " -padPinPortConnect { allPort oneGeom }" \ - + " -checkAlignedSecondaryPin 1" \ - + " -blockPin useLef" \ - + " -allowJogging 1" \ - + " -crossoverViaBottomLayer " + metal_layer_bottom \ - + " -allowLayerChange 1" \ - + " -targetViaTopLayer " + metal_layer_top \ - + " -crossoverViaTopLayer " + metal_layer_top \ - + " -targetViaBottomLayer " + metal_layer_bottom \ - + " -nets { " + gnd_net + " " + pwr_net + " } \n") - file.write("routeDesign -globalDetail\n") - file.write("setExtractRCMode -engine postRoute \n") - file.write("extractRC \n") - file.write("buildTimingGraph \n") - file.write("timeDesign -postRoute -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/timeDesignReports" + "\n") - file.write("optDesign -postRoute -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/optDesignReports" + "\n") - #by default, violations are reported in designname.geom.rpt - file.write("verifyGeometry -report " + (os.path.expanduser(flow_settings['pr_folder']) + "/" + flow_settings['top_level'] + ".geom.rpt") + "\n") - #by default, violations are reported in designname.conn.rpt - file.write("verifyConnectivity -type all -report " + (os.path.expanduser(flow_settings['pr_folder']) + "/" + flow_settings['top_level'] + ".conn.rpt") + "\n") - # report area - file.write("summaryReport -outFile " + os.path.expanduser(flow_settings['pr_folder']) + "/pr_report.txt \n") - # save design - file.write(r'saveNetlist ' + os.path.expanduser(flow_settings['pr_folder']) + r'/netlist.v' + "\n") - file.write(r'saveDesign ' + os.path.expanduser(flow_settings['pr_folder']) + r'/design.enc' + " \n") - file.write(r'rcOut -spef ' + os.path.expanduser(flow_settings['pr_folder']) + r'/spef.spef' + " \n") - file.write(r'write_sdf -ideal_clock_network ' + os.path.expanduser(flow_settings['pr_folder']) + r'/sdf.sdf' + " \n") - #If the user specified a layer mapping file, then use that. Otherwise, just let the tool create a default one. - if flow_settings['map_file'] != "None": - file.write(r'streamOut ' + os.path.expanduser(flow_settings['pr_folder']) + r'/final.gds2' + ' -mapFile ' + flow_settings['map_file'] + ' -stripes 1 -units 1000 -mode ALL' + "\n") - else: - file.write(r'streamOut ' + os.path.expanduser(flow_settings['pr_folder']) + r'/final.gds2' + ' -stripes 1 -units 1000 -mode ALL' + "\n") + if(flow_settings["pnr_tool"] == "encounter"): + # generate the EDI (encounter) configuration + file = open("edi.conf", "w") + file.write("global rda_Input \n") + file.write("set cwd .\n\n") + file.write("set rda_Input(ui_leffile) " + flow_settings['lef_files'] + "\n") + file.write("set rda_Input(ui_timelib,min) " + flow_settings['best_case_libs'] + "\n") + file.write("set rda_Input(ui_timelib) " + flow_settings['standard_libs'] + "\n") + file.write("set rda_Input(ui_timelib,max) " + flow_settings['worst_case_libs'] + "\n") + file.write("set rda_Input(ui_netlist) " + os.path.expanduser(flow_settings['synth_folder']) + "/synthesized.v" + "\n") + file.write("set rda_Input(ui_netlisttype) {Verilog} \n") + file.write("set rda_Input(import_mode) {-treatUndefinedCellAsBbox 0 -keepEmptyModule 1}\n") + file.write("set rda_Input(ui_timingcon_file) " + os.path.expanduser(flow_settings['synth_folder']) + "/synthesized.sdc" + "\n") + file.write("set rda_Input(ui_topcell) " + flow_settings['top_level'] + "\n\n") + gnd_pin = flow_settings['gnd_pin'] + gnd_net = flow_settings['gnd_net'] + pwr_pin = flow_settings['pwr_pin'] + pwr_net = flow_settings['pwr_net'] + file.write("set rda_Input(ui_gndnet) {" + gnd_net + "} \n") + file.write("set rda_Input(ui_pwrnet) {" + pwr_net + "} \n") + if flow_settings['tilehi_tielo_cells_between_power_gnd'] is True: + file.write("set rda_Input(ui_pg_connections) [list {PIN:" + gnd_pin + ":}" + " {TIEL::} " + "{NET:" + gnd_net + ":} {NET:" + pwr_net + ":}" + " {TIEH::} " + "{PIN:" + pwr_pin + ":} ] \n") + else: + file.write("set rda_Input(ui_pg_connections) [list {PIN:" + gnd_pin + ":} {NET:" + gnd_net + ":} {NET:" + pwr_net + ":} {PIN:" + pwr_pin + ":} ] \n") + file.write("set rda_Input(PIN:" + gnd_pin + ":) {" + gnd_pin + "} \n") + file.write("set rda_Input(TIEL::) {" + gnd_pin + "} \n") + file.write("set rda_Input(NET:" + gnd_net + ":) {" + gnd_net + "} \n") + file.write("set rda_Input(PIN:" + pwr_pin + ":) {" + pwr_pin + "} \n") + file.write("set rda_Input(TIEH::) {" + pwr_pin + "} \n") + file.write("set rda_Input(NET:" + pwr_net + ":) {" + pwr_net + "} \n\n") + if (flow_settings['inv_footprint'] != "None"): + file.write("set rda_Input(ui_inv_footprint) {" + flow_settings['inv_footprint'] + "}\n") + if (flow_settings['buf_footprint'] != "None"): + file.write("set rda_Input(ui_buf_footprint) {" + flow_settings['buf_footprint'] + "}\n") + if (flow_settings['delay_footprint'] != "None"): + file.write("set rda_Input(ui_delay_footprint) {" + flow_settings['delay_footprint'] + "}\n") + file.close() + metal_layer_bottom = flow_settings["metal_layer_names"][0] + metal_layer_second = flow_settings["metal_layer_names"][1] + metal_layer_top = flow_settings["metal_layer_names"][int(metal_layer)-1] + power_ring_metal_top = flow_settings["power_ring_metal_layer_names"][0] + power_ring_metal_bottom = flow_settings["power_ring_metal_layer_names"][1] + power_ring_metal_left = flow_settings["power_ring_metal_layer_names"][2] + power_ring_metal_right = flow_settings["power_ring_metal_layer_names"][3] + # generate the EDI (encounter) script + file = open("edi.tcl", "w") + file.write("loadConfig edi.conf \n") + file.write("floorPlan -site " + flow_settings['core_site_name'] \ + + " -r " + str(flow_settings['height_to_width_ratio']) \ + + " " + str(core_utilization) \ + + " " + str(flow_settings['space_around_core']) \ + + " " + str(flow_settings['space_around_core']) + " ") + file.write(str(flow_settings['space_around_core']) + " " + str(flow_settings['space_around_core']) + "\n") + file.write("setMaxRouteLayer " + str(metal_layer) + " \n") + file.write("fit \n") + file.write("addRing -spacing_bottom " + str(flow_settings['power_ring_spacing']) \ + + " -spacing_right " + str(flow_settings['power_ring_spacing']) \ + + " -spacing_top " + str(flow_settings['power_ring_spacing']) \ + + " -spacing_left " + str(flow_settings['power_ring_spacing']) \ + + " -width_right " + str(flow_settings['power_ring_width']) \ + + " -width_left " + str(flow_settings['power_ring_width']) \ + + " -width_bottom " + str(flow_settings['power_ring_width']) \ + + " -width_top " + str(flow_settings['power_ring_width']) \ + + " -center 1" \ + + " -around core" \ + + " -layer_top " + power_ring_metal_top \ + + " -layer_bottom " + power_ring_metal_bottom \ + + " -layer_left " + power_ring_metal_left \ + + " -layer_right " + power_ring_metal_right \ + + " -nets { " + gnd_net + " " + pwr_net + " }" \ + + " -stacked_via_top_layer "+ metal_layer_top \ + + " -stacked_via_bottom_layer " + metal_layer_bottom + " \n") + file.write("setPlaceMode -fp false -maxRouteLayer " + str(metal_layer) + "\n") + file.write("placeDesign -inPlaceOpt -noPrePlaceOpt \n") + file.write("checkPlace " + flow_settings['top_level'] +" \n") + file.write("trialroute \n") + file.write("buildTimingGraph \n") + file.write("timeDesign -preCTS -idealClock -numPaths 10 -prefix preCTS -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/timeDesignpreCTSReports" + "\n") + file.write("optDesign -preCTS -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/optDesignpreCTSReports" + "\n") + # I won't do a CTS anyway as the blocks are small. + file.write("addFiller -cell {" + " ".join([str(item) for item in flow_settings['filler_cell_names']]) + "} -prefix FILL -merge true \n") + file.write("clearGlobalNets \n") + file.write("globalNetConnect " + gnd_net + " -type pgpin -pin " + gnd_pin + " -inst {} \n") + file.write("globalNetConnect " + pwr_net + " -type pgpin -pin " + pwr_pin + " -inst {} \n") + file.write("globalNetConnect " + gnd_net + " -type net -net " + gnd_net + " \n") + file.write("globalNetConnect " + pwr_net + " -type net -net " + pwr_net + " \n") + file.write("globalNetConnect " + pwr_net + " -type pgpin -pin " + pwr_pin + " -inst * \n") + file.write("globalNetConnect " + gnd_net + " -type pgpin -pin " + gnd_pin + " -inst * \n") + file.write("globalNetConnect " + pwr_net + " -type tiehi -inst * \n") + file.write("globalNetConnect " + gnd_net + " -type tielo -inst * \n") + file.write("sroute -connect { blockPin padPin padRing corePin floatingStripe }" \ + + " -layerChangeRange { " + metal_layer_bottom + " " + metal_layer_top + " }" \ + + " -blockPinTarget { nearestRingStripe nearestTarget }" \ + + " -padPinPortConnect { allPort oneGeom }" \ + + " -checkAlignedSecondaryPin 1" \ + + " -blockPin useLef" \ + + " -allowJogging 1" \ + + " -crossoverViaBottomLayer " + metal_layer_bottom \ + + " -allowLayerChange 1" \ + + " -targetViaTopLayer " + metal_layer_top \ + + " -crossoverViaTopLayer " + metal_layer_top \ + + " -targetViaBottomLayer " + metal_layer_bottom \ + + " -nets { " + gnd_net + " " + pwr_net + " } \n") + file.write("routeDesign -globalDetail\n") + file.write("setExtractRCMode -engine postRoute \n") + file.write("extractRC \n") + file.write("buildTimingGraph \n") + file.write("timeDesign -postRoute -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/timeDesignReports" + "\n") + file.write("optDesign -postRoute -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/optDesignReports" + "\n") + #by default, violations are reported in designname.geom.rpt + file.write("verifyGeometry -report " + (os.path.expanduser(flow_settings['pr_folder']) + "/" + flow_settings['top_level'] + ".geom.rpt") + "\n") + #by default, violations are reported in designname.conn.rpt + file.write("verifyConnectivity -type all -report " + (os.path.expanduser(flow_settings['pr_folder']) + "/" + flow_settings['top_level'] + ".conn.rpt") + "\n") + # report area + file.write("summaryReport -outFile " + os.path.expanduser(flow_settings['pr_folder']) + "/pr_report.txt \n") + # save design + file.write(r'saveNetlist ' + os.path.expanduser(flow_settings['pr_folder']) + r'/netlist.v' + "\n") + file.write(r'saveDesign ' + os.path.expanduser(flow_settings['pr_folder']) + r'/design.enc' + " \n") + file.write(r'rcOut -spef ' + os.path.expanduser(flow_settings['pr_folder']) + r'/spef.spef' + " \n") + file.write(r'write_sdf -ideal_clock_network ' + os.path.expanduser(flow_settings['pr_folder']) + r'/sdf.sdf' + " \n") + #If the user specified a layer mapping file, then use that. Otherwise, just let the tool create a default one. + if flow_settings['map_file'] != "None": + file.write(r'streamOut ' + os.path.expanduser(flow_settings['pr_folder']) + r'/final.gds2' + ' -mapFile ' + flow_settings['map_file'] + ' -stripes 1 -units 1000 -mode ALL' + "\n") + else: + file.write(r'streamOut ' + os.path.expanduser(flow_settings['pr_folder']) + r'/final.gds2' + ' -stripes 1 -units 1000 -mode ALL' + "\n") + elif(flow_settings["pnr_tool"] == "innovus"): + + """ + ###### 10/17/2022 11:00pm ###### + setDesignMode -process 65 + floorPlan -site core -r 4.0 0.85 10 10 10 10 + setDesignMode -topRoutingLayer 7 + earlyGlobalRoute + timeDesign -preCTS -idealClock -numPaths 10 -prefix preCTS -outDir /fs1/eecg/vaughn/morestep/COFFE/output_files/strtx_III_dsp/pr/timeDesignpreCTSReports + optDesign -preCTS -outDir /fs1/eecg/vaughn/morestep/COFFE/output_files/strtx_III_dsp/pr/optDesignpreCTSReports + addFiller -cell {FILL1 FILL16 FILL1_LL FILL2 FILL32 FILL64 FILL8 FILL_NW_FA_LL FILL_NW_HH FILL_NW_LL} -prefix FILL -merge true + clearGlobalNets + globalNetConnect VSS -type pgpin -pin VSS -inst {} + globalNetConnect VDD -type pgpin -pin VDD -inst {} + globalNetConnect VSS -type net -net VSS + globalNetConnect VDD -type net -net VDD + globalNetConnect VDD -type pgpin -pin VDD -inst * + globalNetConnect VSS -type pgpin -pin VSS -inst * + globalNetConnect VDD -type tiehi -inst * + globalNetConnect VSS -type tielo -inst * + sroute -connect { blockPin padPin padRing corePin floatingStripe } -layerChangeRange { M1 M7 } -blockPinTarget { nearestRingStripe nearestTarget } -padPinPortConnect { allPort oneGeom } -checkAlignedSecondaryPin 1 -blockPin useLef -allowJogging 1 -crossoverViaBottomLayer M1 -allowLayerChange 1 -targetViaTopLayer M7 -crossoverViaTopLayer M7 -targetViaBottomLayer M1 -nets { VSS VDD } + routeDesign -globalDetail + setExtractRCMode -engine postRoute + extractRC + buildTimingGraph + setAnalysisMode -analysisType onChipVariation -cppr both + timeDesign -postRoute -outDir /fs1/eecg/vaughn/morestep/COFFE/output_files/strtx_III_dsp/pr/timeDesignReports + optDesign -postRoute -outDir /fs1/eecg/vaughn/morestep/COFFE/output_files/strtx_III_dsp/pr/optDesignReports + #setRouteMode -earlyGlobalMaxRouteLayer 7 (this command does same as top command) + """ file.write("exit \n") file.close() def run_pnr(flow_settings,metal_layer,core_utilization,synth_report_str): @@ -344,7 +406,8 @@ def run_sim(): def write_pt_power_script(flow_settings,mode_enabled,clock_period,x): """" - writes the tcl script for timing analysis using Synopsys Design Compiler, tested under 2017 version + writes the tcl script for power analysis using Synopsys Design Compiler, tested under 2017 version + Update: changed the [all_nets] argument used in set_switching_activity to use -baseClk and -inputs args instead """ # Create a script to measure power: file = open("primetime_power.tcl", "w") @@ -352,7 +415,7 @@ def write_pt_power_script(flow_settings,mode_enabled,clock_period,x): file.write("set search_path " + flow_settings['search_path'] + " \n") file.write("set my_top_level " + flow_settings['top_level'] + "\n") file.write("set my_clock_pin " + flow_settings['clock_pin_name'] + "\n") - file.write("set target_library " + flow_settings['target_library'] + "\n") + file.write("set target_library " + flow_settings['primetime_libs'] + "\n") file.write("set link_library " + flow_settings['link_library'] + "\n") file.write("read_verilog " + os.path.expanduser(flow_settings['pr_folder']) + "/netlist.v \n") file.write("link \n") @@ -379,7 +442,9 @@ def write_pt_power_script(flow_settings,mode_enabled,clock_period,x): file.close() def write_pt_timing_script(flow_settings,mode_enabled,clock_period,x): - """""" + """ + writes the tcl script for timing analysis using Synopsys Design Compiler, tested under 2017 version + """ # backannotate into primetime # This part should be reported for all the modes in the design. file = open("primetime.tcl", "w") @@ -387,7 +452,7 @@ def write_pt_timing_script(flow_settings,mode_enabled,clock_period,x): file.write("set search_path " + flow_settings['search_path'] + " \n") file.write("set my_top_level " + flow_settings['top_level'] + "\n") file.write("set my_clock_pin " + flow_settings['clock_pin_name'] + "\n") - file.write("set target_library " + flow_settings['target_library'] + "\n") + file.write("set target_library " + flow_settings['primetime_libs'] + "\n") file.write("set link_library " + flow_settings['link_library'] + "\n") file.write("read_verilog " + os.path.expanduser(flow_settings['pr_folder']) + "/netlist.v \n") if mode_enabled and x <2**len(flow_settings['mode_signal']): @@ -504,7 +569,7 @@ def flow_settings_pre_process(processed_flow_settings,cur_env): processed_flow_settings["best_case_libs"] = "\"" + " ".join(processed_flow_settings['best_case_libs']) + "\"" processed_flow_settings["standard_libs"] = "\"" + " ".join(processed_flow_settings['standard_libs']) + "\"" processed_flow_settings["worst_case_libs"] = "\"" + " ".join(processed_flow_settings['worst_case_libs']) + "\"" - + processed_flow_settings["primetime_libs"] = "\"" + " ".join(processed_flow_settings['primetime_libs']) + "\"" # wire loads in the library are WireAreaLowkCon WireAreaLowkAgr WireAreaForZero def hardblock_flow(flow_settings): cur_env = os.environ.copy() @@ -536,6 +601,7 @@ def hardblock_flow(flow_settings): # Optional: use modelsim to generate an activity file for the design: if flow_settings['generate_activity_file'] is True: run_sim() + #loops over every combination of user inputted modes to set the set_case_analysis value (determines value of mode mux) for x in range(0, 2**len(flow_settings['mode_signal']) + 1): library_setup_time, data_arrival_time, total_delay, total_dynamic_power = run_power_timing(flow_settings,mode_enabled,clock_period,x,pnr_report_str) # write the final report file: diff --git a/coffe/utils.py b/coffe/utils.py index b2640cc..5dba53a 100644 --- a/coffe/utils.py +++ b/coffe/utils.py @@ -697,6 +697,9 @@ def check_hard_params(hard_params,optional_params): if ((val == "" or val == -1 or val == -1.0 or val == []) and key not in optional_params): print("param \"%s\" is unset, please go to your hardblock/process params file and set it" % (key)) sys.exit(1) + elif(key == "pnr_tool" and val != "encounter" and val != "innovus" ): + print("ERROR: pnr_tool must be set as either \"encounter\" or \"innovus\" ") + sys.exit(1) def load_hard_params(filename): """ Parse the hard block description file and load values into dictionary. @@ -743,7 +746,7 @@ def load_hard_params(filename): 'space_around_core': -1, 'pr_folder': "", #'primetime_lib_path': '', - #'primetime_lib_name': '', + 'primetime_lib_names': '', 'primetime_folder': "" , 'delay_cost_exp': 1.0, 'area_cost_exp': 1.0, @@ -766,6 +769,8 @@ def load_hard_params(filename): 'mode_signal': [], 'process_lib_paths': [], 'process_params_file': "", + 'pnr_tool': "", + 'process_size': "", } hard_file = open(filename, 'r') @@ -871,9 +876,15 @@ def load_hard_params(filename): hard_params['mode_signal'].append(value) elif param == "process_params_file": hard_params["process_params_file"] = value + elif param == "pnr_tool": + hard_params["pnr_tool"] = value + elif param == "process_size": + hard_params["process_size"] = value #To allow for the legacy way of inputting process specific params I'll keep these in (the only reason for having a seperate file is for understandability) if param == "process_lib_paths": hard_params["process_lib_paths"] = sanatize_str_input_to_list(value) + elif param == "primetime_libs": + hard_params["primetime_libs"] = sanatize_str_input_to_list(value) elif param == 'target_libraries': hard_params['target_libraries'] = sanatize_str_input_to_list(value) elif param == 'lef_files': @@ -975,6 +986,8 @@ def load_hard_params(filename): hard_params['pwr_pin'] = value.strip() elif param == 'wire_selection': hard_params['wire_selection'].append(value) + elif param == "primetime_libs": + hard_params["primetime_libs"] = sanatize_str_input_to_list(value) process_param_file.close() #TODO make this more accessable outside of the code, but for now this is how I declare optional parameters From 41987e642368b544c99b4bd442e2b5c83ffba80b Mon Sep 17 00:00:00 2001 From: Stephen More Date: Tue, 18 Oct 2022 19:35:53 -0400 Subject: [PATCH 02/10] checkpoint of innovus changes --- coffe/hardblock_functions.py | 318 +++++++++++++++++++++-------------- coffe/utils.py | 12 +- 2 files changed, 198 insertions(+), 132 deletions(-) diff --git a/coffe/hardblock_functions.py b/coffe/hardblock_functions.py index 1a0ef4b..f09111b 100644 --- a/coffe/hardblock_functions.py +++ b/coffe/hardblock_functions.py @@ -17,6 +17,7 @@ def write_synth_tcl(flow_settings,clock_period,wire_selection): """ file = open("dc_script.tcl","w") file.write("cd " + flow_settings['synth_folder'] + "\n") + #search path should have all directories which contain source , std cell libs, DesignCompiler libs file.write("set search_path " + flow_settings["search_path"] + " \n") if len(flow_settings["design_files"]) == 1: file.write("set my_files " + flow_settings["design_files"][0] + "\n") @@ -156,134 +157,195 @@ def run_synth(flow_settings,clock_period,wire_selection): exit() return synth_report_str + +def write_innovus_view_file(flow_settings): + """Write .view file for innovus place and route, this is used for for creating the delay corners from timing libs and importings constraints""" + view_fname = flow_settings["top_level"] + file = open(flow_settings["top_level"]+".view","w") + file.write("# Version:1.0 MMMC View Definition File\n# Do Not Remove Above Line") + #I created a typical delay corner but I don't think its being used as its not called in create_analysis_view command, however, may be useful? not sure but its here + #One could put RC values (maybe temperature in here) later for now they will all be the same + file.write("create_rc_corner -name RC_BEST -preRoute_res {1.0} -preRoute_cap {1.0} -preRoute_clkres {0.0} -preRoute_clkcap {0.0} -postRoute_res {1.0} -postRoute_cap {1.0} -postRoute_xcap {1.0} -postRoute_clkres {0.0} -postRoute_clkcap {0.0}"+ "\n") + file.write("create_rc_corner -name RC_TYP -preRoute_res {1.0} -preRoute_cap {1.0} -preRoute_clkres {0.0} -preRoute_clkcap {0.0} -postRoute_res {1.0} -postRoute_cap {1.0} -postRoute_xcap {1.0} -postRoute_clkres {0.0} -postRoute_clkcap {0.0}" + "\n") + file.write("create_rc_corner -name RC_WORST -preRoute_res {1.0} -preRoute_cap {1.0} -preRoute_clkres {0.0} -preRoute_clkcap {0.0} -postRoute_res {1.0} -postRoute_cap {1.0} -postRoute_xcap {1.0} -postRoute_clkres {0.0} -postRoute_clkcap {0.0}" + "\n") + #create libraries for each timing corner + file.write("create_library_set -name MIN_TIMING -timing {" + flow_settings["best_case_libs"] + "}" + "\n") + file.write("create_library_set -name TYP_TIMING -timing {" + flow_settings["standard_libs"] + "}" + "\n") + file.write("create_library_set -name MAX_TIMING -timing {" + flow_settings["worst_case_libs"] + "}" + "\n") + #import constraints from synthesis generated sdc + file.write("create_constraint_mode -name CONSTRAINTS -sdc_files {" + flow_settings['synth_folder'] + "/synthesized.sdc" + "}" + "\n") + file.write("create_delay_corner -name MIN_DELAY -library_set {MIN_TIMING} -rc_corner {RC_BEST}" + "\n") + file.write("create_delay_corner -name TYP_DELAY -library_set {TYP_TIMING} -rc_corner {RC_TYP}" + "\n") + file.write("create_delay_corner -name MAX_DELAY -library_set {MAX_TIMING} -rc_corner {RC_WORST}" + "\n") + file.write("create_analysis_view -name BEST_CASE -constraint_mode {CONSTRAINTS} -delay_corner {MIN_DELAY}" + "\n") + file.write("create_analysis_view -name TYP_CASE -constraint_mode {CONSTRAINTS} -delay_corner {TYP_DELAY}" + "\n") + file.write("create_analysis_view -name WORST_CASE -constraint_mode {CONSTRAINTS} -delay_corner {MAX_DELAY}" + "\n") + #This sets our analysis view to be using our worst case analysis view for setup and best for timing, + #This makes sense as the BC libs would have the most severe hold violations and vice versa for setup + file.write("set_analysis_view -setup {WORST_CASE} -hold {BEST_CASE}" + "\n") + +def write_innovus_globals(flow_settings): + print('tes') + def write_pnr_script(flow_settings,metal_layer,core_utilization): """" writes the tcl script for place and route using Cadence Encounter, tested under 2009 version """ - # generate the EDI (encounter) configuration - file = open("edi.conf", "w") - file.write("global rda_Input \n") - file.write("set cwd .\n\n") - file.write("set rda_Input(ui_leffile) " + flow_settings['lef_files'] + "\n") - file.write("set rda_Input(ui_timelib,min) " + flow_settings['best_case_libs'] + "\n") - file.write("set rda_Input(ui_timelib) " + flow_settings['standard_libs'] + "\n") - file.write("set rda_Input(ui_timelib,max) " + flow_settings['worst_case_libs'] + "\n") - file.write("set rda_Input(ui_netlist) " + os.path.expanduser(flow_settings['synth_folder']) + "/synthesized.v" + "\n") - file.write("set rda_Input(ui_netlisttype) {Verilog} \n") - file.write("set rda_Input(import_mode) {-treatUndefinedCellAsBbox 0 -keepEmptyModule 1}\n") - file.write("set rda_Input(ui_timingcon_file) " + os.path.expanduser(flow_settings['synth_folder']) + "/synthesized.sdc" + "\n") - file.write("set rda_Input(ui_topcell) " + flow_settings['top_level'] + "\n\n") - gnd_pin = flow_settings['gnd_pin'] - gnd_net = flow_settings['gnd_net'] - pwr_pin = flow_settings['pwr_pin'] - pwr_net = flow_settings['pwr_net'] - file.write("set rda_Input(ui_gndnet) {" + gnd_net + "} \n") - file.write("set rda_Input(ui_pwrnet) {" + pwr_net + "} \n") - if flow_settings['tilehi_tielo_cells_between_power_gnd'] is True: - file.write("set rda_Input(ui_pg_connections) [list {PIN:" + gnd_pin + ":}" + " {TIEL::} " + "{NET:" + gnd_net + ":} {NET:" + pwr_net + ":}" + " {TIEH::} " + "{PIN:" + pwr_pin + ":} ] \n") - else: - file.write("set rda_Input(ui_pg_connections) [list {PIN:" + gnd_pin + ":} {NET:" + gnd_net + ":} {NET:" + pwr_net + ":} {PIN:" + pwr_pin + ":} ] \n") - file.write("set rda_Input(PIN:" + gnd_pin + ":) {" + gnd_pin + "} \n") - file.write("set rda_Input(TIEL::) {" + gnd_pin + "} \n") - file.write("set rda_Input(NET:" + gnd_net + ":) {" + gnd_net + "} \n") - file.write("set rda_Input(PIN:" + pwr_pin + ":) {" + pwr_pin + "} \n") - file.write("set rda_Input(TIEH::) {" + pwr_pin + "} \n") - file.write("set rda_Input(NET:" + pwr_net + ":) {" + pwr_net + "} \n\n") - if (flow_settings['inv_footprint'] != "None"): - file.write("set rda_Input(ui_inv_footprint) {" + flow_settings['inv_footprint'] + "}\n") - if (flow_settings['buf_footprint'] != "None"): - file.write("set rda_Input(ui_buf_footprint) {" + flow_settings['buf_footprint'] + "}\n") - if (flow_settings['delay_footprint'] != "None"): - file.write("set rda_Input(ui_delay_footprint) {" + flow_settings['delay_footprint'] + "}\n") - file.close() - metal_layer_bottom = flow_settings["metal_layer_names"][0] - metal_layer_second = flow_settings["metal_layer_names"][1] - metal_layer_top = flow_settings["metal_layer_names"][int(metal_layer)-1] - power_ring_metal_top = flow_settings["power_ring_metal_layer_names"][0] - power_ring_metal_bottom = flow_settings["power_ring_metal_layer_names"][1] - power_ring_metal_left = flow_settings["power_ring_metal_layer_names"][2] - power_ring_metal_right = flow_settings["power_ring_metal_layer_names"][3] - # generate the EDI (encounter) script - file = open("edi.tcl", "w") - file.write("loadConfig edi.conf \n") - file.write("floorPlan -site " + flow_settings['core_site_name'] \ - + " -r " + str(flow_settings['height_to_width_ratio']) \ - + " " + str(core_utilization) \ - + " " + str(flow_settings['space_around_core']) \ - + " " + str(flow_settings['space_around_core']) + " ") - file.write(str(flow_settings['space_around_core']) + " " + str(flow_settings['space_around_core']) + "\n") - file.write("setMaxRouteLayer " + str(metal_layer) + " \n") - file.write("fit \n") - file.write("addRing -spacing_bottom " + str(flow_settings['power_ring_spacing']) \ - + " -spacing_right " + str(flow_settings['power_ring_spacing']) \ - + " -spacing_top " + str(flow_settings['power_ring_spacing']) \ - + " -spacing_left " + str(flow_settings['power_ring_spacing']) \ - + " -width_right " + str(flow_settings['power_ring_width']) \ - + " -width_left " + str(flow_settings['power_ring_width']) \ - + " -width_bottom " + str(flow_settings['power_ring_width']) \ - + " -width_top " + str(flow_settings['power_ring_width']) \ - + " -center 1" \ - + " -around core" \ - + " -layer_top " + power_ring_metal_top \ - + " -layer_bottom " + power_ring_metal_bottom \ - + " -layer_left " + power_ring_metal_left \ - + " -layer_right " + power_ring_metal_right \ - + " -nets { " + gnd_net + " " + pwr_net + " }" \ - + " -stacked_via_top_layer "+ metal_layer_top \ - + " -stacked_via_bottom_layer " + metal_layer_bottom + " \n") - file.write("setPlaceMode -fp false -maxRouteLayer " + str(metal_layer) + "\n") - file.write("placeDesign -inPlaceOpt -noPrePlaceOpt \n") - file.write("checkPlace " + flow_settings['top_level'] +" \n") - file.write("trialroute \n") - file.write("buildTimingGraph \n") - file.write("timeDesign -preCTS -idealClock -numPaths 10 -prefix preCTS -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/timeDesignpreCTSReports" + "\n") - file.write("optDesign -preCTS -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/optDesignpreCTSReports" + "\n") - # I won't do a CTS anyway as the blocks are small. - file.write("addFiller -cell {" + " ".join([str(item) for item in flow_settings['filler_cell_names']]) + "} -prefix FILL -merge true \n") - file.write("clearGlobalNets \n") - file.write("globalNetConnect " + gnd_net + " -type pgpin -pin " + gnd_pin + " -inst {} \n") - file.write("globalNetConnect " + pwr_net + " -type pgpin -pin " + pwr_pin + " -inst {} \n") - file.write("globalNetConnect " + gnd_net + " -type net -net " + gnd_net + " \n") - file.write("globalNetConnect " + pwr_net + " -type net -net " + pwr_net + " \n") - file.write("globalNetConnect " + pwr_net + " -type pgpin -pin " + pwr_pin + " -inst * \n") - file.write("globalNetConnect " + gnd_net + " -type pgpin -pin " + gnd_pin + " -inst * \n") - file.write("globalNetConnect " + pwr_net + " -type tiehi -inst * \n") - file.write("globalNetConnect " + gnd_net + " -type tielo -inst * \n") - file.write("sroute -connect { blockPin padPin padRing corePin floatingStripe }" \ - + " -layerChangeRange { " + metal_layer_bottom + " " + metal_layer_top + " }" \ - + " -blockPinTarget { nearestRingStripe nearestTarget }" \ - + " -padPinPortConnect { allPort oneGeom }" \ - + " -checkAlignedSecondaryPin 1" \ - + " -blockPin useLef" \ - + " -allowJogging 1" \ - + " -crossoverViaBottomLayer " + metal_layer_bottom \ - + " -allowLayerChange 1" \ - + " -targetViaTopLayer " + metal_layer_top \ - + " -crossoverViaTopLayer " + metal_layer_top \ - + " -targetViaBottomLayer " + metal_layer_bottom \ - + " -nets { " + gnd_net + " " + pwr_net + " } \n") - file.write("routeDesign -globalDetail\n") - file.write("setExtractRCMode -engine postRoute \n") - file.write("extractRC \n") - file.write("buildTimingGraph \n") - file.write("timeDesign -postRoute -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/timeDesignReports" + "\n") - file.write("optDesign -postRoute -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/optDesignReports" + "\n") - #by default, violations are reported in designname.geom.rpt - file.write("verifyGeometry -report " + (os.path.expanduser(flow_settings['pr_folder']) + "/" + flow_settings['top_level'] + ".geom.rpt") + "\n") - #by default, violations are reported in designname.conn.rpt - file.write("verifyConnectivity -type all -report " + (os.path.expanduser(flow_settings['pr_folder']) + "/" + flow_settings['top_level'] + ".conn.rpt") + "\n") - # report area - file.write("summaryReport -outFile " + os.path.expanduser(flow_settings['pr_folder']) + "/pr_report.txt \n") - # save design - file.write(r'saveNetlist ' + os.path.expanduser(flow_settings['pr_folder']) + r'/netlist.v' + "\n") - file.write(r'saveDesign ' + os.path.expanduser(flow_settings['pr_folder']) + r'/design.enc' + " \n") - file.write(r'rcOut -spef ' + os.path.expanduser(flow_settings['pr_folder']) + r'/spef.spef' + " \n") - file.write(r'write_sdf -ideal_clock_network ' + os.path.expanduser(flow_settings['pr_folder']) + r'/sdf.sdf' + " \n") - #If the user specified a layer mapping file, then use that. Otherwise, just let the tool create a default one. - if flow_settings['map_file'] != "None": - file.write(r'streamOut ' + os.path.expanduser(flow_settings['pr_folder']) + r'/final.gds2' + ' -mapFile ' + flow_settings['map_file'] + ' -stripes 1 -units 1000 -mode ALL' + "\n") - else: - file.write(r'streamOut ' + os.path.expanduser(flow_settings['pr_folder']) + r'/final.gds2' + ' -stripes 1 -units 1000 -mode ALL' + "\n") + if(flow_settings["pnr_tool"] == "encounter"): + # generate the EDI (encounter) configuration + file = open("edi.conf", "w") + file.write("global rda_Input \n") + file.write("set cwd .\n\n") + file.write("set rda_Input(ui_leffile) " + flow_settings['lef_files'] + "\n") + file.write("set rda_Input(ui_timelib,min) " + flow_settings['best_case_libs'] + "\n") + file.write("set rda_Input(ui_timelib) " + flow_settings['standard_libs'] + "\n") + file.write("set rda_Input(ui_timelib,max) " + flow_settings['worst_case_libs'] + "\n") + file.write("set rda_Input(ui_netlist) " + os.path.expanduser(flow_settings['synth_folder']) + "/synthesized.v" + "\n") + file.write("set rda_Input(ui_netlisttype) {Verilog} \n") + file.write("set rda_Input(import_mode) {-treatUndefinedCellAsBbox 0 -keepEmptyModule 1}\n") + file.write("set rda_Input(ui_timingcon_file) " + os.path.expanduser(flow_settings['synth_folder']) + "/synthesized.sdc" + "\n") + file.write("set rda_Input(ui_topcell) " + flow_settings['top_level'] + "\n\n") + gnd_pin = flow_settings['gnd_pin'] + gnd_net = flow_settings['gnd_net'] + pwr_pin = flow_settings['pwr_pin'] + pwr_net = flow_settings['pwr_net'] + file.write("set rda_Input(ui_gndnet) {" + gnd_net + "} \n") + file.write("set rda_Input(ui_pwrnet) {" + pwr_net + "} \n") + if flow_settings['tilehi_tielo_cells_between_power_gnd'] is True: + file.write("set rda_Input(ui_pg_connections) [list {PIN:" + gnd_pin + ":}" + " {TIEL::} " + "{NET:" + gnd_net + ":} {NET:" + pwr_net + ":}" + " {TIEH::} " + "{PIN:" + pwr_pin + ":} ] \n") + else: + file.write("set rda_Input(ui_pg_connections) [list {PIN:" + gnd_pin + ":} {NET:" + gnd_net + ":} {NET:" + pwr_net + ":} {PIN:" + pwr_pin + ":} ] \n") + file.write("set rda_Input(PIN:" + gnd_pin + ":) {" + gnd_pin + "} \n") + file.write("set rda_Input(TIEL::) {" + gnd_pin + "} \n") + file.write("set rda_Input(NET:" + gnd_net + ":) {" + gnd_net + "} \n") + file.write("set rda_Input(PIN:" + pwr_pin + ":) {" + pwr_pin + "} \n") + file.write("set rda_Input(TIEH::) {" + pwr_pin + "} \n") + file.write("set rda_Input(NET:" + pwr_net + ":) {" + pwr_net + "} \n\n") + if (flow_settings['inv_footprint'] != "None"): + file.write("set rda_Input(ui_inv_footprint) {" + flow_settings['inv_footprint'] + "}\n") + if (flow_settings['buf_footprint'] != "None"): + file.write("set rda_Input(ui_buf_footprint) {" + flow_settings['buf_footprint'] + "}\n") + if (flow_settings['delay_footprint'] != "None"): + file.write("set rda_Input(ui_delay_footprint) {" + flow_settings['delay_footprint'] + "}\n") + file.close() + metal_layer_bottom = flow_settings["metal_layer_names"][0] + metal_layer_second = flow_settings["metal_layer_names"][1] + metal_layer_top = flow_settings["metal_layer_names"][int(metal_layer)-1] + power_ring_metal_top = flow_settings["power_ring_metal_layer_names"][0] + power_ring_metal_bottom = flow_settings["power_ring_metal_layer_names"][1] + power_ring_metal_left = flow_settings["power_ring_metal_layer_names"][2] + power_ring_metal_right = flow_settings["power_ring_metal_layer_names"][3] + # generate the EDI (encounter) script + file = open("edi.tcl", "w") + file.write("loadConfig edi.conf \n") + file.write("floorPlan -site " + flow_settings['core_site_name'] \ + + " -r " + str(flow_settings['height_to_width_ratio']) \ + + " " + str(core_utilization) \ + + " " + str(flow_settings['space_around_core']) \ + + " " + str(flow_settings['space_around_core']) + " ") + file.write(str(flow_settings['space_around_core']) + " " + str(flow_settings['space_around_core']) + "\n") + file.write("setMaxRouteLayer " + str(metal_layer) + " \n") + file.write("fit \n") + file.write("addRing -spacing_bottom " + str(flow_settings['power_ring_spacing']) \ + + " -spacing_right " + str(flow_settings['power_ring_spacing']) \ + + " -spacing_top " + str(flow_settings['power_ring_spacing']) \ + + " -spacing_left " + str(flow_settings['power_ring_spacing']) \ + + " -width_right " + str(flow_settings['power_ring_width']) \ + + " -width_left " + str(flow_settings['power_ring_width']) \ + + " -width_bottom " + str(flow_settings['power_ring_width']) \ + + " -width_top " + str(flow_settings['power_ring_width']) \ + + " -center 1" \ + + " -around core" \ + + " -layer_top " + power_ring_metal_top \ + + " -layer_bottom " + power_ring_metal_bottom \ + + " -layer_left " + power_ring_metal_left \ + + " -layer_right " + power_ring_metal_right \ + + " -nets { " + gnd_net + " " + pwr_net + " }" \ + + " -stacked_via_top_layer "+ metal_layer_top \ + + " -stacked_via_bottom_layer " + metal_layer_bottom + " \n") + file.write("setPlaceMode -fp false -maxRouteLayer " + str(metal_layer) + "\n") + file.write("placeDesign -inPlaceOpt -noPrePlaceOpt \n") + file.write("checkPlace " + flow_settings['top_level'] +" \n") + file.write("trialroute \n") + file.write("buildTimingGraph \n") + file.write("timeDesign -preCTS -idealClock -numPaths 10 -prefix preCTS -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/timeDesignpreCTSReports" + "\n") + file.write("optDesign -preCTS -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/optDesignpreCTSReports" + "\n") + # I won't do a CTS anyway as the blocks are small. + file.write("addFiller -cell {" + " ".join([str(item) for item in flow_settings['filler_cell_names']]) + "} -prefix FILL -merge true \n") + file.write("clearGlobalNets \n") + file.write("globalNetConnect " + gnd_net + " -type pgpin -pin " + gnd_pin + " -inst {} \n") + file.write("globalNetConnect " + pwr_net + " -type pgpin -pin " + pwr_pin + " -inst {} \n") + file.write("globalNetConnect " + gnd_net + " -type net -net " + gnd_net + " \n") + file.write("globalNetConnect " + pwr_net + " -type net -net " + pwr_net + " \n") + file.write("globalNetConnect " + pwr_net + " -type pgpin -pin " + pwr_pin + " -inst * \n") + file.write("globalNetConnect " + gnd_net + " -type pgpin -pin " + gnd_pin + " -inst * \n") + file.write("globalNetConnect " + pwr_net + " -type tiehi -inst * \n") + file.write("globalNetConnect " + gnd_net + " -type tielo -inst * \n") + file.write("sroute -connect { blockPin padPin padRing corePin floatingStripe }" \ + + " -layerChangeRange { " + metal_layer_bottom + " " + metal_layer_top + " }" \ + + " -blockPinTarget { nearestRingStripe nearestTarget }" \ + + " -padPinPortConnect { allPort oneGeom }" \ + + " -checkAlignedSecondaryPin 1" \ + + " -blockPin useLef" \ + + " -allowJogging 1" \ + + " -crossoverViaBottomLayer " + metal_layer_bottom \ + + " -allowLayerChange 1" \ + + " -targetViaTopLayer " + metal_layer_top \ + + " -crossoverViaTopLayer " + metal_layer_top \ + + " -targetViaBottomLayer " + metal_layer_bottom \ + + " -nets { " + gnd_net + " " + pwr_net + " } \n") + file.write("routeDesign -globalDetail\n") + file.write("setExtractRCMode -engine postRoute \n") + file.write("extractRC \n") + file.write("buildTimingGraph \n") + file.write("timeDesign -postRoute -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/timeDesignReports" + "\n") + file.write("optDesign -postRoute -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/optDesignReports" + "\n") + #by default, violations are reported in designname.geom.rpt + file.write("verifyGeometry -report " + (os.path.expanduser(flow_settings['pr_folder']) + "/" + flow_settings['top_level'] + ".geom.rpt") + "\n") + #by default, violations are reported in designname.conn.rpt + file.write("verifyConnectivity -type all -report " + (os.path.expanduser(flow_settings['pr_folder']) + "/" + flow_settings['top_level'] + ".conn.rpt") + "\n") + # report area + file.write("summaryReport -outFile " + os.path.expanduser(flow_settings['pr_folder']) + "/pr_report.txt \n") + # save design + file.write(r'saveNetlist ' + os.path.expanduser(flow_settings['pr_folder']) + r'/netlist.v' + "\n") + file.write(r'saveDesign ' + os.path.expanduser(flow_settings['pr_folder']) + r'/design.enc' + " \n") + file.write(r'rcOut -spef ' + os.path.expanduser(flow_settings['pr_folder']) + r'/spef.spef' + " \n") + file.write(r'write_sdf -ideal_clock_network ' + os.path.expanduser(flow_settings['pr_folder']) + r'/sdf.sdf' + " \n") + #If the user specified a layer mapping file, then use that. Otherwise, just let the tool create a default one. + if flow_settings['map_file'] != "None": + file.write(r'streamOut ' + os.path.expanduser(flow_settings['pr_folder']) + r'/final.gds2' + ' -mapFile ' + flow_settings['map_file'] + ' -stripes 1 -units 1000 -mode ALL' + "\n") + else: + file.write(r'streamOut ' + os.path.expanduser(flow_settings['pr_folder']) + r'/final.gds2' + ' -stripes 1 -units 1000 -mode ALL' + "\n") + elif(flow_settings["pnr_tool"] == "innovus"): + + """ + ###### 10/17/2022 11:00pm ###### + setDesignMode -process 65 + floorPlan -site core -r 4.0 0.85 10 10 10 10 + setDesignMode -topRoutingLayer 7 + earlyGlobalRoute + timeDesign -preCTS -idealClock -numPaths 10 -prefix preCTS -outDir /fs1/eecg/vaughn/morestep/COFFE/output_files/strtx_III_dsp/pr/timeDesignpreCTSReports + optDesign -preCTS -outDir /fs1/eecg/vaughn/morestep/COFFE/output_files/strtx_III_dsp/pr/optDesignpreCTSReports + addFiller -cell {FILL1 FILL16 FILL1_LL FILL2 FILL32 FILL64 FILL8 FILL_NW_FA_LL FILL_NW_HH FILL_NW_LL} -prefix FILL -merge true + clearGlobalNets + globalNetConnect VSS -type pgpin -pin VSS -inst {} + globalNetConnect VDD -type pgpin -pin VDD -inst {} + globalNetConnect VSS -type net -net VSS + globalNetConnect VDD -type net -net VDD + globalNetConnect VDD -type pgpin -pin VDD -inst * + globalNetConnect VSS -type pgpin -pin VSS -inst * + globalNetConnect VDD -type tiehi -inst * + globalNetConnect VSS -type tielo -inst * + sroute -connect { blockPin padPin padRing corePin floatingStripe } -layerChangeRange { M1 M7 } -blockPinTarget { nearestRingStripe nearestTarget } -padPinPortConnect { allPort oneGeom } -checkAlignedSecondaryPin 1 -blockPin useLef -allowJogging 1 -crossoverViaBottomLayer M1 -allowLayerChange 1 -targetViaTopLayer M7 -crossoverViaTopLayer M7 -targetViaBottomLayer M1 -nets { VSS VDD } + routeDesign -globalDetail + setExtractRCMode -engine postRoute + extractRC + buildTimingGraph + setAnalysisMode -analysisType onChipVariation -cppr both + timeDesign -postRoute -outDir /fs1/eecg/vaughn/morestep/COFFE/output_files/strtx_III_dsp/pr/timeDesignReports + optDesign -postRoute -outDir /fs1/eecg/vaughn/morestep/COFFE/output_files/strtx_III_dsp/pr/optDesignReports + #setRouteMode -earlyGlobalMaxRouteLayer 7 (this command does same as top command) + """ file.write("exit \n") file.close() def run_pnr(flow_settings,metal_layer,core_utilization,synth_report_str): @@ -344,7 +406,8 @@ def run_sim(): def write_pt_power_script(flow_settings,mode_enabled,clock_period,x): """" - writes the tcl script for timing analysis using Synopsys Design Compiler, tested under 2017 version + writes the tcl script for power analysis using Synopsys Design Compiler, tested under 2017 version + Update: changed the [all_nets] argument used in set_switching_activity to use -baseClk and -inputs args instead """ # Create a script to measure power: file = open("primetime_power.tcl", "w") @@ -379,7 +442,9 @@ def write_pt_power_script(flow_settings,mode_enabled,clock_period,x): file.close() def write_pt_timing_script(flow_settings,mode_enabled,clock_period,x): - """""" + """ + writes the tcl script for timing analysis using Synopsys Design Compiler, tested under 2017 version + """ # backannotate into primetime # This part should be reported for all the modes in the design. file = open("primetime.tcl", "w") @@ -537,6 +602,7 @@ def hardblock_flow(flow_settings): # Optional: use modelsim to generate an activity file for the design: if flow_settings['generate_activity_file'] is True: run_sim() + #loops over every combination of user inputted modes to set the set_case_analysis value (determines value of mode mux) for x in range(0, 2**len(flow_settings['mode_signal']) + 1): library_setup_time, data_arrival_time, total_delay, total_dynamic_power = run_power_timing(flow_settings,mode_enabled,clock_period,x,pnr_report_str) # write the final report file: diff --git a/coffe/utils.py b/coffe/utils.py index 50114c1..eef2664 100644 --- a/coffe/utils.py +++ b/coffe/utils.py @@ -769,8 +769,8 @@ def load_hard_params(filename): 'mode_signal': [], 'process_lib_paths': [], 'process_params_file': "", - #'pnr_tool': "", - #'process_size': "", + 'pnr_tool': "", + 'process_size': "", } hard_file = open(filename, 'r') @@ -876,10 +876,10 @@ def load_hard_params(filename): hard_params['mode_signal'].append(value) elif param == "process_params_file": hard_params["process_params_file"] = value - # elif param == "pnr_tool": - # hard_params["pnr_tool"] = value - # elif param == "process_size": - # hard_params["process_size"] = value + elif param == "pnr_tool": + hard_params["pnr_tool"] = value + elif param == "process_size": + hard_params["process_size"] = value #To allow for the legacy way of inputting process specific params I'll keep these in (the only reason for having a seperate file is for understandability) if param == "process_lib_paths": hard_params["process_lib_paths"] = sanatize_str_input_to_list(value) From 9b1a362bc10d5f2cbe18dc509d80fc59e41694d2 Mon Sep 17 00:00:00 2001 From: Stephen More Date: Mon, 24 Oct 2022 08:24:13 -0400 Subject: [PATCH 03/10] innovus support changes --- coffe/hardblock_functions.py | 474 +++++++++++------- coffe/utils.py | 6 +- input_files/strtx_III_dsp/dsp_hb_settings.txt | 23 +- .../strtx_III_dsp/process_specific_params.txt | 8 +- 4 files changed, 318 insertions(+), 193 deletions(-) diff --git a/coffe/hardblock_functions.py b/coffe/hardblock_functions.py index 55dabc0..371973a 100644 --- a/coffe/hardblock_functions.py +++ b/coffe/hardblock_functions.py @@ -85,7 +85,7 @@ def run_synth(flow_settings,clock_period,wire_selection): """ write_synth_tcl(flow_settings,clock_period,wire_selection) # Run the scrip in design compiler shell - subprocess.call('dc_shell-t -f dc_script.tcl | tee dc.log', shell=True,executable="/bin/bash") + subprocess.call('dc_shell-t -f dc_script.tcl | tee dc.log', shell=True,executable="/bin/bash") # clean after DC! subprocess.call('rm -rf command.log', shell=True) subprocess.call('rm -rf default.svf', shell=True) @@ -107,7 +107,7 @@ def run_synth(flow_settings,clock_period,wire_selection): synth_report_str = "period_" + clock_period + "_" + "wire_mdl_" + wire_selection report_dest_str = flow_settings['synth_folder'] + "/" + synth_report_str + "_reports" mkdir_cmd_str = "mkdir -p " + report_dest_str - copy_rep_cmd_str = "cp " + flow_settings['synth_folder'] + "/*.rpt " + report_dest_str + copy_rep_cmd_str = "cp " + flow_settings['synth_folder'] + "/* " + report_dest_str copy_logs_cmd_str = "cp " + "dc.log "+ "dc_script.tcl " + report_dest_str subprocess.call(mkdir_cmd_str,shell=True) subprocess.call(copy_rep_cmd_str,shell=True) @@ -157,12 +157,14 @@ def run_synth(flow_settings,clock_period,wire_selection): exit() return synth_report_str +def file_write_ln(fd, line): + fd.write(line + "\n") def write_innovus_view_file(flow_settings): """Write .view file for innovus place and route, this is used for for creating the delay corners from timing libs and importings constraints""" - view_fname = flow_settings["top_level"] - file = open(flow_settings["top_level"]+".view","w") - file.write("# Version:1.0 MMMC View Definition File\n# Do Not Remove Above Line") + fname = flow_settings["top_level"]+".view" + file = open(fname,"w") + file.write("# Version:1.0 MMMC View Definition File\n# Do Not Remove Above Line\n") #I created a typical delay corner but I don't think its being used as its not called in create_analysis_view command, however, may be useful? not sure but its here #One could put RC values (maybe temperature in here) later for now they will all be the same file.write("create_rc_corner -name RC_BEST -preRoute_res {1.0} -preRoute_cap {1.0} -preRoute_clkres {0.0} -preRoute_clkcap {0.0} -postRoute_res {1.0} -postRoute_cap {1.0} -postRoute_xcap {1.0} -postRoute_clkres {0.0} -postRoute_clkcap {0.0}"+ "\n") @@ -183,169 +185,269 @@ def write_innovus_view_file(flow_settings): #This sets our analysis view to be using our worst case analysis view for setup and best for timing, #This makes sense as the BC libs would have the most severe hold violations and vice versa for setup file.write("set_analysis_view -setup {WORST_CASE} -hold {BEST_CASE}" + "\n") + file.close() + return fname -def write_innovus_globals(flow_settings): - print('tes') -def write_pnr_script(flow_settings,metal_layer,core_utilization): - """" - writes the tcl script for place and route using Cadence Encounter, tested under 2009 version - """ - if(flow_settings["pnr_tool"] == "encounter"): - # generate the EDI (encounter) configuration - file = open("edi.conf", "w") - file.write("global rda_Input \n") - file.write("set cwd .\n\n") - file.write("set rda_Input(ui_leffile) " + flow_settings['lef_files'] + "\n") - file.write("set rda_Input(ui_timelib,min) " + flow_settings['best_case_libs'] + "\n") - file.write("set rda_Input(ui_timelib) " + flow_settings['standard_libs'] + "\n") - file.write("set rda_Input(ui_timelib,max) " + flow_settings['worst_case_libs'] + "\n") - file.write("set rda_Input(ui_netlist) " + os.path.expanduser(flow_settings['synth_folder']) + "/synthesized.v" + "\n") - file.write("set rda_Input(ui_netlisttype) {Verilog} \n") - file.write("set rda_Input(import_mode) {-treatUndefinedCellAsBbox 0 -keepEmptyModule 1}\n") - file.write("set rda_Input(ui_timingcon_file) " + os.path.expanduser(flow_settings['synth_folder']) + "/synthesized.sdc" + "\n") - file.write("set rda_Input(ui_topcell) " + flow_settings['top_level'] + "\n\n") - gnd_pin = flow_settings['gnd_pin'] - gnd_net = flow_settings['gnd_net'] - pwr_pin = flow_settings['pwr_pin'] - pwr_net = flow_settings['pwr_net'] - file.write("set rda_Input(ui_gndnet) {" + gnd_net + "} \n") - file.write("set rda_Input(ui_pwrnet) {" + pwr_net + "} \n") - if flow_settings['tilehi_tielo_cells_between_power_gnd'] is True: - file.write("set rda_Input(ui_pg_connections) [list {PIN:" + gnd_pin + ":}" + " {TIEL::} " + "{NET:" + gnd_net + ":} {NET:" + pwr_net + ":}" + " {TIEH::} " + "{PIN:" + pwr_pin + ":} ] \n") - else: - file.write("set rda_Input(ui_pg_connections) [list {PIN:" + gnd_pin + ":} {NET:" + gnd_net + ":} {NET:" + pwr_net + ":} {PIN:" + pwr_pin + ":} ] \n") - file.write("set rda_Input(PIN:" + gnd_pin + ":) {" + gnd_pin + "} \n") - file.write("set rda_Input(TIEL::) {" + gnd_pin + "} \n") - file.write("set rda_Input(NET:" + gnd_net + ":) {" + gnd_net + "} \n") - file.write("set rda_Input(PIN:" + pwr_pin + ":) {" + pwr_pin + "} \n") - file.write("set rda_Input(TIEH::) {" + pwr_pin + "} \n") - file.write("set rda_Input(NET:" + pwr_net + ":) {" + pwr_net + "} \n\n") - if (flow_settings['inv_footprint'] != "None"): - file.write("set rda_Input(ui_inv_footprint) {" + flow_settings['inv_footprint'] + "}\n") - if (flow_settings['buf_footprint'] != "None"): - file.write("set rda_Input(ui_buf_footprint) {" + flow_settings['buf_footprint'] + "}\n") - if (flow_settings['delay_footprint'] != "None"): - file.write("set rda_Input(ui_delay_footprint) {" + flow_settings['delay_footprint'] + "}\n") - file.close() - metal_layer_bottom = flow_settings["metal_layer_names"][0] - metal_layer_second = flow_settings["metal_layer_names"][1] - metal_layer_top = flow_settings["metal_layer_names"][int(metal_layer)-1] - power_ring_metal_top = flow_settings["power_ring_metal_layer_names"][0] - power_ring_metal_bottom = flow_settings["power_ring_metal_layer_names"][1] - power_ring_metal_left = flow_settings["power_ring_metal_layer_names"][2] - power_ring_metal_right = flow_settings["power_ring_metal_layer_names"][3] - # generate the EDI (encounter) script - file = open("edi.tcl", "w") - file.write("loadConfig edi.conf \n") - file.write("floorPlan -site " + flow_settings['core_site_name'] \ - + " -r " + str(flow_settings['height_to_width_ratio']) \ - + " " + str(core_utilization) \ - + " " + str(flow_settings['space_around_core']) \ - + " " + str(flow_settings['space_around_core']) + " ") - file.write(str(flow_settings['space_around_core']) + " " + str(flow_settings['space_around_core']) + "\n") - file.write("setMaxRouteLayer " + str(metal_layer) + " \n") - file.write("fit \n") - file.write("addRing -spacing_bottom " + str(flow_settings['power_ring_spacing']) \ - + " -spacing_right " + str(flow_settings['power_ring_spacing']) \ - + " -spacing_top " + str(flow_settings['power_ring_spacing']) \ - + " -spacing_left " + str(flow_settings['power_ring_spacing']) \ - + " -width_right " + str(flow_settings['power_ring_width']) \ - + " -width_left " + str(flow_settings['power_ring_width']) \ - + " -width_bottom " + str(flow_settings['power_ring_width']) \ - + " -width_top " + str(flow_settings['power_ring_width']) \ - + " -center 1" \ - + " -around core" \ - + " -layer_top " + power_ring_metal_top \ - + " -layer_bottom " + power_ring_metal_bottom \ - + " -layer_left " + power_ring_metal_left \ - + " -layer_right " + power_ring_metal_right \ - + " -nets { " + gnd_net + " " + pwr_net + " }" \ - + " -stacked_via_top_layer "+ metal_layer_top \ - + " -stacked_via_bottom_layer " + metal_layer_bottom + " \n") - file.write("setPlaceMode -fp false -maxRouteLayer " + str(metal_layer) + "\n") - file.write("placeDesign -inPlaceOpt -noPrePlaceOpt \n") - file.write("checkPlace " + flow_settings['top_level'] +" \n") - file.write("trialroute \n") - file.write("buildTimingGraph \n") - file.write("timeDesign -preCTS -idealClock -numPaths 10 -prefix preCTS -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/timeDesignpreCTSReports" + "\n") - file.write("optDesign -preCTS -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/optDesignpreCTSReports" + "\n") - # I won't do a CTS anyway as the blocks are small. - file.write("addFiller -cell {" + " ".join([str(item) for item in flow_settings['filler_cell_names']]) + "} -prefix FILL -merge true \n") - file.write("clearGlobalNets \n") - file.write("globalNetConnect " + gnd_net + " -type pgpin -pin " + gnd_pin + " -inst {} \n") - file.write("globalNetConnect " + pwr_net + " -type pgpin -pin " + pwr_pin + " -inst {} \n") - file.write("globalNetConnect " + gnd_net + " -type net -net " + gnd_net + " \n") - file.write("globalNetConnect " + pwr_net + " -type net -net " + pwr_net + " \n") - file.write("globalNetConnect " + pwr_net + " -type pgpin -pin " + pwr_pin + " -inst * \n") - file.write("globalNetConnect " + gnd_net + " -type pgpin -pin " + gnd_pin + " -inst * \n") - file.write("globalNetConnect " + pwr_net + " -type tiehi -inst * \n") - file.write("globalNetConnect " + gnd_net + " -type tielo -inst * \n") - file.write("sroute -connect { blockPin padPin padRing corePin floatingStripe }" \ - + " -layerChangeRange { " + metal_layer_bottom + " " + metal_layer_top + " }" \ - + " -blockPinTarget { nearestRingStripe nearestTarget }" \ - + " -padPinPortConnect { allPort oneGeom }" \ - + " -checkAlignedSecondaryPin 1" \ - + " -blockPin useLef" \ - + " -allowJogging 1" \ - + " -crossoverViaBottomLayer " + metal_layer_bottom \ - + " -allowLayerChange 1" \ - + " -targetViaTopLayer " + metal_layer_top \ - + " -crossoverViaTopLayer " + metal_layer_top \ - + " -targetViaBottomLayer " + metal_layer_bottom \ - + " -nets { " + gnd_net + " " + pwr_net + " } \n") - file.write("routeDesign -globalDetail\n") - file.write("setExtractRCMode -engine postRoute \n") - file.write("extractRC \n") - file.write("buildTimingGraph \n") - file.write("timeDesign -postRoute -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/timeDesignReports" + "\n") - file.write("optDesign -postRoute -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/optDesignReports" + "\n") - #by default, violations are reported in designname.geom.rpt - file.write("verifyGeometry -report " + (os.path.expanduser(flow_settings['pr_folder']) + "/" + flow_settings['top_level'] + ".geom.rpt") + "\n") - #by default, violations are reported in designname.conn.rpt - file.write("verifyConnectivity -type all -report " + (os.path.expanduser(flow_settings['pr_folder']) + "/" + flow_settings['top_level'] + ".conn.rpt") + "\n") - # report area - file.write("summaryReport -outFile " + os.path.expanduser(flow_settings['pr_folder']) + "/pr_report.txt \n") - # save design - file.write(r'saveNetlist ' + os.path.expanduser(flow_settings['pr_folder']) + r'/netlist.v' + "\n") - file.write(r'saveDesign ' + os.path.expanduser(flow_settings['pr_folder']) + r'/design.enc' + " \n") - file.write(r'rcOut -spef ' + os.path.expanduser(flow_settings['pr_folder']) + r'/spef.spef' + " \n") - file.write(r'write_sdf -ideal_clock_network ' + os.path.expanduser(flow_settings['pr_folder']) + r'/sdf.sdf' + " \n") - #If the user specified a layer mapping file, then use that. Otherwise, just let the tool create a default one. - if flow_settings['map_file'] != "None": - file.write(r'streamOut ' + os.path.expanduser(flow_settings['pr_folder']) + r'/final.gds2' + ' -mapFile ' + flow_settings['map_file'] + ' -stripes 1 -units 1000 -mode ALL' + "\n") - else: - file.write(r'streamOut ' + os.path.expanduser(flow_settings['pr_folder']) + r'/final.gds2' + ' -stripes 1 -units 1000 -mode ALL' + "\n") - elif(flow_settings["pnr_tool"] == "innovus"): +def write_innovus_script(flow_settings,metal_layer,core_utilization,init_script_fname): + #some format adjustment (could move to preproc function) + core_utilization = str(core_utilization) + metal_layer = str(metal_layer) + flow_settings["power_ring_spacing"] = str(flow_settings["power_ring_spacing"]) + + metal_layer_bottom = flow_settings["metal_layer_names"][0] + metal_layer_second = flow_settings["metal_layer_names"][1] + metal_layer_top = flow_settings["metal_layer_names"][int(metal_layer)-1] + power_ring_metal_top = flow_settings["power_ring_metal_layer_names"][0] + power_ring_metal_bottom = flow_settings["power_ring_metal_layer_names"][1] + power_ring_metal_left = flow_settings["power_ring_metal_layer_names"][2] + power_ring_metal_right = flow_settings["power_ring_metal_layer_names"][3] + #output files + output_files = [] + fname = flow_settings["top_level"] + "_innovus.tcl" + file = open(fname,"w") + file_lines = [ + "source " + init_script_fname, + "setDesignMode -process " + flow_settings["process_size"], + "floorPlan -site " + + " ".join([flow_settings["core_site_name"], + "-r",flow_settings["height_to_width_ratio"],core_utilization, + flow_settings["space_around_core"], + flow_settings["space_around_core"], + flow_settings["space_around_core"], + flow_settings["space_around_core"]]), + "setDesignMode -topRoutingLayer " + metal_layer, + "fit", + # "addRing -type core_rings -nets {VDD VSS} -layer {top M1 bottom M1 left M2 right M2} -width 3 -spacing 3 -offset 3 -follow io" + " ".join(["addRing", "-type core_rings","-nets","{" + " ".join([flow_settings["pwr_net"],flow_settings["gnd_net"]]) + "}", + "-layer {" + " ".join(["top",metal_layer_bottom,"bottom",metal_layer_bottom,"left",metal_layer_second,"right",metal_layer_second]) + "}", + "-width", flow_settings["power_ring_width"], + "-spacing", flow_settings["power_ring_spacing"], + "-offset", flow_settings["power_ring_width"], + "-follow io"]), + "setPlaceMode -fp false", + "place_design -noPrePlaceOpt", + "earlyGlobalRoute", + "timeDesign -preCTS -idealClock -numPaths 10 -prefix preCTS -outDir " + os.path.join(flow_settings["pr_folder"],"timeDesignpreCTSReports"), + "optDesign -preCTS -outDir " + os.path.join(flow_settings["pr_folder"],"optDesignpreCTSReports"), + "addFiller -cell {" + " ".join(flow_settings["filler_cell_names"]) + "} -prefix FILL -merge true", + "clearGlobalNets", + "globalNetConnect " + flow_settings["gnd_pin"] + " -type pgpin -pin " + flow_settings["gnd_pin"] + " -inst {}", + "globalNetConnect " + flow_settings["pwr_pin"] + " -type pgpin -pin " + flow_settings["pwr_pin"] + " -inst {}", + "globalNetConnect " + flow_settings["gnd_net"] + " -type net -net " + flow_settings["gnd_net"], + "globalNetConnect " + flow_settings["pwr_net"] + " -type net -net " + flow_settings["pwr_net"], + "globalNetConnect " + flow_settings["pwr_pin"] + " -type pgpin -pin " + flow_settings["pwr_pin"] + " -inst *", + "globalNetConnect " + flow_settings["gnd_pin"] + " -type pgpin -pin " + flow_settings["gnd_pin"] + " -inst *", + "globalNetConnect " + flow_settings["pwr_pin"] + " -type tiehi -inst *", + "globalNetConnect " + flow_settings["gnd_pin"] + " -type tielo -inst *", + "sroute -connect { blockPin padPin padRing corePin floatingStripe } -layerChangeRange { "+ " ".join([metal_layer_bottom,metal_layer_top]) + " }"\ + + " -blockPinTarget { nearestRingStripe nearestTarget } -padPinPortConnect { allPort oneGeom } -checkAlignedSecondaryPin 1 -blockPin useLef -allowJogging 1"\ + + " -crossoverViaBottomLayer " + metal_layer_bottom + " -targetViaBottomLayer " + metal_layer_bottom + " -allowLayerChange 1"\ + + " -targetViaTopLayer " + metal_layer_top + " -crossoverViaTopLayer " + metal_layer_top + " -nets {" + " ".join([flow_settings["gnd_net"],flow_settings["pwr_net"]]) + "}", + "routeDesign -globalDetail", + "setExtractRCMode -engine postRoute", + "extractRC", + "buildTimingGraph", + "setAnalysisMode -analysisType onChipVariation -cppr both", + "timeDesign -postRoute -outDir " + os.path.join(flow_settings["pr_folder"],"timeDesignReports"), + "optDesign -postRoute -outDir " + os.path.join(flow_settings["pr_folder"],"optDesignReports"), + "verify_drc -report " + os.path.join(flow_settings["pr_folder"],"geom.rpt"), + "verifyConnectivity -type all -report " + os.path.join(flow_settings["pr_folder"],"conn.rpt"), + "report_timing > " + os.path.join(flow_settings["pr_folder"],flow_settings["top_level"] +"setup_timing.rpt"), + "setAnalysisMode -checkType hold", + "report_timing > " + os.path.join(flow_settings["pr_folder"],"hold_timing.rpt"), + "report_power > " + os.path.join(flow_settings["pr_folder"],"power.rpt"), + "report_constraint -all_violators > " + os.path.join(flow_settings["pr_folder"],"violators.rpt"), + "summaryReport -outFile " + os.path.join(flow_settings["pr_folder"],"pr_report.txt"), + "saveNetlist " + os.path.join(flow_settings["pr_folder"],"netlist.v"), + "saveDesign " + os.path.join(flow_settings["pr_folder"],"design.enc"), + "rcOut -spef " + os.path.join(flow_settings["pr_folder"],"spef.spef"), + "write_sdf -ideal_clock_network " + os.path.join(flow_settings["pr_folder"],"sdf.sdf"), + "exit"] + #If the user specified a layer mapping file, then use that. Otherwise, just let the tool create a default one. + if flow_settings['map_file'] != "None": + file_lines.append("streamOut " + os.path.join(flow_settings["pr_folder"],"final.gds2") + " -mapFile " + flow_settings["map_file"] + " -stripes 1 -units 1000 -mode ALL") + else: + file_lines.append("streamOut " + os.path.join(flow_settings["pr_folder"],"final.gds2") + " -stripes 1 -units 1000 -mode ALL") + for line in file_lines: + file_write_ln(file,line) + file.close() + return fname + +def write_innovus_init_script(flow_settings,view_fname): + flow_settings["lef_files"] = flow_settings["lef_files"].strip("\"") + fname = flow_settings["top_level"]+"_innovus_init.tcl" + file = open(fname,"w") + file_lines = [ + "set_global _enable_mmmc_by_default_flow $CTE::mmmc_default", + "suppressMessage ENCEXT-2799", + "set ::TimeLib::tsgMarkCellLatchConstructFlag 1", + "set conf_qxconf_file NULL", + "set conf_qxlib_file NULL", + "set dbgDualViewAwareXTree 1", + "set defHierChar /", + "set distributed_client_message_echo 1", + "set distributed_mmmc_disable_reports_auto_redirection 0", + "set dlgflprecConfigFile /CMC/tools/cadence/INNOVUS21.12.000_lnx86/tools.lnx86/dlApp/run_flprec.cfg", + "set enable_ilm_dual_view_gui_and_attribute 1", + "set enc_enable_print_mode_command_reset_options 1", + "set init_design_settop 0", + "set init_gnd_net " + flow_settings["gnd_net"], + #/CMC/kits/tsmc_65nm_libs/tcbn65gplus/TSMCHOME/digital/Back_End/lef/tcbn65gplus_200a/lef/tcbn65gplus_9lmT2.lef /CMC/kits/tsmc_65nm_libs/tpzn65gpgv2/TSMCHOME/digital/Back_End/lef/tpzn65gpgv2_140c/mt_2/9lm/lef/antenna_9lm.lef /CMC/kits/tsmc_65nm_libs/tpzn65gpgv2/TSMCHOME/digital/Back_End/lef/tpzn65gpgv2_140c/mt_2/9lm/lef/tpzn65gpgv2_9lm.lef + "set init_lef_file {" + flow_settings["lef_files"] + "}", + "set init_mmmc_file {" + view_fname + "}", + "set init_pwr_net " + flow_settings["pwr_net"], + "set init_top_cell " + flow_settings["top_level"], + "set init_verilog ../synth/synthesized.v", + "get_message -id GLOBAL-100 -suppress", + "get_message -id GLOBAL-100 -suppress", + "set latch_time_borrow_mode max_borrow", + "set pegDefaultResScaleFactor 1", + "set pegDetailResScaleFactor 1", + "set pegEnableDualViewForTQuantus 1", + "get_message -id GLOBAL-100 -suppress", + "get_message -id GLOBAL-100 -suppress", + "set report_inactive_arcs_format {from to when arc_type sense reason}", + "set spgUnflattenIlmInCheckPlace 2", + "get_message -id GLOBAL-100 -suppress", + "get_message -id GLOBAL-100 -suppress", + "set timing_remove_data_path_pessimism_min_slack_threshold -1.70141e+38", + "set defStreamOutCheckUncolored false", + "set init_verilog_tolerate_port_mismatch 0", + "set load_netlist_ignore_undefined_cell 1", + "init_design" + ] + for line in file_lines: + file_write_ln(file,line) + file.close() + return fname + - """ - ###### 10/17/2022 11:00pm ###### - setDesignMode -process 65 - floorPlan -site core -r 4.0 0.85 10 10 10 10 - setDesignMode -topRoutingLayer 7 - earlyGlobalRoute - timeDesign -preCTS -idealClock -numPaths 10 -prefix preCTS -outDir /fs1/eecg/vaughn/morestep/COFFE/output_files/strtx_III_dsp/pr/timeDesignpreCTSReports - optDesign -preCTS -outDir /fs1/eecg/vaughn/morestep/COFFE/output_files/strtx_III_dsp/pr/optDesignpreCTSReports - addFiller -cell {FILL1 FILL16 FILL1_LL FILL2 FILL32 FILL64 FILL8 FILL_NW_FA_LL FILL_NW_HH FILL_NW_LL} -prefix FILL -merge true - clearGlobalNets - globalNetConnect VSS -type pgpin -pin VSS -inst {} - globalNetConnect VDD -type pgpin -pin VDD -inst {} - globalNetConnect VSS -type net -net VSS - globalNetConnect VDD -type net -net VDD - globalNetConnect VDD -type pgpin -pin VDD -inst * - globalNetConnect VSS -type pgpin -pin VSS -inst * - globalNetConnect VDD -type tiehi -inst * - globalNetConnect VSS -type tielo -inst * - sroute -connect { blockPin padPin padRing corePin floatingStripe } -layerChangeRange { M1 M7 } -blockPinTarget { nearestRingStripe nearestTarget } -padPinPortConnect { allPort oneGeom } -checkAlignedSecondaryPin 1 -blockPin useLef -allowJogging 1 -crossoverViaBottomLayer M1 -allowLayerChange 1 -targetViaTopLayer M7 -crossoverViaTopLayer M7 -targetViaBottomLayer M1 -nets { VSS VDD } - routeDesign -globalDetail - setExtractRCMode -engine postRoute - extractRC - buildTimingGraph - setAnalysisMode -analysisType onChipVariation -cppr both - timeDesign -postRoute -outDir /fs1/eecg/vaughn/morestep/COFFE/output_files/strtx_III_dsp/pr/timeDesignReports - optDesign -postRoute -outDir /fs1/eecg/vaughn/morestep/COFFE/output_files/strtx_III_dsp/pr/optDesignReports - #setRouteMode -earlyGlobalMaxRouteLayer 7 (this command does same as top command) - """ +def write_enc_script(flow_settings,metal_layer,core_utilization,synth_report_str): + # generate the EDI (encounter) configuration + file = open("edi.conf", "w") + file.write("global rda_Input \n") + file.write("set cwd .\n\n") + file.write("set rda_Input(ui_leffile) " + flow_settings['lef_files'] + "\n") + file.write("set rda_Input(ui_timelib,min) " + flow_settings['best_case_libs'] + "\n") + file.write("set rda_Input(ui_timelib) " + flow_settings['standard_libs'] + "\n") + file.write("set rda_Input(ui_timelib,max) " + flow_settings['worst_case_libs'] + "\n") + file.write("set rda_Input(ui_netlist) " + os.path.expanduser(flow_settings['synth_folder']) + "/synthesized.v" + "\n") + file.write("set rda_Input(ui_netlisttype) {Verilog} \n") + file.write("set rda_Input(import_mode) {-treatUndefinedCellAsBbox 0 -keepEmptyModule 1}\n") + file.write("set rda_Input(ui_timingcon_file) " + os.path.expanduser(flow_settings['synth_folder']) + "/synthesized.sdc" + "\n") + file.write("set rda_Input(ui_topcell) " + flow_settings['top_level'] + "\n\n") + gnd_pin = flow_settings['gnd_pin'] + gnd_net = flow_settings['gnd_net'] + pwr_pin = flow_settings['pwr_pin'] + pwr_net = flow_settings['pwr_net'] + file.write("set rda_Input(ui_gndnet) {" + gnd_net + "} \n") + file.write("set rda_Input(ui_pwrnet) {" + pwr_net + "} \n") + if flow_settings['tilehi_tielo_cells_between_power_gnd'] is True: + file.write("set rda_Input(ui_pg_connections) [list {PIN:" + gnd_pin + ":}" + " {TIEL::} " + "{NET:" + gnd_net + ":} {NET:" + pwr_net + ":}" + " {TIEH::} " + "{PIN:" + pwr_pin + ":} ] \n") + else: + file.write("set rda_Input(ui_pg_connections) [list {PIN:" + gnd_pin + ":} {NET:" + gnd_net + ":} {NET:" + pwr_net + ":} {PIN:" + pwr_pin + ":} ] \n") + file.write("set rda_Input(PIN:" + gnd_pin + ":) {" + gnd_pin + "} \n") + file.write("set rda_Input(TIEL::) {" + gnd_pin + "} \n") + file.write("set rda_Input(NET:" + gnd_net + ":) {" + gnd_net + "} \n") + file.write("set rda_Input(PIN:" + pwr_pin + ":) {" + pwr_pin + "} \n") + file.write("set rda_Input(TIEH::) {" + pwr_pin + "} \n") + file.write("set rda_Input(NET:" + pwr_net + ":) {" + pwr_net + "} \n\n") + if (flow_settings['inv_footprint'] != "None"): + file.write("set rda_Input(ui_inv_footprint) {" + flow_settings['inv_footprint'] + "}\n") + if (flow_settings['buf_footprint'] != "None"): + file.write("set rda_Input(ui_buf_footprint) {" + flow_settings['buf_footprint'] + "}\n") + if (flow_settings['delay_footprint'] != "None"): + file.write("set rda_Input(ui_delay_footprint) {" + flow_settings['delay_footprint'] + "}\n") + file.close() + metal_layer_bottom = flow_settings["metal_layer_names"][0] + metal_layer_second = flow_settings["metal_layer_names"][1] + metal_layer_top = flow_settings["metal_layer_names"][int(metal_layer)-1] + power_ring_metal_top = flow_settings["power_ring_metal_layer_names"][0] + power_ring_metal_bottom = flow_settings["power_ring_metal_layer_names"][1] + power_ring_metal_left = flow_settings["power_ring_metal_layer_names"][2] + power_ring_metal_right = flow_settings["power_ring_metal_layer_names"][3] + # generate the EDI (encounter) script + file = open("edi.tcl", "w") + file.write("loadConfig edi.conf \n") + file.write("floorPlan -site " + flow_settings['core_site_name'] \ + + " -r " + str(flow_settings['height_to_width_ratio']) \ + + " " + str(core_utilization) \ + + " " + str(flow_settings['space_around_core']) \ + + " " + str(flow_settings['space_around_core']) + " ") + file.write(str(flow_settings['space_around_core']) + " " + str(flow_settings['space_around_core']) + "\n") + file.write("setMaxRouteLayer " + str(metal_layer) + " \n") + file.write("fit \n") + file.write("addRing -spacing_bottom " + str(flow_settings['power_ring_spacing']) \ + + " -spacing_right " + str(flow_settings['power_ring_spacing']) \ + + " -spacing_top " + str(flow_settings['power_ring_spacing']) \ + + " -spacing_left " + str(flow_settings['power_ring_spacing']) \ + + " -width_right " + str(flow_settings['power_ring_width']) \ + + " -width_left " + str(flow_settings['power_ring_width']) \ + + " -width_bottom " + str(flow_settings['power_ring_width']) \ + + " -width_top " + str(flow_settings['power_ring_width']) \ + + " -center 1" \ + + " -around core" \ + + " -layer_top " + power_ring_metal_top \ + + " -layer_bottom " + power_ring_metal_bottom \ + + " -layer_left " + power_ring_metal_left \ + + " -layer_right " + power_ring_metal_right \ + + " -nets { " + gnd_net + " " + pwr_net + " }" \ + + " -stacked_via_top_layer "+ metal_layer_top \ + + " -stacked_via_bottom_layer " + metal_layer_bottom + " \n") + file.write("setPlaceMode -fp false -maxRouteLayer " + str(metal_layer) + "\n") + file.write("placeDesign -inPlaceOpt -noPrePlaceOpt \n") + file.write("checkPlace " + flow_settings['top_level'] +" \n") + file.write("trialroute \n") + file.write("buildTimingGraph \n") + file.write("timeDesign -preCTS -idealClock -numPaths 10 -prefix preCTS -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/timeDesignpreCTSReports" + "\n") + file.write("optDesign -preCTS -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/optDesignpreCTSReports" + "\n") + # I won't do a CTS anyway as the blocks are small. + file.write("addFiller -cell {" + " ".join([str(item) for item in flow_settings['filler_cell_names']]) + "} -prefix FILL -merge true \n") + file.write("clearGlobalNets \n") + file.write("globalNetConnect " + gnd_net + " -type pgpin -pin " + gnd_pin + " -inst {} \n") + file.write("globalNetConnect " + pwr_net + " -type pgpin -pin " + pwr_pin + " -inst {} \n") + file.write("globalNetConnect " + gnd_net + " -type net -net " + gnd_net + " \n") + file.write("globalNetConnect " + pwr_net + " -type net -net " + pwr_net + " \n") + file.write("globalNetConnect " + pwr_net + " -type pgpin -pin " + pwr_pin + " -inst * \n") + file.write("globalNetConnect " + gnd_net + " -type pgpin -pin " + gnd_pin + " -inst * \n") + file.write("globalNetConnect " + pwr_net + " -type tiehi -inst * \n") + file.write("globalNetConnect " + gnd_net + " -type tielo -inst * \n") + file.write("sroute -connect { blockPin padPin padRing corePin floatingStripe }" \ + + " -layerChangeRange { " + metal_layer_bottom + " " + metal_layer_top + " }" \ + + " -blockPinTarget { nearestRingStripe nearestTarget }" \ + + " -padPinPortConnect { allPort oneGeom }" \ + + " -checkAlignedSecondaryPin 1" \ + + " -blockPin useLef" \ + + " -allowJogging 1" \ + + " -crossoverViaBottomLayer " + metal_layer_bottom \ + + " -allowLayerChange 1" \ + + " -targetViaTopLayer " + metal_layer_top \ + + " -crossoverViaTopLayer " + metal_layer_top \ + + " -targetViaBottomLayer " + metal_layer_bottom \ + + " -nets { " + gnd_net + " " + pwr_net + " } \n") + file.write("routeDesign -globalDetail\n") + file.write("setExtractRCMode -engine postRoute \n") + file.write("extractRC \n") + file.write("buildTimingGraph \n") + file.write("timeDesign -postRoute -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/timeDesignReports" + "\n") + file.write("optDesign -postRoute -outDir " + os.path.expanduser(flow_settings['pr_folder']) + "/optDesignReports" + "\n") + #by default, violations are reported in designname.geom.rpt + file.write("verifyGeometry -report " + (os.path.expanduser(flow_settings['pr_folder']) + "/" + flow_settings['top_level'] + ".geom.rpt") + "\n") + #by default, violations are reported in designname.conn.rpt + file.write("verifyConnectivity -type all -report " + (os.path.expanduser(flow_settings['pr_folder']) + "/" + flow_settings['top_level'] + ".conn.rpt") + "\n") + # report area + file.write("summaryReport -outFile " + os.path.expanduser(flow_settings['pr_folder']) + "/pr_report.txt \n") + # save design + file.write(r'saveNetlist ' + os.path.expanduser(flow_settings['pr_folder']) + r'/netlist.v' + "\n") + file.write(r'saveDesign ' + os.path.expanduser(flow_settings['pr_folder']) + r'/design.enc' + " \n") + file.write(r'rcOut -spef ' + os.path.expanduser(flow_settings['pr_folder']) + r'/spef.spef' + " \n") + file.write(r'write_sdf -ideal_clock_network ' + os.path.expanduser(flow_settings['pr_folder']) + r'/sdf.sdf' + " \n") + #If the user specified a layer mapping file, then use that. Otherwise, just let the tool create a default one. + if flow_settings['map_file'] != "None": + file.write(r'streamOut ' + os.path.expanduser(flow_settings['pr_folder']) + r'/final.gds2' + ' -mapFile ' + flow_settings['map_file'] + ' -stripes 1 -units 1000 -mode ALL' + "\n") + else: + file.write(r'streamOut ' + os.path.expanduser(flow_settings['pr_folder']) + r'/final.gds2' + ' -stripes 1 -units 1000 -mode ALL' + "\n") file.write("exit \n") file.close() def run_pnr(flow_settings,metal_layer,core_utilization,synth_report_str): @@ -353,12 +455,21 @@ def run_pnr(flow_settings,metal_layer,core_utilization,synth_report_str): runs place and route using cadence encounter Prereqs: flow_settings_pre_process() function to properly format params for scripts """ - write_pnr_script(flow_settings,metal_layer,core_utilization) - # Run the scrip in EDI - subprocess.call('encounter -nowin -init edi.tcl | tee edi.log', shell=True,executable="/bin/bash") - # clean after EDI! - subprocess.call('mv encounter.log ' + os.path.expanduser(flow_settings['pr_folder']) + '/encounter_log.log', shell=True) - subprocess.call('mv encounter.cmd ' + os.path.expanduser(flow_settings['pr_folder']) + '/encounter.cmd', shell=True) + pnr_report_str = synth_report_str + "_" + "metal_layers_" + metal_layer + "_" + "util_" + core_utilization + report_dest_str = os.path.expanduser(flow_settings['pr_folder']) + "/" + pnr_report_str + "_reports" + if(flow_settings["pnr_tool"] == "encounter"): + write_enc_script(flow_settings,metal_layer,core_utilization) + copy_logs_cmd_str = "cp " + "edi.log " + "edi.tcl " + "edi.conf " + report_dest_str + # Run the scrip in EDI + subprocess.call('encounter -nowin -init edi.tcl | tee edi.log', shell=True,executable="/bin/bash") + elif(flow_settings["pnr_tool"] == "innovus"): + view_fname = write_innovus_view_file(flow_settings) + init_script_fname = write_innovus_init_script(flow_settings,view_fname) + innovus_script_fname = write_innovus_script(flow_settings,metal_layer,core_utilization,init_script_fname) + run_innovus_cmd = "innovus -no_gui -init " + innovus_script_fname + " | tee inn.log" + copy_logs_cmd_str = " ".join(["cp","inn.log",init_script_fname, view_fname,innovus_script_fname,report_dest_str]) + subprocess.call(run_innovus_cmd, shell=True,executable="/bin/bash") + # read total area from the report file: file = open(os.path.expanduser(flow_settings['pr_folder']) + "/pr_report.txt" ,"r") for line in file: @@ -366,15 +477,22 @@ def run_pnr(flow_settings,metal_layer,core_utilization,synth_report_str): total_area = re.findall(r'\d+\.{0,1}\d*', line) file.close() #Copy pnr results to a unique dir in pnr dir - pnr_report_str = synth_report_str + "_" + "metal_layers_" + metal_layer + "_" + "util_" + core_utilization - report_dest_str = os.path.expanduser(flow_settings['pr_folder']) + "/" + pnr_report_str + "_reports" + clean_logs_cmd_str = copy_logs_cmd_str.split(" ") + clean_logs_cmd_str[0] = "rm -f" + clean_logs_cmd_str = " ".join(clean_logs_cmd_str) + mkdir_cmd_str = "mkdir -p " + report_dest_str - copy_rep_cmd_str = "cp " + os.path.expanduser(flow_settings['pr_folder']) + "/*.rpt " + os.path.expanduser(flow_settings['pr_folder']) + "/pr_report.txt " + report_dest_str - copy_logs_cmd_str = "cp " + "edi.log " + "edi.tcl " + "edi.conf " + report_dest_str + #+ os.path.expanduser(flow_settings['pr_folder']) + "/pr_report.txt " + copy_rep_cmd_str = "cp " + os.path.expanduser(flow_settings['pr_folder']) + "/* " + report_dest_str + # if flow_settings["pnr_tool"] == "encounter": + # copy_logs_cmd_str = "cp " + "edi.log " + "edi.tcl " + "edi.conf " + report_dest_str + # elif flow_settings["pnr_tool"] == "innovus": + # copy_logs_cmd_str = "cp " + "inn.log " + "edi.tcl " + "edi.conf " + report_dest_str subprocess.call(mkdir_cmd_str,shell=True) subprocess.call(copy_rep_cmd_str,shell=True) subprocess.call(copy_logs_cmd_str,shell=True) - subprocess.call('rm -f edi.log edi.conf edi.tcl', shell=True) + subprocess.call(clean_logs_cmd_str,shell=True) + # subprocess.call('rm -f edi.log edi.conf edi.tcl encounter.log encounter.cmd', shell=True) return pnr_report_str, total_area def run_sim(): @@ -417,7 +535,7 @@ def write_pt_power_script(flow_settings,mode_enabled,clock_period,x): file.write("set my_clock_pin " + flow_settings['clock_pin_name'] + "\n") file.write("set target_library " + flow_settings['primetime_libs'] + "\n") file.write("set link_library " + flow_settings['link_library'] + "\n") - file.write("read_verilog " + os.path.expanduser(flow_settings['pr_folder']) + "/netlist.v \n") + file.write("read_verilog " + os.path.join(flow_settings['pr_folder'],"netlist.v") + "\n") file.write("link \n") file.write("set my_period " + str(clock_period) + " \n") file.write("set find_clock [ find port [list $my_clock_pin] ] \n") @@ -542,7 +660,7 @@ def flow_settings_pre_process(processed_flow_settings,cur_env): syn_root = cur_env.get("SYNOPSYS") search_path_dirs = [os.path.join(syn_root,"libraries",dirname) for dirname in ["syn","syn_ver","sim_ver"] ] except: - print("could not find 'SYNOPSYS' environment variable set, please run the following command to your sysopsys home directory") + print("could not find 'SYNOPSYS' environment variable set, please source your ASIC tools or run the following command to your sysopsys home directory") print("export SYNOPSYS=/abs/path/to/synopsys/home") print("Ex. export SYNOPSYS=/CMC/tools/synopsys/syn_vN-2017.09/") sys.exit(1) diff --git a/coffe/utils.py b/coffe/utils.py index eef2664..f535b7e 100644 --- a/coffe/utils.py +++ b/coffe/utils.py @@ -878,8 +878,6 @@ def load_hard_params(filename): hard_params["process_params_file"] = value elif param == "pnr_tool": hard_params["pnr_tool"] = value - elif param == "process_size": - hard_params["process_size"] = value #To allow for the legacy way of inputting process specific params I'll keep these in (the only reason for having a seperate file is for understandability) if param == "process_lib_paths": hard_params["process_lib_paths"] = sanatize_str_input_to_list(value) @@ -921,6 +919,8 @@ def load_hard_params(filename): hard_params['pwr_pin'] = value.strip() elif param == 'wire_selection': hard_params['wire_selection'].append(value) + elif param == "process_size": + hard_params["process_size"] = value hard_file.close() @@ -988,6 +988,8 @@ def load_hard_params(filename): hard_params['wire_selection'].append(value) elif param == "primetime_libs": hard_params["primetime_libs"] = sanatize_str_input_to_list(value) + elif param == "process_size": + hard_params["process_size"] = value process_param_file.close() #TODO make this more accessable outside of the code, but for now this is how I declare optional parameters diff --git a/input_files/strtx_III_dsp/dsp_hb_settings.txt b/input_files/strtx_III_dsp/dsp_hb_settings.txt index aed3bde..7b62229 100755 --- a/input_files/strtx_III_dsp/dsp_hb_settings.txt +++ b/input_files/strtx_III_dsp/dsp_hb_settings.txt @@ -17,7 +17,9 @@ area_cost_exp=1.0 #ASIC flow settings #path to absolute paths needed for process parameters (relative to coffe home repo) process_params_file=input_files/strtx_III_dsp/process_specific_params.txt - +#run_synth=False +#run_pnr=True +#run_pt=False ######################################## ########## Synthesis Settings ########## ######################################## @@ -25,12 +27,12 @@ process_params_file=input_files/strtx_III_dsp/process_specific_params.txt # Name of the clock pin in the design clock_pin_name=clk # Desired clock period in ns -#clock_period=1.53 +clock_period=1.53 #clock_period=1.66 #clock_period=1.81 clock_period=2.0 #clock_period=2.22 -#clock_period=2.5 +clock_period=2.5 # Name of the top-level entity in the design #top_level=ASU_conv @@ -68,6 +70,8 @@ target_libraries="/CMC/kits/tsmc_65nm_libs/tcbn65gplus/TSMCHOME/digital/Front_En ########## Place and Route Settings ########## ############################################## +pnr_tool=innovus + # Libraries required in EDI: #metal_layers=9 @@ -114,9 +118,10 @@ tilehi_tielo_cells_between_power_gnd=True #core_site_name=core #specify the utilization of the core site. you can specify multiple ones on different lines. -#core_utilization=0.85 +core_utilization=0.80 +core_utilization=0.85 core_utilization=0.90 -#core_utilization=0.95 +core_utilization=0.95 #lef_files="/CMC/kits/tsmc_65nm_libs/tcbn65gplus/TSMCHOME/digital/Back_End/lef/tcbn65gplus_200a/lef/tcbn65gplus_9lmT2.lef /CMC/kits/tsmc_65nm_libs/tpzn65gpgv2/TSMCHOME/digital/Back_End/lef/tpzn65gpgv2_140c/mt_2/9lm/lef/antenna_9lm.lef /CMC/kits/tsmc_65nm_libs/tpzn65gpgv2/TSMCHOME/digital/Back_End/lef/tpzn65gpgv2_140c/mt_2/9lm/lef/tpzn65gpgv2_9lm.lef" @@ -129,8 +134,8 @@ core_utilization=0.90 # EDI settings: -power_ring_width=3 -power_ring_spacing=3 +power_ring_width=1.8 +power_ring_spacing=1.8 height_to_width_ratio=4.0 space_around_core=10 @@ -142,8 +147,8 @@ pr_folder=~/COFFE/output_files/strtx_III_dsp/pr ########## Prime Time Settings ############### ############################################## -#mode_signal=mode_0 -#mode_signal=mode_1 +mode_signal=mode_0 +mode_signal=mode_1 primetime_folder=~/COFFE/output_files/strtx_III_dsp/pt diff --git a/input_files/strtx_III_dsp/process_specific_params.txt b/input_files/strtx_III_dsp/process_specific_params.txt index d624ad2..9e232dc 100644 --- a/input_files/strtx_III_dsp/process_specific_params.txt +++ b/input_files/strtx_III_dsp/process_specific_params.txt @@ -4,7 +4,7 @@ ############# ASIC Flow Settings ############ ############################################# #node size of process in nm -#process_size=65 +process_size=65 process_lib_paths="/CMC/kits/tsmc_65nm_libs/tcbn65gplus/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tcbn65gplus_140b /CMC/kits/tsmc_65nm_libs/tpzn65gpgv2/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tpzn65gpgv2_140c" @@ -29,10 +29,10 @@ standard_libs="/CMC/kits/tsmc_65nm_libs/tcbn65gplus/TSMCHOME/digital/Front_End/t worst_case_libs="/CMC/kits/tsmc_65nm_libs/tcbn65gplus/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tcbn65gplus_140b/tcbn65gpluswc.lib /CMC/kits/tsmc_65nm_libs/tpzn65gpgv2/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tpzn65gpgv2_140c/tpzn65gpgv2wc.lib" -#metal_layers=8 -metal_layers=7 +metal_layers=8 +#metal_layers=7 #metal_layers=6 -#metal_layers=5 +metal_layers=5 #names of metal layers starting from the bottom-most layer on the left. use a python list format. metal_layer_names=["M1", "M2", "M3", "M4", "M5", "M6", "M7", "M8", "M9", "AP"] From 6dfc833be96c9a8cafadf16fc6f3d2ad888ca9d9 Mon Sep 17 00:00:00 2001 From: Stephen More Date: Mon, 24 Oct 2022 09:51:10 -0400 Subject: [PATCH 04/10] updated user manual --- User Manual.md | 49 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/User Manual.md b/User Manual.md index de1b76e..36c7860 100644 --- a/User Manual.md +++ b/User Manual.md @@ -29,15 +29,24 @@ To run COFFE, simply run coffe.py and follow the instructions. There are several sample input files in the test directory accompanying COFFE which stimulate all existing features. These files describe what each of the parameters are; simply read them and change them to form your desired architecture. We have also included several tests with COFFE which should smoothly run when using the latest version. To test your setup, you can run those. -# How to run a test for ASIC flow (using stratix III like DSP) +# How to run a full test for ASIC flow (using stratix III like DSP) +Note: +This test runs the ASIC flow, COFFE custom flow, and utility scripts + The following test was tested with the following tools: -Synopsys Design Compiler 2017 -Cadence Encounter 2009 Prerequisites: Make sure the ASIC tools are on your environments path, this can be done with the following commands: -$(which dc_shell-t) -$(which encounter) +```console +which dc_shell-t +#if using encounter +which encounter +#if using innovus +which innovus +which genus +``` 1. Now the configuration files for the asic tools must be edited to match the environment and ASIC PDK being used (If you're using UofT servers you can skip this portion as they're already setup) @@ -45,8 +54,6 @@ $(which encounter) open up the following file in editor: - ~/COFFE/input_files/strtx_III_dsp/dsp_hb_settings.txt - If you only want to run the asic flow, set the "asic_flow_only" param to True - - set the "target_libraries" and "link_libraries" parameters to the absolute paths to the standard cell front end .db files provided by semiconductor PDK (surrounded by quotes). - set the "inv_footprint", "buf_footprint", and "delay_footprint" params to footprints, found in front end .lib files from pdk (found under similar names to "INVD0" "BUFFD1" "DEL0") @@ -68,24 +75,38 @@ $(which encounter) clock_period=2.5 etc... 2. run the following command (run this with python2): - - $(python2 coffe.py -i 1 input_files/strtx_III_dsp/dsp_coffe_params.txt) + ```console + python2 coffe.py -i 1 input_files/strtx_III_dsp/dsp_coffe_params.txt + ``` 3. Once the program has finished go to the following directory: - ~/COFFE/analyze_results run the following command the argument points to where the .txt reports from post ASIC flow exist, which should be the same as the arch_out_folder param in dsp_coffe_params.txt): - - $(python2 condense_results.py -r ../output_files/strtx_III_dsp/arch_out_dir) + ```console + python2 condense_results.py -r ../output_files/strtx_III_dsp/arch_out_dir + ``` The above command creates a csv file with all reports from the specified directory. To plot the power, area, and delay results against target frequency run the following command (this requires python3 and matplotlib to be installed): - - $(python3 plot_coffe_results.py -c report_csv_out/condensed_report.csv) - + ```console + python3 plot_coffe_results.py -c report_csv_out/condensed_report.csv + ``` 4. A script that runs all of the above commands can be run from COFFE repo: - - $(chmod +x ./unit_test.sh) - - $(./unit_test.sh) - - - + ```console + chmod +x ./unit_test.sh + ./unit_test.sh + ``` + +## Running Full COFFE flow +Prereqs: if using INNOVUS make sure you have sourced GENUS and INNOVUS Cadence tools (innovus uses genus during place and route) +```console +python2 coffe.py -i 1 input_files/strtx_III_dsp/dsp_coffe_params.txt +``` +## Running ASIC COFFE flow +```console +python2 coffe.py -ho -i 1 input_files/strtx_III_dsp/dsp_coffe_params.txt +``` From 6881b9a2aed67f8cf2737f29e8931f606ffac304 Mon Sep 17 00:00:00 2001 From: Stephen More Date: Thu, 27 Oct 2022 10:49:46 -0400 Subject: [PATCH 05/10] addressed PR comments, fixed minor error in writing innovus script, removed abs path from innvous init script uses innovus defined env var instead --- coffe/hardblock_functions.py | 33 ++++++++++++++++++++++++++++----- coffe/utils.py | 3 +++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/coffe/hardblock_functions.py b/coffe/hardblock_functions.py index 371973a..1472b12 100644 --- a/coffe/hardblock_functions.py +++ b/coffe/hardblock_functions.py @@ -104,7 +104,7 @@ def run_synth(flow_settings,clock_period,wire_selection): check_file.close() #Copy synthesis results to a unique dir in synth dir - synth_report_str = "period_" + clock_period + "_" + "wire_mdl_" + wire_selection + synth_report_str = flow_settings["top_level"] + "_period_" + clock_period + "_" + "wire_mdl_" + wire_selection report_dest_str = flow_settings['synth_folder'] + "/" + synth_report_str + "_reports" mkdir_cmd_str = "mkdir -p " + report_dest_str copy_rep_cmd_str = "cp " + flow_settings['synth_folder'] + "/* " + report_dest_str @@ -190,6 +190,10 @@ def write_innovus_view_file(flow_settings): def write_innovus_script(flow_settings,metal_layer,core_utilization,init_script_fname): + """ + This function writes the innvous script which actually performs place and route. + Precondition to this script is the creation of an initialization script which is sourced on the first line. + """ #some format adjustment (could move to preproc function) core_utilization = str(core_utilization) metal_layer = str(metal_layer) @@ -262,8 +266,7 @@ def write_innovus_script(flow_settings,metal_layer,core_utilization,init_script_ "saveNetlist " + os.path.join(flow_settings["pr_folder"],"netlist.v"), "saveDesign " + os.path.join(flow_settings["pr_folder"],"design.enc"), "rcOut -spef " + os.path.join(flow_settings["pr_folder"],"spef.spef"), - "write_sdf -ideal_clock_network " + os.path.join(flow_settings["pr_folder"],"sdf.sdf"), - "exit"] + "write_sdf -ideal_clock_network " + os.path.join(flow_settings["pr_folder"],"sdf.sdf")] #If the user specified a layer mapping file, then use that. Otherwise, just let the tool create a default one. if flow_settings['map_file'] != "None": file_lines.append("streamOut " + os.path.join(flow_settings["pr_folder"],"final.gds2") + " -mapFile " + flow_settings["map_file"] + " -stripes 1 -units 1000 -mode ALL") @@ -271,10 +274,16 @@ def write_innovus_script(flow_settings,metal_layer,core_utilization,init_script_ file_lines.append("streamOut " + os.path.join(flow_settings["pr_folder"],"final.gds2") + " -stripes 1 -units 1000 -mode ALL") for line in file_lines: file_write_ln(file,line) + file_write_ln(file,"exit") file.close() return fname def write_innovus_init_script(flow_settings,view_fname): + """ + This function generates init script which sets variables used in pnr, + The contents of this file were generated from using the innovus GUI + setting relavent files/nets graphically and exporting the .globals file + """ flow_settings["lef_files"] = flow_settings["lef_files"].strip("\"") fname = flow_settings["top_level"]+"_innovus_init.tcl" file = open(fname,"w") @@ -288,7 +297,8 @@ def write_innovus_init_script(flow_settings,view_fname): "set defHierChar /", "set distributed_client_message_echo 1", "set distributed_mmmc_disable_reports_auto_redirection 0", - "set dlgflprecConfigFile /CMC/tools/cadence/INNOVUS21.12.000_lnx86/tools.lnx86/dlApp/run_flprec.cfg", + #The below config file comes from the INNOVUS directory, if not using an x86 system this will probably break + "set dlgflprecConfigFile " + os.path.join(flow_settings["EDI_HOME"],"tools.lnx86/dlApp/run_flprec.cfg"), "set enable_ilm_dual_view_gui_and_attribute 1", "set enc_enable_print_mode_command_reset_options 1", "set init_design_settop 0", @@ -324,6 +334,9 @@ def write_innovus_init_script(flow_settings,view_fname): def write_enc_script(flow_settings,metal_layer,core_utilization,synth_report_str): + """ + Writes script for place and route using cadence encounter (tested under 2009 version) + """ # generate the EDI (encounter) configuration file = open("edi.conf", "w") file.write("global rda_Input \n") @@ -525,7 +538,9 @@ def run_sim(): def write_pt_power_script(flow_settings,mode_enabled,clock_period,x): """" writes the tcl script for power analysis using Synopsys Design Compiler, tested under 2017 version - Update: changed the [all_nets] argument used in set_switching_activity to use -baseClk and -inputs args instead + Update: changed the [all_nets] argument used in set_switching_activity to use -baseClk and -inputs args instead. + This function takes the RC values generated from pnr script in form of .spef file and the user inputted switching probability or + a .saif file generated from a testbench to estimate power. """ # Create a script to measure power: file = open("primetime_power.tcl", "w") @@ -664,6 +679,14 @@ def flow_settings_pre_process(processed_flow_settings,cur_env): print("export SYNOPSYS=/abs/path/to/synopsys/home") print("Ex. export SYNOPSYS=/CMC/tools/synopsys/syn_vN-2017.09/") sys.exit(1) + #Place and route + if(processed_flow_settings["pnr_tool"] == "innovus"): + try: + edi_root = cur_env.get("EDI_HOME") + processed_flow_settings["EDI_HOME"] = edi_root + except: + print("could not find 'EDI_HOME' environment variable set, please source your ASIC tools or run the following command to your INNOVUS/ENCOUNTER home directory") + sys.exit(1) for p_lib_path in processed_flow_settings["process_lib_paths"]: search_path_dirs.append(p_lib_path) diff --git a/coffe/utils.py b/coffe/utils.py index f535b7e..5562d93 100644 --- a/coffe/utils.py +++ b/coffe/utils.py @@ -700,6 +700,9 @@ def check_hard_params(hard_params,optional_params): elif(key == "pnr_tool" and val != "encounter" and val != "innovus" ): print("ERROR: pnr_tool must be set as either \"encounter\" or \"innovus\" ") sys.exit(1) + if(hard_params["pnr_tool"] == "innovus" and hard_params["process_size"] == ""): + print("param process_size is unset, please go to your hardblock/process params file and set it") + sys.exit(1) def load_hard_params(filename): """ Parse the hard block description file and load values into dictionary. From cdb40b924ebcdb255a6dcdb9b7e1338de4671bb0 Mon Sep 17 00:00:00 2001 From: Stephen More Date: Thu, 27 Oct 2022 15:50:36 -0400 Subject: [PATCH 06/10] fixed mistake in report directory copying --- coffe/hardblock_functions.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/coffe/hardblock_functions.py b/coffe/hardblock_functions.py index 1472b12..ce487f8 100644 --- a/coffe/hardblock_functions.py +++ b/coffe/hardblock_functions.py @@ -105,7 +105,7 @@ def run_synth(flow_settings,clock_period,wire_selection): #Copy synthesis results to a unique dir in synth dir synth_report_str = flow_settings["top_level"] + "_period_" + clock_period + "_" + "wire_mdl_" + wire_selection - report_dest_str = flow_settings['synth_folder'] + "/" + synth_report_str + "_reports" + report_dest_str = os.path.join(flow_settings['synth_folder'],synth_report_str + "_reports") mkdir_cmd_str = "mkdir -p " + report_dest_str copy_rep_cmd_str = "cp " + flow_settings['synth_folder'] + "/* " + report_dest_str copy_logs_cmd_str = "cp " + "dc.log "+ "dc_script.tcl " + report_dest_str @@ -257,7 +257,7 @@ def write_innovus_script(flow_settings,metal_layer,core_utilization,init_script_ "optDesign -postRoute -outDir " + os.path.join(flow_settings["pr_folder"],"optDesignReports"), "verify_drc -report " + os.path.join(flow_settings["pr_folder"],"geom.rpt"), "verifyConnectivity -type all -report " + os.path.join(flow_settings["pr_folder"],"conn.rpt"), - "report_timing > " + os.path.join(flow_settings["pr_folder"],flow_settings["top_level"] +"setup_timing.rpt"), + "report_timing > " + os.path.join(flow_settings["pr_folder"],"setup_timing.rpt"), "setAnalysisMode -checkType hold", "report_timing > " + os.path.join(flow_settings["pr_folder"],"hold_timing.rpt"), "report_power > " + os.path.join(flow_settings["pr_folder"],"power.rpt"), @@ -492,19 +492,23 @@ def run_pnr(flow_settings,metal_layer,core_utilization,synth_report_str): #Copy pnr results to a unique dir in pnr dir clean_logs_cmd_str = copy_logs_cmd_str.split(" ") clean_logs_cmd_str[0] = "rm -f" + del clean_logs_cmd_str[-1] #removes the last element in the string (this is the desintation report directory) clean_logs_cmd_str = " ".join(clean_logs_cmd_str) mkdir_cmd_str = "mkdir -p " + report_dest_str #+ os.path.expanduser(flow_settings['pr_folder']) + "/pr_report.txt " copy_rep_cmd_str = "cp " + os.path.expanduser(flow_settings['pr_folder']) + "/* " + report_dest_str + copy_rec_cmd_str = " ".join(["cp -r",os.path.join(flow_settings['pr_folder'],"design.enc.dat"),report_dest_str]) # if flow_settings["pnr_tool"] == "encounter": # copy_logs_cmd_str = "cp " + "edi.log " + "edi.tcl " + "edi.conf " + report_dest_str # elif flow_settings["pnr_tool"] == "innovus": # copy_logs_cmd_str = "cp " + "inn.log " + "edi.tcl " + "edi.conf " + report_dest_str subprocess.call(mkdir_cmd_str,shell=True) subprocess.call(copy_rep_cmd_str,shell=True) + subprocess.call(copy_rec_cmd_str,shell=True) subprocess.call(copy_logs_cmd_str,shell=True) subprocess.call(clean_logs_cmd_str,shell=True) + # subprocess.call('rm -f edi.log edi.conf edi.tcl encounter.log encounter.cmd', shell=True) return pnr_report_str, total_area From cae1c8895bb5ca96657b012ef6cd930534b7b24f Mon Sep 17 00:00:00 2001 From: Stephen More Date: Tue, 1 Nov 2022 08:12:47 -0400 Subject: [PATCH 07/10] minor cleanup changes, cleaned up dsp_hb_settings file to remove params stored in process_specific_params.txt --- coffe/hardblock_functions.py | 20 ++--- input_files/strtx_III_dsp/dsp_hb_settings.txt | 81 ++++--------------- 2 files changed, 23 insertions(+), 78 deletions(-) diff --git a/coffe/hardblock_functions.py b/coffe/hardblock_functions.py index ce487f8..18aa0c7 100644 --- a/coffe/hardblock_functions.py +++ b/coffe/hardblock_functions.py @@ -104,7 +104,7 @@ def run_synth(flow_settings,clock_period,wire_selection): check_file.close() #Copy synthesis results to a unique dir in synth dir - synth_report_str = flow_settings["top_level"] + "_period_" + clock_period + "_" + "wire_mdl_" + wire_selection + synth_report_str = flow_settings["top_level"] + "_period_" + clock_period + "_" + "wiremdl_" + wire_selection report_dest_str = os.path.join(flow_settings['synth_folder'],synth_report_str + "_reports") mkdir_cmd_str = "mkdir -p " + report_dest_str copy_rep_cmd_str = "cp " + flow_settings['synth_folder'] + "/* " + report_dest_str @@ -262,6 +262,7 @@ def write_innovus_script(flow_settings,metal_layer,core_utilization,init_script_ "report_timing > " + os.path.join(flow_settings["pr_folder"],"hold_timing.rpt"), "report_power > " + os.path.join(flow_settings["pr_folder"],"power.rpt"), "report_constraint -all_violators > " + os.path.join(flow_settings["pr_folder"],"violators.rpt"), + "report_area > " + os.path.join(flow_settings["pr_folder"],"area.rpt"), "summaryReport -outFile " + os.path.join(flow_settings["pr_folder"],"pr_report.txt"), "saveNetlist " + os.path.join(flow_settings["pr_folder"],"netlist.v"), "saveDesign " + os.path.join(flow_settings["pr_folder"],"design.enc"), @@ -333,7 +334,7 @@ def write_innovus_init_script(flow_settings,view_fname): return fname -def write_enc_script(flow_settings,metal_layer,core_utilization,synth_report_str): +def write_enc_script(flow_settings,metal_layer,core_utilization): """ Writes script for place and route using cadence encounter (tested under 2009 version) """ @@ -469,10 +470,10 @@ def run_pnr(flow_settings,metal_layer,core_utilization,synth_report_str): Prereqs: flow_settings_pre_process() function to properly format params for scripts """ pnr_report_str = synth_report_str + "_" + "metal_layers_" + metal_layer + "_" + "util_" + core_utilization - report_dest_str = os.path.expanduser(flow_settings['pr_folder']) + "/" + pnr_report_str + "_reports" + report_dest_str = os.path.join(flow_settings['pr_folder'],pnr_report_str + "_reports") if(flow_settings["pnr_tool"] == "encounter"): write_enc_script(flow_settings,metal_layer,core_utilization) - copy_logs_cmd_str = "cp " + "edi.log " + "edi.tcl " + "edi.conf " + report_dest_str + copy_logs_cmd_str = "cp " + "edi.log " + "edi.tcl " + "edi.conf " + "encounter.log " + "encounter.cmd " + report_dest_str # Run the scrip in EDI subprocess.call('encounter -nowin -init edi.tcl | tee edi.log', shell=True,executable="/bin/bash") elif(flow_settings["pnr_tool"] == "innovus"): @@ -492,24 +493,19 @@ def run_pnr(flow_settings,metal_layer,core_utilization,synth_report_str): #Copy pnr results to a unique dir in pnr dir clean_logs_cmd_str = copy_logs_cmd_str.split(" ") clean_logs_cmd_str[0] = "rm -f" - del clean_logs_cmd_str[-1] #removes the last element in the string (this is the desintation report directory) + #removes the last element in the string (this is the desintation report directory) + del clean_logs_cmd_str[-1] clean_logs_cmd_str = " ".join(clean_logs_cmd_str) mkdir_cmd_str = "mkdir -p " + report_dest_str - #+ os.path.expanduser(flow_settings['pr_folder']) + "/pr_report.txt " copy_rep_cmd_str = "cp " + os.path.expanduser(flow_settings['pr_folder']) + "/* " + report_dest_str copy_rec_cmd_str = " ".join(["cp -r",os.path.join(flow_settings['pr_folder'],"design.enc.dat"),report_dest_str]) - # if flow_settings["pnr_tool"] == "encounter": - # copy_logs_cmd_str = "cp " + "edi.log " + "edi.tcl " + "edi.conf " + report_dest_str - # elif flow_settings["pnr_tool"] == "innovus": - # copy_logs_cmd_str = "cp " + "inn.log " + "edi.tcl " + "edi.conf " + report_dest_str subprocess.call(mkdir_cmd_str,shell=True) subprocess.call(copy_rep_cmd_str,shell=True) subprocess.call(copy_rec_cmd_str,shell=True) subprocess.call(copy_logs_cmd_str,shell=True) subprocess.call(clean_logs_cmd_str,shell=True) - # subprocess.call('rm -f edi.log edi.conf edi.tcl encounter.log encounter.cmd', shell=True) return pnr_report_str, total_area def run_sim(): @@ -631,7 +627,7 @@ def run_power_timing(flow_settings,mode_enabled,clock_period,x,pnr_report_str): pt_report_str = pnr_report_str + "_" + "mode_" + str(x) report_dest_str = os.path.expanduser(flow_settings['primetime_folder']) + "/" + pt_report_str + "_reports" mkdir_cmd_str = "mkdir -p " + report_dest_str - copy_rep_cmd_str = "cp " + os.path.expanduser(flow_settings['primetime_folder']) + "/*.rpt " + report_dest_str + copy_rep_cmd_str = "cp " + os.path.expanduser(flow_settings['primetime_folder']) + "/* " + report_dest_str copy_logs_cmd_str = "cp " + "pt.log pt_pwr.log primetime.tcl primetime_power.tcl " + report_dest_str subprocess.call(mkdir_cmd_str,shell=True) subprocess.call(copy_rep_cmd_str,shell=True) diff --git a/input_files/strtx_III_dsp/dsp_hb_settings.txt b/input_files/strtx_III_dsp/dsp_hb_settings.txt index 7b62229..7f57a0d 100755 --- a/input_files/strtx_III_dsp/dsp_hb_settings.txt +++ b/input_files/strtx_III_dsp/dsp_hb_settings.txt @@ -17,9 +17,8 @@ area_cost_exp=1.0 #ASIC flow settings #path to absolute paths needed for process parameters (relative to coffe home repo) process_params_file=input_files/strtx_III_dsp/process_specific_params.txt -#run_synth=False -#run_pnr=True -#run_pt=False + + ######################################## ########## Synthesis Settings ########## ######################################## @@ -27,15 +26,14 @@ process_params_file=input_files/strtx_III_dsp/process_specific_params.txt # Name of the clock pin in the design clock_pin_name=clk # Desired clock period in ns -clock_period=1.53 -#clock_period=1.66 -#clock_period=1.81 -clock_period=2.0 -#clock_period=2.22 -clock_period=2.5 +#clock_period=1.53 +clock_period=1.66 +clock_period=1.81 +#clock_period=2.0 +clock_period=2.22 +#clock_period=2.5 # Name of the top-level entity in the design -#top_level=ASU_conv top_level=dsp # The name of the folder in which post-synthesis files and synthesis reports are to be stored @@ -59,81 +57,32 @@ toggle_rate=25 # Should COFFE generate an activity file for the design (using modelsim) generate_activity_file=False -# Location of the library files. -# if you have more than one library, please provide them similiar to the example below. - -#link_libraries="/CMC/kits/tsmc_65nm_libs/tcbn65gplus/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tcbn65gplus_140b/tcbn65gpluswc.db /CMC/kits/tsmc_65nm_libs/tpzn65gpgv2/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tpzn65gpgv2_140c/tpzn65gpgv2wc.db" - -target_libraries="/CMC/kits/tsmc_65nm_libs/tcbn65gplus/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tcbn65gplus_140b/tcbn65gpluswc.db /CMC/kits/tsmc_65nm_libs/tpzn65gpgv2/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tpzn65gpgv2_140c/tpzn65gpgv2wc.db" ############################################## ########## Place and Route Settings ########## ############################################## +#This can be of value "innovus" or "encounter" depending on version of cadence pnr tool used pnr_tool=innovus -# Libraries required in EDI: - -#metal_layers=9 -#metal_layers=8 -#metal_layers=7 -#metal_layers=6 -#metal_layers=5 - -#names of metal layers starting from the bottom-most layer on the left. use a python list format. -#metal_layer_names=["M1", "M2", "M3", "M4", "M5", "M6", "M7", "M8", "M9","AP"] - -#names of metal layers to use for each side of the power ring -#order: top, bottom, left, right -#power_ring_metal_layer_names=["M1", "M1", "M2", "M2"] - #name of the file to use for layer mapping. used for stream out. #set it to None if you want the tool to create a generic map file map_file=streamOut.map -#wire_selection=WireAreaLowkCon -#wire_selection=WireAreaLowkAgr -#wire_selection=WireAreaForZero -#specify names of ground and power pins and nets in the library -#gnd_net=VSS -#gnd_pin=VSS -#pwr_net=VDD -#pwr_pin=VDD - tilehi_tielo_cells_between_power_gnd=True - -#specify footprint names for inverters, buffers, delays. -#this is optional. you can get these values from the lib file. -#you can also specify None, if you can't find them in the lib file. -#inv_footprint=INVD0 -#buf_footprint=BUFFD1 -#delay_footprint=DEL0 - -#list of filler cell names. use a python list format. -#the names can be obtained from .lib files. -#filler_cell_names=["FILL1", "FILL16", "FILL1_LL", "FILL2", "FILL32", "FILL64", "FILL8", "FILL_NW_FA_LL", "FILL_NW_HH", "FILL_NW_LL"] - #name of the core site in the floorplan. can be obtained from lef files. #core_site_name=core #specify the utilization of the core site. you can specify multiple ones on different lines. -core_utilization=0.80 +#core_utilization=0.80 core_utilization=0.85 core_utilization=0.90 core_utilization=0.95 -#lef_files="/CMC/kits/tsmc_65nm_libs/tcbn65gplus/TSMCHOME/digital/Back_End/lef/tcbn65gplus_200a/lef/tcbn65gplus_9lmT2.lef /CMC/kits/tsmc_65nm_libs/tpzn65gpgv2/TSMCHOME/digital/Back_End/lef/tpzn65gpgv2_140c/mt_2/9lm/lef/antenna_9lm.lef /CMC/kits/tsmc_65nm_libs/tpzn65gpgv2/TSMCHOME/digital/Back_End/lef/tpzn65gpgv2_140c/mt_2/9lm/lef/tpzn65gpgv2_9lm.lef" - -#best_case_libs="/CMC/kits/tsmc_65nm_libs/tcbn65gplus/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tcbn65gplus_140b/tcbn65gplusbc.lib /CMC/kits/tsmc_65nm_libs/tpzn65gpgv2/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tpzn65gpgv2_140c/tpzn65gpgv2bc.lib" - -#standard_libs="/CMC/kits/tsmc_65nm_libs/tcbn65gplus/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tcbn65gplus_140b/tcbn65gplustc.lib /CMC/kits/tsmc_65nm_libs/tpzn65gpgv2/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tpzn65gpgv2_140c/tpzn65gpgv2tc.lib" - -#worst_case_libs="/CMC/kits/tsmc_65nm_libs/tcbn65gplus/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tcbn65gplus_140b/tcbn65gpluswc.lib /CMC/kits/tsmc_65nm_libs/tpzn65gpgv2/TSMCHOME/digital/Front_End/timing_power_noise/NLDM/tpzn65gpgv2_140c/tpzn65gpgv2wc.lib" - - - -# EDI settings: +# EDI settings (Cadence Encounter or innovus): +# These settings are the width of power/gnd wires and the spacing between them +# The space_around_core param is the distance between core and IO (leaves enough space for power rings) power_ring_width=1.8 power_ring_spacing=1.8 height_to_width_ratio=4.0 @@ -147,8 +96,8 @@ pr_folder=~/COFFE/output_files/strtx_III_dsp/pr ########## Prime Time Settings ############### ############################################## -mode_signal=mode_0 -mode_signal=mode_1 +#mode_signal=mode_0 +#mode_signal=mode_1 primetime_folder=~/COFFE/output_files/strtx_III_dsp/pt From d6194708ca200bed8e1db3f7eb1f13f8a79725b4 Mon Sep 17 00:00:00 2001 From: Stephen More Date: Tue, 1 Nov 2022 08:35:39 -0400 Subject: [PATCH 08/10] updated comments --- input_files/strtx_III_dsp/dsp_hb_settings.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/input_files/strtx_III_dsp/dsp_hb_settings.txt b/input_files/strtx_III_dsp/dsp_hb_settings.txt index 7f57a0d..ab2aa57 100755 --- a/input_files/strtx_III_dsp/dsp_hb_settings.txt +++ b/input_files/strtx_III_dsp/dsp_hb_settings.txt @@ -4,6 +4,14 @@ ########## General Design Settings ########## ############################################# +########### GENERAL INFORMATION ############# +# To sweep asic flow parameters you can create +# parameter lists by setting the same parameter to another value +# Ex. +# period=2.0 +# period=1.66 +# ^ this would sweep period and evaluate asic flow for both values + # The folder in which all the design files are located: design_folder=~/COFFE/input_files/strtx_III_dsp/dsp_block_hdl From ff0fb4fe375a07346629ed7a63b9cb8b5436bb68 Mon Sep 17 00:00:00 2001 From: Stephen More Date: Tue, 1 Nov 2022 08:39:25 -0400 Subject: [PATCH 09/10] updated comments --- coffe/hardblock_functions.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/coffe/hardblock_functions.py b/coffe/hardblock_functions.py index 18aa0c7..e745a05 100644 --- a/coffe/hardblock_functions.py +++ b/coffe/hardblock_functions.py @@ -577,6 +577,7 @@ def write_pt_power_script(flow_settings,mode_enabled,clock_period,x): def write_pt_timing_script(flow_settings,mode_enabled,clock_period,x): """ writes the tcl script for timing analysis using Synopsys Design Compiler, tested under 2017 version + This should look for setup/hold violations using the worst case (hold) and best case (setup) libs """ # backannotate into primetime # This part should be reported for all the modes in the design. @@ -603,6 +604,9 @@ def write_pt_timing_script(flow_settings,mode_enabled,clock_period,x): file.close() def run_power_timing(flow_settings,mode_enabled,clock_period,x,pnr_report_str): + """ + This runs STA using PrimeTime and the pnr generated .spef and netlist file to get a more accurate result for delay + """ if not mode_enabled: x = 2**len(flow_settings['mode_signal']) write_pt_timing_script(flow_settings,mode_enabled,clock_period,x) From 667c6fea3f02a5d73e6a20e4d0889ed27a289e41 Mon Sep 17 00:00:00 2001 From: Stephen More Date: Tue, 1 Nov 2022 08:41:51 -0400 Subject: [PATCH 10/10] updated comments --- input_files/strtx_III_dsp/dsp_hb_settings.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/input_files/strtx_III_dsp/dsp_hb_settings.txt b/input_files/strtx_III_dsp/dsp_hb_settings.txt index ab2aa57..4c70c2c 100755 --- a/input_files/strtx_III_dsp/dsp_hb_settings.txt +++ b/input_files/strtx_III_dsp/dsp_hb_settings.txt @@ -83,6 +83,9 @@ tilehi_tielo_cells_between_power_gnd=True #core_site_name=core #specify the utilization of the core site. you can specify multiple ones on different lines. +# description of utilization parameter can be found here: +# https://community.cadence.com/cadence_technology_forums/f/digital-implementation/48060/what-is-the-meaning-of-cell-utlilization + #core_utilization=0.80 core_utilization=0.85 core_utilization=0.90 @@ -91,6 +94,9 @@ core_utilization=0.95 # EDI settings (Cadence Encounter or innovus): # These settings are the width of power/gnd wires and the spacing between them # The space_around_core param is the distance between core and IO (leaves enough space for power rings) +# Calculations: +# 1.8 x 2 (ring for VDD and VSS) + 1.8 x 3 (spacing between IO ring and first ring, the rings and last ring and core) = 9 um (1 um of extra space) + power_ring_width=1.8 power_ring_spacing=1.8 height_to_width_ratio=4.0