""" This is a DRC/LVS/PEX interface file for magic + netgen. This assumes you have the SCMOS magic rules installed. Get these from: ftp://ftp.mosis.edu/pub/sondeen/magic/new/beta/current.tar.gz and install them in: cd /opt/local/lib/magic/sys tar zxvf current.tar.gz ln -s 2001a current 1. magic can perform drc with the following: #!/bin/sh magic -dnull -noconsole << EOF tech load SCN3ME_SUBM.30 #scalegrid 1 2 gds rescale no gds polygon subcell true gds warning default gds read $1 load $1 writeall force drc count drc why quit -noprompt EOF 2. magic can perform extraction with the following: #!/bin/sh rm -f $1.ext rm -f $1.spice magic -dnull -noconsole << EOF tech load SCN3ME_SUBM.30 #scalegrid 1 2 gds rescale no gds polygon subcell true gds warning default gds read $1 extract ext2spice scale off ext2spice quit -noprompt EOF 3. netgen can perform LVS with: #!/bin/sh netgen -noconsole < 0: for line in results: if "error tiles" in line: debug.info(1,line.rstrip("\n")) debug.error("DRC Errors {0}\t{1}".format(cell_name, errors)) else: debug.info(1, "DRC Errors {0}\t{1}".format(cell_name, errors)) return errors def run_lvs(cell_name, gds_name, sp_name, final_verification=False): """Run LVS check on a given top-level name which is implemented in gds_name and sp_name. Final verification will ensure that there are no remaining virtual conections. """ global num_lvs_runs num_lvs_runs += 1 run_drc(cell_name, gds_name, extract=True) write_netgen_script(cell_name, sp_name) # run LVS cwd = os.getcwd() os.chdir(OPTS.openram_temp) errfile = "{0}{1}.lvs.err".format(OPTS.openram_temp, cell_name) outfile = "{0}{1}.lvs.out".format(OPTS.openram_temp, cell_name) resultsfile = "{0}{1}.lvs.report".format(OPTS.openram_temp, cell_name) cmd = "{0}run_lvs.sh lvs 2> {1} 1> {2}".format(OPTS.openram_temp, errfile, outfile) debug.info(2, cmd) os.system(cmd) os.chdir(cwd) total_errors = 0 # check the result for these lines in the summary: f = open(resultsfile, "r") results = f.readlines() f.close() # Look for the results after the final "Subcircuit summary:" # which will be the top-level netlist. final_results = [] for line in reversed(results): if "Subcircuit summary:" in line: break else: final_results.insert(0,line) # There were property errors in any module. test = re.compile("Property errors were found.") propertyerrors = list(filter(test.search, results)) total_errors += len(propertyerrors) # Require pins to match? # Cell pin lists for pnand2_1.spice and pnand2_1 altered to match. # test = re.compile(".*altered to match.") # pinerrors = list(filter(test.search, results)) # if len(pinerrors)>0: # debug.warning("Pins altered to match in {}.".format(cell_name)) #if len(propertyerrors)>0: # debug.warning("Property errors found, but not checking them.") # Netlists do not match. test = re.compile("Netlists do not match.") incorrect = list(filter(test.search, final_results)) total_errors += len(incorrect) # Netlists match uniquely. test = re.compile("match uniquely.") correct = list(filter(test.search, final_results)) # Fail if they don't match. Something went wrong! if len(correct) == 0: total_errors += 1 if total_errors>0: # Just print out the whole file, it is short. for e in results: debug.info(1,e.strip("\n")) debug.error("{0}\tLVS mismatch (results in {1})".format(cell_name,resultsfile)) else: debug.info(1, "{0}\tLVS matches".format(cell_name)) return total_errors def run_pex(name, gds_name, sp_name, output=None): """Run pex on a given top-level name which is implemented in gds_name and sp_name. """ global num_pex_runs num_pex_runs += 1 debug.warning("PEX using magic not implemented.") return 1 from tech import drc if output == None: output = name + ".pex.netlist" # check if lvs report has been done # if not run drc and lvs if not os.path.isfile(name + ".lvs.report"): run_drc(name, gds_name) run_lvs(name, gds_name, sp_name) pex_rules = drc["xrc_rules"] pex_runset = { 'pexRulesFile': pex_rules, 'pexRunDir': OPTS.openram_temp, 'pexLayoutPaths': gds_name, 'pexLayoutPrimary': name, #'pexSourcePath' : OPTS.openram_temp+"extracted.sp", 'pexSourcePath': sp_name, 'pexSourcePrimary': name, 'pexReportFile': name + ".lvs.report", 'pexPexNetlistFile': output, 'pexPexReportFile': name + ".pex.report", 'pexMaskDBFile': name + ".maskdb", 'cmnFDIDEFLayoutPath': name + ".def", } # write the runset file f = open(OPTS.openram_temp + "pex_runset", "w") for k in sorted(pex_runset.iterkeys()): f.write("*{0}: {1}\n".format(k, pex_runset[k])) f.close() # run pex cwd = os.getcwd() os.chdir(OPTS.openram_temp) errfile = "{0}{1}.pex.err".format(OPTS.openram_temp, name) outfile = "{0}{1}.pex.out".format(OPTS.openram_temp, name) cmd = "{0} -gui -pex {1}pex_runset -batch 2> {2} 1> {3}".format(OPTS.pex_exe, OPTS.openram_temp, errfile, outfile) debug.info(2, cmd) os.system(cmd) os.chdir(cwd) # also check the output file f = open(outfile, "r") results = f.readlines() f.close() # Errors begin with "ERROR:" test = re.compile("ERROR:") stdouterrors = list(filter(test.search, results)) for e in stdouterrors: debug.error(e.strip("\n")) out_errors = len(stdouterrors) assert(os.path.isfile(output)) #correct_port(name, output, sp_name) return out_errors def print_drc_stats(): debug.info(1,"DRC runs: {0}".format(num_drc_runs)) def print_lvs_stats(): debug.info(1,"LVS runs: {0}".format(num_lvs_runs)) def print_pex_stats(): debug.info(1,"PEX runs: {0}".format(num_pex_runs))