mirror of https://github.com/lnis-uofu/SOFA.git
Merge pull request #37 from LNIS-Projects/xt_dev
Python Script to Convert pre-PnR Verilog Testbench to post-PnR Verilog Testbench
This commit is contained in:
commit
5bb0db4e91
|
@ -59,8 +59,10 @@ write_verilog_testbench --file ${OPENFPGA_VERILOG_OUTPUT_DIR}/verilog_testbench
|
||||||
--print_top_testbench \
|
--print_top_testbench \
|
||||||
--print_preconfig_top_testbench \
|
--print_preconfig_top_testbench \
|
||||||
--print_simulation_ini ${OPENFPGA_VERILOG_OUTPUT_DIR}/SimulationDeck/simulation_deck.ini \
|
--print_simulation_ini ${OPENFPGA_VERILOG_OUTPUT_DIR}/SimulationDeck/simulation_deck.ini \
|
||||||
--include_signal_init \
|
|
||||||
--explicit_port_mapping
|
--explicit_port_mapping
|
||||||
|
# Exclude signal initialization since it does not help simulator converge
|
||||||
|
# due to the lack of reset pins for flip-flops
|
||||||
|
#--include_signal_init
|
||||||
|
|
||||||
# Write the SDC to run timing analysis for a mapped FPGA fabric
|
# Write the SDC to run timing analysis for a mapped FPGA fabric
|
||||||
write_analysis_sdc --file ${OPENFPGA_VERILOG_OUTPUT_DIR}/sdc_analysis
|
write_analysis_sdc --file ${OPENFPGA_VERILOG_OUTPUT_DIR}/sdc_analysis
|
||||||
|
|
|
@ -11,6 +11,7 @@ import shutil
|
||||||
import re
|
import re
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
|
import subprocess
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
# Initialize logger
|
# Initialize logger
|
||||||
|
@ -64,7 +65,8 @@ for root, dirs, files in os.walk(openfpga_arch_template_dirpath):
|
||||||
shutil.copy(openfpga_arch_template_dirpath + src_file, des_file);
|
shutil.copy(openfpga_arch_template_dirpath + src_file, des_file);
|
||||||
homepath_to_replace = re.sub("/", "\/", skywater_openfpga_homepath);
|
homepath_to_replace = re.sub("/", "\/", skywater_openfpga_homepath);
|
||||||
cmd = "sed -i 's/${SKYWATER_OPENFPGA_HOME}/" + homepath_to_replace + "/g' " + des_file;
|
cmd = "sed -i 's/${SKYWATER_OPENFPGA_HOME}/" + homepath_to_replace + "/g' " + des_file;
|
||||||
os.system(cmd);
|
# Error out if this command fails
|
||||||
|
subprocess.run(cmd, shell=True, check=True);
|
||||||
num_arch_file_processed += 1;
|
num_arch_file_processed += 1;
|
||||||
|
|
||||||
logging.info("Processed for " + str(num_arch_file_processed) + " openfpga architecture templates");
|
logging.info("Processed for " + str(num_arch_file_processed) + " openfpga architecture templates");
|
||||||
|
@ -102,7 +104,8 @@ for task_template_file in get_list_of_task_config_files(skywater_openfpga_task_d
|
||||||
shutil.copy(task_template_file, task_conf_file);
|
shutil.copy(task_template_file, task_conf_file);
|
||||||
homepath_to_replace = re.sub("/", "\/", skywater_openfpga_homepath);
|
homepath_to_replace = re.sub("/", "\/", skywater_openfpga_homepath);
|
||||||
cmd = "sed -i 's/${SKYWATER_OPENFPGA_HOME}/" + homepath_to_replace + "/g' " + task_conf_file;
|
cmd = "sed -i 's/${SKYWATER_OPENFPGA_HOME}/" + homepath_to_replace + "/g' " + task_conf_file;
|
||||||
os.system(cmd);
|
# Error out if this command fails
|
||||||
|
subprocess.run(cmd, shell=True, check=True);
|
||||||
num_task_config_file_processed += 1;
|
num_task_config_file_processed += 1;
|
||||||
|
|
||||||
logging.info("Processed for " + str(num_task_config_file_processed) + "openfpga task templates");
|
logging.info("Processed for " + str(num_task_config_file_processed) + "openfpga task templates");
|
||||||
|
@ -148,12 +151,14 @@ for task_name in openfpga_task_list:
|
||||||
# Remove all the previous runs in the openfpga task to ensure a clean start
|
# Remove all the previous runs in the openfpga task to ensure a clean start
|
||||||
logging.info("Clean up previous runs for openfpga task: " + task_name + "...");
|
logging.info("Clean up previous runs for openfpga task: " + task_name + "...");
|
||||||
cmd = "python3 openfpga_flow/scripts/run_fpga_task.py " + task_name + " --debug --show_thread_logs --remove_run_dir all";
|
cmd = "python3 openfpga_flow/scripts/run_fpga_task.py " + task_name + " --debug --show_thread_logs --remove_run_dir all";
|
||||||
os.system(cmd);
|
# Error out if this task run fails
|
||||||
|
subprocess.run(cmd, shell=True, check=True);
|
||||||
logging.info("Done");
|
logging.info("Done");
|
||||||
# Execute new task run
|
# Execute new task run
|
||||||
cmd = "python3 openfpga_flow/scripts/run_fpga_task.py " + task_name + " --debug --show_thread_logs";
|
cmd = "python3 openfpga_flow/scripts/run_fpga_task.py " + task_name + " --debug --show_thread_logs";
|
||||||
logging.info("Running openfpga task: " + task_name + "...");
|
logging.info("Running openfpga task: " + task_name + "...");
|
||||||
os.system(cmd);
|
# Error out if this task run fails
|
||||||
|
subprocess.run(cmd, shell=True, check=True);
|
||||||
logging.info("Done");
|
logging.info("Done");
|
||||||
|
|
||||||
os.chdir(skywater_openfpga_homepath);
|
os.chdir(skywater_openfpga_homepath);
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
#####################################################################
|
||||||
|
# Python script to convert pre-PnR Verilog testbench
|
||||||
|
# to post-PnR Verilog testbench
|
||||||
|
# This script will
|
||||||
|
# - Add ports required by post-PnR Verilog module
|
||||||
|
# - Scan-chain head and tail ports
|
||||||
|
# - Add signal stimuli for the scan-chain head and tails
|
||||||
|
# - Rename fpga_top to fpga_core when instanciate Design Under Test (DUT)
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
import os
|
||||||
|
from os.path import dirname, abspath, isfile
|
||||||
|
import shutil
|
||||||
|
import re
|
||||||
|
import argparse
|
||||||
|
import logging
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# Initialize logger
|
||||||
|
#####################################################################
|
||||||
|
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG)
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# Parse the options
|
||||||
|
#####################################################################
|
||||||
|
parser = argparse.ArgumentParser(description='Converter for post-PnR Verilog testbench')
|
||||||
|
parser.add_argument('--pre_pnr_testbench', required=True,
|
||||||
|
help='Specify the file path for the pre-PnR Verilog testbench as input')
|
||||||
|
parser.add_argument('--post_pnr_testbench', required=True,
|
||||||
|
help='Specify the file path for the post-PnR Verilog testbench to be outputted')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# Check options:
|
||||||
|
# - Input file must be valid
|
||||||
|
# Otherwise, error out
|
||||||
|
# - Remove any output file if already exist
|
||||||
|
# TODO: give a warning when remove files
|
||||||
|
#####################################################################
|
||||||
|
if not isfile(args.pre_pnr_testbench):
|
||||||
|
logging.error("Invalid pre-PnR testbench: " + args.pre_pnr_testbench + "\nFile does not exist!\n")
|
||||||
|
exit(1)
|
||||||
|
if isfile(args.post_pnr_testbench):
|
||||||
|
logging.warn("Remove existing post-PnR testbench: " + args.post_pnr_testbench + "!\n")
|
||||||
|
os.remove(args.post_pnr_testbench)
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# Open the post-pnr Verilog testbench and start modification
|
||||||
|
#####################################################################
|
||||||
|
logging.info("Converting pre-PnR testbench:"+ args.pre_pnr_testbench)
|
||||||
|
logging.info(" To post-PnR testbench:"+ args.post_pnr_testbench)
|
||||||
|
# Create output file handler
|
||||||
|
tb_file = open(args.post_pnr_testbench, "w")
|
||||||
|
|
||||||
|
# Read line by line from pre-PnR testbench
|
||||||
|
with open(args.pre_pnr_testbench, "r") as wp:
|
||||||
|
template_netlist = wp.readlines()
|
||||||
|
for line_num, curr_line in enumerate(template_netlist):
|
||||||
|
# If the current line satisfy the following conditions
|
||||||
|
# It should be modified and outputted to post-PnR Verilog testbenches
|
||||||
|
# Other lines can be directly copied to post-PnR Verilog testbenches
|
||||||
|
line2output = curr_line \
|
||||||
|
# Condition A:
|
||||||
|
# Add sc_head and sc_tail wire definition after ccff tail definition
|
||||||
|
if (curr_line == "wire [0:0] ccff_tail;\n"):
|
||||||
|
line2output = line2output \
|
||||||
|
+ "// ---- Scan-chain head ----\n" \
|
||||||
|
+ "wire [0:0] sc_head;\n" \
|
||||||
|
+ "// ---- Scan-chain tail ----\n" \
|
||||||
|
+ "wire [0:0] sc_tail;\n"
|
||||||
|
# Condition B:
|
||||||
|
# Assign an initial value to sc_head after other ports
|
||||||
|
elif (curr_line == "\tassign IO_ISOL_N[0] = 1'b1;\n"):
|
||||||
|
line2output = line2output \
|
||||||
|
+ "\tassign sc_head[0] = 1'b0;\n"
|
||||||
|
# Condition C:
|
||||||
|
# Replace fpga_top with fpga_core in DUT instanciation
|
||||||
|
elif (curr_line == "\tfpga_top FPGA_DUT (\n"):
|
||||||
|
line2output = "\tfpga_core FPGA_DUT (\n"
|
||||||
|
# Condition D:
|
||||||
|
# Add sc_head and sc_tail to the port mapping of FPGA core instance
|
||||||
|
elif (curr_line == "\t\t.ccff_tail(ccff_tail[0]));\n"):
|
||||||
|
line2output = "\t\t.ccff_tail(ccff_tail[0]),\n" \
|
||||||
|
+ "\t\t.sc_head(sc_head[0]),\n" \
|
||||||
|
+ "\t\t.sc_tail(sc_tail[0])\n" \
|
||||||
|
+ "\t\t);\n"
|
||||||
|
|
||||||
|
tb_file.write(line2output)
|
||||||
|
|
||||||
|
tb_file.close()
|
||||||
|
logging.info("Done")
|
Loading…
Reference in New Issue