def main(): app_path = os.path.dirname(os.path.realpath(__file__)) # Parse command-line args parser = argparse.ArgumentParser( description= 'BLASYS -- Approximate Logic Synthesis Using Boolean Matrix Factorization' ) parser.add_argument('-i', help='Input verilog file', required=True, dest='input') parser.add_argument('-o', help='Output testbench file', required=True, dest='output') parser.add_argument('-n', help='Number of test vectors', type=int, default=10000, dest='number') args = parser.parse_args() print_banner() print('Start creating testbench ...') # Load path to yosys, lsoracle, iverilog, vvp, abc with open(os.path.join(app_path, 'config', 'params.yml'), 'r') as config_file: config = yaml.safe_load(config_file) create_testbench(args.input, args.output, args.number, config['yosys'])
def main(): # System config max_cpu = mp.cpu_count() app_path = os.path.dirname(os.path.realpath(__file__)) # Parse command-line args parser = argparse.ArgumentParser(description='BLASYS -- Approximate Logic Synthesis Using Boolean Matrix Factorization') parser.add_argument('-i', '--input', help='Input verilog file', required=True, dest='input') parser.add_argument('-tb', '--testbench', help='Number of test vectors', required=True, dest='testbench') parser.add_argument('-n', '--number', help='Number of partitions', default=None, type=int, dest='npart') parser.add_argument('-o', '--output', help='Output directory', default=None, dest='output') parser.add_argument('-ts', '--threshold', help='Threshold on error', default='None', dest='threshold') parser.add_argument('-lib', '--liberty', help='Liberty file name', default=None, dest='liberty') parser.add_argument('-ss', '--stepsize', help='Step size of optimization process', default=1, type=int, dest='stepsize') parser.add_argument('-m', '--metric', help='Choose error metric', dest='metric', default='HD') parser.add_argument('-tr', '--track', help='Number of tracks in greedy search', dest='track', type=int, default=3) parser.add_argument('-cpu', '--cpu_count', help='Specify number of CPU in parallel mode', dest='cpu', type=int, default=max_cpu) # Flags parser.add_argument('--parallel', help='Run the flow in parallel mode if specified', dest='parallel', action='store_true') parser.add_argument('--no_partition', help='Factorize without partition', dest='single', action='store_true') parser.add_argument('--sta', help='Use OpenSTA to estimate power and delay', dest='sta', action='store_true') args = parser.parse_args() print_banner() # Load path to yosys, lsoracle, iverilog, vvp, abc with open(os.path.join(app_path, 'config', 'params.yml'), 'r') as config_file: config = yaml.safe_load(config_file) config['part_config'] = os.path.join(app_path, 'config', 'test.ini') if args.threshold == 'None': threshold_list = [np.inf] else: threshold_list = list(map(float, args.threshold.split(','))) # Create optimizer worker = GreedyWorker(args.input, args.liberty, config, args.testbench, args.metric, args.sta) # Output directory worker.create_output_dir(args.output) # Evaluate input circuit worker.evaluate_initial() # Partition mode or non_partition mode if args.single is not True: worker.convert2aig() if args.npart is None: worker.recursive_partitioning() else: worker.recursive_partitioning(args.npart) worker.greedy_opt(args.parallel, args.cpu, args.stepsize, threshold_list, track=args.track) else: worker.blasys()
worker.greedy_opt(args.parallel, args.cpu, args.stepsize, threshold_list, track=args.track, accel=accelerate) else: worker.blasys() if __name__ == '__main__': # Open command-line interface if len(sys.argv) == 1: print_banner() Blasys().cmdloop() # Use script file as command-line elif len(sys.argv) == 3 and sys.argv[1] == '-f': script = sys.argv[2] blasys = Blasys() print_banner() with open(script, 'r') as f: cmd = f.readline() count = 0 while cmd: print('[' + str(count) + '] Run BLASYS command: ' + cmd) blasys.onecmd(cmd) cmd = f.readline() count += 1
def main(): app_path = os.path.dirname(os.path.realpath(__file__)) # Parse command-line args parser = argparse.ArgumentParser( description= 'BLASYS -- Approximate Logic Synthesis Using Boolean Matrix Factorization' ) parser.add_argument('-i', help='Input verilog file', required=True, dest='input') parser.add_argument('-tb', '--testbench', help='Number of test vectors', required=True, dest='testbench') parser.add_argument('-n', help='Number of partitions', default=None, type=int, dest='npart') parser.add_argument('-o', help='Output directory', default='output', dest='output') parser.add_argument('-ts', '--threshold', help='Threshold on error', default='None', dest='threshold') parser.add_argument('-lib', '--liberty', help='Liberty file name', required=True, dest='liberty') parser.add_argument('-ss', '--stepsize', help='Step size of optimization process', default=1, type=int, dest='stepsize') parser.add_argument('--parallel', help='Run the flow in parallel mode if specified', dest='parallel', action='store_true') parser.add_argument('--weight', help='Use weight in error metric', dest='use_weight', action='store_true') parser.add_argument('--single', help='Factorize without partition', dest='single', action='store_true') parser.add_argument('--track', help='Number of tracks in greedy search', dest='track', type=int, default=3) args = parser.parse_args() print_banner() # Load path to yosys, lsoracle, iverilog, vvp, abc with open(os.path.join(app_path, 'config', 'params.yml'), 'r') as config_file: config = yaml.safe_load(config_file) config['part_config'] = os.path.join(app_path, 'config', 'test.ini') if args.threshold == 'None': threshold_list = [np.inf] else: threshold_list = list(map(float, args.threshold.split(','))) worker = GreedyWorker(args.input, args.liberty, config, args.testbench) worker.create_output_dir(args.output) pis, pos = worker.evaluate_initial() if args.single is not True: worker.convert2aig() if args.npart is None: worker.recursive_partitioning() else: worker.recursive_partitioning(args.npart) worker.greedy_opt(args.parallel, args.stepsize, threshold_list, use_weight=args.use_weight, track=args.track) else: worker.blasys(args.use_weight)
def main(): app_path = os.path.dirname(os.path.realpath(__file__)) # Parse command-line args parser = argparse.ArgumentParser( description= 'BLASYS -- Approximate Logic Synthesis Using Boolean Matrix Factorization' ) parser.add_argument('-i', help='Input verilog file', required=True, dest='input') parser.add_argument('-tb', '--testbench', help='Testbench verilog file', required=True, dest='testbench') parser.add_argument('-o', help='Output directory', default='output', dest='output') parser.add_argument('-ts', '--threshold', help='Threshold on error', default=0.9, type=float, dest='threshold') parser.add_argument('-lib', '--liberty', help='Liberty file name', required=True, dest='liberty') parser.add_argument('-ss', '--stepsize', help='Step size in optimization process', default=1, type=int, dest='stepsize') parser.add_argument('--parallel', help='Run the flow in parallel mode if specified', dest='parallel', action='store_true') args = parser.parse_args() print_banner() # Get modulename with open(args.input) as file: line = file.readline() while line: tokens = re.split('[ (]', line) for i in range(len(tokens)): if tokens[i] == 'module': modulename = tokens[i + 1] break line = file.readline() # Create output dir print('Generate file directory ...') if os.path.isdir(args.output): shutil.rmtree(args.output) os.mkdir(args.output) os.mkdir(os.path.join(args.output, 'approx_design')) os.mkdir(os.path.join(args.output, 'truthtable')) os.mkdir(os.path.join(args.output, 'result')) # Load path to yosys, lsoracle, iverilog, vvp, abc with open(os.path.join(app_path, 'config', 'params.yml'), 'r') as config_file: config = yaml.safe_load(config_file) config['part_config'] = os.path.join(app_path, 'config', 'test.ini') config['script'] = os.path.join(args.output, 'abc.script') print(config['script']) with open(config['script'], 'w') as f: f.write('strash;fraig;refactor;rewrite -z;scorr;map') # Generate ground truth table print('Generate truthtable for input verilog ...') ground_truth = os.path.join(args.output, modulename + '.truth') subprocess.call([ config['iverilog'], '-o', ground_truth[:-5] + 'iv', args.input, args.testbench ]) with open(ground_truth, 'w') as f: subprocess.call([config['vvp'], ground_truth[:-5] + 'iv'], stdout=f) os.remove(ground_truth[:-5] + 'iv') # Get original chip area print('Synthesizing input design with original partitions...') output_synth = os.path.join(args.output, modulename) input_area = synth_design(args.input, output_synth, args.liberty, config['script'], config['yosys']) print('Original design area ', str(input_area)) initial_area = input_area with open(os.path.join(args.output, 'result', 'result.txt'), 'w') as f: f.write('Original chip area {:.2f}\n'.format(initial_area)) f.flush() # Partition into subcircuit with < 2000 cells modulenames, toplevel = recursive_partitioning(args.input, args.output, modulename, config) print('Generate testbench for each partition ...') for i in modulenames: module_file = os.path.join(args.output, 'partition', i) with open(module_file + '_tb.v', 'w') as f: create_testbench(module_file + '.v', 5000, f) file_list = [ os.path.join(args.output, 'partition', i + '.v') for i in modulenames ] tb_list = [ os.path.join(args.output, 'partition', i + '_tb.v') for i in modulenames ] output_list = [os.path.join(args.output, i) for i in modulenames] worker_list = [] # Initialize greedyWorker for each subcircuit for inp, tb, out in zip(file_list, tb_list, output_list): worker = GreedyWorker(inp, tb, args.liberty, config) worker.create_output_dir(out) worker.evaluate_initial() worker.recursive_partitioning() worker_list.append(worker) err_summary = [0.0] area_summary = [initial_area] curr_iter_list = [-1 for i in modulenames] max_iter_list = [-1 for i in modulenames] curr_file_list = file_list it = 0 while 1: err_list = [] area_list = [] candidate_list = [] candidate_iter_num = [] changed = {} count = 0 for i, (w, d) in enumerate(zip(worker_list, output_list)): if max(w.curr_stream) == 1: curr_iter_list[i] = -1 else: i_list = curr_iter_list.copy() i_list[i] += 1 if i_list[i] > max_iter_list[i]: w.next_iter(args.parallel, args.stepsize, least_error=True) max_iter_list[i] += 1 objective = os.path.join(d, 'approx_design', 'iter{}.v'.format(i_list[i])) k_list = curr_file_list.copy() k_list[i] = objective candidate_iter_num.append(i_list) candidate_list.append(k_list) changed[count] = i count += 1 if len(candidate_list) == 0: a = np.array(area_summary) i = np.argmin(a) source_file = os.path.join(args.output, 'approx_design', 'iter{}.v'.format(i)) target_file = os.path.join( args.output, 'result', '{}_{}metric.v'.format(modulename, round(100 * args.threshold))) shutil.copyfile(source_file, target_file) with open(os.path.join(args.output, 'result', 'result.txt'), 'a') as f: f.write('{}% error metric chip area {:.2f}\n'.format( 'REST', area_summary[i])) sys.exit(0) if args.parallel: pool = mp.Pool(mp.cpu_count()) results = [ pool.apply_async(evaluate_design, args=(candidate_list[i] + [toplevel], args.testbench, ground_truth, args.output, 'iter' + str(it) + 'design' + str(i), config, args.liberty)) for i in range(len(candidate_list)) ] pool.close() pool.join() for result in results: err_list.append(result.get()[0]) area_list.append(result.get()[1]) else: for i, l in enumerate(candidate_list): err, area = evaluate_design( l + [toplevel], args.testbench, ground_truth, args.output, 'iter' + str(it) + 'design' + str(i), config, args.liberty) err_list.append(err) area_list.append(area) rank = optimization(np.array(err_list), np.array(area_list) / initial_area, args.threshold + 0.01) idx = rank[0] err_summary.append(err_list[idx]) area_summary.append(area_list[idx]) shutil.copyfile( os.path.join(args.output, 'approx_design', 'iter{}design{}_syn.v'.format(it, idx)), os.path.join(args.output, 'approx_design', 'iter{}.v'.format(it))) curr_file_list = candidate_list[idx] curr_iter_list = candidate_iter_num[idx] for i, e in enumerate(err_list): if e <= err_summary[-2] and area_list[i] <= area_summary[-2]: curr_file_list[changed[i]] = candidate_list[i][changed[i]] curr_iter_list[changed[i]] = candidate_iter_num[i][changed[i]] with open(os.path.join(args.output, 'data.csv'), 'a') as data: data.write('{:.6f},{:.6f}\n'.format(err_list[idx], area_list[idx])) data.flush() if err_list[idx] >= args.threshold + 0.01: a = np.array(area_summary) e = np.array(err_summary) a[e > args.threshold] = np.inf i = np.argmin(a) source_file = os.path.join(args.output, 'approx_design', 'iter{}.v'.format(i)) target_file = os.path.join( args.output, 'result', '{}_{}metric.v'.format(modulename, round(100 * args.threshold))) shutil.copyfile(source_file, target_file) with open(os.path.join(args.output, 'result', 'result.txt'), 'a') as f: f.write('{:.1f}% error metric chip area {:.2f}\n'.format( 100 * args.threshold, area_summary[i])) f.flush() sys.exit(0) it += 1
def main(): app_path = os.path.dirname(os.path.realpath(__file__)) # Parse command-line args parser = argparse.ArgumentParser( description= 'BLASYS -- Approximate Logic Synthesis Using Boolean Matrix Factorization' ) parser.add_argument('-i', help='Input verilog file', required=True, dest='input') parser.add_argument('-tb', '--testbench', help='Testbench verilog file', required=True, dest='testbench') parser.add_argument('-n', help='Number of partitions', default=None, type=int, dest='npart') parser.add_argument('-o', help='Output directory', default='output', dest='output') parser.add_argument('-ts', '--threshold', help='Threshold on error', default=0.9, type=float, dest='threshold') parser.add_argument('-lib', '--liberty', help='Liberty file name', required=True, dest='liberty') parser.add_argument('-ss', '--stepsize', help='Step size of optimization process', default=1, type=int, dest='stepsize') parser.add_argument('--parallel', help='Run the flow in parallel mode if specified', dest='parallel', action='store_true') args = parser.parse_args() print_banner() # Load path to yosys, lsoracle, iverilog, vvp, abc with open(os.path.join(app_path, 'config', 'params.yml'), 'r') as config_file: config = yaml.safe_load(config_file) config['part_config'] = os.path.join(app_path, 'config', 'test.ini') worker = GreedyWorker(args.input, args.testbench, args.liberty, config) worker.create_output_dir(args.output) worker.evaluate_initial() if args.npart is None: worker.recursive_partitioning() else: worker.recursive_partitioning(args.npart) worker.greedy_opt(args.parallel, args.stepsize, args.threshold)