[test] add new testcase

This commit is contained in:
tangxifan 2023-11-13 14:11:34 -08:00
parent 0b83ca3902
commit d78f18d235
7 changed files with 1477 additions and 1 deletions

View File

@ -140,6 +140,9 @@ echo -e "Testing through channels in tileable routing";
run-task fpga_verilog/thru_channel/thru_narrow_tile $@
run-task fpga_verilog/thru_channel/thru_wide_tile $@
echo -e "Testing wire concatation in tileable routing";
run-task fpga_verilog/rr_concat_wire $@
echo -e "Testing the generation of preconfigured fabric wrapper for different HDL simulators";
run-task fpga_verilog/verilog_netlist_formats/embed_bitstream_none $@
run-task fpga_verilog/verilog_netlist_formats/embed_bitstream_modelsim $@

View File

@ -0,0 +1,173 @@
#####################################################################
# A script to create a bus group file based on an input verilog file
# The bug group file is an input required by OpenFPGA
#####################################################################
import os
from os.path import dirname, abspath
import argparse
import logging
import subprocess
import hashlib
import yaml
import pyverilog
from pyverilog.dataflow.dataflow_analyzer import VerilogDataflowAnalyzer
from xml.dom import minidom
#####################################################################
# Error codes
#####################################################################
error_codes = {
"SUCCESS": 0,
"MD5_ERROR": 1,
"OPTION_ERROR": 2,
"FILE_ERROR": 3
}
#####################################################################
# Initialize logger
#####################################################################
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO);
#####################################################################
# Generate the string for a Verilog port
#####################################################################
def gen_verilog_port_str(port_name, msb, lsb):
port_str = str(port_name) + "[" + str(msb) + ":" + str(lsb) + "]"
return port_str
#####################################################################
# Generate the string for a flatten Verilog port
#####################################################################
def gen_flatten_verilog_port_str(port_name, pin_id):
port_str = str(port_name) + "_" + str(pin_id) + "_"
return port_str
#####################################################################
# Parse a verilog file and collect bus port information
#####################################################################
def parse_verilog_file_bus_ports(verilog_files, top_module):
# Check if verilog file exists
verilog_file_list = []
for verilog_f in verilog_files:
print(verilog_f)
verilog_f_abspath = os.path.abspath(verilog_f["name"])
if not os.path.exists(verilog_f_abspath):
raise IOError("file not found: " + verilog_f_abspath)
verilog_file_list.append(verilog_f_abspath)
# Parse verilog file
analyzer = VerilogDataflowAnalyzer(verilog_file_list, top_module)
analyzer.generate()
# Get port information
terms = analyzer.getTerms()
# Create XML tree
xml = minidom.Document()
bus_group = xml.createElement("bus_group")
xml.appendChild(bus_group)
for tk, tv in sorted(terms.items(), key=lambda x: str(x[0])):
logging.debug(tv.name)
logging.debug(tv.termtype)
logging.debug("[" + str(tv.lsb) + ":" + str(tv.msb) + "]")
for tk, tv in sorted(terms.items(), key=lambda x: str(x[0])):
# Skip ports that do not belong to top module
if (top_module != str(tv.name).split(".")[-2]):
continue
port_name = str(tv.name).split(".")[-1]
# Skip minus lsb or msb, which are in don't care set
if (("Minus" == str(tv.lsb)) or ("Minus" == str(tv.msb))):
continue
port_lsb = int(str(tv.lsb))
port_msb = int(str(tv.msb))
# Only care input and outports
if ((not ("Input" in tv.termtype)) and (not ("Output" in tv.termtype))):
continue
# Only care bus (msb - lsb > 0)
if (abs(port_lsb - port_msb) == 0):
continue
# Reaching here, this is a bus port we need
# Get the second part of the name, which is the port name
cur_bus = xml.createElement("bus")
cur_bus.setAttribute("name", gen_verilog_port_str(port_name, port_msb, port_lsb))
# Get if this is little endian or not
cur_bus.setAttribute("big_endian", "false")
if (port_lsb > port_msb):
cur_bus.setAttribute("big_endian", "true")
bus_group.appendChild(cur_bus)
# Add all the pins
for ipin in range(min([port_msb, port_lsb]), max([port_msb, port_lsb]) + 1):
cur_pin = xml.createElement("pin")
cur_pin.setAttribute('id', str(ipin))
cur_pin.setAttribute('name', gen_flatten_verilog_port_str(port_name, ipin))
cur_bus.appendChild(cur_pin)
return xml, bus_group
#####################################################################
# Generate bus group files with a given task list
#####################################################################
def generate_bus_group_files(task_db):
# Iterate over all the tasks
for verilog_fname in task_db.keys():
space_limit = 120
log_str = "Parsing verilog file: "
top_module_name = task_db[verilog_fname]["top_module"]
logging_space = "." * (space_limit - len(log_str) - len(top_module_name))
logging.info(log_str + top_module_name)
xml, bus_group_data = parse_verilog_file_bus_ports(task_db[verilog_fname]["source"], top_module_name)
logging.info(log_str + top_module_name + logging_space + "Done")
# Write bus ports to an XML file
bus_group_frelname = task_db[verilog_fname]["bus_group_file"]
bus_group_fname = os.path.abspath(bus_group_frelname)
log_str = "Writing bus group file:"
logging_space = "." * (space_limit - len(log_str) - len(bus_group_frelname))
logging.info(log_str + bus_group_frelname)
xml_str = xml.toprettyxml(indent="\t")
with open(bus_group_fname, "w") as bus_group_f:
bus_group_f.write(xml_str)
logging.info(log_str + bus_group_frelname + logging_space + "Done")
#####################################################################
# Read task list from a yaml file
#####################################################################
def read_yaml_to_task_database(yaml_filename):
task_db = {}
with open(yaml_filename, 'r') as stream:
try:
task_db = yaml.load(stream, Loader=yaml.FullLoader)
logging.info("Found " + str(len(task_db)) + " tasks to create symbolic links")
except yaml.YAMLError as exc:
logging.error(exc)
exit(error_codes["FILE_ERROR"]);
return task_db
#####################################################################
# Write result database to a yaml file
#####################################################################
def write_result_database_to_yaml(result_db, yaml_filename):
with open(yaml_filename, 'w') as yaml_file:
yaml.dump(result_db, yaml_file, default_flow_style=False)
#####################################################################
# Main function
#####################################################################
if __name__ == '__main__':
# Execute when the module is not initialized from an import statement
# Parse the options and apply sanity checks
parser = argparse.ArgumentParser(description='Create bus group files for Verilog inputs')
parser.add_argument('--task_list',
required=True,
help='Configuration file in YAML format which contains a list of input Verilog and output bus group files')
args = parser.parse_args()
# Create a database for tasks
task_db = {}
task_db = read_yaml_to_task_database(args.task_list)
# Generate links based on the task list in database
generate_bus_group_files(task_db)
logging.info("Created " + str(len(task_db)) + " bus group files")
exit(error_codes["SUCCESS"])

View File

@ -0,0 +1,5 @@
counter8:
source:
- name: counter_output_verilog.v
top_module: counter
bus_group_file: bus_group.xml

View File

@ -0,0 +1,7 @@
<pin_constraints>
<!-- For a given .blif file, we want to assign
- the reset signal to the op_reset[0] port of the FPGA fabric
-->
<set_io pin="op_reset[0]" net="reset"/>
</pin_constraints>

View File

@ -0,0 +1,48 @@
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# Configuration file for running experiments
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
# Each job execute fpga_flow script on combination of architecture & benchmark
# timeout_each_job is timeout for each job
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
[GENERAL]
run_engine=openfpga_shell
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
power_analysis = false
spice_output=false
verilog_output=true
timeout_each_job = 20*60
fpga_flow=yosys_vpr
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/auto_bus_group_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_dpram8K_dsp36_fracff_40nm_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
openfpga_verilog_port_mapping=--explicit_port_mapping
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileableConcatWire_adder_chain_dpram8K_dsp36_fracff_40nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/counters/counter_8bit_async_reset/counter.v
[SYNTHESIS_PARAM]
# Yosys script parameters
bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_cell_sim.v
bench_yosys_dff_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_fracff_40nm_dff_map.v
bench_yosys_bram_map_rules_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram.txt
bench_yosys_bram_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_bram_map.v
bench_yosys_dsp_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/k6_frac_N10_tileable_adder_chain_dpram8K_dsp36_40nm_dsp_map.v
bench_yosys_dsp_map_parameters_common=-D DSP_A_MAXWIDTH=36 -D DSP_B_MAXWIDTH=36 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=mult_36x36
bench_read_verilog_options_common = -nolatches
bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_dff_flow.ys
bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys
bench0_top = counter
bench0_openfpga_pin_constraints_file=${PATH:TASK_DIR}/config/pin_constraints_reset.xml
bench0_openfpga_bus_group_file=bus_group.xml
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=
vpr_fpga_verilog_formal_verification_top_netlist=

View File

@ -5,8 +5,9 @@ Please reveal the following architecture features in the names to help quickly s
* The keyword 'frac' is to specify if fracturable LUT is used or not.
* The keyword 'Native' is to specify if fracturable LUT design is a native one (without mode switch) or a standard one (with mode switch).
- N<le\_size>: Number of logic elements for a CLB. If you have multiple CLB architectures, this should be largest number.
- tileable<IO>: If the routing architecture is tileable or not.
- tileable<IO|ConcatWire>: If the routing architecture is tileable or not.
* The keyword 'IO' specifies if the I/O tile is tileable or not
* The keyword 'ConcatWire' specifies if the routing wires can be continued in the same direction or not. For example, L4 -> L1
- fracff<2edge>: Use multi-mode flip-flop model, where reset/set polarity is configurable. When 2edge is specified, clock polarity can be switched between postive edge triggered and negative edge triggered
- adder\_chain: If hard adder/carry chain is used inside CLBs
- register\_chain: If shift register chain is used inside CLBs