From a08de860005d477f1cf6ab1b244c3aeb6ed101aa Mon Sep 17 00:00:00 2001 From: komaljaved-rs <86342771+komaljaved-rs@users.noreply.github.com> Date: Wed, 30 Jun 2021 14:58:13 +0500 Subject: [PATCH 001/229] Update build.yml --- .github/workflows/build.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 77ccb1527..6b88712f1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,10 +3,11 @@ name: linux_build # Run CI on push, PR, and weekly. on: - push: - pull_request: - schedule: - - cron: "0 0 * * 0 " # weekly + workflow_dispatch: +# push: +# pull_request: +# schedule: +# - cron: "0 0 * * 0 " # weekly # Environment variables env: From 4b6b0273ba6c94562afba559ac629eb9a3595f0b Mon Sep 17 00:00:00 2001 From: komaljaved-rs <86342771+komaljaved-rs@users.noreply.github.com> Date: Thu, 1 Jul 2021 14:44:48 +0500 Subject: [PATCH 002/229] Create openfpga.yml --- .github/workflows/openfpga.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/openfpga.yml diff --git a/.github/workflows/openfpga.yml b/.github/workflows/openfpga.yml new file mode 100644 index 000000000..072f2824b --- /dev/null +++ b/.github/workflows/openfpga.yml @@ -0,0 +1,31 @@ +# This is a basic workflow to help you get started with Actions + +name: CI + +# Controls when the workflow will run +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + + # Runs a single command using the runners shell + - name: Run a one-line script + run: echo Hello, world! + + # Runs a set of commands using the runners shell + - name: Run a multi-line script + run: | + echo Add other actions to build, + echo test, and deploy your project. + ./ci_test.sh From cbb4b32f7fdaee57820e172e46eee5c33d7e4fc0 Mon Sep 17 00:00:00 2001 From: komaljaved-rs <86342771+komaljaved-rs@users.noreply.github.com> Date: Thu, 1 Jul 2021 14:45:38 +0500 Subject: [PATCH 003/229] Rename openfpga.yml to ci_test.yml --- .github/workflows/{openfpga.yml => ci_test.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{openfpga.yml => ci_test.yml} (100%) diff --git a/.github/workflows/openfpga.yml b/.github/workflows/ci_test.yml similarity index 100% rename from .github/workflows/openfpga.yml rename to .github/workflows/ci_test.yml From 1e81dd897f3c734bdc3f18ad1e85e611d057802d Mon Sep 17 00:00:00 2001 From: komaljaved-rs <86342771+komaljaved-rs@users.noreply.github.com> Date: Thu, 1 Jul 2021 14:47:59 +0500 Subject: [PATCH 004/229] Update ci_test.yml --- .github/workflows/ci_test.yml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index 072f2824b..5319389ed 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -12,20 +12,14 @@ jobs: # This workflow contains a single job called "build" build: # The type of runner that the job will run on - runs-on: ubuntu-latest + runs-on: self-hosted # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 - # Runs a single command using the runners shell - - name: Run a one-line script - run: echo Hello, world! - # Runs a set of commands using the runners shell - - name: Run a multi-line script - run: | - echo Add other actions to build, - echo test, and deploy your project. - ./ci_test.sh + - name: Executing Script + run: + ./ci_test.sh From 6559f7108227ff3a68a91e06409b9842950c7c01 Mon Sep 17 00:00:00 2001 From: komaljaved-rs Date: Thu, 1 Jul 2021 15:07:37 +0500 Subject: [PATCH 005/229] added ci_scripts --- .gitmodules | 3 + RTL_Benchmark | 1 + ci_test.sh | 26 + openfpga_flow/scripts/run_ci_tests.py | 531 ++++++++++++++++++ openfpga_flow/tasks/ci_tests/config/task.conf | 39 ++ 5 files changed, 600 insertions(+) create mode 160000 RTL_Benchmark create mode 100755 ci_test.sh create mode 100644 openfpga_flow/scripts/run_ci_tests.py create mode 100644 openfpga_flow/tasks/ci_tests/config/task.conf diff --git a/.gitmodules b/.gitmodules index 1fb1d4212..e99222f81 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,6 @@ path = yosys url = https://github.com/QuickLogic-Corp/yosys.git branch = quicklogic-rebased +[submodule "RTL_Benchmark"] + path = RTL_Benchmark + url = git@github.com:RapidSilicon/RTL_Benchmark.git diff --git a/RTL_Benchmark b/RTL_Benchmark new file mode 160000 index 000000000..f976d0771 --- /dev/null +++ b/RTL_Benchmark @@ -0,0 +1 @@ +Subproject commit f976d0771598259f6d4a5ca10899d55b7e5d7a3d diff --git a/ci_test.sh b/ci_test.sh new file mode 100755 index 000000000..bd0ac8e3e --- /dev/null +++ b/ci_test.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +export OPENFPGA_PATH=/home/komal.javed@lmlhr.com/rapidsilicon/openfpga_new + +for dir in RTL_Benchmark/*; do + if [ -d "$dir" ]; then + echo "Looking for top file in $dir/rtl" + + top_file="$(basename "$dir")" + + FILE=$dir/rtl/$top_file.v + + if [ -f "$FILE" ]; then + echo -e "${CYAN}$top_file exists ${ENDCOLOR}" + export design_path=${OPENFPGA_PATH}/$FILE + export design_top=$top_file + echo "design = $design_path" + python3 openfpga_flow/scripts/run_ci_tests.py ci_tests + else + echo -e "${RED}Top file not found. Make sure design exists${ENDCOLOR}" + exit 1 + fi + fi +done + + diff --git a/openfpga_flow/scripts/run_ci_tests.py b/openfpga_flow/scripts/run_ci_tests.py new file mode 100644 index 000000000..0e6c4e86f --- /dev/null +++ b/openfpga_flow/scripts/run_ci_tests.py @@ -0,0 +1,531 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Script Name : run_fpga_task.py +# Description : This script designed to run openfpga_flow tasks, +# Opensfpga task are design to run opefpga_flow on each +# Combination of architecture, benchmark and script paramters +# Args : python3 run_fpga_task.py --help +# Author : Ganesh Gore +# Email : ganesh.gore@utah.edu +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +import os +import sys +import shutil +import time +from datetime import timedelta +import shlex +import argparse +from configparser import ConfigParser, ExtendedInterpolation +import logging +import glob +import subprocess +import threading +import csv +from string import Template +import pprint +from importlib import util +from collections import OrderedDict + +if util.find_spec("coloredlogs"): + import coloredlogs +if util.find_spec("humanize"): + import humanize + +if sys.version_info[0] < 3: + raise Exception("run_fpga_task script must be using Python 3") + +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configure logging system +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +LOG_FORMAT = "%(levelname)5s (%(threadName)15s) - %(message)s" +if util.find_spec("coloredlogs"): + coloredlogs.install(level='INFO', stream=sys.stdout, + fmt=LOG_FORMAT) +else: + logging.basicConfig(level=logging.INFO, stream=sys.stdout, + format=LOG_FORMAT) +logger = logging.getLogger('OpenFPGA_Task_logs') + + +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Read commandline arguments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +parser = argparse.ArgumentParser() +parser.add_argument('tasks', nargs='+') +parser.add_argument('--maxthreads', type=int, default=2, + help="Number of fpga_flow threads to run default = 2," + + "Typically <= Number of processors on the system") +parser.add_argument('--remove_run_dir', type=str, + help="Remove run dir " + + "'all' to remove all." + + ", to remove specific run dir" + + "- To remove range of directory") +parser.add_argument('--config', help="Override default configuration") +parser.add_argument('--test_run', action="store_true", + help="Dummy run shows final generated VPR commands") +parser.add_argument('--debug', action="store_true", + help="Run script in debug mode") +parser.add_argument('--continue_on_fail', action="store_true", + help="Exit script with return code") +parser.add_argument('--show_thread_logs', action="store_true", + help="Skips logs from running thread") +args = parser.parse_args() + +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Read script configuration file +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +task_script_dir = os.path.dirname(os.path.abspath(__file__)) +DESIGN_PATH_ENV=os.environ['design_path'] +DESIGN_TOP_ENV=os.environ['design_top'] +script_env_vars = ({"PATH": { + "DESIGN_PATH": DESIGN_PATH_ENV, + "DESIGN_TOP":DESIGN_TOP_ENV, + "OPENFPGA_FLOW_PATH": task_script_dir, + "ARCH_PATH": os.path.join("${PATH:OPENFPGA_PATH}", "arch"), + "OPENFPGA_SHELLSCRIPT_PATH": os.path.join("${PATH:OPENFPGA_PATH}", "OpenFPGAShellScripts"), + "BENCH_PATH": os.path.join("${PATH:OPENFPGA_PATH}", "benchmarks"), + "TECH_PATH": os.path.join("${PATH:OPENFPGA_PATH}", "tech"), + "SPICENETLIST_PATH": os.path.join("${PATH:OPENFPGA_PATH}", "SpiceNetlists"), + "VERILOG_PATH": os.path.join("${PATH:OPENFPGA_PATH}", "VerilogNetlists"), + "OPENFPGA_PATH": os.path.abspath(os.path.join(task_script_dir, os.pardir, + os.pardir))}}) + +config = ConfigParser(interpolation=ExtendedInterpolation()) +config.read_dict(script_env_vars) +config.read_file(open(os.path.join(task_script_dir, 'run_fpga_task.conf'))) +gc = config["GENERAL CONFIGURATION"] + + +def main(): + validate_command_line_arguments() + for eachtask in args.tasks: + logger.info("Currently running task %s" % eachtask) + eachtask = eachtask.replace("\\", "/").split("/") + job_run_list = generate_each_task_actions(eachtask) + if args.remove_run_dir: + continue + eachtask = "_".join(eachtask) + if not args.test_run: + run_actions(job_run_list) + collect_results(job_run_list) + else: + pprint.pprint(job_run_list) + logger.info("Task execution completed") + exit(0) + +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Subroutines starts here +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + + +def clean_up_and_exit(msg): + logger.error(msg) + logger.error("Exiting . . . . . .") + exit(1) + + +def validate_command_line_arguments(): + if args.debug: + logger.info("Setting loggger in debug mode") + logger.setLevel(logging.DEBUG) + logger.info("Set up to run %d Parallel threads", args.maxthreads) + + +def remove_run_dir(): + remove_dir = [] + try: + argval = args.remove_run_dir.lower() + if argval == "all": + for eachRun in glob.glob("run*"): + remove_dir += [eachRun] + elif "-" in argval: + minval, maxval = map(int, argval.split("-")) + if minval > maxval: + raise Exception("Enter valid range to remove") + for eachRun in glob.glob("run*"): + if minval <= int(eachRun[-3:]) <= maxval: + remove_dir += [eachRun] + elif "," in argval: + for eachRun in argval.split(","): + remove_dir += ["run%03d" % int(eachRun)] + else: + logger.error("Unknow argument to --remove_run_dir") + except: + logger.exception("Failed to parse remove rund_dir options") + + try: + for eachdir in remove_dir: + logger.info('Removing run_dir %s' % (eachdir)) + if os.path.exists('latest'): + if eachdir == os.readlink('latest'): + remove_dir += ["latest"] + shutil.rmtree(eachdir, ignore_errors=True) + except: + logger.exception("Failed to remove %s run directory" % + (eachdir or "Unknown")) + + +def generate_each_task_actions(taskname): + """ + This script generates all the scripts required for each benchmark + """ + + # Check if task directory exists and consistent + local_tasks = os.path.join(*(taskname)) + repo_tasks = os.path.join(gc["task_dir"], *(taskname)) + if os.path.isdir(local_tasks): + os.chdir(local_tasks) + curr_task_dir = os.path.abspath(os.getcwd()) + elif os.path.isdir(repo_tasks): + curr_task_dir = repo_tasks + else: + clean_up_and_exit("Task directory [%s] not found" % taskname + " locally at [%s]" % local_tasks + " or in OpenFPGA task directory [%s]" % repo_tasks) + + os.chdir(curr_task_dir) + + curr_task_conf_file = os.path.join(curr_task_dir, "config", "task.conf") + if not os.path.isfile(curr_task_conf_file): + clean_up_and_exit( + "Missing configuration file for task %s" % curr_task_dir) + + # Create run directory for current task run ./runxxx + run_dirs = [int(os.path.basename(x)[-3:]) for x in glob.glob('run*[0-9]')] + curr_run_dir = "run%03d" % (max(run_dirs+[0, ])+1) + if args.remove_run_dir: + remove_run_dir() + return + try: + os.mkdir(curr_run_dir) + if os.path.islink('latest') or os.path.exists('latest'): + os.remove("latest") + os.symlink(curr_run_dir, "latest") + logger.info('Created "%s" directory for current task run' % + curr_run_dir) + except: + logger.exception("") + logger.error("Failed to create new run directory in task directory") + os.chdir(curr_run_dir) + + # Read task configuration file and check consistency + task_conf = ConfigParser(allow_no_value=True, + interpolation=ExtendedInterpolation()) + script_env_vars['PATH']["TASK_NAME"] = "/".join(taskname) + script_env_vars['PATH']["TASK_DIR"] = curr_task_dir + task_conf.read_dict(script_env_vars) + task_conf.read_file(open(curr_task_conf_file)) + + required_sec = ["GENERAL", "BENCHMARKS", "ARCHITECTURES"] + missing_section = list(set(required_sec)-set(task_conf.sections())) + if missing_section: + clean_up_and_exit("Missing sections %s" % " ".join(missing_section) + + " in task configuration file") + + # Declare varibles to access sections + TaskFileSections = task_conf.sections() + SynthSection = task_conf["SYNTHESIS_PARAM"] + GeneralSection = task_conf["GENERAL"] + + # Check if specified architecture files exist + # TODO Store it as a dictionary and take reference from the key + archfile_list = [] + for _, arch_file in task_conf["ARCHITECTURES"].items(): + arch_full_path = arch_file + if os.path.isfile(arch_full_path): + archfile_list.append(arch_full_path) + else: + clean_up_and_exit("Architecture file not found: " + + "%s " % arch_file) + if not len(archfile_list) == len(list(set(archfile_list))): + clean_up_and_exit("Found duplicate architectures in config file") + + # Get Flow information + logger.info('Running "%s" flow' % + GeneralSection.get("fpga_flow", fallback="yosys_vpr")) + + # Check if specified benchmark files exist + benchmark_list = [] + for bech_name, each_benchmark in task_conf["BENCHMARKS"].items(): + # Declare varible to store paramteres for current benchmark + CurrBenchPara = {} + + # Parse benchmark file + bench_files = [] + for eachpath in each_benchmark.split(","): + files = glob.glob(eachpath) + if not len(files): + clean_up_and_exit(("No files added benchmark %s" % bech_name) + + " with path %s " % (eachpath)) + bench_files += files + + # Read provided benchmark configurations + # Common configurations + # - All the benchmarks may share the same yosys synthesis template script + # - All the benchmarks may share the same rewrite yosys template script, which converts post-synthesis .v netlist to be compatible with .blif port definition. This is required for correct verification at the end of flows + # - All the benchmarks may share the same routing channel width in VPR runs. This is designed to enable architecture evaluations for a fixed device model + ys_for_task_common = SynthSection.get("bench_yosys_common") + ys_rewrite_for_task_common = SynthSection.get("bench_yosys_rewrite_common") + chan_width_common = SynthSection.get("bench_chan_width_common") + + # Individual benchmark configuration + CurrBenchPara["files"] = bench_files + CurrBenchPara["top_module"] = SynthSection.get(bech_name+"_top", + fallback="top") + CurrBenchPara["ys_script"] = SynthSection.get(bech_name+"_yosys", + fallback=ys_for_task_common) + CurrBenchPara["ys_rewrite_script"] = SynthSection.get(bech_name+"_yosys_rewrite", + fallback=ys_rewrite_for_task_common) + CurrBenchPara["chan_width"] = SynthSection.get(bech_name+"_chan_width", + fallback=chan_width_common) + + if GeneralSection.get("fpga_flow") == "vpr_blif": + # Check if activity file exist + if not SynthSection.get(bech_name+"_act"): + clean_up_and_exit("Missing argument %s" % (bech_name+"_act") + + "for vpr_blif flow") + CurrBenchPara["activity_file"] = SynthSection.get(bech_name+"_act") + + # Check if base verilog file exists + if not SynthSection.get(bech_name+"_verilog"): + clean_up_and_exit("Missing argument %s for vpr_blif flow" % + (bech_name+"_verilog")) + CurrBenchPara["verilog_file"] = SynthSection.get( + bech_name+"_verilog") + + # Add script parameter list in current benchmark + ScriptSections = [x for x in TaskFileSections if "SCRIPT_PARAM" in x] + script_para_list = {} + for eachset in ScriptSections: + command = [] + for key, values in task_conf[eachset].items(): + command += ["--"+key, values] if values else ["--"+key] + + # Set label for Sript Parameters + set_lbl = eachset.replace("SCRIPT_PARAM", "") + set_lbl = set_lbl[1:] if set_lbl else "Common" + script_para_list[set_lbl] = command + CurrBenchPara["script_params"] = script_para_list + + benchmark_list.append(CurrBenchPara) + + # Count the number of duplicated top module name among benchmark + # This is required as flow run directory names for these benchmarks are different than others + # which are uniquified + benchmark_top_module_count = [] + for bench in benchmark_list: + benchmark_top_module_count.append(bench["top_module"]) + + # Create OpenFPGA flow run commnad for each combination of + # architecture, benchmark and parameters + # Create run_job object [arch, bench, run_dir, commnad] + flow_run_cmd_list = [] + for indx, arch in enumerate(archfile_list): + for bench in benchmark_list: + for lbl, param in bench["script_params"].items(): + if (benchmark_top_module_count.count(bench["top_module"]) > 1): + flow_run_dir = get_flow_rundir(arch, "bench" + str(benchmark_list.index(bench)) + "_" + bench["top_module"], lbl) + else: + flow_run_dir = get_flow_rundir(arch, bench["top_module"], lbl) + + command = create_run_command( + curr_job_dir=flow_run_dir, + archfile=arch, + benchmark_obj=bench, + param=param, + task_conf=task_conf) + flow_run_cmd_list.append({ + "arch": arch, + "bench": bench, + "name": "%02d_%s_%s" % (indx, bench["top_module"], lbl), + "run_dir": flow_run_dir, + "commands": command, + "finished": False, + "status": False}) + + logger.info('Found %d Architectures %d Benchmarks & %d Script Parameters' % + (len(archfile_list), len(benchmark_list), len(ScriptSections))) + logger.info('Created total %d jobs' % len(flow_run_cmd_list)) + return flow_run_cmd_list + +# Make the directory name unique by including the benchmark index in the list. +# This is because benchmarks may share the same top module names +def get_flow_rundir(arch, top_module, flow_params=None): + path = [ + os.path.basename(arch).replace(".xml", ""), + top_module, + flow_params if flow_params else "common" + ] + return os.path.abspath(os.path.join(*path)) + + +def create_run_command(curr_job_dir, archfile, benchmark_obj, param, task_conf): + """ + Create_run_script function accepts run directory, architecture list and + fpga_flow configuration file and prepare final executable fpga_flow script + TODO : Replace this section after convert fpga_flow to python script + Config file creation and bechnmark list can be skipped + """ + # = = = = = = = = = File/Directory Consitancy Check = = = = = = = = = = + if not os.path.isdir(gc["misc_dir"]): + clean_up_and_exit("Miscellaneous directory does not exist") + + # = = = = = = = = = = = = Create execution folder = = = = = = = = = = = = + if os.path.isdir(curr_job_dir): + question = "One the result directory already exist.\n" + question += "%s\n" % curr_job_dir + reply = str(input(question+' (y/n): ')).lower().strip() + if reply[:1] in ['y', 'yes']: + shutil.rmtree(curr_job_dir) + else: + logger.info("Result directory removal denied by the user") + exit() + os.makedirs(curr_job_dir) + + # Make execution command to run Open FPGA flow + task_gc = task_conf["GENERAL"] + task_OFPGAc = task_conf["OpenFPGA_SHELL"] + command = [archfile] + benchmark_obj["files"] + command += ["--top_module", benchmark_obj["top_module"]] + command += ["--run_dir", curr_job_dir] + + if task_gc.get("fpga_flow"): + command += ["--fpga_flow", task_gc.get("fpga_flow")] + + if task_gc.get("run_engine") == "openfpga_shell": + for eachKey in task_OFPGAc.keys(): + command += [f"--{eachKey}", + task_OFPGAc.get(f"{eachKey}")] + + if benchmark_obj.get("activity_file"): + command += ["--activity_file", benchmark_obj.get("activity_file")] + + if benchmark_obj.get("verilog_file"): + command += ["--base_verilog", benchmark_obj.get("verilog_file")] + + if benchmark_obj.get("ys_script"): + command += ["--yosys_tmpl", benchmark_obj["ys_script"]] + + if benchmark_obj.get("ys_rewrite_script"): + command += ["--ys_rewrite_tmpl", benchmark_obj["ys_rewrite_script"]] + + if task_gc.getboolean("power_analysis"): + command += ["--power"] + command += ["--power_tech", task_gc.get("power_tech_file")] + + if task_gc.get("arch_variable_file"): + command += ["--arch_variable_file", task_gc.get("arch_variable_file")] + + if task_gc.getboolean("spice_output"): + command += ["--vpr_fpga_spice"] + + if task_gc.getboolean("verilog_output"): + command += ["--vpr_fpga_verilog"] + command += ["--vpr_fpga_verilog_dir", curr_job_dir] + command += ["--vpr_fpga_x2p_rename_illegal_port"] + + # Add other paramters to pass + command += param + + if args.debug: + command += ["--debug"] + return command + + +def strip_child_logger_info(line): + try: + logtype, message = line.split(" - ", 1) + lognumb = {"CRITICAL": 50, "ERROR": 40, "WARNING": 30, + "INFO": 20, "DEBUG": 10, "NOTSET": 0} + logger.log(lognumb[logtype.strip().upper()], message) + except: + logger.info(line) + + +def run_single_script(s, eachJob, job_list): + with s: + thread_name = threading.currentThread().getName() + eachJob["starttime"] = time.time() + try: + logfile = "%s_out.log" % thread_name + with open(logfile, 'w+') as output: + output.write("* "*20 + '\n') + output.write("RunDirectory : %s\n" % os.getcwd()) + command = [os.getenv('PYTHON_EXEC', gc["python_path"]), gc["script_default"]] + \ + eachJob["commands"] + output.write(" ".join(command) + '\n') + output.write("* "*20 + '\n') + logger.debug("Running OpenFPGA flow with [%s]" % command) + process = subprocess.Popen(command, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True) + for line in process.stdout: + if args.show_thread_logs: + strip_child_logger_info(line[:-1]) + sys.stdout.buffer.flush() + output.write(line) + process.wait() + if process.returncode: + raise subprocess.CalledProcessError(0, " ".join(command)) + eachJob["status"] = True + except: + logger.exception("Failed to execute openfpga flow - " + + eachJob["name"]) + if not args.continue_on_fail: + os._exit(1) + eachJob["endtime"] = time.time() + timediff = timedelta(seconds=(eachJob["endtime"]-eachJob["starttime"])) + timestr = humanize.naturaldelta(timediff) if "humanize" in sys.modules \ + else str(timediff) + logger.info("%s Finished with returncode %d, Time Taken %s " % + (thread_name, process.returncode, timestr)) + eachJob["finished"] = True + no_of_finished_job = sum([not eachJ["finished"] for eachJ in job_list]) + logger.info("***** %d runs pending *****" % (no_of_finished_job)) + + +def run_actions(job_list): + thread_sema = threading.Semaphore(args.maxthreads) + thread_list = [] + for _, eachjob in enumerate(job_list): + t = threading.Thread(target=run_single_script, name=eachjob["name"], + args=(thread_sema, eachjob, job_list)) + t.start() + thread_list.append(t) + for eachthread in thread_list: + eachthread.join() + + +def collect_results(job_run_list): + task_result = [] + for run in job_run_list: + if not run["status"]: + logger.warning("Skipping %s run", run["name"]) + continue + # Check if any result file exist + if not glob.glob(os.path.join(run["run_dir"], "*.result")): + logger.info("No result files found for %s" % run["name"]) + + # Read and merge result file + vpr_res = ConfigParser(allow_no_value=True, + interpolation=ExtendedInterpolation()) + vpr_res.read_file( + open(os.path.join(run["run_dir"], "vpr_stat.result"))) + result = OrderedDict() + result["name"] = run["name"] + result["TotalRunTime"] = int(run["endtime"]-run["starttime"]) + result.update(vpr_res["RESULTS"]) + task_result.append(result) + colnames = [] + for eachLbl in task_result: + colnames.extend(eachLbl.keys()) + if len(task_result): + with open("task_result.csv", 'w', newline='') as csvfile: + writer = csv.DictWriter( + csvfile, extrasaction='ignore', fieldnames=list(set(colnames))) + writer.writeheader() + for eachResult in task_result: + writer.writerow(eachResult) + + +if __name__ == "__main__": + main() diff --git a/openfpga_flow/tasks/ci_tests/config/task.conf b/openfpga_flow/tasks/ci_tests/config/task.conf new file mode 100644 index 000000000..3a3bb1972 --- /dev/null +++ b/openfpga_flow/tasks/ci_tests/config/task.conf @@ -0,0 +1,39 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr +arch_variable_file=${PATH:TASK_DIR}/design_variables.yml + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/generate_fabric_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_40nm_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +# Use a absolute path for the Verilog netlists to be generated +# This is designed to allow the test case 'basic_tests/generate_testbench' +# to use the Verilog netlists along with testbenches in HDL simulation +openfpga_verilog_output_dir=${PATH:OPENFPGA_PATH}/openfpga_flow/tasks/basic_tests/generate_fabric/latest/k6_frac_N10_tileable_40nm/and2/MIN_ROUTE_CHAN_WIDTH + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:DESIGN_PATH} + +[SYNTHESIS_PARAM] +bench0_top =${PATH:DESIGN_TOP} +#bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +#bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] From 2469f25ef4a747511c8373827e2268022127e241 Mon Sep 17 00:00:00 2001 From: komaljaved-rs Date: Thu, 1 Jul 2021 15:14:59 +0500 Subject: [PATCH 006/229] updated submodule --- RTL_Benchmark | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RTL_Benchmark b/RTL_Benchmark index f976d0771..16bc04733 160000 --- a/RTL_Benchmark +++ b/RTL_Benchmark @@ -1 +1 @@ -Subproject commit f976d0771598259f6d4a5ca10899d55b7e5d7a3d +Subproject commit 16bc04733bc63c1f3b137ebe52628a3ffe127c13 From 4b8e178947115daefd162ba524926f19b01eea8e Mon Sep 17 00:00:00 2001 From: komaljaved-rs <86342771+komaljaved-rs@users.noreply.github.com> Date: Thu, 1 Jul 2021 15:44:59 +0500 Subject: [PATCH 007/229] Update ci_test.yml --- .github/workflows/ci_test.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index 5319389ed..23c329e8f 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -18,6 +18,11 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 + + - name: Updating submodules + run: | + git submodule init + git submodule update --init --recursive # Runs a set of commands using the runners shell - name: Executing Script From 6d11dc275d0e7cba39bbe5e6ad52c4b82b790cb2 Mon Sep 17 00:00:00 2001 From: komaljaved-rs <86342771+komaljaved-rs@users.noreply.github.com> Date: Thu, 1 Jul 2021 16:01:38 +0500 Subject: [PATCH 008/229] Update ci_test.yml --- .github/workflows/ci_test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index 23c329e8f..540f26486 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -18,6 +18,8 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 + with: + submodules: true - name: Updating submodules run: | From 061811994daa444e3430413c3ce83c03916f4278 Mon Sep 17 00:00:00 2001 From: komaljaved-rs <86342771+komaljaved-rs@users.noreply.github.com> Date: Thu, 1 Jul 2021 16:05:08 +0500 Subject: [PATCH 009/229] Update ci_test.yml --- .github/workflows/ci_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index 540f26486..d0158fcf6 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -17,7 +17,7 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 + - uses: actions/checkout@v1 with: submodules: true From ff785569f0ef9a76d240b68d45263f2b79f9a8c5 Mon Sep 17 00:00:00 2001 From: komaljaved-rs Date: Thu, 1 Jul 2021 16:23:55 +0500 Subject: [PATCH 010/229] updated ci_test --- ci_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci_test.sh b/ci_test.sh index bd0ac8e3e..0c3d8d166 100755 --- a/ci_test.sh +++ b/ci_test.sh @@ -15,7 +15,7 @@ for dir in RTL_Benchmark/*; do export design_path=${OPENFPGA_PATH}/$FILE export design_top=$top_file echo "design = $design_path" - python3 openfpga_flow/scripts/run_ci_tests.py ci_tests + python3 $OPENFPGA_PATH/openfpga_flow/scripts/run_ci_tests.py ci_tests else echo -e "${RED}Top file not found. Make sure design exists${ENDCOLOR}" exit 1 From be14e4f448aa368cb6c547c6c11a0dfc4df76047 Mon Sep 17 00:00:00 2001 From: komaljaved-rs Date: Thu, 1 Jul 2021 16:31:42 +0500 Subject: [PATCH 011/229] added design_variables.yml --- openfpga_flow/tasks/ci_tests/design_variables.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 openfpga_flow/tasks/ci_tests/design_variables.yml diff --git a/openfpga_flow/tasks/ci_tests/design_variables.yml b/openfpga_flow/tasks/ci_tests/design_variables.yml new file mode 100644 index 000000000..de1dbf341 --- /dev/null +++ b/openfpga_flow/tasks/ci_tests/design_variables.yml @@ -0,0 +1 @@ +TEST_VARIABLE: 100 \ No newline at end of file From cc546cdedc62c07e27b91c8742eef4dc7ad83b0a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Sep 2021 16:42:24 -0700 Subject: [PATCH 012/229] [CI] Enable github actions --- .github/workflows/build.yml | 9 ++++----- yosys | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6b88712f1..77ccb1527 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,11 +3,10 @@ name: linux_build # Run CI on push, PR, and weekly. on: - workflow_dispatch: -# push: -# pull_request: -# schedule: -# - cron: "0 0 * * 0 " # weekly + push: + pull_request: + schedule: + - cron: "0 0 * * 0 " # weekly # Environment variables env: diff --git a/yosys b/yosys index f44a4f908..c9555c9ad 160000 --- a/yosys +++ b/yosys @@ -1 +1 @@ -Subproject commit f44a4f90867b49837da048f9055fdcd8a13c335b +Subproject commit c9555c9adeba886a308c60615ac794ec20d9276e From a2a5d6b97bde22166d45f0b095a573d356f41b1b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Sep 2021 16:46:35 -0700 Subject: [PATCH 013/229] [Git] Removed RTL benchmarks now as it is failing CI; Should consider bring it back sometime --- .gitmodules | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index e99222f81..1fb1d4212 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,6 +2,3 @@ path = yosys url = https://github.com/QuickLogic-Corp/yosys.git branch = quicklogic-rebased -[submodule "RTL_Benchmark"] - path = RTL_Benchmark - url = git@github.com:RapidSilicon/RTL_Benchmark.git From d37cfe96bdfa88bf15200d40d890f4628ffe2ecb Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Sep 2021 16:51:07 -0700 Subject: [PATCH 014/229] [Git] Remove RTL benchmarks submodule --- RTL_Benchmark | 1 - 1 file changed, 1 deletion(-) delete mode 160000 RTL_Benchmark diff --git a/RTL_Benchmark b/RTL_Benchmark deleted file mode 160000 index 16bc04733..000000000 --- a/RTL_Benchmark +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 16bc04733bc63c1f3b137ebe52628a3ffe127c13 From 5d22de7ac9fca30bc98b8c75bea8dd6922e343f7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 2 Sep 2021 20:00:47 -0700 Subject: [PATCH 015/229] [Yosys] Revert to an older version of yosys that works in regresstion tests --- yosys | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys b/yosys index c9555c9ad..f44a4f908 160000 --- a/yosys +++ b/yosys @@ -1 +1 @@ -Subproject commit c9555c9adeba886a308c60615ac794ec20d9276e +Subproject commit f44a4f90867b49837da048f9055fdcd8a13c335b From 5759f5f35b1d09c7011257854b77a611747a839f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 3 Sep 2021 17:55:23 -0700 Subject: [PATCH 016/229] [Engine] Start developing QL memory bank: upgrade infrastructures of fabric builder --- .../libarchopenfpga/src/circuit_types.h | 3 +- openfpga/src/fabric/build_top_module.cpp | 2 +- .../src/fabric/build_top_module_memory.cpp | 190 +++++++++++++----- openfpga/src/fabric/build_top_module_memory.h | 16 +- openfpga/src/fabric/module_manager.cpp | 34 +++- openfpga/src/fabric/module_manager.h | 17 +- 6 files changed, 202 insertions(+), 60 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/circuit_types.h b/libopenfpga/libarchopenfpga/src/circuit_types.h index f13a8a5ee..3a2604a42 100644 --- a/libopenfpga/libarchopenfpga/src/circuit_types.h +++ b/libopenfpga/libarchopenfpga/src/circuit_types.h @@ -125,10 +125,11 @@ enum e_config_protocol_type { CONFIG_MEM_STANDALONE, CONFIG_MEM_SCAN_CHAIN, CONFIG_MEM_MEMORY_BANK, + CONFIG_MEM_QL_MEMORY_BANK, CONFIG_MEM_FRAME_BASED, NUM_CONFIG_PROTOCOL_TYPES }; -constexpr std::array CONFIG_PROTOCOL_TYPE_STRING = {{"standalone", "scan_chain", "memory_bank", "frame_based"}}; +constexpr std::array CONFIG_PROTOCOL_TYPE_STRING = {{"standalone", "scan_chain", "memory_bank", "ql_memory_bank", "frame_based"}}; #endif diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 56b7d4b2b..1066b57bb 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -407,7 +407,7 @@ int build_top_module(ModuleManager& module_manager, * This is a much easier job after adding sub modules (instances), * we just need to find all the I/O ports from the child modules and build a list of it */ - vtr::vector top_module_num_config_bits = find_top_module_regional_num_config_bit(module_manager, top_module, circuit_lib, sram_model, config_protocol.type()); + vtr::vector top_module_num_config_bits = find_top_module_regional_num_config_bit(module_manager, top_module, circuit_lib, sram_model, config_protocol.type()); if (!top_module_num_config_bits.empty()) { add_top_module_sram_ports(module_manager, top_module, diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 422a73ff2..44545e608 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -74,8 +74,9 @@ void organize_top_module_tile_cb_modules(ModuleManager& module_manager, if (0 < find_module_num_config_bits(module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type)) { + vtr::Point config_coord(rr_gsb.get_cb_x(cb_type) * 2, rr_gsb.get_cb_y(cb_type) * 2); /* Note that use the original CB coodinate for instance id searching ! */ - module_manager.add_configurable_child(top_module, cb_module, cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)]); + module_manager.add_configurable_child(top_module, cb_module, cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)], config_coord); } } @@ -84,6 +85,37 @@ void organize_top_module_tile_cb_modules(ModuleManager& module_manager, * to the memory modules and memory instances * This function is designed for organizing memory modules in top-level * module + * This function also adds coordindates for each configurable child under the top-level module + * of a FPGA fabric. A configurable child could be a programmable block (grid), + * a Connection Block (CBx/y) or a Switch block (SB). + * This function, we consider a coordinate system as follows + * - Each row may consist of either (1) grid and CBy or (2) CBx and SB + * - Each column may consist of either (1) grid and CBx or (2) CBy and SB + * + * Column 0 Column 1 + * + * +---------------+----------+ + * | | | + * | | | + * | Grid | CBY | Row 3 + * | | | + * | | | + * +---------------+----------+ + * | | | + * | CBX | SB | Row 2 + * | | | + * +---------------+----------+ + * | | | + * | | | + * | Grid | CBY | Row 1 + * | | | + * | | | + * +---------------+----------+ + * | | | + * | CBX | SB | Row 0 + * | | | + * +---------------+----------+ + *******************************************************************/ static void organize_top_module_tile_memory_modules(ModuleManager& module_manager, @@ -130,7 +162,8 @@ void organize_top_module_tile_memory_modules(ModuleManager& module_manager, if (0 < find_module_num_config_bits(module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type)) { - module_manager.add_configurable_child(top_module, sb_module, sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()]); + vtr::Point config_coord(rr_gsb.get_sb_x() * 2 + 1, rr_gsb.get_sb_y() * 2 + 1); + module_manager.add_configurable_child(top_module, sb_module, sb_instance_ids[rr_gsb.get_sb_x()][rr_gsb.get_sb_y()], config_coord); } } @@ -172,11 +205,11 @@ void organize_top_module_tile_memory_modules(ModuleManager& module_manager, if (0 < find_module_num_config_bits(module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type)) { - module_manager.add_configurable_child(top_module, grid_module, grid_instance_ids[tile_coord.x()][tile_coord.y()]); + vtr::Point config_coord(tile_coord.x() * 2, tile_coord.y() * 2); + module_manager.add_configurable_child(top_module, grid_module, grid_instance_ids[tile_coord.x()][tile_coord.y()], config_coord); } } - /******************************************************************** * Split memory modules into different configurable regions * This function will create regions based on the definition @@ -496,6 +529,7 @@ void shuffle_top_module_configurable_children(ModuleManager& module_manager, /* Cache the configurable children and their instances */ std::vector orig_configurable_children = module_manager.configurable_children(top_module); std::vector orig_configurable_child_instances = module_manager.configurable_child_instances(top_module); + std::vector> orig_configurable_child_coordinates = module_manager.configurable_child_coordinates(top_module); /* Reorganize the configurable children */ module_manager.clear_configurable_children(top_module); @@ -503,7 +537,8 @@ void shuffle_top_module_configurable_children(ModuleManager& module_manager, for (size_t ikey = 0; ikey < num_keys; ++ikey) { module_manager.add_configurable_child(top_module, orig_configurable_children[shuffled_keys[ikey]], - orig_configurable_child_instances[shuffled_keys[ikey]]); + orig_configurable_child_instances[shuffled_keys[ikey]], + orig_configurable_child_coordinates[shuffled_keys[ikey]]); } /* Reset configurable regions */ @@ -614,13 +649,13 @@ int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager * - This function should be called after the configurable children * is loaded to the top-level module! ********************************************************************/ -vtr::vector find_top_module_regional_num_config_bit(const ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& config_protocol_type) { +vtr::vector find_top_module_regional_num_config_bit(const ModuleManager& module_manager, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const e_config_protocol_type& config_protocol_type) { /* Initialize the number of configuration bits for each region */ - vtr::vector num_config_bits(module_manager.regions(top_module).size(), 0); + vtr::vector num_config_bits(module_manager.regions(top_module).size(), TopModuleNumConfigBits(0, 0)); switch (config_protocol_type) { case CONFIG_MEM_STANDALONE: @@ -632,7 +667,36 @@ vtr::vector find_top_module_regional_num_config_bit(cons */ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { for (const ModuleId& child_module : module_manager.region_configurable_children(top_module, config_region)) { - num_config_bits[config_region] += find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type); + num_config_bits[config_region].first += find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type); + } + } + break; + } + case CONFIG_MEM_QL_MEMORY_BANK: { + /* For QL memory bank: we will use the row and column information for each configuration child + * in order to identify the number of unique BLs and WLs + * In this configuration protocol, + * - all the configurable child in the same row will share the same WLs + * - the number of WLs per row is limited by the configurable child which requires most WLs + * - each row has independent WLs + * - all the configurable child in the same column will share the same BLs + * - the number of BLs per column is limited by the configurable child which requires most BLs + * - each column has independent BLs + */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + std::map num_bls; + std::map num_wls; + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + num_bls[coord.x()] = std::max(num_bls[coord.x()], find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type)); + num_wls[coord.y()] = std::max(num_wls[coord.y()], find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type)); + for (const auto& kv : num_bls) { + num_config_bits[config_region].first += kv.first; + } + for (const auto& kv : num_wls) { + num_config_bits[config_region].second += kv.second; + } } } break; @@ -646,14 +710,14 @@ vtr::vector find_top_module_regional_num_config_bit(cons for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { for (const ModuleId& child_module : module_manager.region_configurable_children(top_module, config_region)) { size_t temp_num_config_bits = find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type); - num_config_bits[config_region] = std::max((int)temp_num_config_bits, (int)num_config_bits[config_region]); + num_config_bits[config_region].first = std::max(temp_num_config_bits, num_config_bits[config_region].first); } /* If there are more than 2 configurable children, we need a decoder * Otherwise, we can just short wire the address port to the children */ if (1 < module_manager.region_configurable_children(top_module, config_region).size()) { - num_config_bits[config_region] += find_mux_local_decoder_addr_size(module_manager.region_configurable_children(top_module, config_region).size()); + num_config_bits[config_region].first += find_mux_local_decoder_addr_size(module_manager.region_configurable_children(top_module, config_region).size()); } } @@ -706,34 +770,40 @@ size_t generate_top_module_sram_port_size(const ConfigProtocol& config_protocol, * top-level module * The type and names of added ports strongly depend on the * organization of SRAMs. - * 1. Standalone SRAMs: - * two ports will be added, which are BL and WL - * 2. Scan-chain Flip-flops: - * two ports will be added, which are the head of scan-chain - * and the tail of scan-chain - * IMPORTANT: the port size will be forced to 1 in this case - * because the head and tail are both 1-bit ports!!! - * 3. Memory decoders: - * - An enable signal - * - A BL address port - * - A WL address port - * - A data-in port for the BL decoder - * 4. Frame-based memory: - * - An Enable signal - * - An address port, whose size depends on the number of config bits - * and the maximum size of address ports of configurable children - * - An data_in port (single-bit) + * - Standalone SRAMs: + * two ports will be added, which are BL and WL + * - Scan-chain Flip-flops: + * two ports will be added, which are the head of scan-chain + * and the tail of scan-chain + * IMPORTANT: the port size will be forced to 1 in this case + * because the head and tail are both 1-bit ports!!! + * - Memory decoders: + * - An enable signal + * - A BL address port + * - A WL address port + * - A data-in port for the BL decoder + * - QL memory decoder: + * - An enable signal + * - An BL address port + * - A WL address port + * - A data-in port for the BL decoder + * @note In this memory decoders, the address size will be computed in a different way than the regular one + * - Frame-based memory: + * - An Enable signal + * - An address port, whose size depends on the number of config bits + * and the maximum size of address ports of configurable children + * - An data_in port (single-bit) ********************************************************************/ void add_top_module_sram_ports(ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, - const vtr::vector& num_config_bits) { + const vtr::vector& num_config_bits) { std::vector sram_port_names = generate_sram_port_names(circuit_lib, sram_model, config_protocol.type()); size_t total_num_config_bits = 0; - for (const size_t& curr_num_config_bits : num_config_bits) { - total_num_config_bits += curr_num_config_bits; + for (const auto& curr_num_config_bits : num_config_bits) { + total_num_config_bits += curr_num_config_bits.first; } size_t sram_port_size = generate_top_module_sram_port_size(config_protocol, total_num_config_bits); @@ -754,7 +824,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, /* BL address size is the largest among all the regions */ size_t bl_addr_size = 0; for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - bl_addr_size = std::max(bl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region])); + bl_addr_size = std::max(bl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].first)); } BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), bl_addr_size); module_manager.add_port(module_id, bl_addr_port, ModuleManager::MODULE_INPUT_PORT); @@ -762,7 +832,33 @@ void add_top_module_sram_ports(ModuleManager& module_manager, /* WL address size is the largest among all the regions */ size_t wl_addr_size = 0; for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - wl_addr_size = std::max(wl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region])); + wl_addr_size = std::max(wl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].first)); + } + BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); + module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); + + /* Data input should be dependent on the number of configuration regions*/ + BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), config_protocol.num_regions()); + module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); + + break; + } + case CONFIG_MEM_QL_MEMORY_BANK: { + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); + + /* BL address size is the largest among all the regions */ + size_t bl_addr_size = 0; + for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + bl_addr_size = std::max(bl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].first)); + } + BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), bl_addr_size); + module_manager.add_port(module_id, bl_addr_port, ModuleManager::MODULE_INPUT_PORT); + + /* WL address size is the largest among all the regions */ + size_t wl_addr_size = 0; + for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + wl_addr_size = std::max(wl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].second)); } BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); @@ -798,8 +894,8 @@ void add_top_module_sram_ports(ModuleManager& module_manager, module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); size_t max_num_config_bits = 0; - for (const size_t& curr_num_config_bits : num_config_bits) { - max_num_config_bits = std::max(max_num_config_bits, curr_num_config_bits); + for (const auto& curr_num_config_bits : num_config_bits) { + max_num_config_bits = std::max(max_num_config_bits, curr_num_config_bits.first); } BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), max_num_config_bits); @@ -910,7 +1006,7 @@ static void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& top_module, - const vtr::vector& num_config_bits) { + const vtr::vector& num_config_bits) { /* Find Enable port from the top-level module */ ModulePortId en_port = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort en_port_info = module_manager.module_port(top_module, en_port); @@ -935,13 +1031,13 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag /* Each memory bank has a unified number of BL/WLs */ size_t num_bls = 0; - for (const size_t& curr_config_bits : num_config_bits) { - num_bls = std::max(num_bls, find_memory_decoder_data_size(curr_config_bits)); + for (const auto& curr_config_bits : num_config_bits) { + num_bls = std::max(num_bls, find_memory_decoder_data_size(curr_config_bits.first)); } size_t num_wls = 0; - for (const size_t& curr_config_bits : num_config_bits) { - num_wls = std::max(num_wls, find_memory_decoder_data_size(curr_config_bits)); + for (const auto& curr_config_bits : num_config_bits) { + num_wls = std::max(num_wls, find_memory_decoder_data_size(curr_config_bits.first)); } /* Create separated memory bank circuitry, i.e., BL/WL decoders for each region */ @@ -1582,7 +1678,7 @@ static void add_top_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& top_module, - const vtr::vector& num_config_bits) { + const vtr::vector& num_config_bits) { /* Find the number of address bits for the top-level module */ ModulePortId top_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_ADDRESS_PORT_NAME)); BasicPort top_addr_port_info = module_manager.module_port(top_module, top_addr_port); @@ -1598,7 +1694,7 @@ void add_top_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_mana * - The number of address bits of the configurable child is the same as top-level */ if ( (1 == module_manager.region_configurable_children(top_module, config_region).size()) - && (num_config_bits[config_region] == top_addr_size)) { + && (num_config_bits[config_region].first == top_addr_size)) { add_top_module_nets_cmos_memory_frame_short_config_bus(module_manager, top_module, config_region); } else { add_top_module_nets_cmos_memory_frame_decoder_config_bus(module_manager, decoder_lib, top_module, config_region); @@ -1655,7 +1751,7 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const ConfigProtocol& config_protocol, - const vtr::vector& num_config_bits) { + const vtr::vector& num_config_bits) { switch (config_protocol.type()) { case CONFIG_MEM_STANDALONE: add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, @@ -1717,7 +1813,7 @@ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, const ModuleId& parent_module, const ConfigProtocol& config_protocol, const e_circuit_model_design_tech& mem_tech, - const vtr::vector& num_config_bits) { + const vtr::vector& num_config_bits) { vtr::ScopedStartFinishTimer timer("Add module nets for configuration buses"); diff --git a/openfpga/src/fabric/build_top_module_memory.h b/openfpga/src/fabric/build_top_module_memory.h index e1d495fd4..d44522ff0 100644 --- a/openfpga/src/fabric/build_top_module_memory.h +++ b/openfpga/src/fabric/build_top_module_memory.h @@ -26,6 +26,8 @@ /* begin namespace openfpga */ namespace openfpga { +typedef std::pair TopModuleNumConfigBits; + void organize_top_module_memory_modules(ModuleManager& module_manager, const ModuleId& top_module, const CircuitLibrary& circuit_lib, @@ -48,25 +50,25 @@ int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager const ConfigProtocol& config_protocol, const FabricKey& fabric_key); -vtr::vector find_top_module_regional_num_config_bit(const ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& config_protocol_type); +vtr::vector find_top_module_regional_num_config_bit(const ModuleManager& module_manager, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const e_config_protocol_type& config_protocol_type); void add_top_module_sram_ports(ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, - const vtr::vector& num_config_bits); + const vtr::vector& num_config_bits); void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const ConfigProtocol& config_protocol, const e_circuit_model_design_tech& mem_tech, - const vtr::vector& num_config_bits); + const vtr::vector& num_config_bits); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/module_manager.cpp b/openfpga/src/fabric/module_manager.cpp index 87fa0ca5c..de5ed0fa6 100644 --- a/openfpga/src/fabric/module_manager.cpp +++ b/openfpga/src/fabric/module_manager.cpp @@ -84,6 +84,13 @@ std::vector ModuleManager::configurable_child_instances(const ModuleId& return configurable_child_instances_[parent_module]; } +std::vector> ModuleManager::configurable_child_coordinates(const ModuleId& parent_module) const { + /* Validate the module_id */ + VTR_ASSERT(valid_module_id(parent_module)); + + return configurable_child_coordinates_[parent_module]; +} + /* Find the source ids of modules */ ModuleManager::module_net_src_range ModuleManager::module_net_sources(const ModuleId& module, const ModuleNetId& net) const { /* Validate the module_id */ @@ -135,6 +142,22 @@ std::vector ModuleManager::region_configurable_child_instances(const Mod return region_config_child_instances; } +std::vector> ModuleManager::region_configurable_child_coordinates(const ModuleId& parent_module, + const ConfigRegionId& region) const { + /* Validate the module_id */ + VTR_ASSERT(valid_module_id(parent_module)); + VTR_ASSERT(valid_region_id(parent_module, region)); + + std::vector> region_config_child_coordinates; + region_config_child_coordinates.reserve(config_region_children_[parent_module][region].size()); + + for (const size_t& child_id : config_region_children_[parent_module][region]) { + region_config_child_coordinates.push_back(configurable_child_coordinates_[parent_module][child_id]); + } + + return region_config_child_coordinates; +} + /****************************************************************************** * Public Accessors ******************************************************************************/ @@ -534,6 +557,7 @@ ModuleId ModuleManager::add_module(const std::string& name) { configurable_children_.emplace_back(); configurable_child_instances_.emplace_back(); configurable_child_regions_.emplace_back(); + configurable_child_coordinates_.emplace_back(); config_region_ids_.emplace_back(); config_region_children_.emplace_back(); @@ -716,7 +740,8 @@ void ModuleManager::set_child_instance_name(const ModuleId& parent_module, */ void ModuleManager::add_configurable_child(const ModuleId& parent_module, const ModuleId& child_module, - const size_t& child_instance) { + const size_t& child_instance, + const vtr::Point coord) { /* Validate the id of both parent and child modules */ VTR_ASSERT ( valid_module_id(parent_module) ); VTR_ASSERT ( valid_module_id(child_module) ); @@ -726,6 +751,7 @@ void ModuleManager::add_configurable_child(const ModuleId& parent_module, configurable_children_[parent_module].push_back(child_module); configurable_child_instances_[parent_module].push_back(child_instance); configurable_child_regions_[parent_module].push_back(ConfigRegionId::INVALID()); + configurable_child_coordinates_[parent_module].push_back(coord); } void ModuleManager::reserve_configurable_child(const ModuleId& parent_module, @@ -738,9 +764,12 @@ void ModuleManager::reserve_configurable_child(const ModuleId& parent_module, if (num_children > configurable_child_instances_[parent_module].size()) { configurable_child_instances_[parent_module].reserve(num_children); } - if (num_children > configurable_child_instances_[parent_module].size()) { + if (num_children > configurable_child_regions_[parent_module].size()) { configurable_child_regions_[parent_module].reserve(num_children); } + if (num_children > configurable_child_coordinates_[parent_module].size()) { + configurable_child_coordinates_[parent_module].reserve(num_children); + } } ConfigRegionId ModuleManager::add_config_region(const ModuleId& module) { @@ -981,6 +1010,7 @@ void ModuleManager::clear_configurable_children(const ModuleId& parent_module) { configurable_children_[parent_module].clear(); configurable_child_instances_[parent_module].clear(); configurable_child_regions_[parent_module].clear(); + configurable_child_coordinates_[parent_module].clear(); } void ModuleManager::clear_config_region(const ModuleId& parent_module) { diff --git a/openfpga/src/fabric/module_manager.h b/openfpga/src/fabric/module_manager.h index d58442c73..3d4405b7a 100644 --- a/openfpga/src/fabric/module_manager.h +++ b/openfpga/src/fabric/module_manager.h @@ -8,6 +8,7 @@ #include #include "vtr_vector.h" +#include "vtr_geometry.h" #include "module_manager_fwd.h" #include "openfpga_port.h" @@ -148,6 +149,8 @@ class ModuleManager { std::vector configurable_children(const ModuleId& parent_module) const; /* Find all the instances of configurable child modules under a parent module */ std::vector configurable_child_instances(const ModuleId& parent_module) const; + /* Find the coordindate of a configurable child module under a parent module */ + std::vector> configurable_child_coordinates(const ModuleId& parent_module) const; /* Find the source ids of modules */ module_net_src_range module_net_sources(const ModuleId& module, const ModuleNetId& net) const; /* Find the sink ids of modules */ @@ -161,6 +164,10 @@ class ModuleManager { /* Find all the instances of configurable child modules under a region of a parent module */ std::vector region_configurable_child_instances(const ModuleId& parent_module, const ConfigRegionId& region) const; + + /* Find all the coordinates of configurable child modules under a region of a parent module */ + std::vector> region_configurable_child_coordinates(const ModuleId& parent_module, + const ConfigRegionId& region) const; public: /* Public accessors */ size_t num_modules() const; @@ -252,8 +259,13 @@ class ModuleManager { void add_child_module(const ModuleId& parent_module, const ModuleId& child_module); /* Set the instance name of a child module */ void set_child_instance_name(const ModuleId& parent_module, const ModuleId& child_module, const size_t& instance_id, const std::string& instance_name); - /* Add a configurable child module to module */ - void add_configurable_child(const ModuleId& module, const ModuleId& child_module, const size_t& child_instance); + /* Add a configurable child module to module + * This function also set the coordinate of a configurable child + * The coordinate is a relative position in each region, which is used to + * idenify BL/WL sharing + * By default, it is an invalid coordinate + */ + void add_configurable_child(const ModuleId& module, const ModuleId& child_module, const size_t& child_instance, const vtr::Point coord = vtr::Point(-1, -1)); /* Reserved a number of configurable children * for memory efficiency */ @@ -350,6 +362,7 @@ class ModuleManager { vtr::vector> configurable_children_; /* Child modules with configurable memory bits that this module contain */ vtr::vector> configurable_child_instances_; /* Instances of child modules with configurable memory bits that this module contain */ vtr::vector> configurable_child_regions_; /* Instances of child modules with configurable memory bits that this module contain */ + vtr::vector>> configurable_child_coordinates_; /* Relative coorindates of child modules with configurable memory bits that this module contain */ /* Configurable regions to group the configurable children * Note: From f75456e3040718b66f8c44270a7b8047c617187e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 5 Sep 2021 11:53:33 -0700 Subject: [PATCH 017/229] [Engine] Update BL/WL estimation function for QL memory bank protocol --- openfpga/src/fabric/build_top_module_memory.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 44545e608..a00d8a9c9 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -689,8 +689,8 @@ vtr::vector find_top_module_regional_num for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - num_bls[coord.x()] = std::max(num_bls[coord.x()], find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type)); - num_wls[coord.y()] = std::max(num_wls[coord.y()], find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type)); + num_bls[coord.x()] = std::max(num_bls[coord.x()], find_memory_decoder_addr_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type))); + num_wls[coord.y()] = std::max(num_wls[coord.y()], find_memory_decoder_addr_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type))); for (const auto& kv : num_bls) { num_config_bits[config_region].first += kv.first; } @@ -850,7 +850,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, /* BL address size is the largest among all the regions */ size_t bl_addr_size = 0; for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - bl_addr_size = std::max(bl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].first)); + bl_addr_size = std::max(bl_addr_size, num_config_bits[config_region].first); } BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), bl_addr_size); module_manager.add_port(module_id, bl_addr_port, ModuleManager::MODULE_INPUT_PORT); @@ -858,7 +858,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, /* WL address size is the largest among all the regions */ size_t wl_addr_size = 0; for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - wl_addr_size = std::max(wl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].second)); + wl_addr_size = std::max(wl_addr_size, num_config_bits[config_region].second); } BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); From cf2e479d18d2a1361b9063a6e549b137b0973a66 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 5 Sep 2021 12:01:38 -0700 Subject: [PATCH 018/229] [Engine] Refactor the TopModuleNumConfigBits data structure --- openfpga/src/fabric/build_top_module.cpp | 2 +- .../src/fabric/build_top_module_memory.cpp | 22 +++++++++---------- openfpga/src/fabric/build_top_module_memory.h | 16 +++++++------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 1066b57bb..e345e00ce 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -407,7 +407,7 @@ int build_top_module(ModuleManager& module_manager, * This is a much easier job after adding sub modules (instances), * we just need to find all the I/O ports from the child modules and build a list of it */ - vtr::vector top_module_num_config_bits = find_top_module_regional_num_config_bit(module_manager, top_module, circuit_lib, sram_model, config_protocol.type()); + TopModuleNumConfigBits top_module_num_config_bits = find_top_module_regional_num_config_bit(module_manager, top_module, circuit_lib, sram_model, config_protocol.type()); if (!top_module_num_config_bits.empty()) { add_top_module_sram_ports(module_manager, top_module, diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index a00d8a9c9..5faf4fc02 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -649,13 +649,13 @@ int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager * - This function should be called after the configurable children * is loaded to the top-level module! ********************************************************************/ -vtr::vector find_top_module_regional_num_config_bit(const ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& config_protocol_type) { +TopModuleNumConfigBits find_top_module_regional_num_config_bit(const ModuleManager& module_manager, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const e_config_protocol_type& config_protocol_type) { /* Initialize the number of configuration bits for each region */ - vtr::vector num_config_bits(module_manager.regions(top_module).size(), TopModuleNumConfigBits(0, 0)); + TopModuleNumConfigBits num_config_bits(module_manager.regions(top_module).size(), std::pair(0, 0)); switch (config_protocol_type) { case CONFIG_MEM_STANDALONE: @@ -799,7 +799,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, - const vtr::vector& num_config_bits) { + const TopModuleNumConfigBits& num_config_bits) { std::vector sram_port_names = generate_sram_port_names(circuit_lib, sram_model, config_protocol.type()); size_t total_num_config_bits = 0; for (const auto& curr_num_config_bits : num_config_bits) { @@ -1006,7 +1006,7 @@ static void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& top_module, - const vtr::vector& num_config_bits) { + const TopModuleNumConfigBits& num_config_bits) { /* Find Enable port from the top-level module */ ModulePortId en_port = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort en_port_info = module_manager.module_port(top_module, en_port); @@ -1678,7 +1678,7 @@ static void add_top_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& top_module, - const vtr::vector& num_config_bits) { + const TopModuleNumConfigBits& num_config_bits) { /* Find the number of address bits for the top-level module */ ModulePortId top_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_ADDRESS_PORT_NAME)); BasicPort top_addr_port_info = module_manager.module_port(top_module, top_addr_port); @@ -1751,7 +1751,7 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const ConfigProtocol& config_protocol, - const vtr::vector& num_config_bits) { + const TopModuleNumConfigBits& num_config_bits) { switch (config_protocol.type()) { case CONFIG_MEM_STANDALONE: add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, @@ -1813,7 +1813,7 @@ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, const ModuleId& parent_module, const ConfigProtocol& config_protocol, const e_circuit_model_design_tech& mem_tech, - const vtr::vector& num_config_bits) { + const TopModuleNumConfigBits& num_config_bits) { vtr::ScopedStartFinishTimer timer("Add module nets for configuration buses"); diff --git a/openfpga/src/fabric/build_top_module_memory.h b/openfpga/src/fabric/build_top_module_memory.h index d44522ff0..fa6f34cdd 100644 --- a/openfpga/src/fabric/build_top_module_memory.h +++ b/openfpga/src/fabric/build_top_module_memory.h @@ -26,7 +26,7 @@ /* begin namespace openfpga */ namespace openfpga { -typedef std::pair TopModuleNumConfigBits; +typedef vtr::vector> TopModuleNumConfigBits; void organize_top_module_memory_modules(ModuleManager& module_manager, const ModuleId& top_module, @@ -50,25 +50,25 @@ int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager const ConfigProtocol& config_protocol, const FabricKey& fabric_key); -vtr::vector find_top_module_regional_num_config_bit(const ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& config_protocol_type); +TopModuleNumConfigBits find_top_module_regional_num_config_bit(const ModuleManager& module_manager, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const e_config_protocol_type& config_protocol_type); void add_top_module_sram_ports(ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, - const vtr::vector& num_config_bits); + const TopModuleNumConfigBits& num_config_bits); void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const ConfigProtocol& config_protocol, const e_circuit_model_design_tech& mem_tech, - const vtr::vector& num_config_bits); + const TopModuleNumConfigBits& num_config_bits); } /* end namespace openfpga */ From ed80d6b3f4e4ad23c52e4ae935fc230badfc2b22 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 5 Sep 2021 13:23:38 -0700 Subject: [PATCH 019/229] [Engine] Place QL memory bank source codes in a separated source file so that integration to OpenFPGA open-source version is easier --- openfpga/src/fabric/build_top_module.cpp | 1 + .../src/fabric/build_top_module_memory.cpp | 20 +- openfpga/src/fabric/build_top_module_memory.h | 5 +- .../fabric/build_top_module_memory_bank.cpp | 383 ++++++++++++++++++ .../src/fabric/build_top_module_memory_bank.h | 33 ++ .../fabric/build_top_module_memory_utils.h | 28 ++ 6 files changed, 463 insertions(+), 7 deletions(-) create mode 100644 openfpga/src/fabric/build_top_module_memory_bank.cpp create mode 100644 openfpga/src/fabric/build_top_module_memory_bank.h create mode 100644 openfpga/src/fabric/build_top_module_memory_utils.h diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index e345e00ce..add2ea30b 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -422,6 +422,7 @@ int build_top_module(ModuleManager& module_manager, if (0 < module_manager.configurable_children(top_module).size()) { add_top_module_nets_memory_config_bus(module_manager, decoder_lib, top_module, + circuit_lib, sram_model, config_protocol, circuit_lib.design_tech_type(sram_model), top_module_num_config_bits); } diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 5faf4fc02..297a5abf4 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -23,6 +23,7 @@ #include "decoder_library_utils.h" #include "module_manager_utils.h" #include "build_decoder_modules.h" +#include "build_top_module_memory_bank.h" #include "build_top_module_memory.h" /* begin namespace openfpga */ @@ -689,8 +690,8 @@ TopModuleNumConfigBits find_top_module_regional_num_config_bit(const ModuleManag for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - num_bls[coord.x()] = std::max(num_bls[coord.x()], find_memory_decoder_addr_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type))); - num_wls[coord.y()] = std::max(num_wls[coord.y()], find_memory_decoder_addr_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type))); + num_bls[coord.x()] = std::max(num_bls[coord.x()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type))); + num_wls[coord.y()] = std::max(num_wls[coord.y()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type))); for (const auto& kv : num_bls) { num_config_bits[config_region].first += kv.first; } @@ -850,7 +851,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, /* BL address size is the largest among all the regions */ size_t bl_addr_size = 0; for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - bl_addr_size = std::max(bl_addr_size, num_config_bits[config_region].first); + bl_addr_size = std::max(bl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].first)); } BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), bl_addr_size); module_manager.add_port(module_id, bl_addr_port, ModuleManager::MODULE_INPUT_PORT); @@ -858,7 +859,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, /* WL address size is the largest among all the regions */ size_t wl_addr_size = 0; for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - wl_addr_size = std::max(wl_addr_size, num_config_bits[config_region].second); + wl_addr_size = std::max(wl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].second)); } BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); @@ -1750,6 +1751,8 @@ static void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, const TopModuleNumConfigBits& num_config_bits) { switch (config_protocol.type()) { @@ -1766,6 +1769,9 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, case CONFIG_MEM_MEMORY_BANK: add_top_module_nets_cmos_memory_bank_config_bus(module_manager, decoder_lib, parent_module, num_config_bits); break; + case CONFIG_MEM_QL_MEMORY_BANK: + add_top_module_nets_cmos_ql_memory_bank_config_bus(module_manager, decoder_lib, parent_module, circuit_lib, sram_model, num_config_bits); + break; case CONFIG_MEM_FRAME_BASED: add_top_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, parent_module, num_config_bits); break; @@ -1811,6 +1817,8 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, const e_circuit_model_design_tech& mem_tech, const TopModuleNumConfigBits& num_config_bits) { @@ -1820,7 +1828,9 @@ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, switch (mem_tech) { case CIRCUIT_MODEL_DESIGN_CMOS: add_top_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, - parent_module, + parent_module, + circuit_lib, + sram_model, config_protocol, num_config_bits); break; diff --git a/openfpga/src/fabric/build_top_module_memory.h b/openfpga/src/fabric/build_top_module_memory.h index fa6f34cdd..336125df0 100644 --- a/openfpga/src/fabric/build_top_module_memory.h +++ b/openfpga/src/fabric/build_top_module_memory.h @@ -18,6 +18,7 @@ #include "device_rr_gsb.h" #include "fabric_key.h" #include "config_protocol.h" +#include "build_top_module_memory_utils.h" /******************************************************************** * Function declaration @@ -26,8 +27,6 @@ /* begin namespace openfpga */ namespace openfpga { -typedef vtr::vector> TopModuleNumConfigBits; - void organize_top_module_memory_modules(ModuleManager& module_manager, const ModuleId& top_module, const CircuitLibrary& circuit_lib, @@ -66,6 +65,8 @@ void add_top_module_sram_ports(ModuleManager& module_manager, void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, const e_circuit_model_design_tech& mem_tech, const TopModuleNumConfigBits& num_config_bits); diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp new file mode 100644 index 000000000..4854b711c --- /dev/null +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -0,0 +1,383 @@ +/******************************************************************** + * This file includes functions that are used to organize memories + * in the top module of FPGA fabric + *******************************************************************/ +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from vpr library */ +#include "vpr_utils.h" + +/* Headers from openfpgashell library */ +#include "command_exit_codes.h" + +#include "rr_gsb_utils.h" +#include "openfpga_reserved_words.h" +#include "openfpga_naming.h" + +#include "memory_utils.h" +#include "decoder_library_utils.h" +#include "module_manager_utils.h" +#include "build_decoder_modules.h" +#include "build_top_module_memory_bank.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/********************************************************************* + * Top-level function to add nets for quicklogic memory banks + * Each configuration region has independent memory bank circuitry + * - Find the number of BLs and WLs required for each region + * - Create BL and WL decoders, and add them to decoder library + * - Create nets to connect from top-level module inputs to inputs of decoders + * - Create nets to connect from outputs of decoders to BL/WL of configurable children + * + * Detailed schematic of how memory banks are connected in the top-level: + * Consider a random Region X, local BL address lines are aligned to the LSB of the + * top-level BL address lines + * + * top_bl_addr[N-1:0] + * ^ + * | local_bl_addr[N-1:0] + * | + * +-----+------------------+ + * | | | + * | +-------------------+ | + * | | Word Line Decoder | | + * | +-------------------+ | + * | | + * + * The BL/WL decoders should have the same circuit designs no matter what region + * they are placed even when the number of configuration bits are different + * from one region to another! + * This is designed to avoid any address collision between memory banks + * since they are programmed in the same clock cycle + * For example: + * - Memory Bank A has 36 memory cells. + * Its BL decoder has 3 address bit and 6 data output bit + * Its WL decoder has 3 address bit and 6 data output bit + * - Memory Bank B has 16 memory cells. + * Its BL decoder has 2 address bit and 4 data output bit + * Its WL decoder has 2 address bit and 4 data output bit + * - If we try to program the 36th memory cell in bank A + * the BL address will be 3'b110 + * the WL address will be 3'b110 + * the data input will be 1'b0 + * - If we try to program the 4th memory cell in bank A + * the BL address will be 3'b010 + * the WL address will be 3'b010 + * the data input will be 1'b1 + * However, in both cases, this will trigger a parasitic programming in bank B + * the BL address will be 2'b10 + * the WL address will be 2'b10 + * Assume the data input is expected to be 1'b1 for bank B + * but it will be overwritten to 1'b0 when programming the 36th cell in bank A! + * + * Detailed schematic of each memory bank: + * @note The numbers are just made to show a simplified example, practical cases are more complicated! + * + * WL_enable WL address + * | | + * v v + * +-----------------------------------------------+ + * | Word Line Decoder | + * +-----------------------------------------------+ + * +---------+ | | | + * BL | | | | | + * enable ---->| |-----------+---------------+---- ... |------+--> BL[0:2] + * | | | | | | | | + * | | | v | v | v + * | Bit | | +-------+ | +-------+ | +------+ + * BL | Line | +-->| SRAM | +-->| SRAM | +->| SRAM | + * address ---->| Decoder | | | [0:8] | | | [0:5] | ... | | [0:7]| + * | | | +-------+ | +-------+ | +------+ + * | | | | | + * | |-----------+--------------+--------- | -----+--> BL[0:9] + * | | | | | | | | + * | | | v | v | v + * | | | +-------+ | +-------+ | +-------+ + * | | +-->| SRAM | | | SRAM | +->| SRAM | + * | | | | [0:80]| | | [0:63]| ... | | [0:31]| + * | | | +-------+ | +-------+ | +-------+ + * | | | | + * | | | ... ... ... | ... + * | | | | | + * | |-----------+---------------+---- --- | -----+--> BL[0:3] + * | | | | | | | | + * | | | v | v | v + * | | | +-------+ | +-------+ | +-------+ + * | | +-->| SRAM | +-->| SRAM | +->| SRAM | + * | | | |[0:5] | | | [0:8] | ... | | [0:2] | + * | | | +-------+ | +-------+ | +-------+ + * BL | | v v v + * data_in ---->| | WL[0:9] WL[0:7] WL[0:4] + * +---------+ + * + **********************************************************************/ +void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const TopModuleNumConfigBits& num_config_bits) { + /* Find Enable port from the top-level module */ + ModulePortId en_port = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort en_port_info = module_manager.module_port(top_module, en_port); + + /* Find data-in port from the top-level module */ + ModulePortId din_port = module_manager.find_module_port(top_module, std::string(DECODER_DATA_IN_PORT_NAME)); + BasicPort din_port_info = module_manager.module_port(top_module, din_port); + + /* Data in port should match the number of configuration regions */ + VTR_ASSERT(din_port_info.get_width() == module_manager.regions(top_module).size()); + + /* Find BL and WL address port from the top-level module */ + ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port); + + ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port); + + /* Find the top-level number of BLs and WLs required to access each memory bit */ + size_t bl_addr_size = bl_addr_port_info.get_width(); + size_t wl_addr_size = wl_addr_port_info.get_width(); + + /* Each memory bank has a unified number of BL/WLs */ + size_t num_bls = 0; + for (const auto& curr_config_bits : num_config_bits) { + num_bls = std::max(num_bls, find_memory_decoder_data_size(curr_config_bits.first)); + } + + size_t num_wls = 0; + for (const auto& curr_config_bits : num_config_bits) { + num_wls = std::max(num_wls, find_memory_decoder_data_size(curr_config_bits.second)); + } + + /* Create separated memory bank circuitry, i.e., BL/WL decoders for each region */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + /************************************************************** + * Add the BL decoder module + * Search the decoder library + * If we find one, we use the module. + * Otherwise, we create one and add it to the decoder library + */ + DecoderId bl_decoder_id = decoder_lib.find_decoder(bl_addr_size, num_bls, + true, true, false); + if (DecoderId::INVALID() == bl_decoder_id) { + bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false); + } + VTR_ASSERT(DecoderId::INVALID() != bl_decoder_id); + + /* Create a module if not existed yet */ + std::string bl_decoder_module_name = generate_memory_decoder_with_data_in_subckt_name(bl_addr_size, num_bls); + ModuleId bl_decoder_module = module_manager.find_module(bl_decoder_module_name); + if (ModuleId::INVALID() == bl_decoder_module) { + /* BL decoder has the same ports as the frame-based decoders + * We reuse it here + */ + bl_decoder_module = build_bl_memory_decoder_module(module_manager, + decoder_lib, + bl_decoder_id); + } + VTR_ASSERT(ModuleId::INVALID() != bl_decoder_module); + size_t curr_bl_decoder_instance_id = module_manager.num_instance(top_module, bl_decoder_module); + module_manager.add_child_module(top_module, bl_decoder_module); + + /************************************************************** + * Add the WL decoder module + * Search the decoder library + * If we find one, we use the module. + * Otherwise, we create one and add it to the decoder library + */ + DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls, + true, false, false); + if (DecoderId::INVALID() == wl_decoder_id) { + wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false); + } + VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id); + + /* Create a module if not existed yet */ + std::string wl_decoder_module_name = generate_memory_decoder_subckt_name(wl_addr_size, num_wls); + ModuleId wl_decoder_module = module_manager.find_module(wl_decoder_module_name); + if (ModuleId::INVALID() == wl_decoder_module) { + /* BL decoder has the same ports as the frame-based decoders + * We reuse it here + */ + wl_decoder_module = build_wl_memory_decoder_module(module_manager, + decoder_lib, + wl_decoder_id); + } + VTR_ASSERT(ModuleId::INVALID() != wl_decoder_module); + size_t curr_wl_decoder_instance_id = module_manager.num_instance(top_module, wl_decoder_module); + module_manager.add_child_module(top_module, wl_decoder_module); + + /************************************************************** + * Add module nets from the top module to BL decoder's inputs + */ + ModulePortId bl_decoder_en_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort bl_decoder_en_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_en_port); + + ModulePortId bl_decoder_addr_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort bl_decoder_addr_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_addr_port); + + ModulePortId bl_decoder_din_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_IN_PORT_NAME)); + BasicPort bl_decoder_din_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_din_port); + + /* Data in port of the local BL decoder should always be 1 */ + VTR_ASSERT(1 == bl_decoder_din_port_info.get_width()); + + /* Top module Enable port -> BL Decoder Enable port */ + add_module_bus_nets(module_manager, + top_module, + top_module, 0, en_port, + bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_en_port); + + /* Top module Address port -> BL Decoder Address port */ + add_module_bus_nets(module_manager, + top_module, + top_module, 0, bl_addr_port, + bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_addr_port); + + /* Top module data_in port -> BL Decoder data_in port: + * Note that each region has independent data_in connection from the top-level module + * The pin index is the configuration region index + */ + ModuleNetId din_net = create_module_source_pin_net(module_manager, top_module, + top_module, 0, + din_port, + din_port_info.pins()[size_t(config_region)]); + VTR_ASSERT(ModuleNetId::INVALID() != din_net); + + /* Configure the net sink */ + module_manager.add_module_net_sink(top_module, din_net, bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_din_port, bl_decoder_din_port_info.pins()[0]); + + /************************************************************** + * Add module nets from the top module to WL decoder's inputs + */ + ModulePortId wl_decoder_en_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort wl_decoder_en_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_en_port); + + ModulePortId wl_decoder_addr_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort wl_decoder_addr_port_info = module_manager.module_port(wl_decoder_module, bl_decoder_addr_port); + + /* Top module Enable port -> WL Decoder Enable port */ + add_module_bus_nets(module_manager, + top_module, + top_module, 0, en_port, + wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_en_port); + + /* Top module Address port -> WL Decoder Address port */ + add_module_bus_nets(module_manager, + top_module, + top_module, 0, wl_addr_port, + wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_addr_port); + + /************************************************************** + * Add nets from BL data out to each configurable child + */ + size_t cur_bl_index = 0; + + ModulePortId bl_decoder_dout_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort bl_decoder_dout_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_dout_port); + + std::map num_bls_per_tile; + std::map num_wls_per_tile; + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + num_bls_per_tile[coord.x()] = std::max(num_bls_per_tile[coord.x()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK))); + num_wls_per_tile[coord.y()] = std::max(num_wls_per_tile[coord.y()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK))); + + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the BL port */ + ModulePortId child_bl_port = module_manager.find_module_port(child_module, std::string(MEMORY_BL_PORT_NAME)); + BasicPort child_bl_port_info = module_manager.module_port(child_module, child_bl_port); + + for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { + /* Find the BL decoder data index: + * It should be the residual when divided by the number of BLs + */ + size_t bl_pin_id = std::floor(cur_bl_index / num_bls); + if (!(bl_pin_id < bl_decoder_dout_port_info.pins().size())) + VTR_ASSERT(bl_pin_id < bl_decoder_dout_port_info.pins().size()); + + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + bl_decoder_module, curr_bl_decoder_instance_id, + bl_decoder_dout_port, + bl_decoder_dout_port_info.pins()[bl_pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_bl_port, sink_bl_pin); + + /* Increment the BL index */ + cur_bl_index++; + } + } + + /************************************************************** + * Add nets from WL data out to each configurable child + */ + size_t cur_wl_index = 0; + + ModulePortId wl_decoder_dout_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort wl_decoder_dout_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_dout_port); + + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the WL port */ + ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME)); + BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port); + + for (const size_t& sink_wl_pin : child_wl_port_info.pins()) { + /* Find the BL decoder data index: + * It should be the residual when divided by the number of BLs + */ + size_t wl_pin_id = cur_wl_index % num_wls; + + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + wl_decoder_module, curr_wl_decoder_instance_id, + wl_decoder_dout_port, + wl_decoder_dout_port_info.pins()[wl_pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_wl_port, sink_wl_pin); + + /* Increment the WL index */ + cur_wl_index++; + } + } + + /************************************************************** + * Add the BL and WL decoders to the end of configurable children list + * Note: this MUST be done after adding all the module nets to other regular configurable children + */ + module_manager.add_configurable_child(top_module, bl_decoder_module, curr_bl_decoder_instance_id); + module_manager.add_configurable_child_to_region(top_module, + config_region, + bl_decoder_module, + curr_bl_decoder_instance_id, + module_manager.configurable_children(top_module).size() - 1); + + module_manager.add_configurable_child(top_module, wl_decoder_module, curr_wl_decoder_instance_id); + module_manager.add_configurable_child_to_region(top_module, + config_region, + wl_decoder_module, + curr_wl_decoder_instance_id, + module_manager.configurable_children(top_module).size() - 1); + } +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_memory_bank.h b/openfpga/src/fabric/build_top_module_memory_bank.h new file mode 100644 index 000000000..69f4408ef --- /dev/null +++ b/openfpga/src/fabric/build_top_module_memory_bank.h @@ -0,0 +1,33 @@ +#ifndef BUILD_TOP_MODULE_MEMORY_BANK_H +#define BUILD_TOP_MODULE_MEMORY_BANK_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ + +#include +#include +#include "vtr_vector.h" +#include "vtr_ndmatrix.h" +#include "module_manager.h" +#include "circuit_library.h" +#include "decoder_library.h" +#include "build_top_module_memory_utils.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const TopModuleNumConfigBits& num_config_bits); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fabric/build_top_module_memory_utils.h b/openfpga/src/fabric/build_top_module_memory_utils.h new file mode 100644 index 000000000..235f54055 --- /dev/null +++ b/openfpga/src/fabric/build_top_module_memory_utils.h @@ -0,0 +1,28 @@ +#ifndef BUILD_TOP_MODULE_MEMORY_UTILS_H +#define BUILD_TOP_MODULE_MEMORY_UTILS_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ + +#include +#include +#include "vtr_vector.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +/* A data structure to store the number of configuration bits for each configurable region + * of the top-level module. + * For different configuration protocol, the std::pair represents different data + * See details in each function about how the data is organized + */ +typedef vtr::vector> TopModuleNumConfigBits; + +} /* end namespace openfpga */ + +#endif From 475ce2c6d9a9d664ffbd7afe31d676362b334151 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 5 Sep 2021 17:49:01 -0700 Subject: [PATCH 020/229] [Engine] Upgrade fabric generator in support QL memory bank connections --- .../fabric/build_top_module_memory_bank.cpp | 89 ++++++++++++++++--- 1 file changed, 75 insertions(+), 14 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 4854b711c..97986f3ed 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -3,6 +3,7 @@ * in the top module of FPGA fabric *******************************************************************/ #include +#include /* Headers from vtrutil library */ #include "vtr_assert.h" @@ -277,20 +278,75 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_addr_port); /************************************************************** - * Add nets from BL data out to each configurable child + * Precompute the BLs and WLs distribution across the FPGA fabric + * The distribution is a matrix which contains the starting index of BL/WL for each column or row */ - size_t cur_bl_index = 0; + std::pair child_x_range(std::numeric_limits::max(), std::numeric_limits::min()); // Deposit an invalid range first: LSB->max(); MSB->min() + std::pair child_y_range(std::numeric_limits::max(), std::numeric_limits::min()); // Deposit an invalid range first: LSB->max(); MSB->min() + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + child_x_range.first = std::min(coord.x(), child_x_range.first); + child_x_range.second = std::max(coord.x(), child_x_range.second); + child_y_range.first = std::min(coord.y(), child_y_range.first); + child_y_range.second = std::max(coord.y(), child_y_range.second); + } - ModulePortId bl_decoder_dout_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); - BasicPort bl_decoder_dout_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_dout_port); - - std::map num_bls_per_tile; - std::map num_wls_per_tile; + std::map num_bls_per_tile; + std::map num_wls_per_tile; for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; num_bls_per_tile[coord.x()] = std::max(num_bls_per_tile[coord.x()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK))); num_wls_per_tile[coord.y()] = std::max(num_wls_per_tile[coord.y()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK))); + } + + std::map bl_starting_index_per_tile; + for (int ibl = child_x_range.first; ibl <= child_x_range.second; ++ibl) { + if (ibl == child_x_range.first) { + bl_starting_index_per_tile[ibl] = 0; + } else { + bl_starting_index_per_tile[ibl] = num_bls_per_tile[ibl - 1] + bl_starting_index_per_tile[ibl - 1]; + } + } + + std::map wl_starting_index_per_tile; + for (int iwl = child_y_range.first; iwl <= child_y_range.second; ++iwl) { + if (iwl == child_y_range.first) { + wl_starting_index_per_tile[iwl] = 0; + } else { + wl_starting_index_per_tile[iwl] = num_wls_per_tile[iwl - 1] + wl_starting_index_per_tile[iwl - 1]; + } + } + + /************************************************************** + * Add nets from BL data out to each configurable child + * BL data output pins are connected to the BL input pins of each PB/CB/SB + * For all the PB/CB/SB in the same column, they share the same set of BLs + * A quick example + * + * BL[i .. i + sqrt(N)] + * | + * | CLB[1][H] + * | +---------+ + * | | SRAM | + * +-->| [0..N] | + * | +---------+ + * | + * ... + * | CLB[1][1] + * | +---------+ + * | | SRAM | + * +-->| [0..N] | + * | +---------+ + * | + */ + ModulePortId bl_decoder_dout_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort bl_decoder_dout_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_dout_port); + + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + int child_num_unique_blwls = find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK)); size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; @@ -298,11 +354,13 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma ModulePortId child_bl_port = module_manager.find_module_port(child_module, std::string(MEMORY_BL_PORT_NAME)); BasicPort child_bl_port_info = module_manager.module_port(child_module, child_bl_port); + size_t cur_bl_index = 0; + for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { /* Find the BL decoder data index: - * It should be the residual when divided by the number of BLs + * It should be the starting index plus an offset which is the residual when divided by the number of BLs in this tile */ - size_t bl_pin_id = std::floor(cur_bl_index / num_bls); + size_t bl_pin_id = bl_starting_index_per_tile[coord.x()] + std::floor(cur_bl_index / child_num_unique_blwls); if (!(bl_pin_id < bl_decoder_dout_port_info.pins().size())) VTR_ASSERT(bl_pin_id < bl_decoder_dout_port_info.pins().size()); @@ -325,24 +383,27 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma /************************************************************** * Add nets from WL data out to each configurable child */ - size_t cur_wl_index = 0; - ModulePortId wl_decoder_dout_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); BasicPort wl_decoder_dout_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_dout_port); for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + int child_num_unique_blwls = find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK)); + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; /* Find the WL port */ ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME)); BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port); + size_t cur_wl_index = 0; + for (const size_t& sink_wl_pin : child_wl_port_info.pins()) { - /* Find the BL decoder data index: - * It should be the residual when divided by the number of BLs + /* Find the WL decoder data index: + * It should be the starting index plus an offset which is the residual when divided by the number of WLs in this tile */ - size_t wl_pin_id = cur_wl_index % num_wls; + size_t wl_pin_id = wl_starting_index_per_tile[coord.x()] + cur_wl_index % child_num_unique_blwls; /* Create net */ ModuleNetId net = create_module_source_pin_net(module_manager, top_module, From 1085e468e2ea55ea58d150efa6a35879ab7d7223 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 5 Sep 2021 20:45:56 -0700 Subject: [PATCH 021/229] [Engine] Move most utilized functions for memory bank configuration protocol to a separated source file --- .../fabric/build_top_module_memory_bank.cpp | 49 +--- .../fpga_bitstream/build_fabric_bitstream.cpp | 8 + .../build_fabric_bitstream_memory_bank.cpp | 237 ++++++++++++++++++ .../build_fabric_bitstream_memory_bank.h | 29 +++ openfpga/src/utils/memory_bank_utils.cpp | 105 ++++++++ openfpga/src/utils/memory_bank_utils.h | 74 ++++++ 6 files changed, 466 insertions(+), 36 deletions(-) create mode 100644 openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp create mode 100644 openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.h create mode 100644 openfpga/src/utils/memory_bank_utils.cpp create mode 100644 openfpga/src/utils/memory_bank_utils.h diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 97986f3ed..2df41c5e2 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -23,6 +23,7 @@ #include "memory_utils.h" #include "decoder_library_utils.h" #include "module_manager_utils.h" +#include "memory_bank_utils.h" #include "build_decoder_modules.h" #include "build_top_module_memory_bank.h" @@ -281,42 +282,18 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma * Precompute the BLs and WLs distribution across the FPGA fabric * The distribution is a matrix which contains the starting index of BL/WL for each column or row */ - std::pair child_x_range(std::numeric_limits::max(), std::numeric_limits::min()); // Deposit an invalid range first: LSB->max(); MSB->min() - std::pair child_y_range(std::numeric_limits::max(), std::numeric_limits::min()); // Deposit an invalid range first: LSB->max(); MSB->min() - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - child_x_range.first = std::min(coord.x(), child_x_range.first); - child_x_range.second = std::max(coord.x(), child_x_range.second); - child_y_range.first = std::min(coord.y(), child_y_range.first); - child_y_range.second = std::max(coord.y(), child_y_range.second); - } + std::pair child_x_range = compute_memory_bank_regional_configurable_child_x_range(module_manager, top_module, config_region); + std::pair child_y_range = compute_memory_bank_regional_configurable_child_y_range(module_manager, top_module, config_region); - std::map num_bls_per_tile; - std::map num_wls_per_tile; - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - num_bls_per_tile[coord.x()] = std::max(num_bls_per_tile[coord.x()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK))); - num_wls_per_tile[coord.y()] = std::max(num_wls_per_tile[coord.y()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK))); - } + std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, + config_region, + circuit_lib, sram_model); + std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, + config_region, + circuit_lib, sram_model); - std::map bl_starting_index_per_tile; - for (int ibl = child_x_range.first; ibl <= child_x_range.second; ++ibl) { - if (ibl == child_x_range.first) { - bl_starting_index_per_tile[ibl] = 0; - } else { - bl_starting_index_per_tile[ibl] = num_bls_per_tile[ibl - 1] + bl_starting_index_per_tile[ibl - 1]; - } - } - - std::map wl_starting_index_per_tile; - for (int iwl = child_y_range.first; iwl <= child_y_range.second; ++iwl) { - if (iwl == child_y_range.first) { - wl_starting_index_per_tile[iwl] = 0; - } else { - wl_starting_index_per_tile[iwl] = num_wls_per_tile[iwl - 1] + wl_starting_index_per_tile[iwl - 1]; - } - } + std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); + std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); /************************************************************** * Add nets from BL data out to each configurable child @@ -360,7 +337,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma /* Find the BL decoder data index: * It should be the starting index plus an offset which is the residual when divided by the number of BLs in this tile */ - size_t bl_pin_id = bl_starting_index_per_tile[coord.x()] + std::floor(cur_bl_index / child_num_unique_blwls); + size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + std::floor(cur_bl_index / child_num_unique_blwls); if (!(bl_pin_id < bl_decoder_dout_port_info.pins().size())) VTR_ASSERT(bl_pin_id < bl_decoder_dout_port_info.pins().size()); @@ -403,7 +380,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma /* Find the WL decoder data index: * It should be the starting index plus an offset which is the residual when divided by the number of WLs in this tile */ - size_t wl_pin_id = wl_starting_index_per_tile[coord.x()] + cur_wl_index % child_num_unique_blwls; + size_t wl_pin_id = wl_start_index_per_tile[coord.x()] + cur_wl_index % child_num_unique_blwls; /* Create net */ ModuleNetId net = create_module_source_pin_net(module_manager, top_module, diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp index cf028b084..9065a6ae5 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -19,6 +19,7 @@ #include "decoder_library_utils.h" #include "bitstream_manager_utils.h" #include "build_fabric_bitstream.h" +#include "build_fabric_bitstream_memory_bank.h" /* begin namespace openfpga */ namespace openfpga { @@ -575,6 +576,13 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc } break; } + case CONFIG_MEM_QL_MEMORY_BANK: { + build_module_fabric_dependent_bitstream_ql_memory_bank(config_protocol, + bitstream_manager, top_block, + module_manager, top_module, + fabric_bitstream); + break; + } case CONFIG_MEM_FRAME_BASED: { /* Find address port size */ diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp new file mode 100644 index 000000000..1fefa79b2 --- /dev/null +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -0,0 +1,237 @@ +/******************************************************************** + * This file includes functions to build fabric dependent bitstream + * for memory bank configuration protocol + *******************************************************************/ +#include +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from openfpgautil library */ +#include "openfpga_decode.h" + +#include "openfpga_reserved_words.h" +#include "openfpga_naming.h" + +#include "decoder_library_utils.h" +#include "bitstream_manager_utils.h" +#include "build_fabric_bitstream_memory_bank.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * This function aims to build a bitstream for memory-bank protocol + * It will walk through all the configurable children under a module + * in a recursive way, following a Depth-First Search (DFS) strategy + * For each configuration child, we use its instance name as a key to spot the + * configuration bits in bitstream manager. + * Note that it is guarentee that the instance name in module manager is + * consistent with the block names in bitstream manager + * We use this link to reorganize the bitstream in the sequence of memories as we stored + * in the configurable_children() and configurable_child_instances() of each module of module manager + * + * In such configuration organization, each memory cell has an unique index. + * Using this index, we can infer the address codes for both BL and WL decoders. + * Note that, we must get the number of BLs and WLs before using this function! + *******************************************************************/ +static +void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const BitstreamManager& bitstream_manager, + const ConfigBlockId& parent_block, + const ModuleManager& module_manager, + const ModuleId& top_module, + const ModuleId& parent_module, + const ConfigRegionId& config_region, + const size_t& bl_addr_size, + const size_t& wl_addr_size, + const size_t& num_bls, + const size_t& num_wls, + size_t& cur_mem_index, + FabricBitstream& fabric_bitstream, + const FabricBitRegionId& fabric_bitstream_region) { + + /* Depth-first search: if we have any children in the parent_block, + * we dive to the next level first! + */ + if (0 < bitstream_manager.block_children(parent_block).size()) { + /* For top module: + * - Use regional configurable children + * - we will skip the two decoders at the end of the configurable children list + */ + if (parent_module == top_module) { + std::vector configurable_children = module_manager.region_configurable_children(parent_module, config_region); + + VTR_ASSERT(2 <= configurable_children.size()); + size_t num_configurable_children = configurable_children.size() - 2; + + /* Early exit if there is no configurable children */ + if (0 == num_configurable_children) { + /* Ensure that there should be no configuration bits in the parent block */ + VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size()); + return; + } + + for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) { + ModuleId child_module = configurable_children[child_id]; + size_t child_instance = module_manager.region_configurable_child_instances(parent_module, config_region)[child_id]; + + /* Get the instance name and ensure it is not empty */ + std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); + + /* Find the child block that matches the instance name! */ + ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); + /* We must have one valid block id! */ + VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); + + /* Go recursively */ + rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, child_block, + module_manager, top_module, child_module, + config_region, + bl_addr_size, wl_addr_size, + num_bls, num_wls, + cur_mem_index, + fabric_bitstream, + fabric_bitstream_region); + } + } else { + VTR_ASSERT(parent_module != top_module); + /* For other modules: + * - Use configurable children directly + * - no need to exclude decoders as they are not there + */ + std::vector configurable_children = module_manager.configurable_children(parent_module); + + size_t num_configurable_children = configurable_children.size(); + + /* Early exit if there is no configurable children */ + if (0 == num_configurable_children) { + /* Ensure that there should be no configuration bits in the parent block */ + VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size()); + return; + } + + for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) { + ModuleId child_module = configurable_children[child_id]; + size_t child_instance = module_manager.configurable_child_instances(parent_module)[child_id]; + + /* Get the instance name and ensure it is not empty */ + std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); + + /* Find the child block that matches the instance name! */ + ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); + /* We must have one valid block id! */ + VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); + + /* Go recursively */ + rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, child_block, + module_manager, top_module, child_module, + config_region, + bl_addr_size, wl_addr_size, + num_bls, num_wls, + cur_mem_index, + fabric_bitstream, + fabric_bitstream_region); + } + } + /* Ensure that there should be no configuration bits in the parent block */ + VTR_ASSERT(0 == bitstream_manager.block_bits(parent_block).size()); + + return; + } + + /* Note that, reach here, it means that this is a leaf node. + * We add the configuration bits to the fabric_bitstream, + * And then, we can return + */ + for (const ConfigBitId& config_bit : bitstream_manager.block_bits(parent_block)) { + FabricBitId fabric_bit = fabric_bitstream.add_bit(config_bit); + + /* Find BL address */ + size_t cur_bl_index = std::floor(cur_mem_index / num_bls); + std::vector bl_addr_bits_vec = itobin_charvec(cur_bl_index, bl_addr_size); + + /* Find WL address */ + size_t cur_wl_index = cur_mem_index % num_wls; + std::vector wl_addr_bits_vec = itobin_charvec(cur_wl_index, wl_addr_size); + + /* Set BL address */ + fabric_bitstream.set_bit_bl_address(fabric_bit, bl_addr_bits_vec); + + /* Set WL address */ + fabric_bitstream.set_bit_wl_address(fabric_bit, wl_addr_bits_vec); + + /* Set data input */ + fabric_bitstream.set_bit_din(fabric_bit, bitstream_manager.bit_value(config_bit)); + + /* Add the bit to the region */ + fabric_bitstream.add_bit_to_region(fabric_bitstream_region, fabric_bit); + + /* Increase the memory index */ + cur_mem_index++; + } +} + +/******************************************************************** + * Main function to build a fabric-dependent bitstream + * by considering the configuration protocol types + *******************************************************************/ +void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol& config_protocol, + const BitstreamManager& bitstream_manager, + const ConfigBlockId& top_block, + const ModuleManager& module_manager, + const ModuleId& top_module, + FabricBitstream& fabric_bitstream) { + /* Ensure we are in the correct type of configuration protocol*/ + VTR_ASSERT(config_protocol.type() == CONFIG_MEM_QL_MEMORY_BANK); + + /* Find global BL address port size */ + ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port); + + /* Find global WL address port size */ + ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port); + + /* Reserve bits before build-up */ + fabric_bitstream.set_use_address(true); + fabric_bitstream.set_use_wl_address(true); + fabric_bitstream.set_bl_address_length(bl_addr_port_info.get_width()); + fabric_bitstream.set_wl_address_length(wl_addr_port_info.get_width()); + fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); + + /* Build bitstreams by region */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + size_t cur_mem_index = 0; + + /* Find port information for local BL and WL decoder in this region */ + std::vector configurable_children = module_manager.region_configurable_children(top_module, config_region); + VTR_ASSERT(2 <= configurable_children.size()); + ModuleId bl_decoder_module = configurable_children[configurable_children.size() - 2]; + ModuleId wl_decoder_module = configurable_children[configurable_children.size() - 1]; + + ModulePortId bl_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort bl_port_info = module_manager.module_port(bl_decoder_module, bl_port); + + ModulePortId wl_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); + BasicPort wl_port_info = module_manager.module_port(wl_decoder_module, wl_port); + + /* Build the bitstream for all the blocks in this region */ + FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region(); + rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, top_block, + module_manager, top_module, top_module, + config_region, + bl_addr_port_info.get_width(), + wl_addr_port_info.get_width(), + bl_port_info.get_width(), + wl_port_info.get_width(), + cur_mem_index, + fabric_bitstream, + fabric_bitstream_region); + } +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.h b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.h new file mode 100644 index 000000000..41174a2fe --- /dev/null +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.h @@ -0,0 +1,29 @@ +#ifndef BUILD_FABRIC_BITSTREAM_MEMORY_BANK_H +#define BUILD_FABRIC_BITSTREAM_MEMORY_BANK_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include "config_protocol.h" +#include "bitstream_manager.h" +#include "fabric_bitstream.h" +#include "module_manager.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol& config_protocol, + const BitstreamManager& bitstream_manager, + const ConfigBlockId& top_block, + const ModuleManager& module_manager, + const ModuleId& top_module, + FabricBitstream& fabric_bitstream); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/utils/memory_bank_utils.cpp b/openfpga/src/utils/memory_bank_utils.cpp new file mode 100644 index 000000000..d43909e4d --- /dev/null +++ b/openfpga/src/utils/memory_bank_utils.cpp @@ -0,0 +1,105 @@ +/******************************************************************** + * This file includes functions that are used to organize memories + * in the top module of FPGA fabric + *******************************************************************/ +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from vpr library */ +#include "vpr_utils.h" + +/* Headers from openfpgashell library */ +#include "command_exit_codes.h" + +#include "rr_gsb_utils.h" +#include "openfpga_reserved_words.h" +#include "openfpga_naming.h" + +#include "memory_utils.h" +#include "decoder_library_utils.h" +#include "module_manager_utils.h" +#include "memory_bank_utils.h" + +/* begin namespace openfpga */ +namespace openfpga { + +std::pair compute_memory_bank_regional_configurable_child_x_range(const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigRegionId& config_region) { + std::pair child_x_range(std::numeric_limits::max(), std::numeric_limits::min()); // Deposit an invalid range first: LSB->max(); MSB->min() + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + child_x_range.first = std::min(coord.x(), child_x_range.first); + child_x_range.second = std::max(coord.x(), child_x_range.second); + } + + VTR_ASSERT(child_x_range.first <= child_x_range.second); + return child_x_range; +} + +std::pair compute_memory_bank_regional_configurable_child_y_range(const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigRegionId& config_region) { + std::pair child_y_range(std::numeric_limits::max(), std::numeric_limits::min()); // Deposit an invalid range first: LSB->max(); MSB->min() + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + child_y_range.first = std::min(coord.y(), child_y_range.first); + child_y_range.second = std::max(coord.y(), child_y_range.second); + } + + VTR_ASSERT(child_y_range.first <= child_y_range.second); + return child_y_range; +} + +std::map compute_memory_bank_regional_bitline_numbers_per_tile(const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigRegionId& config_region, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model) { + std::map num_bls_per_tile; + + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + num_bls_per_tile[coord.x()] = std::max(num_bls_per_tile[coord.x()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK))); + } + + return num_bls_per_tile; +} + +std::map compute_memory_bank_regional_wordline_numbers_per_tile(const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigRegionId& config_region, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model) { + std::map num_wls_per_tile; + + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + num_wls_per_tile[coord.y()] = std::max(num_wls_per_tile[coord.y()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK))); + } + + return num_wls_per_tile; +} + +std::map compute_memory_bank_regional_blwl_start_index_per_tile(const std::pair& child_xy_range, + const std::map& num_blwls_per_tile) { + std::map blwl_start_index_per_tile; + for (int iblwl = child_xy_range.first; iblwl <= child_xy_range.second; ++iblwl) { + if (iblwl == child_xy_range.first) { + blwl_start_index_per_tile[iblwl] = 0; + } else { + blwl_start_index_per_tile[iblwl] = num_blwls_per_tile.at(iblwl - 1) + blwl_start_index_per_tile[iblwl - 1]; + } + } + return blwl_start_index_per_tile; +} + +} /* end namespace openfpga */ + diff --git a/openfpga/src/utils/memory_bank_utils.h b/openfpga/src/utils/memory_bank_utils.h new file mode 100644 index 000000000..fd08c5e3d --- /dev/null +++ b/openfpga/src/utils/memory_bank_utils.h @@ -0,0 +1,74 @@ +#ifndef MEMORY_BANK_UTILS_H +#define MEMORY_BANK_UTILS_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ + +#include +#include +#include "vtr_vector.h" +#include "vtr_ndmatrix.h" +#include "module_manager.h" +#include "circuit_library.h" +#include "decoder_library.h" +#include "build_top_module_memory_utils.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +/** + * @brief Precompute the range of x coordinates of all the configurable children under a specific configuration region + * The lower bound is stored in the first element of the return struct + * The upper bound is stored in the second element of the return struct + */ +std::pair compute_memory_bank_regional_configurable_child_x_range(const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigRegionId& config_region); + +/** + * @brief Precompute the range of y coordinates of all the configurable children under a specific configuration region + * The lower bound is stored in the first element of the return struct + * The upper bound is stored in the second element of the return struct + */ +std::pair compute_memory_bank_regional_configurable_child_y_range(const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigRegionId& config_region); + +/** + * @brief Precompute the number of bit lines required by each tile under a specific configuration region + * @note + * Not every index in the range computed by the compute_memory_bank_regional_configurable_child_x_range() function has a postive number of bit lines + * If an empty entry is found (e.g., std::map::find(x) is empty), it means there are not bit lines required in that tile + */ +std::map compute_memory_bank_regional_bitline_numbers_per_tile(const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigRegionId& config_region, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model); +/** + * @brief Precompute the number of word lines required by each tile under a specific configuration region + * @note + * Not every index in the range computed by the compute_memory_bank_regional_configurable_child_x_range() function has a postive number of word lines + * If an empty entry is found (e.g., std::map::find(y) is empty), it means there are not word lines required in that tile + */ +std::map compute_memory_bank_regional_wordline_numbers_per_tile(const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigRegionId& config_region, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model); + +/** + * @brief Precompute the BLs and WLs distribution across the FPGA fabric + * The distribution is a matrix which contains the starting index of BL/WL for each column or row + */ +std::map compute_memory_bank_regional_blwl_start_index_per_tile(const std::pair& child_xy_range, + const std::map& num_blwls_per_tile); + +} /* end namespace openfpga */ + +#endif From 6f09f5f7adbaeb9a75bedf62c2690cf01654b709 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 5 Sep 2021 21:25:58 -0700 Subject: [PATCH 022/229] [FPGA-Bitstream] Upgrade bitstream generator to support QL memory bank --- openfpga/src/base/openfpga_bitstream.cpp | 1 + .../fpga_bitstream/build_fabric_bitstream.cpp | 6 ++- .../fpga_bitstream/build_fabric_bitstream.h | 2 + .../build_fabric_bitstream_memory_bank.cpp | 54 ++++++++++++++++--- .../build_fabric_bitstream_memory_bank.h | 2 + 5 files changed, 55 insertions(+), 10 deletions(-) diff --git a/openfpga/src/base/openfpga_bitstream.cpp b/openfpga/src/base/openfpga_bitstream.cpp index b978b200d..315f647bc 100644 --- a/openfpga/src/base/openfpga_bitstream.cpp +++ b/openfpga/src/base/openfpga_bitstream.cpp @@ -76,6 +76,7 @@ int build_fabric_bitstream(OpenfpgaContext& openfpga_ctx, /* Build fabric bitstream here */ openfpga_ctx.mutable_fabric_bitstream() = build_fabric_dependent_bitstream(openfpga_ctx.bitstream_manager(), openfpga_ctx.module_graph(), + openfpga_ctx.arch().circuit_lib, openfpga_ctx.arch().config_protocol, cmd_context.option_enable(cmd, opt_verbose)); diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp index 9065a6ae5..216f44354 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.cpp @@ -490,6 +490,7 @@ void rec_build_module_fabric_dependent_frame_bitstream(const BitstreamManager& b *******************************************************************/ static void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protocol, + const CircuitLibrary& circuit_lib, const BitstreamManager& bitstream_manager, const ConfigBlockId& top_block, const ModuleManager& module_manager, @@ -577,7 +578,7 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc break; } case CONFIG_MEM_QL_MEMORY_BANK: { - build_module_fabric_dependent_bitstream_ql_memory_bank(config_protocol, + build_module_fabric_dependent_bitstream_ql_memory_bank(config_protocol, circuit_lib, bitstream_manager, top_block, module_manager, top_module, fabric_bitstream); @@ -702,6 +703,7 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc *******************************************************************/ FabricBitstream build_fabric_dependent_bitstream(const BitstreamManager& bitstream_manager, const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, const bool& verbose) { FabricBitstream fabric_bitstream; @@ -720,7 +722,7 @@ FabricBitstream build_fabric_dependent_bitstream(const BitstreamManager& bitstre VTR_ASSERT(0 == top_module_name.compare(bitstream_manager.block_name(top_block[0]))); /* Start build-up formally */ - build_module_fabric_dependent_bitstream(config_protocol, + build_module_fabric_dependent_bitstream(config_protocol, circuit_lib, bitstream_manager, top_block[0], module_manager, top_module, fabric_bitstream); diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream.h b/openfpga/src/fpga_bitstream/build_fabric_bitstream.h index 3daadde75..8905b03a5 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream.h @@ -6,6 +6,7 @@ *******************************************************************/ #include #include "config_protocol.h" +#include "circuit_library.h" #include "bitstream_manager.h" #include "fabric_bitstream.h" #include "module_manager.h" @@ -19,6 +20,7 @@ namespace openfpga { FabricBitstream build_fabric_dependent_bitstream(const BitstreamManager& bitstream_manager, const ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, const bool& verbose); diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index 1fefa79b2..5399832b2 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -19,6 +19,7 @@ #include "decoder_library_utils.h" #include "bitstream_manager_utils.h" +#include "memory_bank_utils.h" #include "build_fabric_bitstream_memory_bank.h" /* begin namespace openfpga */ @@ -48,8 +49,11 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B const ConfigRegionId& config_region, const size_t& bl_addr_size, const size_t& wl_addr_size, - const size_t& num_bls, - const size_t& num_wls, + const std::map& num_bls_per_tile, + const std::map& bl_start_index_per_tile, + const std::map& num_wls_per_tile, + const std::map& wl_start_index_per_tile, + vtr::Point& tile_coord, size_t& cur_mem_index, FabricBitstream& fabric_bitstream, const FabricBitRegionId& fabric_bitstream_region) { @@ -79,6 +83,10 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B ModuleId child_module = configurable_children[child_id]; size_t child_instance = module_manager.region_configurable_child_instances(parent_module, config_region)[child_id]; + if (parent_module == top_module) { + tile_coord = module_manager.region_configurable_child_coordinates(parent_module, config_region)[child_id]; + } + /* Get the instance name and ensure it is not empty */ std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); @@ -87,12 +95,19 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B /* We must have one valid block id! */ VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); + /* Reset the memory index for each children under the top-level module */ + if (parent_module == top_module) { + cur_mem_index = 0; + } + /* Go recursively */ rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, child_block, module_manager, top_module, child_module, config_region, bl_addr_size, wl_addr_size, - num_bls, num_wls, + num_bls_per_tile, bl_start_index_per_tile, + num_wls_per_tile, wl_start_index_per_tile, + tile_coord, cur_mem_index, fabric_bitstream, fabric_bitstream_region); @@ -131,7 +146,9 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B module_manager, top_module, child_module, config_region, bl_addr_size, wl_addr_size, - num_bls, num_wls, + num_bls_per_tile, bl_start_index_per_tile, + num_wls_per_tile, wl_start_index_per_tile, + tile_coord, cur_mem_index, fabric_bitstream, fabric_bitstream_region); @@ -151,11 +168,11 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B FabricBitId fabric_bit = fabric_bitstream.add_bit(config_bit); /* Find BL address */ - size_t cur_bl_index = std::floor(cur_mem_index / num_bls); + size_t cur_bl_index = bl_start_index_per_tile.at(tile_coord.x()) + std::floor(cur_mem_index / num_bls_per_tile.at(tile_coord.x())); std::vector bl_addr_bits_vec = itobin_charvec(cur_bl_index, bl_addr_size); /* Find WL address */ - size_t cur_wl_index = cur_mem_index % num_wls; + size_t cur_wl_index = wl_start_index_per_tile.at(tile_coord.y()) + cur_mem_index % num_wls_per_tile.at(tile_coord.y()); std::vector wl_addr_bits_vec = itobin_charvec(cur_wl_index, wl_addr_size); /* Set BL address */ @@ -180,6 +197,7 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B * by considering the configuration protocol types *******************************************************************/ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol& config_protocol, + const CircuitLibrary& circuit_lib, const BitstreamManager& bitstream_manager, const ConfigBlockId& top_block, const ModuleManager& module_manager, @@ -221,13 +239,33 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol /* Build the bitstream for all the blocks in this region */ FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region(); + + /************************************************************** + * Precompute the BLs and WLs distribution across the FPGA fabric + * The distribution is a matrix which contains the starting index of BL/WL for each column or row + */ + std::pair child_x_range = compute_memory_bank_regional_configurable_child_x_range(module_manager, top_module, config_region); + std::pair child_y_range = compute_memory_bank_regional_configurable_child_y_range(module_manager, top_module, config_region); + + std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, + config_region, + circuit_lib, config_protocol.memory_model()); + std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, + config_region, + circuit_lib, config_protocol.memory_model()); + + std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); + std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); + + vtr::Point temp_coord; rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, top_block, module_manager, top_module, top_module, config_region, bl_addr_port_info.get_width(), wl_addr_port_info.get_width(), - bl_port_info.get_width(), - wl_port_info.get_width(), + num_bls_per_tile, bl_start_index_per_tile, + num_wls_per_tile, wl_start_index_per_tile, + temp_coord, cur_mem_index, fabric_bitstream, fabric_bitstream_region); diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.h b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.h index 41174a2fe..58d511394 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.h +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.h @@ -6,6 +6,7 @@ *******************************************************************/ #include #include "config_protocol.h" +#include "circuit_library.h" #include "bitstream_manager.h" #include "fabric_bitstream.h" #include "module_manager.h" @@ -18,6 +19,7 @@ namespace openfpga { void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol& config_protocol, + const CircuitLibrary& circuit_lib, const BitstreamManager& bitstream_manager, const ConfigBlockId& top_block, const ModuleManager& module_manager, From 1aac3197ebb1ecd2372a7ae55f61311cd27da037 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 5 Sep 2021 21:38:00 -0700 Subject: [PATCH 023/229] [FPGA-Verilog] Upgrade testbench generator to support QL memory bank --- .../fpga_verilog/verilog_top_testbench.cpp | 45 +---- .../verilog_top_testbench_constants.h | 42 +++++ .../verilog_top_testbench_memory_bank.cpp | 175 ++++++++++++++++++ .../verilog_top_testbench_memory_bank.h | 43 +++++ 4 files changed, 270 insertions(+), 35 deletions(-) create mode 100644 openfpga/src/fpga_verilog/verilog_top_testbench_constants.h create mode 100644 openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp create mode 100644 openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index e4778c292..4751823a3 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -29,46 +29,14 @@ #include "verilog_constants.h" #include "verilog_writer_utils.h" #include "verilog_testbench_utils.h" +#include "verilog_top_testbench_memory_bank.h" #include "verilog_top_testbench.h" +#include "verilog_top_testbench_constants.h" + /* begin namespace openfpga */ namespace openfpga { -/******************************************************************** - * Local variables used only in this file - *******************************************************************/ -constexpr char* TOP_TESTBENCH_REFERENCE_INSTANCE_NAME = "REF_DUT"; -constexpr char* TOP_TESTBENCH_FPGA_INSTANCE_NAME = "FPGA_DUT"; -constexpr char* TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX = "_benchmark"; -constexpr char* TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX = "_fpga"; - -constexpr char* TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX = "_flag"; - -constexpr char* TOP_TESTBENCH_PROG_TASK_NAME = "prog_cycle_task"; - -constexpr char* TOP_TESTBENCH_SIM_START_PORT_NAME = "sim_start"; - -constexpr char* TOP_TESTBENCH_ERROR_COUNTER = "nb_error"; - -constexpr char* TOP_TB_RESET_PORT_NAME = "greset"; -constexpr char* TOP_TB_SET_PORT_NAME = "gset"; -constexpr char* TOP_TB_PROG_RESET_PORT_NAME = "prog_reset"; -constexpr char* TOP_TB_PROG_SET_PORT_NAME = "prog_set"; -constexpr char* TOP_TB_CONFIG_DONE_PORT_NAME = "config_done"; -constexpr char* TOP_TB_OP_CLOCK_PORT_NAME = "op_clock"; -constexpr char* TOP_TB_OP_CLOCK_PORT_PREFIX = "operating_clk_"; -constexpr char* TOP_TB_PROG_CLOCK_PORT_NAME = "prog_clock"; -constexpr char* TOP_TB_INOUT_REG_POSTFIX = "_reg"; -constexpr char* TOP_TB_CLOCK_REG_POSTFIX = "_reg"; -constexpr char* TOP_TB_BITSTREAM_LENGTH_VARIABLE = "BITSTREAM_LENGTH"; -constexpr char* TOP_TB_BITSTREAM_WIDTH_VARIABLE = "BITSTREAM_WIDTH"; -constexpr char* TOP_TB_BITSTREAM_MEM_REG_NAME = "bit_mem"; -constexpr char* TOP_TB_BITSTREAM_INDEX_REG_NAME = "bit_index"; -constexpr char* TOP_TB_BITSTREAM_ITERATOR_REG_NAME = "ibit"; -constexpr char* TOP_TB_BITSTREAM_SKIP_FLAG_REG_NAME = "skip_bits"; - -constexpr char* AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX = "_autocheck_top_tb"; - /******************************************************************** * Generate a simulation clock port name * This function is designed to produce a uniform clock naming for these ports @@ -1735,6 +1703,13 @@ void print_verilog_full_testbench_bitstream(std::fstream& fp, module_manager, top_module, fabric_bitstream); break; + case CONFIG_MEM_QL_MEMORY_BANK: + print_verilog_full_testbench_ql_memory_bank_bitstream(fp, bitstream_file, + fast_configuration, + bit_value_to_skip, + module_manager, top_module, + fabric_bitstream); + break; case CONFIG_MEM_FRAME_BASED: print_verilog_full_testbench_frame_decoder_bitstream(fp, bitstream_file, fast_configuration, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_constants.h b/openfpga/src/fpga_verilog/verilog_top_testbench_constants.h new file mode 100644 index 000000000..31c251ee4 --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_constants.h @@ -0,0 +1,42 @@ +#ifndef VERILOG_TOP_TESTBENCH_CONSTANTS +#define VERILOG_TOP_TESTBENCH_CONSTANTS + +/* begin namespace openfpga */ +namespace openfpga { + +constexpr char* TOP_TESTBENCH_REFERENCE_INSTANCE_NAME = "REF_DUT"; +constexpr char* TOP_TESTBENCH_FPGA_INSTANCE_NAME = "FPGA_DUT"; +constexpr char* TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX = "_benchmark"; +constexpr char* TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX = "_fpga"; + +constexpr char* TOP_TESTBENCH_CHECKFLAG_PORT_POSTFIX = "_flag"; + +constexpr char* TOP_TESTBENCH_PROG_TASK_NAME = "prog_cycle_task"; + +constexpr char* TOP_TESTBENCH_SIM_START_PORT_NAME = "sim_start"; + +constexpr char* TOP_TESTBENCH_ERROR_COUNTER = "nb_error"; + +constexpr char* TOP_TB_RESET_PORT_NAME = "greset"; +constexpr char* TOP_TB_SET_PORT_NAME = "gset"; +constexpr char* TOP_TB_PROG_RESET_PORT_NAME = "prog_reset"; +constexpr char* TOP_TB_PROG_SET_PORT_NAME = "prog_set"; +constexpr char* TOP_TB_CONFIG_DONE_PORT_NAME = "config_done"; +constexpr char* TOP_TB_OP_CLOCK_PORT_NAME = "op_clock"; +constexpr char* TOP_TB_OP_CLOCK_PORT_PREFIX = "operating_clk_"; +constexpr char* TOP_TB_PROG_CLOCK_PORT_NAME = "prog_clock"; +constexpr char* TOP_TB_INOUT_REG_POSTFIX = "_reg"; +constexpr char* TOP_TB_CLOCK_REG_POSTFIX = "_reg"; +constexpr char* TOP_TB_BITSTREAM_LENGTH_VARIABLE = "BITSTREAM_LENGTH"; +constexpr char* TOP_TB_BITSTREAM_WIDTH_VARIABLE = "BITSTREAM_WIDTH"; +constexpr char* TOP_TB_BITSTREAM_MEM_REG_NAME = "bit_mem"; +constexpr char* TOP_TB_BITSTREAM_INDEX_REG_NAME = "bit_index"; +constexpr char* TOP_TB_BITSTREAM_ITERATOR_REG_NAME = "ibit"; +constexpr char* TOP_TB_BITSTREAM_SKIP_FLAG_REG_NAME = "skip_bits"; + +constexpr char* AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX = "_autocheck_top_tb"; + + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp new file mode 100644 index 000000000..d2a286984 --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -0,0 +1,175 @@ +/******************************************************************** + * This file includes functions that are used to create + * an auto-check top-level testbench for a FPGA fabric + *******************************************************************/ +#include +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_log.h" +#include "vtr_assert.h" +#include "vtr_time.h" + +/* Headers from openfpgautil library */ +#include "openfpga_port.h" +#include "openfpga_digest.h" + +#include "bitstream_manager_utils.h" + +#include "openfpga_reserved_words.h" +#include "openfpga_naming.h" +#include "simulation_utils.h" +#include "openfpga_atom_netlist_utils.h" + +#include "fast_configuration.h" +#include "fabric_bitstream_utils.h" +#include "fabric_global_port_info_utils.h" + +#include "verilog_constants.h" +#include "verilog_writer_utils.h" +#include "verilog_testbench_utils.h" +#include "verilog_top_testbench_memory_bank.h" + +#include "verilog_top_testbench_constants.h" + +/* begin namespace openfpga */ +namespace openfpga { + +void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp, + const std::string& bitstream_file, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricBitstream& fabric_bitstream) { + /* Validate the file stream */ + valid_file_stream(fp); + + /* Reorganize the fabric bitstream by the same address across regions */ + MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); + + /* For fast configuration, identify the final bitstream size to be used */ + size_t num_bits_to_skip = 0; + if (true == fast_configuration) { + num_bits_to_skip = fabric_bits_by_addr.size() - find_memory_bank_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); + } + VTR_ASSERT(num_bits_to_skip < fabric_bits_by_addr.size()); + + /* Feed address and data input pair one by one + * Note: the first cycle is reserved for programming reset + * We should give dummy values + */ + ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_BL_ADDRESS_PORT_NAME)); + BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); + std::vector initial_bl_addr_values(bl_addr_port.get_width(), 0); + + ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_WL_ADDRESS_PORT_NAME)); + BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); + std::vector initial_wl_addr_values(wl_addr_port.get_width(), 0); + + ModulePortId din_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_DATA_IN_PORT_NAME)); + BasicPort din_port = module_manager.module_port(top_module, din_port_id); + std::vector initial_din_values(din_port.get_width(), 0); + + /* Define a constant for the bitstream length */ + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), fabric_bits_by_addr.size() - num_bits_to_skip); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), bl_addr_port.get_width() + wl_addr_port.get_width() + din_port.get_width()); + + /* Declare local variables for bitstream loading in Verilog */ + print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + fp << "reg [0:`" << TOP_TB_BITSTREAM_WIDTH_VARIABLE << " - 1] "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; + fp << std::endl; + + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; + + print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + fp << "initial begin" << std::endl; + fp << "\t"; + fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << std::endl; + + print_verilog_comment(fp, "----- Bit-Line Address port default input -----"); + fp << "\t"; + fp << generate_verilog_port_constant_values(bl_addr_port, initial_bl_addr_values); + fp << ";"; + fp << std::endl; + + print_verilog_comment(fp, "----- Word-Line Address port default input -----"); + fp << "\t"; + fp << generate_verilog_port_constant_values(wl_addr_port, initial_wl_addr_values); + fp << ";"; + fp << std::endl; + + print_verilog_comment(fp, "----- Data-input port default input -----"); + fp << "\t"; + fp << generate_verilog_port_constant_values(din_port, initial_din_values); + fp << ";"; + fp << std::endl; + + fp << "\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " <= 0"; + fp << ";"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); + fp << "always"; + fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t"; + fp << "if ("; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " >= "; + fp << "`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE; + fp << ") begin"; + fp << std::endl; + + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); + fp << "\t\t"; + std::vector config_done_final_values(config_done_port.get_width(), 1); + fp << generate_verilog_port_constant_values(config_done_port, config_done_final_values, true); + fp << ";" << std::endl; + + fp << "\t"; + fp << "end else begin"; + fp << std::endl; + + fp << "\t\t"; + fp << "{"; + fp << generate_verilog_port(VERILOG_PORT_CONKT, bl_addr_port); + fp << ", "; + fp << generate_verilog_port(VERILOG_PORT_CONKT, wl_addr_port); + fp << ", "; + fp << generate_verilog_port(VERILOG_PORT_CONKT, din_port); + fp << "}"; + fp << " <= "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" << TOP_TB_BITSTREAM_INDEX_REG_NAME << "]"; + fp << ";" << std::endl; + + fp << "\t\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " <= "; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " + 1"; + fp << ";" << std::endl; + + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h new file mode 100644 index 000000000..e82a956e2 --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h @@ -0,0 +1,43 @@ +#ifndef VERILOG_TOP_TESTBENCH_MEMORY_BANK +#define VERILOG_TOP_TESTBENCH_MEMORY_BANK + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include +#include "module_manager.h" +#include "bitstream_manager.h" +#include "fabric_bitstream.h" +#include "circuit_library.h" +#include "config_protocol.h" +#include "vpr_context.h" +#include "pin_constraints.h" +#include "io_location_map.h" +#include "fabric_global_port_info.h" +#include "vpr_netlist_annotation.h" +#include "simulation_setting.h" +#include "verilog_testbench_options.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +/** + * @brief Print stimulus for a FPGA fabric with a memory bank configuration protocol + * where configuration bits are programming in serial (one by one) + */ +void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp, + const std::string& bitstream_file, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricBitstream& fabric_bitstream); + +} /* end namespace openfpga */ + +#endif From 6be3c64f1c8f51dadae9316272e2635ce184a86f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 9 Sep 2021 09:22:27 -0700 Subject: [PATCH 024/229] [Arch] Add an example architecture using the physical design friendly memory bank organization --- .../k4_N4_40nm_qlbank_openfpga.xml | 198 ++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_openfpga.xml diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_openfpga.xml new file mode 100644 index 000000000..ac5d59f75 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_openfpga.xml @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From b82cfdf555b5865dd659764d0d3fb15180016f73 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 9 Sep 2021 09:29:21 -0700 Subject: [PATCH 025/229] [Test] Add the QL memory bank test to regression test cases --- .../ql_memory_bank/config/task.conf | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank/config/task.conf new file mode 100644 index 000000000..b7c94008f --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank/config/task.conf @@ -0,0 +1,44 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +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/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +bench1_top = or2 +bench1_chan_width = 300 + +bench2_top = and2_latch +bench2_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 81a2ad58df18510e91a7873b1b435253d8d390d8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 9 Sep 2021 13:48:30 -0700 Subject: [PATCH 026/229] [Test] Deploy the ql memory bank test case to basic regression tests (run on CI) --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index 0a11ed4e0..5bef6a05f 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -53,6 +53,9 @@ run-task basic_tests/full_testbench/smart_fast_memory_bank --debug --show_thread run-task basic_tests/full_testbench/smart_fast_multi_region_memory_bank --debug --show_thread_logs run-task basic_tests/preconfig_testbench/memory_bank --debug --show_thread_logs +echo -e "Testing physical design friendly memory bank configuration protocol of a K4N4 FPGA"; +run-task basic_tests/full_testbench/ql_memory_bank --debug --show_thread_logs + echo -e "Testing testbenches without self checking features"; run-task basic_tests/full_testbench/full_testbench_without_self_checking --debug --show_thread_logs run-task basic_tests/preconfig_testbench/preconfigured_testbench_without_self_checking --debug --show_thread_logs From b787c4e100ba6650a5bd9f1c3cb50c9fcabdf6fc Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 9 Sep 2021 15:06:51 -0700 Subject: [PATCH 027/229] [Engine] Register QL memory bank as a legal protocol --- openfpga/src/base/openfpga_naming.cpp | 1 + openfpga/src/fabric/build_grid_modules.cpp | 2 +- openfpga/src/fabric/build_memory_modules.cpp | 1 + openfpga/src/fabric/build_top_module_memory.cpp | 4 +++- openfpga/src/fpga_bitstream/build_device_bitstream.cpp | 3 ++- openfpga/src/fpga_bitstream/fast_configuration.cpp | 1 + .../src/fpga_bitstream/write_text_fabric_bitstream.cpp | 1 + openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp | 1 + openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 3 +++ openfpga/src/fpga_verilog/verilog_writer_utils.cpp | 3 +++ openfpga/src/utils/circuit_library_utils.cpp | 3 +++ openfpga/src/utils/memory_utils.cpp | 7 +++++++ openfpga/src/utils/module_manager_utils.cpp | 3 +++ openfpga/src/utils/mux_utils.cpp | 5 ++++- 14 files changed, 34 insertions(+), 4 deletions(-) diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index 71d9dff58..c898066b3 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -703,6 +703,7 @@ std::string generate_sram_port_name(const e_config_protocol_type& sram_orgz_type } break; case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: /* Two types of ports are available: * (1) Bit Lines (BLs) of a SRAM cell, enabled by port type of BL diff --git a/openfpga/src/fabric/build_grid_modules.cpp b/openfpga/src/fabric/build_grid_modules.cpp index f1a56c4f1..53ebc9292 100644 --- a/openfpga/src/fabric/build_grid_modules.cpp +++ b/openfpga/src/fabric/build_grid_modules.cpp @@ -279,7 +279,7 @@ void build_primitive_block_module(ModuleManager& module_manager, size_t num_shared_config_bits = find_circuit_num_shared_config_bits(circuit_lib, primitive_model, sram_orgz_type); if (0 < num_shared_config_bits) { /* Check: this SRAM organization type must be memory-bank ! */ - VTR_ASSERT( CONFIG_MEM_MEMORY_BANK == sram_orgz_type ); + VTR_ASSERT( CONFIG_MEM_MEMORY_BANK == sram_orgz_type || CONFIG_MEM_QL_MEMORY_BANK == sram_orgz_type ); /* Generate a list of ports */ add_reserved_sram_ports_to_module_manager(module_manager, primitive_module, num_shared_config_bits); diff --git a/openfpga/src/fabric/build_memory_modules.cpp b/openfpga/src/fabric/build_memory_modules.cpp index 970ef8a95..8a354da75 100644 --- a/openfpga/src/fabric/build_memory_modules.cpp +++ b/openfpga/src/fabric/build_memory_modules.cpp @@ -786,6 +786,7 @@ void build_memory_module(ModuleManager& module_manager, const size_t& num_mems) { switch (sram_orgz_type) { case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: build_memory_flatten_module(module_manager, circuit_lib, module_name, sram_model, num_mems); diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 297a5abf4..582d84b0c 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -265,7 +265,8 @@ void build_top_module_configurable_regions(ModuleManager& module_manager, /* Exclude decoders from the list */ size_t num_configurable_children = module_manager.configurable_children(top_module).size(); - if (CONFIG_MEM_MEMORY_BANK == config_protocol.type()) { + if (CONFIG_MEM_MEMORY_BANK == config_protocol.type() + || CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) { num_configurable_children -= 2; } else if (CONFIG_MEM_FRAME_BASED == config_protocol.type()) { num_configurable_children -= 1; @@ -752,6 +753,7 @@ size_t generate_top_module_sram_port_size(const ConfigProtocol& config_protocol, case CONFIG_MEM_STANDALONE: break; case CONFIG_MEM_SCAN_CHAIN: + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: case CONFIG_MEM_FRAME_BASED: /* CCFF head/tail, data input could be multi-bit ports */ diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index e90d73321..0af563914 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -96,7 +96,8 @@ size_t rec_estimate_device_bitstream_num_bits(const ModuleManager& module_manage /* Memory configuration protocol will have 2 decoders * at the top-level */ - if (CONFIG_MEM_MEMORY_BANK == config_protocol_type) { + if (CONFIG_MEM_MEMORY_BANK == config_protocol_type + || CONFIG_MEM_QL_MEMORY_BANK == config_protocol_type) { VTR_ASSERT(2 <= curr_region_num_config_child); curr_region_num_config_child -= 2; } diff --git a/openfpga/src/fpga_bitstream/fast_configuration.cpp b/openfpga/src/fpga_bitstream/fast_configuration.cpp index 5b3ec0301..112fac5c3 100644 --- a/openfpga/src/fpga_bitstream/fast_configuration.cpp +++ b/openfpga/src/fpga_bitstream/fast_configuration.cpp @@ -87,6 +87,7 @@ bool find_bit_value_to_skip_for_fast_configuration(const e_config_protocol_type& } break; } + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: case CONFIG_MEM_FRAME_BASED: { /* Count how many logic '1' and logic '0' bits we can skip */ diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 5338d7b09..8b2daaf87 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -306,6 +306,7 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage bitstream_manager, fabric_bitstream); break; + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: status = write_memory_bank_fabric_bitstream_to_text_file(fp, apply_fast_configuration, diff --git a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp index adc12ce73..8ea50e015 100644 --- a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp @@ -103,6 +103,7 @@ int write_fabric_config_bit_to_xml_file(std::fstream& fp, case CONFIG_MEM_STANDALONE: case CONFIG_MEM_SCAN_CHAIN: break; + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: { /* Bit line address */ write_tab_to_file(fp, xml_hierarchy_depth + 1); diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 4751823a3..289e4d667 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -217,6 +217,7 @@ void print_verilog_top_testbench_config_protocol_port(std::fstream& fp, case CONFIG_MEM_SCAN_CHAIN: print_verilog_top_testbench_config_chain_port(fp, module_manager, top_module); break; + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: print_verilog_top_testbench_memory_bank_port(fp, module_manager, top_module); break; @@ -835,6 +836,7 @@ size_t calculate_num_config_clock_cycles(const e_config_protocol_type& sram_orgz 100. * ((float)num_config_clock_cycles / (float)(1 + regional_bitstream_max_size) - 1.)); } break; + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: { /* For fast configuration, we will skip all the zero data points */ num_config_clock_cycles = 1 + build_memory_bank_fabric_bitstream_by_address(fabric_bitstream).size(); @@ -1093,6 +1095,7 @@ void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& f break; case CONFIG_MEM_SCAN_CHAIN: break; + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: case CONFIG_MEM_FRAME_BASED: { ModulePortId en_port_id = module_manager.find_module_port(top_module, diff --git a/openfpga/src/fpga_verilog/verilog_writer_utils.cpp b/openfpga/src/fpga_verilog/verilog_writer_utils.cpp index 9a55968b0..7d5c3dd77 100644 --- a/openfpga/src/fpga_verilog/verilog_writer_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_writer_utils.cpp @@ -1010,6 +1010,7 @@ void print_verilog_local_sram_wires(std::fstream& fp, print_verilog_wire_connection(fp, ccff_tail_local_port, ccff_tail_port, false); break; } + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: { /* Generate the name of local wire for the SRAM output and inverted output */ std::vector sram_ports; @@ -1100,6 +1101,7 @@ void print_verilog_local_config_bus(std::fstream& fp, */ break; case CONFIG_MEM_SCAN_CHAIN: + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: { /* Two configuration buses should be outputted * One for the regular SRAM ports of a routing multiplexer @@ -1173,6 +1175,7 @@ void print_verilog_rram_mux_config_bus(std::fstream& fp, */ break; } + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: { /* This is currently most used in ReRAM FPGAs */ /* Print configuration bus to group reserved BL/WLs */ diff --git a/openfpga/src/utils/circuit_library_utils.cpp b/openfpga/src/utils/circuit_library_utils.cpp index 197c873bd..fabdc05da 100644 --- a/openfpga/src/utils/circuit_library_utils.cpp +++ b/openfpga/src/utils/circuit_library_utils.cpp @@ -94,6 +94,7 @@ size_t find_rram_circuit_num_shared_config_bits(const CircuitLibrary& circuit_li case CONFIG_MEM_STANDALONE: case CONFIG_MEM_SCAN_CHAIN: break; + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: { /* Find BL/WL ports */ std::vector blb_ports = circuit_lib.model_ports_by_type(rram_model, CIRCUIT_MODEL_PORT_BLB); @@ -175,6 +176,7 @@ size_t find_circuit_num_config_bits(const e_config_protocol_type& config_protoco switch (config_protocol_type) { case CONFIG_MEM_STANDALONE: case CONFIG_MEM_SCAN_CHAIN: + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: { break; } @@ -293,6 +295,7 @@ bool check_configurable_memory_circuit_model(const e_config_protocol_type& confi break; case CONFIG_MEM_STANDALONE: case CONFIG_MEM_MEMORY_BANK: + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_FRAME_BASED: num_err = check_sram_circuit_model_ports(circuit_lib, config_mem_circuit_model, diff --git a/openfpga/src/utils/memory_utils.cpp b/openfpga/src/utils/memory_utils.cpp index bb7cefee7..b02fe1e88 100644 --- a/openfpga/src/utils/memory_utils.cpp +++ b/openfpga/src/utils/memory_utils.cpp @@ -74,6 +74,7 @@ std::map generate_cmos_mem_module_port2port_map(const Ba port2port_name_map[generate_configurable_memory_inverted_data_out_name()] = mem_output_bus_ports[1]; break; } + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: /* TODO: */ break; @@ -131,6 +132,7 @@ std::map generate_rram_mem_module_port2port_map(const Ba port2port_name_map[generate_configurable_memory_inverted_data_out_name()] = mem_output_bus_ports[1]; break; } + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: /* TODO: link BL/WL/Reserved Ports to the inputs of a memory module */ break; @@ -189,6 +191,7 @@ void update_cmos_mem_module_config_bus(const e_config_protocol_type& sram_orgz_t */ VTR_ASSERT(true == config_bus.rotate(1)); break; + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: /* In this case, a memory module has a number of BL/WL and BLB/WLB (possibly). * LSB and MSB of configuration bus will be shifted by the number of BL/WL/BLB/WLB. @@ -219,6 +222,7 @@ void update_rram_mem_module_config_bus(const e_config_protocol_type& sram_orgz_t */ VTR_ASSERT(true == config_bus.rotate(1)); break; + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: /* In this case, a memory module contains unique BL/WL or BLB/WLB, * which are not shared with other modules @@ -275,6 +279,7 @@ bool check_mem_config_bus(const e_config_protocol_type& sram_orgz_type, */ return (local_expected_msb == config_bus.get_msb()); break; + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: /* TODO: comment on why */ @@ -319,6 +324,7 @@ std::vector generate_sram_port_names(const CircuitLibrary& circuit_ model_port_types.push_back(CIRCUIT_MODEL_PORT_OUTPUT); break; case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: { std::vector ports_to_search; ports_to_search.push_back(CIRCUIT_MODEL_PORT_BL); @@ -373,6 +379,7 @@ size_t generate_sram_port_size(const e_config_protocol_type sram_orgz_type, /* CCFF head/tail are single-bit ports */ sram_port_size = 1; break; + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: break; case CONFIG_MEM_FRAME_BASED: diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 4a719b9a1..13cc579fa 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -313,6 +313,7 @@ void add_sram_ports_to_module_manager(ModuleManager& module_manager, /* Add ports to the module manager */ switch (sram_orgz_type) { case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: { for (const std::string& sram_port_name : sram_port_names) { /* Add generated ports to the ModuleManager */ @@ -1288,6 +1289,7 @@ void add_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, break; } case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); @@ -1742,6 +1744,7 @@ size_t find_module_num_config_bits_from_child_modules(ModuleManager& module_mana switch (sram_orgz_type) { case CONFIG_MEM_STANDALONE: case CONFIG_MEM_SCAN_CHAIN: + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: { /* For scan-chain, standalone and memory bank configuration protocol * The number of configuration bits is the sum of configuration bits diff --git a/openfpga/src/utils/mux_utils.cpp b/openfpga/src/utils/mux_utils.cpp index 15c7a97d7..e4b679df6 100644 --- a/openfpga/src/utils/mux_utils.cpp +++ b/openfpga/src/utils/mux_utils.cpp @@ -257,6 +257,7 @@ size_t find_cmos_mux_num_config_bits(const CircuitLibrary& circuit_lib, size_t num_config_bits = 0; switch (sram_orgz_type) { + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: case CONFIG_MEM_SCAN_CHAIN: case CONFIG_MEM_STANDALONE: @@ -298,6 +299,7 @@ size_t find_rram_mux_num_config_bits(const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type) { size_t num_config_bits = 0; switch (sram_orgz_type) { + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: /* In memory bank, by intensively share the Bit/Word Lines, * we only need 1 additional BL and WL for each MUX level. @@ -365,6 +367,7 @@ size_t find_cmos_mux_num_shared_config_bits(const e_config_protocol_type& sram_o size_t num_shared_config_bits = 0; switch (sram_orgz_type) { + case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK: case CONFIG_MEM_SCAN_CHAIN: case CONFIG_MEM_STANDALONE: @@ -388,7 +391,7 @@ size_t find_rram_mux_num_shared_config_bits(const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type) { size_t num_shared_config_bits = 0; switch (sram_orgz_type) { - case CONFIG_MEM_MEMORY_BANK: { + case CONFIG_MEM_QL_MEMORY_BANK: { /* In memory bank, the number of shared configuration bits is * the sum of largest branch size at each level */ From 35c7b0988879c6fce463158ab7883e82f9fe04e9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 9 Sep 2021 15:23:29 -0700 Subject: [PATCH 028/229] [Engine] Bug fix for mistakes in calculating number of BLs/WLs for QL memory bank --- openfpga/src/fabric/build_top_module_memory.cpp | 16 ++++++++-------- .../src/fabric/build_top_module_memory_bank.cpp | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 582d84b0c..243df74a9 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -693,12 +693,12 @@ TopModuleNumConfigBits find_top_module_regional_num_config_bit(const ModuleManag vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; num_bls[coord.x()] = std::max(num_bls[coord.x()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type))); num_wls[coord.y()] = std::max(num_wls[coord.y()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type))); - for (const auto& kv : num_bls) { - num_config_bits[config_region].first += kv.first; - } - for (const auto& kv : num_wls) { - num_config_bits[config_region].second += kv.second; - } + } + for (const auto& kv : num_bls) { + num_config_bits[config_region].first += kv.second; + } + for (const auto& kv : num_wls) { + num_config_bits[config_region].second += kv.second; } } break; @@ -853,7 +853,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, /* BL address size is the largest among all the regions */ size_t bl_addr_size = 0; for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - bl_addr_size = std::max(bl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].first)); + bl_addr_size = std::max(bl_addr_size, find_mux_local_decoder_addr_size(num_config_bits[config_region].first)); } BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), bl_addr_size); module_manager.add_port(module_id, bl_addr_port, ModuleManager::MODULE_INPUT_PORT); @@ -861,7 +861,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, /* WL address size is the largest among all the regions */ size_t wl_addr_size = 0; for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - wl_addr_size = std::max(wl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region].second)); + wl_addr_size = std::max(wl_addr_size, find_mux_local_decoder_addr_size(num_config_bits[config_region].second)); } BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 2df41c5e2..626f46f95 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -151,12 +151,12 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma /* Each memory bank has a unified number of BL/WLs */ size_t num_bls = 0; for (const auto& curr_config_bits : num_config_bits) { - num_bls = std::max(num_bls, find_memory_decoder_data_size(curr_config_bits.first)); + num_bls = std::max(num_bls, curr_config_bits.first); } size_t num_wls = 0; for (const auto& curr_config_bits : num_config_bits) { - num_wls = std::max(num_wls, find_memory_decoder_data_size(curr_config_bits.second)); + num_wls = std::max(num_wls, curr_config_bits.second); } /* Create separated memory bank circuitry, i.e., BL/WL decoders for each region */ From ba1e277dc9e940ef31bd71f3473c1bae80e66fbc Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 10 Sep 2021 15:05:46 -0700 Subject: [PATCH 029/229] [Engine] Fix a few bugs in the BL/WL arrangement and now bitstream generator is working fine --- .../src/fabric/build_top_module_memory.cpp | 9 ++++++-- .../fabric/build_top_module_memory_bank.cpp | 19 +++++++---------- .../build_fabric_bitstream_memory_bank.cpp | 21 +++++++------------ openfpga/src/utils/decoder_library_utils.cpp | 18 ++++++++++++++++ openfpga/src/utils/decoder_library_utils.h | 2 ++ openfpga/src/utils/memory_bank_utils.cpp | 2 +- 6 files changed, 42 insertions(+), 29 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 243df74a9..9c4ca73f3 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -75,7 +75,12 @@ void organize_top_module_tile_cb_modules(ModuleManager& module_manager, if (0 < find_module_num_config_bits(module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type)) { - vtr::Point config_coord(rr_gsb.get_cb_x(cb_type) * 2, rr_gsb.get_cb_y(cb_type) * 2); + /* CBX coordinate conversion calculation: (1,0) -> (2,1) */ + vtr::Point config_coord(rr_gsb.get_cb_x(cb_type) * 2, rr_gsb.get_cb_y(cb_type) * 2 + 1); + if (cb_type == CHANY) { + /* CBY has a different coordinate conversion calculation: (0,1) -> (1,2) */ + config_coord.set(rr_gsb.get_cb_x(cb_type) * 2 + 1, rr_gsb.get_cb_y(cb_type) * 2); + } /* Note that use the original CB coodinate for instance id searching ! */ module_manager.add_configurable_child(top_module, cb_module, cb_instance_ids[rr_gsb.get_cb_x(cb_type)][rr_gsb.get_cb_y(cb_type)], config_coord); } @@ -692,7 +697,7 @@ TopModuleNumConfigBits find_top_module_regional_num_config_bit(const ModuleManag ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; num_bls[coord.x()] = std::max(num_bls[coord.x()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type))); - num_wls[coord.y()] = std::max(num_wls[coord.y()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type))); + num_wls[coord.y()] = std::max(num_wls[coord.y()], find_memory_wl_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type))); } for (const auto& kv : num_bls) { num_config_bits[config_region].first += kv.second; diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 626f46f95..f1c8b949b 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -323,7 +323,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - int child_num_unique_blwls = find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK)); + int child_num_unique_blwls = num_bls_per_tile.at(coord.x()); size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; @@ -334,12 +334,11 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma size_t cur_bl_index = 0; for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { + size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index % child_num_unique_blwls; /* Find the BL decoder data index: * It should be the starting index plus an offset which is the residual when divided by the number of BLs in this tile */ - size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + std::floor(cur_bl_index / child_num_unique_blwls); - if (!(bl_pin_id < bl_decoder_dout_port_info.pins().size())) - VTR_ASSERT(bl_pin_id < bl_decoder_dout_port_info.pins().size()); + VTR_ASSERT(bl_pin_id < bl_decoder_dout_port_info.pins().size()); /* Create net */ ModuleNetId net = create_module_source_pin_net(module_manager, top_module, @@ -352,7 +351,6 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma module_manager.add_module_net_sink(top_module, net, child_module, child_instance, child_bl_port, sink_bl_pin); - /* Increment the BL index */ cur_bl_index++; } } @@ -366,7 +364,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - int child_num_unique_blwls = find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK)); + int child_num_unique_blwls = num_bls_per_tile.at(coord.x()); size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; @@ -377,10 +375,8 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma size_t cur_wl_index = 0; for (const size_t& sink_wl_pin : child_wl_port_info.pins()) { - /* Find the WL decoder data index: - * It should be the starting index plus an offset which is the residual when divided by the number of WLs in this tile - */ - size_t wl_pin_id = wl_start_index_per_tile[coord.x()] + cur_wl_index % child_num_unique_blwls; + size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + std::floor(cur_wl_index / child_num_unique_blwls); + VTR_ASSERT(wl_pin_id < wl_decoder_dout_port_info.pins().size()); /* Create net */ ModuleNetId net = create_module_source_pin_net(module_manager, top_module, @@ -392,8 +388,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma /* Add net sink */ module_manager.add_module_net_sink(top_module, net, child_module, child_instance, child_wl_port, sink_wl_pin); - - /* Increment the WL index */ + cur_wl_index++; } } diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index 5399832b2..82d9a7f0d 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -54,7 +54,7 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B const std::map& num_wls_per_tile, const std::map& wl_start_index_per_tile, vtr::Point& tile_coord, - size_t& cur_mem_index, + std::map, size_t>& cur_mem_index, FabricBitstream& fabric_bitstream, const FabricBitRegionId& fabric_bitstream_region) { @@ -83,9 +83,7 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B ModuleId child_module = configurable_children[child_id]; size_t child_instance = module_manager.region_configurable_child_instances(parent_module, config_region)[child_id]; - if (parent_module == top_module) { - tile_coord = module_manager.region_configurable_child_coordinates(parent_module, config_region)[child_id]; - } + tile_coord = module_manager.region_configurable_child_coordinates(parent_module, config_region)[child_id]; /* Get the instance name and ensure it is not empty */ std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); @@ -95,11 +93,6 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B /* We must have one valid block id! */ VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); - /* Reset the memory index for each children under the top-level module */ - if (parent_module == top_module) { - cur_mem_index = 0; - } - /* Go recursively */ rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, child_block, module_manager, top_module, child_module, @@ -168,11 +161,11 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B FabricBitId fabric_bit = fabric_bitstream.add_bit(config_bit); /* Find BL address */ - size_t cur_bl_index = bl_start_index_per_tile.at(tile_coord.x()) + std::floor(cur_mem_index / num_bls_per_tile.at(tile_coord.x())); + size_t cur_bl_index = bl_start_index_per_tile.at(tile_coord.x()) + cur_mem_index[tile_coord] % num_bls_per_tile.at(tile_coord.x()); std::vector bl_addr_bits_vec = itobin_charvec(cur_bl_index, bl_addr_size); /* Find WL address */ - size_t cur_wl_index = wl_start_index_per_tile.at(tile_coord.y()) + cur_mem_index % num_wls_per_tile.at(tile_coord.y()); + size_t cur_wl_index = wl_start_index_per_tile.at(tile_coord.y()) + std::floor(cur_mem_index[tile_coord] / num_bls_per_tile.at(tile_coord.x())); std::vector wl_addr_bits_vec = itobin_charvec(cur_wl_index, wl_addr_size); /* Set BL address */ @@ -188,7 +181,7 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B fabric_bitstream.add_bit_to_region(fabric_bitstream_region, fabric_bit); /* Increase the memory index */ - cur_mem_index++; + cur_mem_index[tile_coord]++; } } @@ -223,8 +216,6 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol /* Build bitstreams by region */ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - size_t cur_mem_index = 0; - /* Find port information for local BL and WL decoder in this region */ std::vector configurable_children = module_manager.region_configurable_children(top_module, config_region); VTR_ASSERT(2 <= configurable_children.size()); @@ -258,6 +249,8 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); vtr::Point temp_coord; + std::map, size_t> cur_mem_index; + rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, top_block, module_manager, top_module, top_module, config_region, diff --git a/openfpga/src/utils/decoder_library_utils.cpp b/openfpga/src/utils/decoder_library_utils.cpp index f4db14ba7..1b86463be 100644 --- a/openfpga/src/utils/decoder_library_utils.cpp +++ b/openfpga/src/utils/decoder_library_utils.cpp @@ -86,6 +86,24 @@ size_t find_memory_decoder_data_size(const size_t& num_mems) { return (size_t)std::ceil(std::sqrt((float)num_mems)); } +/*************************************************************************************** + * Find the size of WL data lines for a memory decoder to access a memory array + * This function is applicable to a memory bank organization where BL data lines + * is the dominant factor. It means that the BL data lines is strictly an integeter close + * to the square root of the number of memory cells. + * For example, 203 memory cells leads to 15 BLs to control + * The WL data lines may not be exactly the same as the number of BLs. + * Considering the example of 203 memory cells again, when 15 BLs are used, we just need + * 203 / 15 = 13.5555 -> 14 WLs + ***************************************************************************************/ +size_t find_memory_wl_decoder_data_size(const size_t& num_mems) { + /* Handle exception: zero memory should have zero WLs */ + if (0 == num_mems) { + return 0; + } + return std::ceil(num_mems / (size_t)std::ceil(std::sqrt((float)num_mems))); +} + /*************************************************************************************** * Try to find if the decoder already exists in the library, * If there is no such decoder, add it to the library diff --git a/openfpga/src/utils/decoder_library_utils.h b/openfpga/src/utils/decoder_library_utils.h index aa25d0df2..33f91cb18 100644 --- a/openfpga/src/utils/decoder_library_utils.h +++ b/openfpga/src/utils/decoder_library_utils.h @@ -17,6 +17,8 @@ size_t find_memory_decoder_addr_size(const size_t& num_mems); size_t find_memory_decoder_data_size(const size_t& num_mems); +size_t find_memory_wl_decoder_data_size(const size_t& num_mems); + DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib, const size_t data_size); diff --git a/openfpga/src/utils/memory_bank_utils.cpp b/openfpga/src/utils/memory_bank_utils.cpp index d43909e4d..12a97c23f 100644 --- a/openfpga/src/utils/memory_bank_utils.cpp +++ b/openfpga/src/utils/memory_bank_utils.cpp @@ -82,7 +82,7 @@ std::map compute_memory_bank_regional_wordline_numbers_per_tile(con for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - num_wls_per_tile[coord.y()] = std::max(num_wls_per_tile[coord.y()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK))); + num_wls_per_tile[coord.y()] = std::max(num_wls_per_tile[coord.y()], find_memory_wl_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK))); } return num_wls_per_tile; From 73d21c973062d5e50749b4326028d0871d8d6c72 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 10 Sep 2021 15:30:37 -0700 Subject: [PATCH 030/229] [Doc] Update doc about how to use the QuickLogic memory bank --- .../manual/arch_lang/config_protocol.rst | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/source/manual/arch_lang/config_protocol.rst b/docs/source/manual/arch_lang/config_protocol.rst index 1fb03f9f3..087914c80 100644 --- a/docs/source/manual/arch_lang/config_protocol.rst +++ b/docs/source/manual/arch_lang/config_protocol.rst @@ -16,7 +16,7 @@ Template -.. option:: type="scan_chain|memory_bank|standalone" +.. option:: type="scan_chain|memory_bank|standalone|frame_based|ql_memory_bank" Specify the type of configuration circuits. @@ -24,6 +24,7 @@ Template - ``scan_chain``: configurable memories are connected in a chain. Bitstream is loaded serially to program a FPGA - ``frame_based``: configurable memories are organized by frames. Each module of a FPGA fabric, e.g., Configurable Logic Block (CLB), Switch Block (SB) and Connection Block (CB), is considered as a frame of configurable memories. Inside each frame, all the memory banks are accessed through an address decoder. Users can write each memory cell with a specific address. Note that the frame-based memory organization is applid hierarchically. Each frame may consists of a number of sub frames, each of which follows the similar organization. - ``memory_bank``: configurable memories are organized in an array, where each element can be accessed by an unique address to the BL/WL decoders + - ``ql_memory_bank``: configurable memories are organized in an array, where each element can be accessed by an unique address to the BL/WL decoders. This is a physical design friendly memory bank organization, where BL/WLs are efficiently shared by programmable blocks per column and row - ``standalone``: configurable memories are directly accessed through ports of FPGA fabrics. In other words, there are no protocol to control the memories. This allows full customization on the configuration protocol for hardware engineers. .. note:: Avoid to use ``standalone`` when designing an FPGA chip. It will causes a huge number of I/Os required, far beyond any package size. It is well applicable to eFPGAs, where designers do need customized protocols between FPGA and processors. @@ -147,6 +148,26 @@ Users can customized the number of memory banks to be used across the fabrics. B .. warning:: Please do NOT add inverted Bit-Line and Word-Line inputs. It is not supported yet! + +QuickLogic Memory bank Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The following XML code describes a physical design friendly memory-bank circuitry to configure the core logic of FPGA, as illustrated in :numref:`fig_memory_bank`. +It will use the circuit model defined in :numref:`fig_sram_blwl`. + +.. code-block:: xml + + + + + +.. note:: Memory-bank decoders does require a memory cell to have + + - two outputs (one regular and another inverted) + - a Bit-Line input to load the data + - a Word-Line input to enable data write + +.. warning:: Please do NOT add inverted Bit-Line and Word-Line inputs. It is not supported yet! + Standalone SRAM Example ~~~~~~~~~~~~~~~~~~~~~~~ In the standalone configuration protocol, every memory cell of the core logic of a FPGA fabric can be directly accessed at the top-level module, as illustrated in :numref:`fig_vanilla_config_protocol`. From 4af6413c97610f8b631a47ffa3433fe3e1dce195 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 10 Sep 2021 17:03:44 -0700 Subject: [PATCH 031/229] [Engine] Fixed a critical bug on WL arrangement; Previously we always consider squart of a local tile. Now we apply global optimization where the number of WLs are determined by the max. number of BLs per column --- .../src/fabric/build_top_module_memory.cpp | 20 +++++++++---------- .../fabric/build_top_module_memory_bank.cpp | 3 ++- .../build_fabric_bitstream_memory_bank.cpp | 3 ++- openfpga/src/utils/decoder_library_utils.cpp | 8 ++++---- openfpga/src/utils/decoder_library_utils.h | 2 +- openfpga/src/utils/memory_bank_utils.cpp | 5 +++-- openfpga/src/utils/memory_bank_utils.h | 11 ++++++++-- 7 files changed, 31 insertions(+), 21 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 9c4ca73f3..3021b2563 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -20,6 +20,7 @@ #include "openfpga_naming.h" #include "memory_utils.h" +#include "memory_bank_utils.h" #include "decoder_library_utils.h" #include "module_manager_utils.h" #include "build_decoder_modules.h" @@ -691,18 +692,17 @@ TopModuleNumConfigBits find_top_module_regional_num_config_bit(const ModuleManag * - each column has independent BLs */ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - std::map num_bls; - std::map num_wls; - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - num_bls[coord.x()] = std::max(num_bls[coord.x()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type))); - num_wls[coord.y()] = std::max(num_wls[coord.y()], find_memory_wl_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type))); - } - for (const auto& kv : num_bls) { + std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, + config_region, + circuit_lib, sram_model); + std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, + config_region, + circuit_lib, sram_model, + num_bls_per_tile); + for (const auto& kv : num_bls_per_tile) { num_config_bits[config_region].first += kv.second; } - for (const auto& kv : num_wls) { + for (const auto& kv : num_wls_per_tile) { num_config_bits[config_region].second += kv.second; } } diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index f1c8b949b..72c54258f 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -290,7 +290,8 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma circuit_lib, sram_model); std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, config_region, - circuit_lib, sram_model); + circuit_lib, sram_model, + num_bls_per_tile); std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index 82d9a7f0d..f95cc076a 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -243,7 +243,8 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol circuit_lib, config_protocol.memory_model()); std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, config_region, - circuit_lib, config_protocol.memory_model()); + circuit_lib, config_protocol.memory_model(), + num_bls_per_tile); std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); diff --git a/openfpga/src/utils/decoder_library_utils.cpp b/openfpga/src/utils/decoder_library_utils.cpp index 1b86463be..502620661 100644 --- a/openfpga/src/utils/decoder_library_utils.cpp +++ b/openfpga/src/utils/decoder_library_utils.cpp @@ -96,12 +96,12 @@ size_t find_memory_decoder_data_size(const size_t& num_mems) { * Considering the example of 203 memory cells again, when 15 BLs are used, we just need * 203 / 15 = 13.5555 -> 14 WLs ***************************************************************************************/ -size_t find_memory_wl_decoder_data_size(const size_t& num_mems) { - /* Handle exception: zero memory should have zero WLs */ - if (0 == num_mems) { +size_t find_memory_wl_decoder_data_size(const size_t& num_mems, const size_t& num_bls) { + /* Handle exception: zero BLs should have zero WLs */ + if (0 == num_bls) { return 0; } - return std::ceil(num_mems / (size_t)std::ceil(std::sqrt((float)num_mems))); + return std::ceil((float)num_mems / (float)num_bls); } /*************************************************************************************** diff --git a/openfpga/src/utils/decoder_library_utils.h b/openfpga/src/utils/decoder_library_utils.h index 33f91cb18..34b8662ef 100644 --- a/openfpga/src/utils/decoder_library_utils.h +++ b/openfpga/src/utils/decoder_library_utils.h @@ -17,7 +17,7 @@ size_t find_memory_decoder_addr_size(const size_t& num_mems); size_t find_memory_decoder_data_size(const size_t& num_mems); -size_t find_memory_wl_decoder_data_size(const size_t& num_mems); +size_t find_memory_wl_decoder_data_size(const size_t& num_mems, const size_t& num_bls); DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib, const size_t data_size); diff --git a/openfpga/src/utils/memory_bank_utils.cpp b/openfpga/src/utils/memory_bank_utils.cpp index 12a97c23f..5afd7e0e4 100644 --- a/openfpga/src/utils/memory_bank_utils.cpp +++ b/openfpga/src/utils/memory_bank_utils.cpp @@ -76,13 +76,14 @@ std::map compute_memory_bank_regional_wordline_numbers_per_tile(con const ModuleId& top_module, const ConfigRegionId& config_region, const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model) { + const CircuitModelId& sram_model, + const std::map& num_bls_per_tile) { std::map num_wls_per_tile; for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - num_wls_per_tile[coord.y()] = std::max(num_wls_per_tile[coord.y()], find_memory_wl_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK))); + num_wls_per_tile[coord.y()] = std::max(num_wls_per_tile[coord.y()], find_memory_wl_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK), num_bls_per_tile.at(coord.x()))); } return num_wls_per_tile; diff --git a/openfpga/src/utils/memory_bank_utils.h b/openfpga/src/utils/memory_bank_utils.h index fd08c5e3d..8347e558f 100644 --- a/openfpga/src/utils/memory_bank_utils.h +++ b/openfpga/src/utils/memory_bank_utils.h @@ -53,14 +53,21 @@ std::map compute_memory_bank_regional_bitline_numbers_per_tile(cons /** * @brief Precompute the number of word lines required by each tile under a specific configuration region * @note - * Not every index in the range computed by the compute_memory_bank_regional_configurable_child_x_range() function has a postive number of word lines + * Not every index in the range computed by the compute_memory_bank_regional_configurable_child_y_range() function has a postive number of word lines * If an empty entry is found (e.g., std::map::find(y) is empty), it means there are not word lines required in that tile + * @note + * This function requires an input argument which describes number of bitlines per tile. Base on the information, the number of word lines are inferred + * by total number of memores / number of bit lines at a given tile location + * This strategy is chosen because in each column, the number of bit lines are bounded by the tile which consumes most configuation bits. It may reduces + * the use of word lines. For example, a tile[0][0] has only 8 bits, from which we may infer 3 BLs and 3 WLs. However, when tile[0][1] contains 100 bits, + * which will force the number of BLs to be 10. In such case, tile[0][0] only requires 1 WL */ std::map compute_memory_bank_regional_wordline_numbers_per_tile(const ModuleManager& module_manager, const ModuleId& top_module, const ConfigRegionId& config_region, const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model); + const CircuitModelId& sram_model, + const std::map& num_bls_per_tile); /** * @brief Precompute the BLs and WLs distribution across the FPGA fabric From 26b1e48723681f86b39ae21af60d0adb505c8d01 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 15 Sep 2021 11:27:55 -0700 Subject: [PATCH 032/229] [Engine] Merge BL/WLs in the Grid/CB/SB modules --- openfpga/src/fabric/build_grid_modules.cpp | 6 +- openfpga/src/fabric/build_routing_modules.cpp | 16 +- .../src/fabric/build_top_module_memory.cpp | 3 +- .../fabric/build_top_module_memory_bank.cpp | 9 +- .../build_fabric_bitstream_memory_bank.cpp | 3 +- openfpga/src/utils/memory_bank_utils.cpp | 39 +- openfpga/src/utils/memory_bank_utils.h | 3 +- openfpga/src/utils/memory_utils.cpp | 36 ++ openfpga/src/utils/memory_utils.h | 3 + openfpga/src/utils/module_manager_utils.cpp | 340 +++++++++++++++++- openfpga/src/utils/module_manager_utils.h | 23 ++ 11 files changed, 452 insertions(+), 29 deletions(-) diff --git a/openfpga/src/fabric/build_grid_modules.cpp b/openfpga/src/fabric/build_grid_modules.cpp index 53ebc9292..d6c1a9166 100644 --- a/openfpga/src/fabric/build_grid_modules.cpp +++ b/openfpga/src/fabric/build_grid_modules.cpp @@ -1114,15 +1114,15 @@ void build_physical_tile_module(ModuleManager& module_manager, */ size_t module_num_config_bits = find_module_num_config_bits_from_child_modules(module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type); if (0 < module_num_config_bits) { - add_sram_ports_to_module_manager(module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type, module_num_config_bits); + add_pb_sram_ports_to_module_manager(module_manager, grid_module, circuit_lib, sram_model, sram_orgz_type, module_num_config_bits); } /* Add module nets to connect memory cells inside * This is a one-shot addition that covers all the memory modules in this pb module! */ if (0 < module_manager.configurable_children(grid_module).size()) { - add_module_nets_memory_config_bus(module_manager, decoder_lib, grid_module, - sram_orgz_type, circuit_lib.design_tech_type(sram_model)); + add_pb_module_nets_memory_config_bus(module_manager, decoder_lib, grid_module, + sram_orgz_type, circuit_lib.design_tech_type(sram_model)); } VTR_LOGV(verbose, "Done\n"); diff --git a/openfpga/src/fabric/build_routing_modules.cpp b/openfpga/src/fabric/build_routing_modules.cpp index 2996d8d23..f806148d9 100644 --- a/openfpga/src/fabric/build_routing_modules.cpp +++ b/openfpga/src/fabric/build_routing_modules.cpp @@ -462,16 +462,16 @@ void build_switch_block_module(ModuleManager& module_manager, */ size_t module_num_config_bits = find_module_num_config_bits_from_child_modules(module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type); if (0 < module_num_config_bits) { - add_sram_ports_to_module_manager(module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type, module_num_config_bits); + add_pb_sram_ports_to_module_manager(module_manager, sb_module, circuit_lib, sram_model, sram_orgz_type, module_num_config_bits); } /* Add all the nets to connect configuration ports from memory module to primitive modules * This is a one-shot addition that covers all the memory modules in this primitive module! */ if (0 < module_manager.configurable_children(sb_module).size()) { - add_module_nets_memory_config_bus(module_manager, decoder_lib, - sb_module, - sram_orgz_type, circuit_lib.design_tech_type(sram_model)); + add_pb_module_nets_memory_config_bus(module_manager, decoder_lib, + sb_module, + sram_orgz_type, circuit_lib.design_tech_type(sram_model)); } VTR_LOGV(verbose, "Done\n"); @@ -890,16 +890,16 @@ void build_connection_block_module(ModuleManager& module_manager, */ size_t module_num_config_bits = find_module_num_config_bits_from_child_modules(module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type); if (0 < module_num_config_bits) { - add_sram_ports_to_module_manager(module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type, module_num_config_bits); + add_pb_sram_ports_to_module_manager(module_manager, cb_module, circuit_lib, sram_model, sram_orgz_type, module_num_config_bits); } /* Add all the nets to connect configuration ports from memory module to primitive modules * This is a one-shot addition that covers all the memory modules in this primitive module! */ if (0 < module_manager.configurable_children(cb_module).size()) { - add_module_nets_memory_config_bus(module_manager, decoder_lib, - cb_module, - sram_orgz_type, circuit_lib.design_tech_type(sram_model)); + add_pb_module_nets_memory_config_bus(module_manager, decoder_lib, + cb_module, + sram_orgz_type, circuit_lib.design_tech_type(sram_model)); } VTR_LOGV(verbose, "Done\n"); diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 3021b2563..bcc093062 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -697,8 +697,7 @@ TopModuleNumConfigBits find_top_module_regional_num_config_bit(const ModuleManag circuit_lib, sram_model); std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, config_region, - circuit_lib, sram_model, - num_bls_per_tile); + circuit_lib, sram_model); for (const auto& kv : num_bls_per_tile) { num_config_bits[config_region].first += kv.second; } diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 72c54258f..c1bfac4b2 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -290,8 +290,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma circuit_lib, sram_model); std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, config_region, - circuit_lib, sram_model, - num_bls_per_tile); + circuit_lib, sram_model); std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); @@ -324,7 +323,6 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - int child_num_unique_blwls = num_bls_per_tile.at(coord.x()); size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; @@ -335,7 +333,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma size_t cur_bl_index = 0; for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { - size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index % child_num_unique_blwls; + size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index; /* Find the BL decoder data index: * It should be the starting index plus an offset which is the residual when divided by the number of BLs in this tile */ @@ -365,7 +363,6 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - int child_num_unique_blwls = num_bls_per_tile.at(coord.x()); size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; @@ -376,7 +373,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma size_t cur_wl_index = 0; for (const size_t& sink_wl_pin : child_wl_port_info.pins()) { - size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + std::floor(cur_wl_index / child_num_unique_blwls); + size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + cur_wl_index; VTR_ASSERT(wl_pin_id < wl_decoder_dout_port_info.pins().size()); /* Create net */ diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index f95cc076a..82d9a7f0d 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -243,8 +243,7 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol circuit_lib, config_protocol.memory_model()); std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, config_region, - circuit_lib, config_protocol.memory_model(), - num_bls_per_tile); + circuit_lib, config_protocol.memory_model()); std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); diff --git a/openfpga/src/utils/memory_bank_utils.cpp b/openfpga/src/utils/memory_bank_utils.cpp index 5afd7e0e4..14b3a6cf7 100644 --- a/openfpga/src/utils/memory_bank_utils.cpp +++ b/openfpga/src/utils/memory_bank_utils.cpp @@ -56,6 +56,38 @@ std::pair compute_memory_bank_regional_configurable_child_y_range(cons return child_y_range; } +/******************************************************************** + * Find the size of BL ports for module + *******************************************************************/ +static +size_t find_module_ql_memory_bank_num_blwls(const ModuleManager& module_manager, + const ModuleId& module_id, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& circuit_port_type) { + std::vector config_port_names = generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type); + size_t num_blwls = 0; /* By default it has zero configuration bits*/ + + /* Try to find these ports in the module manager */ + for (const std::string& config_port_name : config_port_names) { + ModulePortId module_port_id = module_manager.find_module_port(module_id, config_port_name); + /* If the port does not exist, go to the next */ + if (false == module_manager.valid_module_port_id(module_id, module_port_id)) { + continue; + } + /* We only care about a give type of ports */ + if (circuit_port_type != circuit_lib.port_type(circuit_lib.model_port(sram_model, config_port_name))) { + continue; + } + /* The port exist, find the port size and update the num_config_bits if the size is larger */ + BasicPort module_port = module_manager.module_port(module_id, module_port_id); + num_blwls = std::max((int)num_blwls, (int)module_port.get_width()); + } + + return num_blwls; +} + std::map compute_memory_bank_regional_bitline_numbers_per_tile(const ModuleManager& module_manager, const ModuleId& top_module, const ConfigRegionId& config_region, @@ -66,7 +98,7 @@ std::map compute_memory_bank_regional_bitline_numbers_per_tile(cons for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - num_bls_per_tile[coord.x()] = std::max(num_bls_per_tile[coord.x()], find_memory_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK))); + num_bls_per_tile[coord.x()] = std::max(num_bls_per_tile[coord.x()], find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_BL)); } return num_bls_per_tile; @@ -76,14 +108,13 @@ std::map compute_memory_bank_regional_wordline_numbers_per_tile(con const ModuleId& top_module, const ConfigRegionId& config_region, const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const std::map& num_bls_per_tile) { + const CircuitModelId& sram_model) { std::map num_wls_per_tile; for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - num_wls_per_tile[coord.y()] = std::max(num_wls_per_tile[coord.y()], find_memory_wl_decoder_data_size(find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK), num_bls_per_tile.at(coord.x()))); + num_wls_per_tile[coord.y()] = std::max(num_wls_per_tile[coord.y()], find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_WL)); } return num_wls_per_tile; diff --git a/openfpga/src/utils/memory_bank_utils.h b/openfpga/src/utils/memory_bank_utils.h index 8347e558f..65d2ea49f 100644 --- a/openfpga/src/utils/memory_bank_utils.h +++ b/openfpga/src/utils/memory_bank_utils.h @@ -66,8 +66,7 @@ std::map compute_memory_bank_regional_wordline_numbers_per_tile(con const ModuleId& top_module, const ConfigRegionId& config_region, const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const std::map& num_bls_per_tile); + const CircuitModelId& sram_model); /** * @brief Precompute the BLs and WLs distribution across the FPGA fabric diff --git a/openfpga/src/utils/memory_utils.cpp b/openfpga/src/utils/memory_utils.cpp index b02fe1e88..bcca022ab 100644 --- a/openfpga/src/utils/memory_utils.cpp +++ b/openfpga/src/utils/memory_utils.cpp @@ -7,6 +7,7 @@ #include "vtr_log.h" #include "openfpga_naming.h" +#include "decoder_library_utils.h" #include "memory_utils.h" /* begin namespace openfpga */ @@ -393,4 +394,39 @@ size_t generate_sram_port_size(const e_config_protocol_type sram_orgz_type, return sram_port_size; } +/******************************************************************** + * @brief Generate a list of ports that are used for SRAM configuration to a module + * - Standalone SRAMs: use the suggested port_size + * - Scan-chain Flip-flops: the port size will be forced to 1 in this case + * - Memory decoders: use the suggested port_size + * - QL Memory decoders: Apply square root as BL/WLs will be grouped + ********************************************************************/ +size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type, + const size_t& num_config_bits) { + size_t sram_port_size = num_config_bits; + + switch (sram_orgz_type) { + case CONFIG_MEM_STANDALONE: + break; + case CONFIG_MEM_SCAN_CHAIN: + /* CCFF head/tail are single-bit ports */ + sram_port_size = 1; + break; + case CONFIG_MEM_QL_MEMORY_BANK: + sram_port_size = find_memory_decoder_data_size(num_config_bits); + break; + case CONFIG_MEM_MEMORY_BANK: + break; + case CONFIG_MEM_FRAME_BASED: + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization!\n"); + exit(1); + } + + return sram_port_size; +} + + } /* end namespace openfpga */ diff --git a/openfpga/src/utils/memory_utils.h b/openfpga/src/utils/memory_utils.h index 1c1eed257..88eecf1f3 100644 --- a/openfpga/src/utils/memory_utils.h +++ b/openfpga/src/utils/memory_utils.h @@ -37,6 +37,9 @@ std::vector generate_sram_port_names(const CircuitLibrary& circuit_ size_t generate_sram_port_size(const e_config_protocol_type sram_orgz_type, const size_t& num_config_bits); +size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type, + const size_t& num_config_bits); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 13cc579fa..9b465ed45 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -4,6 +4,7 @@ ******************************************************************************/ #include +#include #include /* Headers from vtrutil library */ @@ -276,7 +277,6 @@ void add_formal_verification_sram_ports_to_module_manager(ModuleManager& module_ module_manager.set_port_preproc_flag(module_id, port_id, preproc_flag); } - /******************************************************************** * Add a list of ports that are used for SRAM configuration to a module * in the module manager @@ -361,6 +361,90 @@ void add_sram_ports_to_module_manager(ModuleManager& module_manager, } } +/******************************************************************** + * @brief Add a list of ports that are used for SRAM configuration to module + * in the module manager + * @note + * This function is only applicable to programmable blocks, which are + * - Grid + * - CBX/CBY + * - SB + * @note + * The major difference between this function and the add_sram_ports_to_module_manager() + * is the size of sram ports to be added when QL memory bank is selected + * This function will merge/group BL/WLs by considering a memory bank organization + * at block-level + ********************************************************************/ +void add_pb_sram_ports_to_module_manager(ModuleManager& module_manager, + const ModuleId& module_id, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const e_config_protocol_type sram_orgz_type, + const size_t& num_config_bits) { + std::vector sram_port_names = generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type); + size_t sram_port_size = generate_pb_sram_port_size(sram_orgz_type, num_config_bits); + + /* Add ports to the module manager */ + switch (sram_orgz_type) { + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: + for (const std::string& sram_port_name : sram_port_names) { + /* Add generated ports to the ModuleManager */ + BasicPort sram_port(sram_port_name, sram_port_size); + /* For WL ports, we need to fine-tune it */ + if (CIRCUIT_MODEL_PORT_WL == circuit_lib.port_type(circuit_lib.model_port(sram_model, sram_port_name))) { + sram_port.set_width(find_memory_wl_decoder_data_size(num_config_bits, sram_port_size)); + } + module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT); + } + break; + case CONFIG_MEM_MEMORY_BANK: { + for (const std::string& sram_port_name : sram_port_names) { + /* Add generated ports to the ModuleManager */ + BasicPort sram_port(sram_port_name, sram_port_size); + module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT); + } + break; + } + case CONFIG_MEM_SCAN_CHAIN: { + /* Note that configuration chain tail is an output while head is an input + * IMPORTANT: this is co-designed with function generate_sram_port_names() + * If the return vector is changed, the following codes MUST be adapted! + */ + VTR_ASSERT(2 == sram_port_names.size()); + size_t port_counter = 0; + for (const std::string& sram_port_name : sram_port_names) { + /* Add generated ports to the ModuleManager */ + BasicPort sram_port(sram_port_name, sram_port_size); + if (0 == port_counter) { + module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT); + } else { + VTR_ASSERT(1 == port_counter); + module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_OUTPUT_PORT); + } + port_counter++; + } + break; + } + case CONFIG_MEM_FRAME_BASED: { + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); + + BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), num_config_bits); + module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT); + + BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), 1); + module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); + + break; + } + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization !\n"); + exit(1); + } +} + /******************************************************************** * Add ports of a pb_type block to module manager * Port addition will follow the sequence: inout, input, output, clock @@ -863,6 +947,158 @@ void add_module_nets_cmos_flatten_memory_config_bus(ModuleManager& module_manage VTR_ASSERT(net_src_port.get_width() == cur_src_pin_id); } +/******************************************************************** + * @brief Connect all the Bit Lines (BL) of child memory modules under the + * parent module in a memory bank organization + * + * BL<0> BL<1> BL + * | | | + * v v v + * +--------+ +--------+ +--------+ + * | Memory | | Memory | ... | Memory | + * | Module | | Module | | Module | + * | [0,0] | | [1,0] | | [i,0] | + * +--------+ +--------+ +--------+ + * | | | + * v v v + * +--------+ +--------+ +--------+ + * | Memory | | Memory | ... | Memory | + * | Module | | Module | | Module | + * | [0,1] | | [1,1] | | [i,1] | + * +--------+ +--------+ +--------+ + * + *********************************************************************/ +void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manager, + const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& config_port_type) { + /* A counter for the current pin id for the source port of parent module */ + size_t cur_src_pin_id = 0; + + ModuleId net_src_module_id; + size_t net_src_instance_id; + ModulePortId net_src_port_id; + + /* Find the port name of parent module */ + std::string src_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); + net_src_module_id = parent_module; + net_src_instance_id = 0; + net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + + /* Get the pin id for source port */ + BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + + for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { + ModuleId net_sink_module_id; + size_t net_sink_instance_id; + ModulePortId net_sink_port_id; + + /* Find the port name of next memory module */ + std::string sink_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); + net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + + /* Get the pin id for sink port */ + BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); + + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < net_sink_port.pins().size(); ++pin_id) { + size_t cur_bl_src_pin_id = cur_src_pin_id % net_src_port.pins().size(); + /* Create a net and add source and sink to it */ + ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, + net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[cur_bl_src_pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + + /* Move to the next src pin */ + cur_src_pin_id++; + } + } +} + +/******************************************************************** + * @brief Connect all the Word Lines (WL) of child memory modules under the + * parent module in a memory bank organization + * + * +--------+ +--------+ +--------+ + * | Memory | | Memory | ... | Memory | + * | Module | | Module | | Module | + * | [0,0] | | [1,0] | | [i,0] | + * +--------+ +--------+ +--------+ + * ^ ^ ^ + * | | | + * +------------+----------------------+ + * | + * WL<0> + * + * +--------+ +--------+ +--------+ + * | Memory | | Memory | ... | Memory | + * | Module | | Module | | Module | + * | [0,1] | | [1,1] | | [i,1] | + * +--------+ +--------+ +--------+ + * ^ ^ ^ + * | | | + * +------------+----------------------+ + * | + * WL<1> + * + *********************************************************************/ +void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manager, + const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& config_port_type) { + /* A counter for the current pin id for the source port of parent module */ + size_t cur_src_pin_id = 0; + + ModuleId net_src_module_id; + size_t net_src_instance_id; + ModulePortId net_src_port_id; + + /* Find the port name of parent module */ + std::string src_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); + net_src_module_id = parent_module; + net_src_instance_id = 0; + net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + + /* Get the pin id for source port */ + BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + + for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { + ModuleId net_sink_module_id; + size_t net_sink_instance_id; + ModulePortId net_sink_port_id; + + /* Find the port name of next memory module */ + std::string sink_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); + net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + + /* Get the pin id for sink port */ + BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); + + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < net_sink_port.pins().size(); ++pin_id) { + size_t cur_wl_src_pin_id = std::floor(cur_src_pin_id / net_src_port.pins().size()); + /* Create a net and add source and sink to it */ + ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, + net_src_module_id, net_src_instance_id, + net_src_port_id, net_src_port.pins()[cur_wl_src_pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + + /* Move to the next src pin */ + cur_src_pin_id++; + } + } +} + /******************************************************************** * Connect all the memory modules under the parent module in a chain * @@ -1306,6 +1542,73 @@ void add_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, } } +/********************************************************************* + * @brief Add the port-to-port connection between all the memory modules + * and their parent module. This function creates nets to wire the control + * signals of memory module to the configuration ports of primitive module + * + * @note This function is only applicable to programmable blocks, which are + * grid, CBX/CBY, SB. Different from the add_pb_module_nets_cmos_memory_config_bus(), + * this function will merge BL/WLs of child module when connect them to the parent module + * + * QL Memory bank + * -------------- + * + * config_bus (BL) config_bus (WL) + * | | + * parent | | + * +---------------------------------------------+ + * | | | | + * | +---------------+ | | + * | | | | | + * | | +-----------|---+ | + * | | | | | | + * | v v v v | + * | +-------------------------------------+ | + * | | Child Mem 0 | ... | Child Mem N-1 | | + * | +-------------------------------------+ | + * | | | | + * | v v | + * | sram_out sram_outb | + * | | + * +---------------------------------------------+ + + * + **********************************************************************/ +static +void add_pb_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type) { + switch (sram_orgz_type) { + case CONFIG_MEM_SCAN_CHAIN: { + add_module_nets_cmos_memory_chain_config_bus(module_manager, parent_module, + sram_orgz_type); + break; + } + case CONFIG_MEM_STANDALONE: + case CONFIG_MEM_QL_MEMORY_BANK: + add_module_nets_cmos_memory_bank_bl_config_bus(module_manager, parent_module, + sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + add_module_nets_cmos_memory_bank_wl_config_bus(module_manager, parent_module, + sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + break; + case CONFIG_MEM_MEMORY_BANK: + add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, + sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, + sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + break; + case CONFIG_MEM_FRAME_BASED: + add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, parent_module); + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of SRAM organization!\n"); + exit(1); + } +} + /********************************************************************* * TODO: * Add the port-to-port connection between a logic module @@ -1331,7 +1634,6 @@ void add_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, **********************************************************************/ /******************************************************************** - * TODO: * Add the port-to-port connection between a memory module * and the configuration bus of a primitive module * @@ -1382,6 +1684,40 @@ void add_module_nets_memory_config_bus(ModuleManager& module_manager, } } + +/******************************************************************** + * Add the port-to-port connection between the configuration lines of + * a programmable block module (grid, CBX/CBY, SB) and its child module + * + * The configuration bus connection will depend not only + * the design technology of the memory cells but also the + * configuration styles of FPGA fabric. + * Here we will branch on the design technology + * + * Note: this function SHOULD be called after the pb_type_module is created + * and its child module (logic_module and memory_module) is created! + *******************************************************************/ +void add_pb_module_nets_memory_config_bus(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_design_tech& mem_tech) { + switch (mem_tech) { + case CIRCUIT_MODEL_DESIGN_CMOS: + add_pb_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, + parent_module, + sram_orgz_type); + break; + case CIRCUIT_MODEL_DESIGN_RRAM: + /* TODO: */ + break; + default: + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Invalid type of memory design technology!\n"); + exit(1); + } +} + /******************************************************************** * Find the size of shared(reserved) configuration ports for module *******************************************************************/ diff --git a/openfpga/src/utils/module_manager_utils.h b/openfpga/src/utils/module_manager_utils.h index 63787bd34..151773b71 100644 --- a/openfpga/src/utils/module_manager_utils.h +++ b/openfpga/src/utils/module_manager_utils.h @@ -69,6 +69,13 @@ void add_sram_ports_to_module_manager(ModuleManager& module_manager, const e_config_protocol_type sram_orgz_type, const size_t& num_config_bits); +void add_pb_sram_ports_to_module_manager(ModuleManager& module_manager, + const ModuleId& module_id, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const e_config_protocol_type sram_orgz_type, + const size_t& num_config_bits); + void add_primitive_pb_type_ports_to_module_manager(ModuleManager& module_manager, const ModuleId& module_id, t_pb_type* cur_pb_type, @@ -109,6 +116,16 @@ void add_module_nets_cmos_flatten_memory_config_bus(ModuleManager& module_manage const e_config_protocol_type& sram_orgz_type, const e_circuit_model_port_type& config_port_type); +void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manager, + const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& config_port_type); + +void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manager, + const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& config_port_type); + void add_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_manager, const ModuleId& parent_module, const e_config_protocol_type& sram_orgz_type); @@ -123,6 +140,12 @@ void add_module_nets_memory_config_bus(ModuleManager& module_manager, const e_config_protocol_type& sram_orgz_type, const e_circuit_model_design_tech& mem_tech); +void add_pb_module_nets_memory_config_bus(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const ModuleId& parent_module, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_design_tech& mem_tech); + size_t find_module_num_shared_config_bits(const ModuleManager& module_manager, const ModuleId& module_id); From 061952b7fa0101196c4a1487d2dfe5853bcd3570 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 15 Sep 2021 11:51:00 -0700 Subject: [PATCH 033/229] [Engine] Bug fix in computing local WLs for GRID/CB/SB --- openfpga/src/utils/module_manager_utils.cpp | 26 +++++++++------------ 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 9b465ed45..ce9edca12 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -975,15 +975,11 @@ void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manage /* A counter for the current pin id for the source port of parent module */ size_t cur_src_pin_id = 0; - ModuleId net_src_module_id; - size_t net_src_instance_id; - ModulePortId net_src_port_id; - /* Find the port name of parent module */ std::string src_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - net_src_module_id = parent_module; - net_src_instance_id = 0; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + ModuleId net_src_module_id = parent_module; + size_t net_src_instance_id = 0; + ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); /* Get the pin id for source port */ BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); @@ -1054,18 +1050,18 @@ void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manage /* A counter for the current pin id for the source port of parent module */ size_t cur_src_pin_id = 0; - ModuleId net_src_module_id; - size_t net_src_instance_id; - ModulePortId net_src_port_id; - /* Find the port name of parent module */ std::string src_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - net_src_module_id = parent_module; - net_src_instance_id = 0; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + std::string bl_port_name = generate_sram_port_name(sram_orgz_type, CIRCUIT_MODEL_PORT_BL); + + ModuleId net_src_module_id = parent_module; + size_t net_src_instance_id = 0; + ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + ModulePortId net_bl_port_id = module_manager.find_module_port(net_src_module_id, bl_port_name); /* Get the pin id for source port */ BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + BasicPort net_bl_port = module_manager.module_port(net_src_module_id, net_bl_port_id); for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { ModuleId net_sink_module_id; @@ -1083,7 +1079,7 @@ void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manage /* Create a net for each pin */ for (size_t pin_id = 0; pin_id < net_sink_port.pins().size(); ++pin_id) { - size_t cur_wl_src_pin_id = std::floor(cur_src_pin_id / net_src_port.pins().size()); + size_t cur_wl_src_pin_id = std::floor(cur_src_pin_id / net_bl_port.pins().size()); /* Create a net and add source and sink to it */ ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, From f2aa31ddb1bc3ee646f257bbc20ce68861ebd3e6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 15 Sep 2021 13:45:30 -0700 Subject: [PATCH 034/229] [FPGA-Bitstream] Fix the bug which causes bitstream wrong for QL memory bank --- .../build_fabric_bitstream_memory_bank.cpp | 29 ++++++++++++------- openfpga/src/utils/memory_bank_utils.cpp | 14 ++++----- openfpga/src/utils/memory_bank_utils.h | 10 +++++++ openfpga/src/utils/module_manager_utils.cpp | 20 ++++--------- 4 files changed, 40 insertions(+), 33 deletions(-) diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index 82d9a7f0d..3e7f2e9cc 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -47,11 +47,13 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B const ModuleId& top_module, const ModuleId& parent_module, const ConfigRegionId& config_region, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, const size_t& bl_addr_size, const size_t& wl_addr_size, - const std::map& num_bls_per_tile, + size_t& num_bls_cur_tile, const std::map& bl_start_index_per_tile, - const std::map& num_wls_per_tile, + size_t& num_wls_cur_tile, const std::map& wl_start_index_per_tile, vtr::Point& tile_coord, std::map, size_t>& cur_mem_index, @@ -84,6 +86,8 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B size_t child_instance = module_manager.region_configurable_child_instances(parent_module, config_region)[child_id]; tile_coord = module_manager.region_configurable_child_coordinates(parent_module, config_region)[child_id]; + num_bls_cur_tile = find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_BL); + num_wls_cur_tile = find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_WL); /* Get the instance name and ensure it is not empty */ std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); @@ -97,9 +101,10 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, child_block, module_manager, top_module, child_module, config_region, + circuit_lib, sram_model, bl_addr_size, wl_addr_size, - num_bls_per_tile, bl_start_index_per_tile, - num_wls_per_tile, wl_start_index_per_tile, + num_bls_cur_tile, bl_start_index_per_tile, + num_wls_cur_tile, wl_start_index_per_tile, tile_coord, cur_mem_index, fabric_bitstream, @@ -138,9 +143,10 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, child_block, module_manager, top_module, child_module, config_region, + circuit_lib, sram_model, bl_addr_size, wl_addr_size, - num_bls_per_tile, bl_start_index_per_tile, - num_wls_per_tile, wl_start_index_per_tile, + num_bls_cur_tile, bl_start_index_per_tile, + num_wls_cur_tile, wl_start_index_per_tile, tile_coord, cur_mem_index, fabric_bitstream, @@ -161,11 +167,11 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B FabricBitId fabric_bit = fabric_bitstream.add_bit(config_bit); /* Find BL address */ - size_t cur_bl_index = bl_start_index_per_tile.at(tile_coord.x()) + cur_mem_index[tile_coord] % num_bls_per_tile.at(tile_coord.x()); + size_t cur_bl_index = bl_start_index_per_tile.at(tile_coord.x()) + cur_mem_index[tile_coord] % num_bls_cur_tile; std::vector bl_addr_bits_vec = itobin_charvec(cur_bl_index, bl_addr_size); /* Find WL address */ - size_t cur_wl_index = wl_start_index_per_tile.at(tile_coord.y()) + std::floor(cur_mem_index[tile_coord] / num_bls_per_tile.at(tile_coord.x())); + size_t cur_wl_index = wl_start_index_per_tile.at(tile_coord.y()) + std::floor(cur_mem_index[tile_coord] / num_bls_cur_tile); std::vector wl_addr_bits_vec = itobin_charvec(cur_wl_index, wl_addr_size); /* Set BL address */ @@ -250,14 +256,17 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol vtr::Point temp_coord; std::map, size_t> cur_mem_index; + size_t temp_num_bls_cur_tile = 0; + size_t temp_num_wls_cur_tile = 0; rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, top_block, module_manager, top_module, top_module, config_region, + circuit_lib, config_protocol.memory_model(), bl_addr_port_info.get_width(), wl_addr_port_info.get_width(), - num_bls_per_tile, bl_start_index_per_tile, - num_wls_per_tile, wl_start_index_per_tile, + temp_num_bls_cur_tile, bl_start_index_per_tile, + temp_num_wls_cur_tile, wl_start_index_per_tile, temp_coord, cur_mem_index, fabric_bitstream, diff --git a/openfpga/src/utils/memory_bank_utils.cpp b/openfpga/src/utils/memory_bank_utils.cpp index 14b3a6cf7..a441813ad 100644 --- a/openfpga/src/utils/memory_bank_utils.cpp +++ b/openfpga/src/utils/memory_bank_utils.cpp @@ -56,16 +56,12 @@ std::pair compute_memory_bank_regional_configurable_child_y_range(cons return child_y_range; } -/******************************************************************** - * Find the size of BL ports for module - *******************************************************************/ -static size_t find_module_ql_memory_bank_num_blwls(const ModuleManager& module_manager, - const ModuleId& module_id, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const e_config_protocol_type& sram_orgz_type, - const e_circuit_model_port_type& circuit_port_type) { + const ModuleId& module_id, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& circuit_port_type) { std::vector config_port_names = generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type); size_t num_blwls = 0; /* By default it has zero configuration bits*/ diff --git a/openfpga/src/utils/memory_bank_utils.h b/openfpga/src/utils/memory_bank_utils.h index 65d2ea49f..237098927 100644 --- a/openfpga/src/utils/memory_bank_utils.h +++ b/openfpga/src/utils/memory_bank_utils.h @@ -39,6 +39,16 @@ std::pair compute_memory_bank_regional_configurable_child_y_range(cons const ModuleId& top_module, const ConfigRegionId& config_region); +/** + * @brief Find the size of BL or WL ports for a given module + */ +size_t find_module_ql_memory_bank_num_blwls(const ModuleManager& module_manager, + const ModuleId& module_id, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const e_config_protocol_type& sram_orgz_type, + const e_circuit_model_port_type& circuit_port_type); + /** * @brief Precompute the number of bit lines required by each tile under a specific configuration region * @note diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index ce9edca12..12e2d0636 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -985,15 +985,11 @@ void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manage BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { - ModuleId net_sink_module_id; - size_t net_sink_instance_id; - ModulePortId net_sink_port_id; - /* Find the port name of next memory module */ std::string sink_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; - net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + ModuleId net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; + size_t net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; + ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); /* Get the pin id for sink port */ BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); @@ -1064,15 +1060,11 @@ void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manage BasicPort net_bl_port = module_manager.module_port(net_src_module_id, net_bl_port_id); for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { - ModuleId net_sink_module_id; - size_t net_sink_instance_id; - ModulePortId net_sink_port_id; - /* Find the port name of next memory module */ std::string sink_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; - net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; - net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + ModuleId net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; + size_t net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; + ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); /* Get the pin id for sink port */ BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); From 2e45a6143beba3a3fdff978deecbfb3d0312d4f4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 15 Sep 2021 15:11:58 -0700 Subject: [PATCH 035/229] [Engine] Fix a critical bug which causes flatten memory tests failed --- openfpga/src/utils/module_manager_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 12e2d0636..421e7b95f 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -386,7 +386,6 @@ void add_pb_sram_ports_to_module_manager(ModuleManager& module_manager, /* Add ports to the module manager */ switch (sram_orgz_type) { - case CONFIG_MEM_STANDALONE: case CONFIG_MEM_QL_MEMORY_BANK: for (const std::string& sram_port_name : sram_port_names) { /* Add generated ports to the ModuleManager */ @@ -398,6 +397,7 @@ void add_pb_sram_ports_to_module_manager(ModuleManager& module_manager, module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT); } break; + case CONFIG_MEM_STANDALONE: case CONFIG_MEM_MEMORY_BANK: { for (const std::string& sram_port_name : sram_port_names) { /* Add generated ports to the ModuleManager */ From cd2978a43431f70e4aa82bc4611638b894d915cf Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 20 Sep 2021 11:13:02 -0700 Subject: [PATCH 036/229] [Arch] Added a new architecture example which shows how to use the memory bank with readback functionality --- .../k4_N4_40nm_qlbank_wlr_openfpga.xml | 199 ++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_wlr_openfpga.xml diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_wlr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_wlr_openfpga.xml new file mode 100644 index 000000000..228f450a4 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_wlr_openfpga.xml @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 5c1c428ea542d1818f92a57a276b1b13eb3a14ba Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 20 Sep 2021 11:13:36 -0700 Subject: [PATCH 037/229] [HDL] Updated cell library with the SRAM cell with Read Enable signal --- .../openfpga_cell_library/verilog/sram.v | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/openfpga_flow/openfpga_cell_library/verilog/sram.v b/openfpga_flow/openfpga_cell_library/verilog/sram.v index 86f3ddf99..7f70b9723 100644 --- a/openfpga_flow/openfpga_cell_library/verilog/sram.v +++ b/openfpga_flow/openfpga_cell_library/verilog/sram.v @@ -256,6 +256,44 @@ module SRAMSR( endmodule +//----------------------------------------------------- +// Function : A SRAM cell with WL read signal +//----------------------------------------------------- +module SRAM_RE( + input WE, // Word line control signal as write enable + input RE, // Word line read signal as read enable + inout D, // Bit line control signal + output Q, // Data output + output QN // Data output +); + + //----- local variable need to be registered + reg data; + reg data_readback; + + //----- when wl is enabled, we can read in data from bl + always @(WE or RE or D) + begin + if (1'b1 == RE) begin + data_readback <= Q; + end else if ((1'b1 == D)&&(1'b1 == WE)) begin + //----- Cases to program internal memory bit + //----- case 1: bl = 1, wl = 1, a -> 0 + data <= 1'b1; + end else if ((1'b0 == D)&&(1'b1 == WE)) begin + //----- case 2: bl = 0, wl = 1, a -> 0 + data <= 1'b0; + end + end + + // Wire q_reg to Q + assign Q = data; + assign QN = ~data; + assign D = RE ? data_readback : 1'b0; + +endmodule + + //----------------------------------------------------- // Function : A SRAM cell with // - an active-low reset From 60fc3ab36c13c121c47b294088797cdfae598bff Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 20 Sep 2021 11:20:36 -0700 Subject: [PATCH 038/229] [Test] Added a new test case for the WLR memory bank --- .../ql_memory_bank_use_wlr/config/task.conf | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_use_wlr/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_use_wlr/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_use_wlr/config/task.conf new file mode 100644 index 000000000..9ed4b8323 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_use_wlr/config/task.conf @@ -0,0 +1,44 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +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/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_wlr_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +bench1_top = or2 +bench1_chan_width = 300 + +bench2_top = and2_latch +bench2_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 3f6ac4186861647cb2fcd7eed2ab23b0b9498255 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 20 Sep 2021 11:21:58 -0700 Subject: [PATCH 039/229] [Test] Deploy the WLR test to the basic regression tests --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index 5bef6a05f..531ba5f42 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -55,6 +55,7 @@ run-task basic_tests/preconfig_testbench/memory_bank --debug --show_thread_logs echo -e "Testing physical design friendly memory bank configuration protocol of a K4N4 FPGA"; run-task basic_tests/full_testbench/ql_memory_bank --debug --show_thread_logs +run-task basic_tests/full_testbench/ql_memory_bank_use_wlr --debug --show_thread_logs echo -e "Testing testbenches without self checking features"; run-task basic_tests/full_testbench/full_testbench_without_self_checking --debug --show_thread_logs From 0450d57d82f09d7ee0603bf24b5913185d5f79e9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 20 Sep 2021 16:05:01 -0700 Subject: [PATCH 040/229] [Arch] Fixed critical bugs in the OpenFPGA architecture file for QL memory bank with WLR --- .../openfpga_arch/k4_N4_40nm_qlbank_wlr_openfpga.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_wlr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_wlr_openfpga.xml index 228f450a4..62f449b25 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_wlr_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_wlr_openfpga.xml @@ -161,13 +161,13 @@ - + - + From 36a4da863c51e3b5c6349f414210ab4f6498cef6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 20 Sep 2021 16:05:36 -0700 Subject: [PATCH 041/229] [Engine] Support WLR port in OpenFPGA architecture file and fabric generator --- .../libarchopenfpga/src/circuit_types.h | 3 +- .../src/openfpga_reserved_words.h | 3 + openfpga/src/base/openfpga_naming.cpp | 6 +- openfpga/src/fabric/build_decoder_modules.cpp | 12 +++ openfpga/src/fabric/build_memory_modules.cpp | 18 ++++- .../src/fabric/build_top_module_memory.cpp | 18 +++-- .../fabric/build_top_module_memory_bank.cpp | 73 +++++++++++++++++-- openfpga/src/mux_lib/decoder_library.cpp | 15 +++- openfpga/src/mux_lib/decoder_library.h | 9 ++- openfpga/src/utils/decoder_library_utils.cpp | 4 +- openfpga/src/utils/memory_utils.cpp | 3 +- openfpga/src/utils/module_manager_utils.cpp | 40 ++++++---- 12 files changed, 165 insertions(+), 39 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/circuit_types.h b/libopenfpga/libarchopenfpga/src/circuit_types.h index 3a2604a42..12b881db0 100644 --- a/libopenfpga/libarchopenfpga/src/circuit_types.h +++ b/libopenfpga/libarchopenfpga/src/circuit_types.h @@ -101,10 +101,11 @@ enum e_circuit_model_port_type { CIRCUIT_MODEL_PORT_BLB, CIRCUIT_MODEL_PORT_WL, CIRCUIT_MODEL_PORT_WLB, + CIRCUIT_MODEL_PORT_WLR, NUM_CIRCUIT_MODEL_PORT_TYPES }; /* Strings correspond to each port type */ -constexpr std::array CIRCUIT_MODEL_PORT_TYPE_STRING = {{"input", "output", "inout", "clock", "sram", "bl", "blb", "wl", "wlb"}}; +constexpr std::array CIRCUIT_MODEL_PORT_TYPE_STRING = {{"input", "output", "inout", "clock", "sram", "bl", "blb", "wl", "wlb", "wlr"}}; enum e_circuit_model_delay_type { CIRCUIT_MODEL_DELAY_RISE, diff --git a/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h b/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h index 732247178..af151a7a5 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h +++ b/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h @@ -33,6 +33,7 @@ constexpr char* CONNECTION_BLOCK_MEM_INSTANCE_PREFIX = "mem_"; constexpr char* MEMORY_MODULE_POSTFIX = "_mem"; constexpr char* MEMORY_BL_PORT_NAME = "bl"; constexpr char* MEMORY_WL_PORT_NAME = "wl"; +constexpr char* MEMORY_WLR_PORT_NAME = "wlr"; /* Multiplexer naming constant strings */ constexpr char* MUX_BASIS_MODULE_POSTFIX = "_basis"; @@ -48,6 +49,8 @@ constexpr char* DECODER_DATA_OUT_PORT_NAME = "data_out"; constexpr char* DECODER_DATA_OUT_INV_PORT_NAME = "data_out_inv"; constexpr char* DECODER_BL_ADDRESS_PORT_NAME = "bl_address"; constexpr char* DECODER_WL_ADDRESS_PORT_NAME = "wl_address"; +constexpr char* DECODER_READBACK_PORT_NAME = "readback"; +constexpr char* DECODER_DATA_READ_ENABLE_PORT_NAME = "data_out_ren"; /* Inverted port naming */ constexpr char* INV_PORT_POSTFIX = "_inv"; diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index c898066b3..3dab1ca7f 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -719,9 +719,11 @@ std::string generate_sram_port_name(const e_config_protocol_type& sram_orgz_type */ if (CIRCUIT_MODEL_PORT_BL == port_type) { port_name = std::string(MEMORY_BL_PORT_NAME); - } else { - VTR_ASSERT( CIRCUIT_MODEL_PORT_WL == port_type ); + } else if (CIRCUIT_MODEL_PORT_WL == port_type) { port_name = std::string(MEMORY_WL_PORT_NAME); + } else { + VTR_ASSERT( CIRCUIT_MODEL_PORT_WLR == port_type ); + port_name = std::string(MEMORY_WLR_PORT_NAME); } break; case CONFIG_MEM_FRAME_BASED: diff --git a/openfpga/src/fabric/build_decoder_modules.cpp b/openfpga/src/fabric/build_decoder_modules.cpp index 949058ba8..fe18212e7 100644 --- a/openfpga/src/fabric/build_decoder_modules.cpp +++ b/openfpga/src/fabric/build_decoder_modules.cpp @@ -184,6 +184,18 @@ ModuleId build_wl_memory_decoder_module(ModuleManager& module_manager, module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT); } + /* Add readback port */ + if (true == decoder_lib.use_readback(decoder)) { + BasicPort readback_port(std::string(DECODER_READBACK_PORT_NAME), 1); + module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT); + } + + /* Add data read-enable port */ + if (true == decoder_lib.use_readback(decoder)) { + BasicPort data_ren_port(std::string(DECODER_DATA_READ_ENABLE_PORT_NAME), data_size); + module_manager.add_port(module_id, data_ren_port, ModuleManager::MODULE_OUTPUT_PORT); + } + return module_id; } diff --git a/openfpga/src/fabric/build_memory_modules.cpp b/openfpga/src/fabric/build_memory_modules.cpp index 8a354da75..a8f7fceb4 100644 --- a/openfpga/src/fabric/build_memory_modules.cpp +++ b/openfpga/src/fabric/build_memory_modules.cpp @@ -366,12 +366,15 @@ void build_memory_flatten_module(ModuleManager& module_manager, /* Get the BL/WL ports from the SRAM */ std::vector sram_bl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BL, true); std::vector sram_wl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WL, true); + /* Optional: Get the WLR ports from the SRAM */ + std::vector sram_wlr_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR, true); /* Get the output ports from the SRAM */ std::vector sram_output_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, true); - /* Ensure that we have only 1 BL, 1 WL and 2 output ports*/ + /* Ensure that we have only 1 BL, 1 WL and 2 output ports, as well as an optional WLR*/ VTR_ASSERT(1 == sram_bl_ports.size()); VTR_ASSERT(1 == sram_wl_ports.size()); + VTR_ASSERT(2 > sram_wlr_ports.size()); VTR_ASSERT(2 == sram_output_ports.size()); /* Create a module and add to the module manager */ @@ -389,6 +392,12 @@ void build_memory_flatten_module(ModuleManager& module_manager, BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), num_mems); ModulePortId mem_wl_port = module_manager.add_port(mem_module, wl_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort wlr_port(std::string(MEMORY_WLR_PORT_NAME), num_mems); + ModulePortId mem_wlr_port = ModulePortId::INVALID(); + if (!sram_wlr_ports.empty()) { + mem_wlr_port = module_manager.add_port(mem_module, wlr_port, ModuleManager::MODULE_INPUT_PORT); + } + /* Add each output port: port width should match the number of memories */ for (size_t iport = 0; iport < sram_output_ports.size(); ++iport) { std::string port_name; @@ -419,6 +428,9 @@ void build_memory_flatten_module(ModuleManager& module_manager, for (const CircuitPortId& port : sram_wl_ports) { add_module_input_nets_to_mem_modules(module_manager, mem_module, mem_wl_port, circuit_lib, port, sram_mem_module, i, sram_mem_instance); } + for (const CircuitPortId& port : sram_wlr_ports) { + add_module_input_nets_to_mem_modules(module_manager, mem_module, mem_wlr_port, circuit_lib, port, sram_mem_module, i, sram_mem_instance); + } /* Wire outputs of child module to outputs of parent module */ add_module_output_nets_to_mem_modules(module_manager, mem_module, circuit_lib, sram_output_ports, sram_mem_module, i, sram_mem_instance); } @@ -644,9 +656,9 @@ void build_frame_memory_module(ModuleManager& module_manager, * If we find one, we use the module. * Otherwise, we create one and add it to the decoder library */ - DecoderId decoder_id = frame_decoder_lib.find_decoder(addr_size, data_size, true, false, use_data_inv); + DecoderId decoder_id = frame_decoder_lib.find_decoder(addr_size, data_size, true, false, use_data_inv, false); if (DecoderId::INVALID() == decoder_id) { - decoder_id = frame_decoder_lib.add_decoder(addr_size, data_size, true, false, use_data_inv); + decoder_id = frame_decoder_lib.add_decoder(addr_size, data_size, true, false, use_data_inv, false); } VTR_ASSERT(DecoderId::INVALID() != decoder_id); diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index bcc093062..c9ee2b722 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -870,6 +870,12 @@ void add_top_module_sram_ports(ModuleManager& module_manager, BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); + /* Optional: If we have WLR port, we should add a read-back port */ + if (!circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR).empty()) { + BasicPort readback_port(std::string(DECODER_READBACK_PORT_NAME), config_protocol.num_regions()); + module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT); + } + /* Data input should be dependent on the number of configuration regions*/ BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), config_protocol.num_regions()); module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); @@ -1056,9 +1062,9 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag * Otherwise, we create one and add it to the decoder library */ DecoderId bl_decoder_id = decoder_lib.find_decoder(bl_addr_size, num_bls, - true, true, false); + true, true, false, false); if (DecoderId::INVALID() == bl_decoder_id) { - bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false); + bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false, false); } VTR_ASSERT(DecoderId::INVALID() != bl_decoder_id); @@ -1084,9 +1090,9 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag * Otherwise, we create one and add it to the decoder library */ DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls, - true, false, false); + true, false, false, false); if (DecoderId::INVALID() == wl_decoder_id) { - wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false); + wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false, false); } VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id); @@ -1533,9 +1539,9 @@ void add_top_module_nets_cmos_memory_frame_decoder_config_bus(ModuleManager& mod /* Search the decoder library and try to find one * If not found, create a new module and add it to the module manager */ - DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false); + DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false, false); if (DecoderId::INVALID() == decoder_id) { - decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false); + decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false, false); } VTR_ASSERT(DecoderId::INVALID() != decoder_id); diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index c1bfac4b2..7c60a03d8 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -137,6 +137,16 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma /* Data in port should match the number of configuration regions */ VTR_ASSERT(din_port_info.get_width() == module_manager.regions(top_module).size()); + /* Find readback port from the top-level module */ + ModulePortId readback_port = module_manager.find_module_port(top_module, std::string(DECODER_READBACK_PORT_NAME)); + BasicPort readback_port_info; + + /* Readback port if available, should be a 1-bit port */ + if (readback_port) { + readback_port_info = module_manager.module_port(top_module, readback_port); + VTR_ASSERT(readback_port_info.get_width() == 1); + } + /* Find BL and WL address port from the top-level module */ ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port); @@ -168,9 +178,9 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma * Otherwise, we create one and add it to the decoder library */ DecoderId bl_decoder_id = decoder_lib.find_decoder(bl_addr_size, num_bls, - true, true, false); + true, true, false, false); if (DecoderId::INVALID() == bl_decoder_id) { - bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false); + bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false, false); } VTR_ASSERT(DecoderId::INVALID() != bl_decoder_id); @@ -196,9 +206,9 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma * Otherwise, we create one and add it to the decoder library */ DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls, - true, false, false); + true, false, false, readback_port != ModulePortId::INVALID()); if (DecoderId::INVALID() == wl_decoder_id) { - wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false); + wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false, readback_port != ModulePortId::INVALID()); } VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id); @@ -264,7 +274,13 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma BasicPort wl_decoder_en_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_en_port); ModulePortId wl_decoder_addr_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort wl_decoder_addr_port_info = module_manager.module_port(wl_decoder_module, bl_decoder_addr_port); + BasicPort wl_decoder_addr_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_addr_port); + + ModulePortId wl_decoder_readback_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_READBACK_PORT_NAME)); + BasicPort wl_decoder_readback_port_info; + if (wl_decoder_readback_port) { + wl_decoder_readback_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_readback_port); + } /* Top module Enable port -> WL Decoder Enable port */ add_module_bus_nets(module_manager, @@ -278,6 +294,14 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma top_module, 0, wl_addr_port, wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_addr_port); + /* Top module readback port -> WL Decoder readback port */ + if (wl_decoder_readback_port) { + add_module_bus_nets(module_manager, + top_module, + top_module, 0, readback_port, + wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_readback_port); + } + /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric * The distribution is a matrix which contains the starting index of BL/WL for each column or row @@ -391,6 +415,45 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma } } + /************************************************************** + * Optional: Add nets from WLR data out to each configurable child + */ + ModulePortId wl_decoder_data_ren_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_READ_ENABLE_PORT_NAME)); + BasicPort wl_decoder_data_ren_port_info; + if (wl_decoder_data_ren_port) { + wl_decoder_data_ren_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_data_ren_port); + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the WL port */ + ModulePortId child_wlr_port = module_manager.find_module_port(child_module, std::string(MEMORY_WLR_PORT_NAME)); + BasicPort child_wlr_port_info = module_manager.module_port(child_module, child_wlr_port); + + size_t cur_wlr_index = 0; + + for (const size_t& sink_wlr_pin : child_wlr_port_info.pins()) { + size_t wlr_pin_id = wl_start_index_per_tile[coord.y()] + cur_wlr_index; + VTR_ASSERT(wlr_pin_id < wl_decoder_data_ren_port_info.pins().size()); + + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + wl_decoder_module, curr_wl_decoder_instance_id, + wl_decoder_data_ren_port, + wl_decoder_data_ren_port_info.pins()[wlr_pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_wlr_port, sink_wlr_pin); + + cur_wlr_index++; + } + } + } + /************************************************************** * Add the BL and WL decoders to the end of configurable children list * Note: this MUST be done after adding all the module nets to other regular configurable children diff --git a/openfpga/src/mux_lib/decoder_library.cpp b/openfpga/src/mux_lib/decoder_library.cpp index a7c4a8840..8d6017f40 100644 --- a/openfpga/src/mux_lib/decoder_library.cpp +++ b/openfpga/src/mux_lib/decoder_library.cpp @@ -47,6 +47,11 @@ bool DecoderLibrary::use_data_inv_port(const DecoderId& decoder) const { return use_data_inv_port_[decoder]; } +bool DecoderLibrary::use_readback(const DecoderId& decoder) const { + VTR_ASSERT_SAFE(valid_decoder_id(decoder)); + return use_readback_[decoder]; +} + /* Find a decoder to the library, with the specification. * If found, return the id of decoder. * If not found, return an invalid id of decoder @@ -61,13 +66,15 @@ DecoderId DecoderLibrary::find_decoder(const size_t& addr_size, const size_t& data_size, const bool& use_enable, const bool& use_data_in, - const bool& use_data_inv_port) const { + const bool& use_data_inv_port, + const bool& use_readback) const { for (auto decoder : decoders()) { if ( (addr_size == addr_sizes_[decoder]) && (data_size == data_sizes_[decoder]) && (use_enable == use_enable_[decoder]) && (use_data_in == use_data_in_[decoder]) - && (use_data_inv_port == use_data_inv_port_[decoder]) ) { + && (use_data_inv_port == use_data_inv_port_[decoder]) + && (use_readback == use_readback_[decoder]) ) { return decoder; } } @@ -92,7 +99,8 @@ DecoderId DecoderLibrary::add_decoder(const size_t& addr_size, const size_t& data_size, const bool& use_enable, const bool& use_data_in, - const bool& use_data_inv_port) { + const bool& use_data_inv_port, + const bool& use_readback) { DecoderId decoder = DecoderId(decoder_ids_.size()); /* Push to the decoder list */ decoder_ids_.push_back(decoder); @@ -102,6 +110,7 @@ DecoderId DecoderLibrary::add_decoder(const size_t& addr_size, use_enable_.push_back(use_enable); use_data_in_.push_back(use_data_in); use_data_inv_port_.push_back(use_data_inv_port); + use_readback_.push_back(use_readback); return decoder; } diff --git a/openfpga/src/mux_lib/decoder_library.h b/openfpga/src/mux_lib/decoder_library.h index 397308db5..7340f4375 100644 --- a/openfpga/src/mux_lib/decoder_library.h +++ b/openfpga/src/mux_lib/decoder_library.h @@ -50,6 +50,8 @@ class DecoderLibrary { bool use_data_in(const DecoderId& decoder) const; /* Get the flag if a decoder includes a data_inv port which is an inversion of the regular data output port */ bool use_data_inv_port(const DecoderId& decoder) const; + /* Get the flag if a decoder includes a readback port which enables readback from configurable memories */ + bool use_readback(const DecoderId& decoder) const; /* Find a decoder to the library, with the specification. * If found, return the id of decoder. * If not found, return an invalid id of decoder @@ -64,7 +66,8 @@ class DecoderLibrary { const size_t& data_size, const bool& use_enable, const bool& use_data_in, - const bool& use_data_inv_port) const; + const bool& use_data_inv_port, + const bool& use_readback) const; public: /* Public validators */ /* valid ids */ @@ -76,7 +79,8 @@ class DecoderLibrary { const size_t& data_size, const bool& use_enable, const bool& use_data_in, - const bool& use_data_inv_port); + const bool& use_data_inv_port, + const bool& use_readback); private: /* Internal Data */ vtr::vector decoder_ids_; @@ -85,6 +89,7 @@ class DecoderLibrary { vtr::vector use_enable_; vtr::vector use_data_in_; vtr::vector use_data_inv_port_; + vtr::vector use_readback_; }; } /* End namespace openfpga*/ diff --git a/openfpga/src/utils/decoder_library_utils.cpp b/openfpga/src/utils/decoder_library_utils.cpp index 502620661..b44bb106c 100644 --- a/openfpga/src/utils/decoder_library_utils.cpp +++ b/openfpga/src/utils/decoder_library_utils.cpp @@ -112,11 +112,11 @@ DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib, const size_t data_size) { size_t addr_size = find_mux_local_decoder_addr_size(data_size); - DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, false, false, true); + DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, false, false, true, false); if (DecoderId::INVALID() == decoder_id) { /* Add the decoder */ - return decoder_lib.add_decoder(addr_size, data_size, false, false, true); + return decoder_lib.add_decoder(addr_size, data_size, false, false, true, false); } /* There is already a decoder in the library, return the decoder id */ diff --git a/openfpga/src/utils/memory_utils.cpp b/openfpga/src/utils/memory_utils.cpp index bcca022ab..8e2038b06 100644 --- a/openfpga/src/utils/memory_utils.cpp +++ b/openfpga/src/utils/memory_utils.cpp @@ -330,7 +330,8 @@ std::vector generate_sram_port_names(const CircuitLibrary& circuit_ std::vector ports_to_search; ports_to_search.push_back(CIRCUIT_MODEL_PORT_BL); ports_to_search.push_back(CIRCUIT_MODEL_PORT_WL); - /* Try to find a BL/WL/BLB/WLB port and update the port types/module port types to be added */ + ports_to_search.push_back(CIRCUIT_MODEL_PORT_WLR); + /* Try to find a BL/WL/WLR port and update the port types/module port types to be added */ for (const auto& port_to_search : ports_to_search) { std::vector found_port = circuit_lib.model_ports_by_type(sram_model, port_to_search); if (0 == found_port.size()) { diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 421e7b95f..4c25c3a4a 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -195,6 +195,7 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager, port_type2type_map[CIRCUIT_MODEL_PORT_BLB] = ModuleManager::MODULE_INPUT_PORT; port_type2type_map[CIRCUIT_MODEL_PORT_WL] = ModuleManager::MODULE_INPUT_PORT; port_type2type_map[CIRCUIT_MODEL_PORT_WLB] = ModuleManager::MODULE_INPUT_PORT; + port_type2type_map[CIRCUIT_MODEL_PORT_WLR] = ModuleManager::MODULE_INPUT_PORT; port_type2type_map[CIRCUIT_MODEL_PORT_OUTPUT] = ModuleManager::MODULE_OUTPUT_PORT; /* Input ports (ignore all the global ports when searching the circuit_lib */ @@ -390,8 +391,9 @@ void add_pb_sram_ports_to_module_manager(ModuleManager& module_manager, for (const std::string& sram_port_name : sram_port_names) { /* Add generated ports to the ModuleManager */ BasicPort sram_port(sram_port_name, sram_port_size); - /* For WL ports, we need to fine-tune it */ - if (CIRCUIT_MODEL_PORT_WL == circuit_lib.port_type(circuit_lib.model_port(sram_model, sram_port_name))) { + /* For WL and WLR ports, we need to fine-tune it */ + if ( (CIRCUIT_MODEL_PORT_WL == circuit_lib.port_type(circuit_lib.model_port(sram_model, sram_port_name))) + || (CIRCUIT_MODEL_PORT_WLR == circuit_lib.port_type(circuit_lib.model_port(sram_model, sram_port_name))) ) { sram_port.set_width(find_memory_wl_decoder_data_size(num_config_bits, sram_port_size)); } module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT); @@ -885,7 +887,7 @@ void add_module_nets_between_logic_and_memory_sram_bus(ModuleManager& module_man * | | | * +------------+----------------------+ * | - * WL + * WL/WLR * * Note: * - This function will do the connection for only one type of the port, @@ -900,15 +902,16 @@ void add_module_nets_cmos_flatten_memory_config_bus(ModuleManager& module_manage /* A counter for the current pin id for the source port of parent module */ size_t cur_src_pin_id = 0; - ModuleId net_src_module_id; - size_t net_src_instance_id; - ModulePortId net_src_port_id; - /* Find the port name of parent module */ std::string src_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); - net_src_module_id = parent_module; - net_src_instance_id = 0; - net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + ModuleId net_src_module_id = parent_module; + size_t net_src_instance_id = 0; + ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + + /* We may not be able to find WLR port, return now */ + if (!net_src_port_id) { + return; + } /* Get the pin id for source port */ BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); @@ -1025,7 +1028,7 @@ void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manage * | | | * +------------+----------------------+ * | - * WL<0> + * WL<0>/WLR<0> * * +--------+ +--------+ +--------+ * | Memory | | Memory | ... | Memory | @@ -1036,7 +1039,7 @@ void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manage * | | | * +------------+----------------------+ * | - * WL<1> + * WL<1>/WLR<1> * *********************************************************************/ void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manager, @@ -1055,6 +1058,11 @@ void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manage ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); ModulePortId net_bl_port_id = module_manager.find_module_port(net_src_module_id, bl_port_name); + /* We may not be able to find WLR port, return now */ + if (!net_src_port_id) { + return; + } + /* Get the pin id for source port */ BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); BasicPort net_bl_port = module_manager.module_port(net_src_module_id, net_bl_port_id); @@ -1300,9 +1308,9 @@ void add_module_nets_cmos_memory_frame_decoder_config_bus(ModuleManager& module_ /* Search the decoder library and try to find one * If not found, create a new module and add it to the module manager */ - DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false); + DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false, false); if (DecoderId::INVALID() == decoder_id) { - decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false); + decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false, false); } VTR_ASSERT(DecoderId::INVALID() != decoder_id); @@ -1519,6 +1527,8 @@ void add_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, + sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); break; case CONFIG_MEM_FRAME_BASED: add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, parent_module); @@ -1580,6 +1590,8 @@ void add_pb_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, sram_orgz_type, CIRCUIT_MODEL_PORT_BL); add_module_nets_cmos_memory_bank_wl_config_bus(module_manager, parent_module, sram_orgz_type, CIRCUIT_MODEL_PORT_WL); + add_module_nets_cmos_memory_bank_wl_config_bus(module_manager, parent_module, + sram_orgz_type, CIRCUIT_MODEL_PORT_WLR); break; case CONFIG_MEM_MEMORY_BANK: add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, From c84c0d4a3f41ff9a43f84da4918c37e44fff3a87 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 20 Sep 2021 17:07:26 -0700 Subject: [PATCH 042/229] [FPGA-Verilog] Upgrade fpga-verilog to support decoders with WLR --- openfpga/src/fabric/build_decoder_modules.cpp | 1 + .../src/fpga_verilog/verilog_decoders.cpp | 97 ++++++++++++++++++- .../fpga_verilog/verilog_top_testbench.cpp | 11 +++ 3 files changed, 108 insertions(+), 1 deletion(-) diff --git a/openfpga/src/fabric/build_decoder_modules.cpp b/openfpga/src/fabric/build_decoder_modules.cpp index fe18212e7..85ed342aa 100644 --- a/openfpga/src/fabric/build_decoder_modules.cpp +++ b/openfpga/src/fabric/build_decoder_modules.cpp @@ -194,6 +194,7 @@ ModuleId build_wl_memory_decoder_module(ModuleManager& module_manager, if (true == decoder_lib.use_readback(decoder)) { BasicPort data_ren_port(std::string(DECODER_DATA_READ_ENABLE_PORT_NAME), data_size); module_manager.add_port(module_id, data_ren_port, ModuleManager::MODULE_OUTPUT_PORT); + module_manager.set_port_is_register(module_id, data_ren_port.get_name(), true); } return module_id; diff --git a/openfpga/src/fpga_verilog/verilog_decoders.cpp b/openfpga/src/fpga_verilog/verilog_decoders.cpp index 6960ba19e..9b6f4da45 100644 --- a/openfpga/src/fpga_verilog/verilog_decoders.cpp +++ b/openfpga/src/fpga_verilog/verilog_decoders.cpp @@ -289,6 +289,20 @@ void print_verilog_arch_decoder_module(std::fstream& fp, data_inv_port = module_manager.module_port(module_id, data_inv_port_id); } + /* Find readback port */ + ModulePortId readback_port_id = module_manager.find_module_port(module_id, std::string(DECODER_READBACK_PORT_NAME)); + BasicPort readback_port; + if (readback_port_id) { + readback_port = module_manager.module_port(module_id, readback_port_id); + } + + /* Find data read-enable port */ + ModulePortId data_ren_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_READ_ENABLE_PORT_NAME)); + BasicPort data_ren_port; + if (data_ren_port_id) { + data_ren_port = module_manager.module_port(module_id, data_ren_port_id); + } + /* dump module definition + ports */ print_verilog_module_declaration(fp, module_manager, module_id, default_net_type); /* Finish dumping ports */ @@ -303,10 +317,18 @@ void print_verilog_arch_decoder_module(std::fstream& fp, * else data_out is driven by '0' */ if (1 == data_size) { + /* Output logics for data output */ fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port); + /* If there is a readback port, the data output is only enabled when readback is disabled */ + if (readback_port_id) { + fp << " or " << "~" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port); + } fp << ") begin" << std::endl; fp << "\tif ((" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) && ("; + if (readback_port_id) { + fp << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b0) && ("; + } fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << " == 1'b0))"; fp << " begin" << std::endl; fp << "\t\t" << generate_verilog_port_constant_values(data_port, std::vector(1, 1)) << ";" << std::endl; @@ -315,6 +337,26 @@ void print_verilog_arch_decoder_module(std::fstream& fp, fp << "\t" << "end" << std::endl; fp << "end" << std::endl; + /* Output logics for data readback output */ + if (data_ren_port_id) { + fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); + fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port); + /* If there is a readback port, the data output is only enabled when readback is disabled */ + if (readback_port_id) { + fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, readback_port); + } + fp << ") begin" << std::endl; + fp << "\tif ((" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) && ("; + fp << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b1) && ("; + fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << " == 1'b0))"; + fp << " begin" << std::endl; + fp << "\t\t" << generate_verilog_port_constant_values(data_ren_port, std::vector(1, 1)) << ";" << std::endl; + fp << "\t" << "end else begin" << std::endl; + fp << "\t\t" << generate_verilog_port_constant_values(data_ren_port, std::vector(1, 0)) << ";" << std::endl; + fp << "\t" << "end" << std::endl; + fp << "end" << std::endl; + } + /* Depend on if the inverted data output port is needed or not */ if (true == decoder_lib.use_data_inv_port(decoder)) { print_verilog_wire_connection(fp, data_inv_port, addr_port, true); @@ -344,10 +386,23 @@ void print_verilog_arch_decoder_module(std::fstream& fp, * The rest of addr codes 3'b110, 3'b111 will be decoded to data=8'b0_0000; */ + /* Output logics for data output */ fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); + /* If there is a readback port, the data output is only enabled when readback is disabled */ + if (readback_port_id) { + fp << " or " << "~" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port); + } fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port); fp << ") begin" << std::endl; - fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) begin" << std::endl; + if (readback_port_id) { + fp << "\tif ("; + fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) "; + fp << "&&"; + fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b0) "; + fp << ") begin" << std::endl; + } else { + fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) begin" << std::endl; + } fp << "\t\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl; /* Create a string for addr and data */ for (size_t i = 0; i < data_size; ++i) { @@ -373,6 +428,46 @@ void print_verilog_arch_decoder_module(std::fstream& fp, fp << "end" << std::endl; + /* Output logics for data readback output */ + if (data_ren_port_id) { + fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); + /* If there is a readback port, the data output is only enabled when readback is disabled */ + if (readback_port_id) { + fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, readback_port); + } + fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port); + fp << ") begin" << std::endl; + fp << "\tif ("; + fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) "; + fp << "&&"; + fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b1) "; + fp << ") begin" << std::endl; + fp << "\t\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl; + /* Create a string for addr and data */ + for (size_t i = 0; i < data_size; ++i) { + fp << "\t\t\t" << generate_verilog_constant_values(itobin_vec(i, addr_size)); + fp << " : "; + fp << generate_verilog_port_constant_values(data_ren_port, ito1hot_vec(i, data_size)); + fp << ";" << std::endl; + } + /* Different from MUX decoder, we assign default values which is all zero */ + fp << "\t\t\t" << "default"; + fp << " : "; + fp << generate_verilog_port_constant_values(data_ren_port, ito1hot_vec(data_size, data_size)); + fp << ";" << std::endl; + + fp << "\t\t" << "endcase" << std::endl; + fp << "\t" << "end" << std::endl; + + /* If enable is not active, we should give all zero */ + fp << "\t" << "else begin" << std::endl; + fp << "\t\t" << generate_verilog_port_constant_values(data_ren_port, ito1hot_vec(data_size, data_size)); + fp << ";" << std::endl; + fp << "\t" << "end" << std::endl; + + fp << "end" << std::endl; + } + if (true == decoder_lib.use_data_inv_port(decoder)) { print_verilog_wire_connection(fp, data_inv_port, data_port, true); } diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 289e4d667..eb070690d 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -128,6 +128,17 @@ void print_verilog_top_testbench_memory_bank_port(std::fstream& fp, BasicPort din_port = module_manager.module_port(top_module, din_port_id); fp << generate_verilog_port(VERILOG_PORT_REG, din_port) << ";" << std::endl; + /* Print the optional readback port for the decoder here */ + print_verilog_comment(fp, std::string("---- Readback port for memory decoders -----")); + ModulePortId readback_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_READBACK_PORT_NAME)); + if (readback_port_id) { + BasicPort readback_port = module_manager.module_port(top_module, readback_port_id); + fp << generate_verilog_port(VERILOG_PORT_WIRE, readback_port) << ";" << std::endl; + /* Disable readback in full testbenches */ + print_verilog_wire_constant_values(fp, readback_port, std::vector(readback_port.get_width(), 0)); + } + /* Generate enable signal waveform here: * which is a 90 degree phase shift than the programming clock */ From d36d1ebee25e01db8d89de5eba3a1a763d29f98f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 20 Sep 2021 17:07:51 -0700 Subject: [PATCH 043/229] [HDL] Temporarily disable WLR func in primitive HDL modeling --- openfpga_flow/openfpga_cell_library/verilog/sram.v | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openfpga_flow/openfpga_cell_library/verilog/sram.v b/openfpga_flow/openfpga_cell_library/verilog/sram.v index 7f70b9723..5f3c62852 100644 --- a/openfpga_flow/openfpga_cell_library/verilog/sram.v +++ b/openfpga_flow/openfpga_cell_library/verilog/sram.v @@ -274,9 +274,7 @@ module SRAM_RE( //----- when wl is enabled, we can read in data from bl always @(WE or RE or D) begin - if (1'b1 == RE) begin - data_readback <= Q; - end else if ((1'b1 == D)&&(1'b1 == WE)) begin + if ((1'b1 == D)&&(1'b1 == WE)) begin //----- Cases to program internal memory bit //----- case 1: bl = 1, wl = 1, a -> 0 data <= 1'b1; @@ -289,7 +287,6 @@ module SRAM_RE( // Wire q_reg to Q assign Q = data; assign QN = ~data; - assign D = RE ? data_readback : 1'b0; endmodule From 3146d2484ff7d50e4ee619be06afd03bb76b721e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 20 Sep 2021 17:21:33 -0700 Subject: [PATCH 044/229] [Doc] Update documentation on the WLR definition for circuit model --- .../manual/arch_lang/circuit_library.rst | 2 +- .../arch_lang/circuit_model_examples.rst | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/docs/source/manual/arch_lang/circuit_library.rst b/docs/source/manual/arch_lang/circuit_library.rst index c11a8c611..726d29c56 100644 --- a/docs/source/manual/arch_lang/circuit_library.rst +++ b/docs/source/manual/arch_lang/circuit_library.rst @@ -201,7 +201,7 @@ A circuit model may consist of a number of ports. The port list is mandatory in .. note:: Different types of ``circuit_model`` have different XML syntax, with which users can highly customize their circuit topologies. See refer to examples of :ref:``circuit_model_example`` for more details. -.. note:: Note that we have a list of reserved port names, which indicate the usage of these ports when building FPGA fabrics. Please do not use ``mem_out``, ``mem_inv``, ``bl``, ``wl``, ``blb``, ``wlb``, ``ccff_head`` and ``ccff_tail``. +.. note:: Note that we have a list of reserved port names, which indicate the usage of these ports when building FPGA fabrics. Please do not use ``mem_out``, ``mem_inv``, ``bl``, ``wl``, ``blb``, ``wlb``, ``wlr``, ``ccff_head`` and ``ccff_tail``. FPGA I/O Port ^^^^^^^^^^^^^ diff --git a/docs/source/manual/arch_lang/circuit_model_examples.rst b/docs/source/manual/arch_lang/circuit_model_examples.rst index 7113be1c0..acc94704c 100644 --- a/docs/source/manual/arch_lang/circuit_model_examples.rst +++ b/docs/source/manual/arch_lang/circuit_model_examples.rst @@ -333,6 +333,36 @@ The following XML codes describes the SRAM cell shown in :numref:`fig_sram_blwl` .. note:: When the ``memory_bank`` type of configuration procotol is specified, SRAM modules should have a BL and a WL. +.. _circuit_model_sram_blwlr_example: + +SRAM with BL/WL/WLR +``````````````````` +.. _fig_sram_blwlr: + +.. figure:: ./figures/sram_blwlr.png + :scale: 100% + + An example of a SRAM with Bit-Line (BL) and Word-Line (WL) control signals + +The following XML codes describes the SRAM cell shown in :numref:`fig_sram_blwlr`. + +.. code-block:: xml + + + + + + + + + + + + +.. note:: OpenFPGA always assume that a ``WL`` port should be the write enable signal, a ``WLR`` port should be the read enable signal, while a ``BL`` port is the data input. + +.. note:: When the ``memory_bank`` type of configuration procotol is specified, SRAM modules should have a BL and a WL. WLR is optional + .. _circuit_model_config_latch_example: Configurable Latch From d9d959709c1abc745eab8dae7df40bc2b4aea599 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 20 Sep 2021 20:31:53 -0700 Subject: [PATCH 045/229] [Doc] Add missing figures --- .../arch_lang/circuit_model_examples.rst | 4 +- .../manual/arch_lang/figures/sram_blwlr.svg | 213 ++++++++++++++++++ 2 files changed, 215 insertions(+), 2 deletions(-) create mode 100644 docs/source/manual/arch_lang/figures/sram_blwlr.svg diff --git a/docs/source/manual/arch_lang/circuit_model_examples.rst b/docs/source/manual/arch_lang/circuit_model_examples.rst index acc94704c..437cea837 100644 --- a/docs/source/manual/arch_lang/circuit_model_examples.rst +++ b/docs/source/manual/arch_lang/circuit_model_examples.rst @@ -339,10 +339,10 @@ SRAM with BL/WL/WLR ``````````````````` .. _fig_sram_blwlr: -.. figure:: ./figures/sram_blwlr.png +.. figure:: ./figures/sram_blwlr.svg :scale: 100% - An example of a SRAM with Bit-Line (BL) and Word-Line (WL) control signals + An example of a SRAM with Bit-Line (BL), Word-Line (WL) and WL read control signals The following XML codes describes the SRAM cell shown in :numref:`fig_sram_blwlr`. diff --git a/docs/source/manual/arch_lang/figures/sram_blwlr.svg b/docs/source/manual/arch_lang/figures/sram_blwlr.svg new file mode 100644 index 000000000..838dd54ed --- /dev/null +++ b/docs/source/manual/arch_lang/figures/sram_blwlr.svg @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + Produced by OmniGraffle 7.18.5\n2021-09-21 03:12:41 +0000 + + Canvas 1 + + Layer 1 + + + + + + WL + + + + + BL + + + + + + + + + + + + + + + + + SRAM + + + + + out + + + + + outb + + + + + BL + + + + + WL + + + + + + + + + + + + + + + + + + + + + WLR + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + outb + + + + + + + + + + + out + + + + + + + + + + + + + + + + + + + WLR + + + + + GND + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 7688c0570f47adeb7d215cbb716d38b0fca9df83 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Sep 2021 15:08:08 -0700 Subject: [PATCH 046/229] [Engine] Support coordinate definition in fabric key file format; Now QL memory bank can accept fabric key --- libopenfpga/libfabrickey/src/fabric_key.cpp | 20 +++++++++++++++++++ libopenfpga/libfabrickey/src/fabric_key.h | 12 +++++++++++ .../libfabrickey/src/read_xml_fabric_key.cpp | 13 ++++++++++++ .../libfabrickey/src/write_xml_fabric_key.cpp | 6 ++++++ .../src/fabric/build_top_module_memory.cpp | 3 ++- 5 files changed, 53 insertions(+), 1 deletion(-) diff --git a/libopenfpga/libfabrickey/src/fabric_key.cpp b/libopenfpga/libfabrickey/src/fabric_key.cpp index dfe445c75..d15c86e56 100644 --- a/libopenfpga/libfabrickey/src/fabric_key.cpp +++ b/libopenfpga/libfabrickey/src/fabric_key.cpp @@ -54,6 +54,12 @@ std::string FabricKey::key_alias(const FabricKeyId& key_id) const { return key_alias_[key_id]; } +vtr::Point FabricKey::key_coordinate(const FabricKeyId& key_id) const { + /* validate the key_id */ + VTR_ASSERT(valid_key_id(key_id)); + return key_coordinates_[key_id]; +} + bool FabricKey::empty() const { return 0 == key_ids_.size(); } @@ -124,6 +130,7 @@ void FabricKey::reserve_keys(const size_t& num_keys) { key_values_.reserve(num_keys); key_regions_.reserve(num_keys); key_alias_.reserve(num_keys); + key_coordinates_.reserve(num_keys); } FabricKeyId FabricKey::create_key() { @@ -134,6 +141,7 @@ FabricKeyId FabricKey::create_key() { key_values_.emplace_back(); key_regions_.emplace_back(FabricRegionId::INVALID()); key_alias_.emplace_back(); + key_coordinates_.emplace_back(vtr::Point(-1, -1)); return key; } @@ -162,6 +170,14 @@ void FabricKey::set_key_alias(const FabricKeyId& key_id, key_alias_[key_id] = alias; } +void FabricKey::set_key_coordinate(const FabricKeyId& key_id, + const vtr::Point& coord) { + /* validate the key_id */ + VTR_ASSERT(valid_key_id(key_id)); + + key_coordinates_[key_id] = coord; +} + /************************************************************************ * Internal invalidators/validators ***********************************************************************/ @@ -173,3 +189,7 @@ bool FabricKey::valid_region_id(const FabricRegionId& region_id) const { bool FabricKey::valid_key_id(const FabricKeyId& key_id) const { return ( size_t(key_id) < key_ids_.size() ) && ( key_id == key_ids_[key_id] ); } + +bool FabricKey::valid_key_coordinate(const vtr::Point& coord) const { + return coord.x() > -1 && coord.y() > -1; +} diff --git a/libopenfpga/libfabrickey/src/fabric_key.h b/libopenfpga/libfabrickey/src/fabric_key.h index 0ca1d252d..6e9025f9e 100644 --- a/libopenfpga/libfabrickey/src/fabric_key.h +++ b/libopenfpga/libfabrickey/src/fabric_key.h @@ -10,6 +10,7 @@ /* Headers from vtrutil library */ #include "vtr_vector.h" +#include "vtr_geometry.h" #include "fabric_key_fwd.h" @@ -58,6 +59,9 @@ class FabricKey { /* Access the alias of a key */ std::string key_alias(const FabricKeyId& key_id) const; + /* Access the coordinate of a key */ + vtr::Point key_coordinate(const FabricKeyId& key_id) const; + /* Check if there are any keys */ bool empty() const; @@ -93,9 +97,14 @@ class FabricKey { void set_key_alias(const FabricKeyId& key_id, const std::string& alias); + void set_key_coordinate(const FabricKeyId& key_id, + const vtr::Point& coord); + public: /* Public invalidators/validators */ bool valid_region_id(const FabricRegionId& region_id) const; bool valid_key_id(const FabricKeyId& key_id) const; + /* Identify if key coordinate is acceptable to fabric key convention */ + bool valid_key_coordinate(const vtr::Point& coord) const; private: /* Internal data */ /* Unique ids for each region */ vtr::vector region_ids_; @@ -112,6 +121,9 @@ class FabricKey { /* Values for each key */ vtr::vector key_values_; + /* Values for each key */ + vtr::vector> key_coordinates_; + /* Region for each key */ vtr::vector key_regions_; diff --git a/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp b/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp index 24e0d8255..b9e83787f 100644 --- a/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp +++ b/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp @@ -60,6 +60,19 @@ void read_xml_region_key(pugi::xml_node& xml_component_key, fabric_key.set_key_name(FabricKeyId(id), name); fabric_key.set_key_value(FabricKeyId(id), value); fabric_key.add_key_to_region(fabric_region, FabricKeyId(id)); + + /* Parse coordinates */ + vtr::Point coord; + coord.set_x(get_attribute(xml_component_key, "column", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1)); + coord.set_y(get_attribute(xml_component_key, "row", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1)); + /* Require positive coordinate all the time */ + if (!fabric_key.valid_key_coordinate(coord)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_component_key), + "Invalid coordinate '(%d, %d)' which contain negative numbers\n", + coord.x(), coord.y()); + } else { + fabric_key.set_key_coordinate(FabricKeyId(id), coord); + } } /******************************************************************** diff --git a/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp b/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp index ea12d75a1..aa38c8140 100644 --- a/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp +++ b/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp @@ -52,6 +52,12 @@ int write_xml_fabric_component_key(std::fstream& fp, write_xml_attribute(fp, "alias", fabric_key.key_alias(component_key).c_str()); } + vtr::Point coord = fabric_key.key_coordinate(component_key); + if (fabric_key.valid_key_coordinate(coord)) { + write_xml_attribute(fp, "column", coord.x()); + write_xml_attribute(fp, "row", coord.y()); + } + fp << "/>" << "\n"; return 0; diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index c9ee2b722..ca78f8e88 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -636,7 +636,8 @@ int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager /* Now we can add the child to configurable children of the top module */ module_manager.add_configurable_child(top_module, instance_info.first, - instance_info.second); + instance_info.second, + fabric_key.key_coordinate(key)); module_manager.add_configurable_child_to_region(top_module, top_module_config_region, instance_info.first, From dc2d1d1c3cd5139f666dea770dfddbe71caf94aa Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Sep 2021 15:42:20 -0700 Subject: [PATCH 047/229] [Test] Add a new test case to validate the correctness of fabric key file for ql memory bank --- .../config/task.conf | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/fabric_key/generate_random_key_ql_memory_bank/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/fabric_key/generate_random_key_ql_memory_bank/config/task.conf b/openfpga_flow/tasks/basic_tests/fabric_key/generate_random_key_ql_memory_bank/config/task.conf new file mode 100644 index 000000000..f7f308a77 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/fabric_key/generate_random_key_ql_memory_bank/config/task.conf @@ -0,0 +1,36 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 7327850cf3d54a7123396e6c734cf56430bc7297 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Sep 2021 15:43:54 -0700 Subject: [PATCH 048/229] [Test] Deploy the fabric key test case for ql memory bank to basic regression tests --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index 531ba5f42..ddb8317f9 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -84,6 +84,7 @@ echo -e "Testing Secured FPGA fabrics"; run-task basic_tests/fabric_key/generate_vanilla_key --debug --show_thread_logs run-task basic_tests/fabric_key/generate_multi_region_vanilla_key --debug --show_thread_logs run-task basic_tests/fabric_key/generate_random_key --debug --show_thread_logs +run-task basic_tests/fabric_key/generate_random_key_ql_memory_bank --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key_cc_fpga --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key_multi_region_cc_fpga --debug --show_thread_logs From b0a471bdc9f2b9677ac10bdd6d809fed01869e16 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Sep 2021 15:55:11 -0700 Subject: [PATCH 049/229] [Engine] Bug fix in outputting fabric key with coordinates --- openfpga/src/fabric/fabric_key_writer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openfpga/src/fabric/fabric_key_writer.cpp b/openfpga/src/fabric/fabric_key_writer.cpp index 63202ea90..c099d5468 100644 --- a/openfpga/src/fabric/fabric_key_writer.cpp +++ b/openfpga/src/fabric/fabric_key_writer.cpp @@ -70,6 +70,7 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager, for (size_t ichild = 0; ichild < module_manager.region_configurable_children(top_module, config_region).size(); ++ichild) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[ichild]; size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[ichild]; + vtr::Point child_coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[ichild]; FabricKeyId key = fabric_key.create_key(); fabric_key.set_key_name(key, module_manager.module_name(child_module)); @@ -79,6 +80,9 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager, fabric_key.set_key_alias(key, module_manager.instance_name(top_module, child_module, child_instance)); } + /* Add key coordinate */ + fabric_key.set_key_coordinate(key, child_coord); + /* Add keys to the region */ fabric_key.add_key_to_region(fabric_region, key); } From cd0d8b86fafb2460d2c09a46e7f38d663d5a7984 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Sep 2021 15:55:34 -0700 Subject: [PATCH 050/229] [Test] Add a random fabric key generated by OpenFPGA which is designed for QL memory bank --- .../k4_N4_1x1_qlbank_sample_key.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 openfpga_flow/fabric_keys/k4_N4_1x1_qlbank_sample_key.xml diff --git a/openfpga_flow/fabric_keys/k4_N4_1x1_qlbank_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_1x1_qlbank_sample_key.xml new file mode 100644 index 000000000..80621791d --- /dev/null +++ b/openfpga_flow/fabric_keys/k4_N4_1x1_qlbank_sample_key.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + From 141212154100a5a431ba3912f4063f9ddedf14bc Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Sep 2021 16:20:24 -0700 Subject: [PATCH 051/229] [Test] Added a new test to validate the fabric key parser for QL memory bank --- .../config/task.conf | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbank_fpga/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbank_fpga/config/task.conf b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbank_fpga/config/task.conf new file mode 100644 index 000000000..314c9c544 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbank_fpga/config/task.conf @@ -0,0 +1,39 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +external_fabric_key_file=${PATH:OPENFPGA_PATH}/openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml +openfpga_vpr_device_layout=2x2 + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= From aad47ffbc6ccd55d7d5760cddcf272fa52e34493 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Sep 2021 16:22:50 -0700 Subject: [PATCH 052/229] [Test] Upgrade the sample fabric key to ql memory bank for a 2x2 fabric --- .../k4_N4_1x1_qlbank_sample_key.xml | 19 --------- .../k4_N4_2x2_qlbank_sample_key.xml | 39 +++++++++++++++++++ 2 files changed, 39 insertions(+), 19 deletions(-) delete mode 100644 openfpga_flow/fabric_keys/k4_N4_1x1_qlbank_sample_key.xml create mode 100644 openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml diff --git a/openfpga_flow/fabric_keys/k4_N4_1x1_qlbank_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_1x1_qlbank_sample_key.xml deleted file mode 100644 index 80621791d..000000000 --- a/openfpga_flow/fabric_keys/k4_N4_1x1_qlbank_sample_key.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml new file mode 100644 index 000000000..e27f5d97f --- /dev/null +++ b/openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f57aceff877807e7084ffefb47a7769bf6db2f2c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Sep 2021 16:25:14 -0700 Subject: [PATCH 053/229] [Test] Deploy the load external key test case for ql memory bank to basic regression tests --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index ddb8317f9..c9fd5e378 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -88,7 +88,7 @@ run-task basic_tests/fabric_key/generate_random_key_ql_memory_bank --debug --sho run-task basic_tests/fabric_key/load_external_key --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key_cc_fpga --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key_multi_region_cc_fpga --debug --show_thread_logs - +run-task basic_tests/fabric_key/load_external_key_qlbank_fpga --debug --show_thread_logs echo -e "Testing K4 series FPGA"; echo -e "Testing K4N4 with facturable LUTs"; From ab42239b944f2ef291bf0512db92a712d5caba90 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Sep 2021 16:44:58 -0700 Subject: [PATCH 054/229] [Test] Bug fix in the fabric key --- openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml index e27f5d97f..1de56c747 100644 --- a/openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml +++ b/openfpga_flow/fabric_keys/k4_N4_2x2_qlbank_sample_key.xml @@ -33,7 +33,5 @@ - - From e09ab2298e296d3733bf86718219b3d83472008c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Sep 2021 16:45:14 -0700 Subject: [PATCH 055/229] [Engine] Bug fix in fabric key parser on identifying invalid coordinate --- libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp b/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp index b9e83787f..1c42b07bb 100644 --- a/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp +++ b/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp @@ -65,12 +65,7 @@ void read_xml_region_key(pugi::xml_node& xml_component_key, vtr::Point coord; coord.set_x(get_attribute(xml_component_key, "column", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1)); coord.set_y(get_attribute(xml_component_key, "row", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(-1)); - /* Require positive coordinate all the time */ - if (!fabric_key.valid_key_coordinate(coord)) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_component_key), - "Invalid coordinate '(%d, %d)' which contain negative numbers\n", - coord.x(), coord.y()); - } else { + if (fabric_key.valid_key_coordinate(coord)) { fabric_key.set_key_coordinate(FabricKeyId(id), coord); } } From 10774dc15c8dff2ae2f35344148389edd8a14784 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Sep 2021 17:01:52 -0700 Subject: [PATCH 056/229] [Doc] Updated documentation about new syntax in fabric key --- .../source/manual/file_formats/fabric_key.rst | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/docs/source/manual/file_formats/fabric_key.rst b/docs/source/manual/file_formats/fabric_key.rst index f87cf1b2e..185e1b40a 100644 --- a/docs/source/manual/file_formats/fabric_key.rst +++ b/docs/source/manual/file_formats/fabric_key.rst @@ -62,6 +62,14 @@ Each configurable block is defined as a key. There are two ways to define a key, - ``alias`` indicates the instance name of the configurable memory block in the top-level FPGA fabric. If a valid alias is specified, the ``name`` and ``value`` are not required. + - ``column`` indicates the relative x coordinate for a configurable memory in a configurable region at the top-level FPGA fabric. This is required when the memory bank protocol is selection. + + .. note:: The configurable memory blocks in the same column will share the same Bit Line (BL) bus + + - ``row`` indicates the relative y coordinate for a configurable memory in a configurable region at the top-level FPGA fabric. This is required when the memory bank protocol is selection. + + .. note:: The configurable memory blocks in the same row will share the same Word Line (WL) bus + .. warning:: For fast loading of fabric key, strongly recommend to use pairs ``name`` and ``alias`` or ``name`` and ``value`` in the fabric key file. Using only ``alias`` may cause long parsing time for fabric key. The following is an example of a fabric key generate by OpenFPGA for a 2 :math:`\times` 2 FPGA. @@ -149,3 +157,46 @@ This key contains only ``name`` and ``value`` which is fast to parse. + +The following shows another example of a fabric key generate by OpenFPGA for a 2 :math:`\times` 2 FPGA using memory bank. +This key contains only ``name``, ``value``, ``row`` and ``column``. + +.. code-block:: xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 51fc222d61c4a3425228f1aa131d7e72233d7070 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 10:01:33 -0700 Subject: [PATCH 057/229] [Test] Added a new test case for multi-region QL memory bank --- .../config/task.conf | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/full_testbench/multi_region_ql_memory_bank/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_ql_memory_bank/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_ql_memory_bank/config/task.conf new file mode 100644 index 000000000..9975aa59d --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_ql_memory_bank/config/task.conf @@ -0,0 +1,36 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +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/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_qlbank_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout=--device 2x2 +openfpga_fast_configuration= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From d0fe12faddf38c335ac22ad6c51266a5fa636021 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 10:03:39 -0700 Subject: [PATCH 058/229] [Arch] Add an example OpenFPGA architecture for 2-region QL memory bank --- ...4_N4_40nm_multi_region_qlbank_openfpga.xml | 198 ++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_qlbank_openfpga.xml diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_qlbank_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_qlbank_openfpga.xml new file mode 100644 index 000000000..6da1021c5 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_qlbank_openfpga.xml @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 7db7e2d8f69c31ab7907c7c5bbdd16c62b97861e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 10:05:27 -0700 Subject: [PATCH 059/229] [Test] Deploy the new test case for multi region QL memory bank to basic regression tests --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index c9fd5e378..9e008adc8 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -56,6 +56,7 @@ run-task basic_tests/preconfig_testbench/memory_bank --debug --show_thread_logs echo -e "Testing physical design friendly memory bank configuration protocol of a K4N4 FPGA"; run-task basic_tests/full_testbench/ql_memory_bank --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_use_wlr --debug --show_thread_logs +run-task basic_tests/full_testbench/multi_region_ql_memory_bank --debug --show_thread_logs echo -e "Testing testbenches without self checking features"; run-task basic_tests/full_testbench/full_testbench_without_self_checking --debug --show_thread_logs From ad432e4d95d0ccfe907dddbe82d24890df7d201a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 10:20:40 -0700 Subject: [PATCH 060/229] [Engine] Bug fix in finding the start index of BL/WL for each column/row; --- openfpga/src/utils/memory_bank_utils.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openfpga/src/utils/memory_bank_utils.cpp b/openfpga/src/utils/memory_bank_utils.cpp index a441813ad..66eb938f3 100644 --- a/openfpga/src/utils/memory_bank_utils.cpp +++ b/openfpga/src/utils/memory_bank_utils.cpp @@ -123,7 +123,12 @@ std::map compute_memory_bank_regional_blwl_start_index_per_tile(con if (iblwl == child_xy_range.first) { blwl_start_index_per_tile[iblwl] = 0; } else { - blwl_start_index_per_tile[iblwl] = num_blwls_per_tile.at(iblwl - 1) + blwl_start_index_per_tile[iblwl - 1]; + auto result = num_blwls_per_tile.find(iblwl - 1); + if (result == num_blwls_per_tile.end()) { + blwl_start_index_per_tile[iblwl] = blwl_start_index_per_tile[iblwl - 1]; + } else { + blwl_start_index_per_tile[iblwl] = result->second + blwl_start_index_per_tile[iblwl - 1]; + } } } return blwl_start_index_per_tile; From 962acda810d92b3a76d495a070a3795591a9ff80 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 11:09:46 -0700 Subject: [PATCH 061/229] [Engine] Bug fix in fabric key generation when computing configurable children --- openfpga/src/base/openfpga_build_fabric.cpp | 1 + openfpga/src/fabric/fabric_key_writer.cpp | 13 +++++++++-- openfpga/src/fabric/fabric_key_writer.h | 1 + .../fpga_bitstream/build_device_bitstream.cpp | 20 +++-------------- openfpga/src/utils/memory_utils.cpp | 22 +++++++++++++++++++ openfpga/src/utils/memory_utils.h | 9 ++++++++ 6 files changed, 47 insertions(+), 19 deletions(-) diff --git a/openfpga/src/base/openfpga_build_fabric.cpp b/openfpga/src/base/openfpga_build_fabric.cpp index 08e9ef4f8..2c3f491f9 100644 --- a/openfpga/src/base/openfpga_build_fabric.cpp +++ b/openfpga/src/base/openfpga_build_fabric.cpp @@ -132,6 +132,7 @@ int build_fabric(OpenfpgaContext& openfpga_ctx, VTR_ASSERT(false == fkey_fname.empty()); curr_status = write_fabric_key_to_xml_file(openfpga_ctx.module_graph(), fkey_fname, + openfpga_ctx.arch().config_protocol.type(), cmd_context.option_enable(cmd, opt_verbose)); /* If there is any error, final status cannot be overwritten by a success flag */ if (CMD_EXEC_SUCCESS != curr_status) { diff --git a/openfpga/src/fabric/fabric_key_writer.cpp b/openfpga/src/fabric/fabric_key_writer.cpp index c099d5468..d6bea0527 100644 --- a/openfpga/src/fabric/fabric_key_writer.cpp +++ b/openfpga/src/fabric/fabric_key_writer.cpp @@ -14,6 +14,8 @@ #include "openfpga_naming.h" +#include "memory_utils.h" + #include "fabric_key_writer.h" /* begin namespace openfpga */ @@ -29,6 +31,7 @@ namespace openfpga { ***************************************************************************************/ int write_fabric_key_to_xml_file(const ModuleManager& module_manager, const std::string& fname, + const e_config_protocol_type& config_protocol_type, const bool& verbose) { std::string timer_message = std::string("Write fabric key to XML file '") + fname + std::string("'"); @@ -65,9 +68,15 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager, /* Create regions for the keys and load keys by region */ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { FabricRegionId fabric_region = fabric_key.create_region(); - fabric_key.reserve_region_keys(fabric_region, module_manager.region_configurable_children(top_module, config_region).size()); + + /* Each configuration protocol has some child which should not be in the list. They are typically decoders */ + size_t curr_region_num_config_child = module_manager.region_configurable_children(top_module, config_region).size(); + size_t num_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol_type, curr_region_num_config_child); + curr_region_num_config_child -= num_child_to_skip; - for (size_t ichild = 0; ichild < module_manager.region_configurable_children(top_module, config_region).size(); ++ichild) { + fabric_key.reserve_region_keys(fabric_region, curr_region_num_config_child); + + for (size_t ichild = 0; ichild < curr_region_num_config_child; ++ichild) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[ichild]; size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[ichild]; vtr::Point child_coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[ichild]; diff --git a/openfpga/src/fabric/fabric_key_writer.h b/openfpga/src/fabric/fabric_key_writer.h index 68e6468b2..3062db15a 100644 --- a/openfpga/src/fabric/fabric_key_writer.h +++ b/openfpga/src/fabric/fabric_key_writer.h @@ -16,6 +16,7 @@ namespace openfpga { int write_fabric_key_to_xml_file(const ModuleManager& module_manager, const std::string& fname, + const e_config_protocol_type& config_protocol_type, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index 0af563914..1c81e2cb3 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -13,6 +13,7 @@ #include "openfpga_naming.h" +#include "memory_utils.h" #include "module_manager_utils.h" #include "build_grid_bitstream.h" @@ -84,23 +85,8 @@ size_t rec_estimate_device_bitstream_num_bits(const ModuleManager& module_manage if (parent_module == top_module) { for (const ConfigRegionId& config_region : module_manager.regions(parent_module)) { size_t curr_region_num_config_child = module_manager.region_configurable_children(parent_module, config_region).size(); - - /* Frame-based configuration protocol will have 1 decoder - * if there are more than 1 configurable children - */ - if ( (CONFIG_MEM_FRAME_BASED == config_protocol_type) - && (2 <= curr_region_num_config_child)) { - curr_region_num_config_child--; - } - - /* Memory configuration protocol will have 2 decoders - * at the top-level - */ - if (CONFIG_MEM_MEMORY_BANK == config_protocol_type - || CONFIG_MEM_QL_MEMORY_BANK == config_protocol_type) { - VTR_ASSERT(2 <= curr_region_num_config_child); - curr_region_num_config_child -= 2; - } + size_t num_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol_type, curr_region_num_config_child); + curr_region_num_config_child -= num_child_to_skip; /* Visit all the children in a recursively way */ for (size_t ichild = 0; ichild < curr_region_num_config_child; ++ichild) { diff --git a/openfpga/src/utils/memory_utils.cpp b/openfpga/src/utils/memory_utils.cpp index 8e2038b06..e5e44b99c 100644 --- a/openfpga/src/utils/memory_utils.cpp +++ b/openfpga/src/utils/memory_utils.cpp @@ -429,5 +429,27 @@ size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type, return sram_port_size; } +size_t estimate_num_configurable_children_to_skip_by_config_protocol(e_config_protocol_type config_protocol_type, + size_t curr_region_num_config_child) { + size_t num_child_to_skip = 0; + /* Frame-based configuration protocol will have 1 decoder + * if there are more than 1 configurable children + */ + if ( (CONFIG_MEM_FRAME_BASED == config_protocol_type) + && (2 <= curr_region_num_config_child)) { + num_child_to_skip = 1; + } + + /* Memory configuration protocol will have 2 decoders + * at the top-level + */ + if (CONFIG_MEM_MEMORY_BANK == config_protocol_type + || CONFIG_MEM_QL_MEMORY_BANK == config_protocol_type) { + VTR_ASSERT(2 <= curr_region_num_config_child); + num_child_to_skip = 2; + } + + return num_child_to_skip; +} } /* end namespace openfpga */ diff --git a/openfpga/src/utils/memory_utils.h b/openfpga/src/utils/memory_utils.h index 88eecf1f3..d34e5f0ce 100644 --- a/openfpga/src/utils/memory_utils.h +++ b/openfpga/src/utils/memory_utils.h @@ -40,6 +40,15 @@ size_t generate_sram_port_size(const e_config_protocol_type sram_orgz_type, size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type, const size_t& num_config_bits); +/** + * @brief Compute the number of configurable children to be skipped for a given configuration protocol + * For some configuration protocol, the decoders are not counted as configurable children + * (they are included in the list for bitstream generator usage) + * The number of decoders depends on the type of configuration protocol. + */ +size_t estimate_num_configurable_children_to_skip_by_config_protocol(e_config_protocol_type config_protocol_type, + size_t curr_region_num_config_child); + } /* end namespace openfpga */ #endif From 337ed33b689d38e6d7030e3f1205e4f30eebff73 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 11:25:16 -0700 Subject: [PATCH 062/229] [Test] Added a sample fabric key for 2-region QL memory bank --- ..._N4_2x2_multi_region_qlbank_sample_key.xml | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbank_sample_key.xml diff --git a/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbank_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbank_sample_key.xml new file mode 100644 index 000000000..94b3b6090 --- /dev/null +++ b/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbank_sample_key.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From abfa3803330a54c46703c69faacb4a601d1f5e13 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 11:27:09 -0700 Subject: [PATCH 063/229] [Test] Added a test case to validate the fabric key of 2-region QL memory bank --- .../config/task.conf | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga/config/task.conf b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga/config/task.conf new file mode 100644 index 000000000..9ec8f28f7 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga/config/task.conf @@ -0,0 +1,39 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_qlbank_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +external_fabric_key_file=${PATH:OPENFPGA_PATH}/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbank_sample_key.xml +openfpga_vpr_device_layout=auto + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= From efed2685850fbc14b2dacbb93af5e2df8b71de1b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 11:30:08 -0700 Subject: [PATCH 064/229] [Test] Deploy new test (for multi-region QL memory bank) to basic regression tests --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index 9e008adc8..ba0171d2e 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -90,6 +90,7 @@ run-task basic_tests/fabric_key/load_external_key --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key_cc_fpga --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key_multi_region_cc_fpga --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key_qlbank_fpga --debug --show_thread_logs +run-task basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga --debug --show_thread_logs echo -e "Testing K4 series FPGA"; echo -e "Testing K4N4 with facturable LUTs"; From b0aaab9c0373698a3491ac5d7d2e7fa4784469a5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 11:32:13 -0700 Subject: [PATCH 065/229] [Test] Bug fix due to mismatches in device layout between fabric key and VPR settings --- .../load_external_key_multi_region_qlbank_fpga/config/task.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga/config/task.conf b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga/config/task.conf index 9ec8f28f7..97a862f1b 100644 --- a/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga/config/task.conf @@ -20,7 +20,7 @@ openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scrip openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_qlbank_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml external_fabric_key_file=${PATH:OPENFPGA_PATH}/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbank_sample_key.xml -openfpga_vpr_device_layout=auto +openfpga_vpr_device_layout=2x2 [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From 212c5bd642249dae85f458fa1398318b23413c31 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 15:04:19 -0700 Subject: [PATCH 066/229] [Arch] Add an example architecture which uses flatten BL/WL for QL memory bank organization --- .../k4_N4_40nm_qlbankflatten_openfpga.xml | 201 ++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_openfpga.xml diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_openfpga.xml new file mode 100644 index 000000000..00cd1a519 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_openfpga.xml @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 3cfd5c3531c6a8941f21f3d25ebd60bbbe8b1710 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 15:04:59 -0700 Subject: [PATCH 067/229] [Arch] Added an example architecture which uses shift-registers to configure BL/WLs for QL memory banks --- .../k4_N4_40nm_qlbanksr_openfpga.xml | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml new file mode 100644 index 000000000..68c4921a2 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 53da5d49feeee01fd7cac32855ee43b2aad963be Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 15:48:14 -0700 Subject: [PATCH 068/229] [Arch] Correct XML syntax errors --- .../openfpga_arch/k4_N4_40nm_qlbankflatten_openfpga.xml | 2 +- openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_openfpga.xml index 00cd1a519..f5d450cac 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_openfpga.xml @@ -166,7 +166,7 @@ - + diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml index 68c4921a2..f91f65468 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml @@ -177,7 +177,7 @@ - + From a98df811ed216384a15df3edfab38e04cbf8ad7e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 15:50:47 -0700 Subject: [PATCH 069/229] [Arch] Bug fix: wrong circuit model name was used for CCFF --- openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml index f91f65468..3e04af1c3 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml @@ -178,8 +178,8 @@ - - + + From 655b195d8bda5f954124b46847cc273521c22c96 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 15:56:44 -0700 Subject: [PATCH 070/229] [Test] Added a test case to validate the correctness of QL memory bank where BL/WL are flatten on the top level --- .../ql_memory_bank_flatten/config/task.conf | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_flatten/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_flatten/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_flatten/config/task.conf new file mode 100644 index 000000000..1263c9211 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_flatten/config/task.conf @@ -0,0 +1,44 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +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/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +bench1_top = or2 +bench1_chan_width = 300 + +bench2_top = and2_latch +bench2_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 1ca1b0f3e92e2de9491762a4ac1bf8315cc7700b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 15:58:05 -0700 Subject: [PATCH 071/229] [Test] Deploy the new test case (flatten BL/WL for QL memory bank) to basic regression tests --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index ba0171d2e..cc74b9a4a 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -57,6 +57,7 @@ echo -e "Testing physical design friendly memory bank configuration protocol of run-task basic_tests/full_testbench/ql_memory_bank --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_use_wlr --debug --show_thread_logs run-task basic_tests/full_testbench/multi_region_ql_memory_bank --debug --show_thread_logs +run-task basic_tests/full_testbench/ql_memory_bank_flatten --debug --show_thread_logs echo -e "Testing testbenches without self checking features"; run-task basic_tests/full_testbench/full_testbench_without_self_checking --debug --show_thread_logs From d4e3445153db13606d3ee7b015c01f01a038bbbd Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 22 Sep 2021 17:32:45 -0700 Subject: [PATCH 072/229] [Engine] update internal data structure for new syntax in configuration protocol --- libopenfpga/libarchopenfpga/src/config_protocol.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libopenfpga/libarchopenfpga/src/config_protocol.h b/libopenfpga/libarchopenfpga/src/config_protocol.h index 550401098..034805c65 100644 --- a/libopenfpga/libarchopenfpga/src/config_protocol.h +++ b/libopenfpga/libarchopenfpga/src/config_protocol.h @@ -5,6 +5,15 @@ #include "circuit_types.h" #include "circuit_library_fwd.h" +/* Data type to define the protocol through which BL/WL can be manipulated */ +enum e_blwl_protocol_type { + BLWL_PROTOCOL_FLATTEN, + BLWL_PROTOCOL_DECODER, + BLWL_PROTOCOL_SHIFT_REGISTER, + NUM_BLWL_PROTOCOLS_TYPES +}; +constexpr std::array BLWL_PROTOCOL_TYPE_STRING = {{"flatten", "decoder", "shift_register"}}; + /******************************************************************** * A data structure to store configuration protocol information *******************************************************************/ From 6645b70ae3604c56510c602788d597fd0e57630e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 23 Sep 2021 14:25:25 -0700 Subject: [PATCH 073/229] [Engine] Upgrade parser to support BL/WL protocols --- .../libarchopenfpga/src/config_protocol.cpp | 73 ++++++++++++++++++ .../libarchopenfpga/src/config_protocol.h | 29 ++++++- .../src/openfpga_arch_linker.cpp | 23 ++++++ .../src/read_xml_config_protocol.cpp | 76 +++++++++++++++++++ 4 files changed, 200 insertions(+), 1 deletion(-) diff --git a/libopenfpga/libarchopenfpga/src/config_protocol.cpp b/libopenfpga/libarchopenfpga/src/config_protocol.cpp index 1499a4baf..948046493 100644 --- a/libopenfpga/libarchopenfpga/src/config_protocol.cpp +++ b/libopenfpga/libarchopenfpga/src/config_protocol.cpp @@ -1,4 +1,5 @@ #include "vtr_assert.h" +#include "vtr_log.h" #include "config_protocol.h" @@ -32,6 +33,30 @@ int ConfigProtocol::num_regions() const { return num_regions_; } +e_blwl_protocol_type ConfigProtocol::bl_protocol_type() const { + return bl_protocol_type_; +} + +std::string ConfigProtocol::bl_memory_model_name() const { + return bl_memory_model_name_; +} + +CircuitModelId ConfigProtocol::bl_memory_model() const { + return bl_memory_model_; +} + +e_blwl_protocol_type ConfigProtocol::wl_protocol_type() const { + return wl_protocol_type_; +} + +std::string ConfigProtocol::wl_memory_model_name() const { + return wl_memory_model_name_; +} + +CircuitModelId ConfigProtocol::wl_memory_model() const { + return wl_memory_model_; +} + /************************************************************************ * Public Mutators ***********************************************************************/ @@ -50,3 +75,51 @@ void ConfigProtocol::set_memory_model(const CircuitModelId& memory_model) { void ConfigProtocol::set_num_regions(const int& num_regions) { num_regions_ = num_regions; } + +void ConfigProtocol::set_bl_protocol_type(const e_blwl_protocol_type& type) { + if (CONFIG_MEM_QL_MEMORY_BANK != type_) { + VTR_LOG_ERROR("BL protocol type is only applicable for configuration protocol '%d'", CONFIG_PROTOCOL_TYPE_STRING[type_]); + return; + } + bl_protocol_type_ = type; +} + +void ConfigProtocol::set_bl_memory_model_name(const std::string& memory_model_name) { + if (BLWL_PROTOCOL_SHIFT_REGISTER != bl_protocol_type_) { + VTR_LOG_ERROR("BL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]); + return; + } + bl_memory_model_name_ = memory_model_name; +} + +void ConfigProtocol::set_bl_memory_model(const CircuitModelId& memory_model) { + if (BLWL_PROTOCOL_SHIFT_REGISTER != bl_protocol_type_) { + VTR_LOG_ERROR("BL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]); + return; + } + bl_memory_model_ = memory_model; +} + +void ConfigProtocol::set_wl_protocol_type(const e_blwl_protocol_type& type) { + if (CONFIG_MEM_QL_MEMORY_BANK != type_) { + VTR_LOG_ERROR("WL protocol type is only applicable for configuration protocol '%d'", CONFIG_PROTOCOL_TYPE_STRING[type_]); + return; + } + wl_protocol_type_ = type; +} + +void ConfigProtocol::set_wl_memory_model_name(const std::string& memory_model_name) { + if (BLWL_PROTOCOL_SHIFT_REGISTER != wl_protocol_type_) { + VTR_LOG_ERROR("WL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]); + return; + } + wl_memory_model_name_ = memory_model_name; +} + +void ConfigProtocol::set_wl_memory_model(const CircuitModelId& memory_model) { + if (BLWL_PROTOCOL_SHIFT_REGISTER != wl_protocol_type_) { + VTR_LOG_ERROR("WL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]); + return; + } + wl_memory_model_ = memory_model; +} diff --git a/libopenfpga/libarchopenfpga/src/config_protocol.h b/libopenfpga/libarchopenfpga/src/config_protocol.h index 034805c65..24de1ff47 100644 --- a/libopenfpga/libarchopenfpga/src/config_protocol.h +++ b/libopenfpga/libarchopenfpga/src/config_protocol.h @@ -10,7 +10,7 @@ enum e_blwl_protocol_type { BLWL_PROTOCOL_FLATTEN, BLWL_PROTOCOL_DECODER, BLWL_PROTOCOL_SHIFT_REGISTER, - NUM_BLWL_PROTOCOLS_TYPES + NUM_BLWL_PROTOCOL_TYPES }; constexpr std::array BLWL_PROTOCOL_TYPE_STRING = {{"flatten", "decoder", "shift_register"}}; @@ -25,11 +25,25 @@ class ConfigProtocol { std::string memory_model_name() const; CircuitModelId memory_model() const; int num_regions() const; + + e_blwl_protocol_type bl_protocol_type() const; + std::string bl_memory_model_name() const; + CircuitModelId bl_memory_model() const; + e_blwl_protocol_type wl_protocol_type() const; + std::string wl_memory_model_name() const; + CircuitModelId wl_memory_model() const; public: /* Public Mutators */ void set_type(const e_config_protocol_type& type); void set_memory_model_name(const std::string& memory_model_name); void set_memory_model(const CircuitModelId& memory_model); void set_num_regions(const int& num_regions); + + void set_bl_protocol_type(const e_blwl_protocol_type& type); + void set_bl_memory_model_name(const std::string& memory_model_name); + void set_bl_memory_model(const CircuitModelId& memory_model); + void set_wl_protocol_type(const e_blwl_protocol_type& type); + void set_wl_memory_model_name(const std::string& memory_model_name); + void set_wl_memory_model(const CircuitModelId& memory_model); private: /* Internal data */ /* The type of configuration protocol. * In other words, it is about how to organize and access each configurable memory @@ -42,6 +56,19 @@ class ConfigProtocol { /* Number of configurable regions */ int num_regions_; + + /* BL & WL protocol: This is only applicable to memory-bank configuration protocols + * - type: defines which protocol to be used. By default, we consider decoders + * - bl/wl_memory_model: defines the circuit model to be used when building shift register chains for BL/WL configuration. + * It must be a valid CCFF circuit model. This is only applicable when shift-register protocol is selected + * for BL or WL. + */ + e_blwl_protocol_type bl_protocol_type_ = BLWL_PROTOCOL_DECODER; + std::string bl_memory_model_name_; + CircuitModelId bl_memory_model_; + e_blwl_protocol_type wl_protocol_type_ = BLWL_PROTOCOL_DECODER; + std::string wl_memory_model_name_; + CircuitModelId wl_memory_model_; }; #endif diff --git a/libopenfpga/libarchopenfpga/src/openfpga_arch_linker.cpp b/libopenfpga/libarchopenfpga/src/openfpga_arch_linker.cpp index eab105ec3..33009f537 100644 --- a/libopenfpga/libarchopenfpga/src/openfpga_arch_linker.cpp +++ b/libopenfpga/libarchopenfpga/src/openfpga_arch_linker.cpp @@ -22,6 +22,29 @@ void link_config_protocol_to_circuit_library(openfpga::Arch& openfpga_arch) { } openfpga_arch.config_protocol.set_memory_model(config_memory_model); + + /* Optional: we need to bind the memory model for BL/WL protocols */ + if (!openfpga_arch.config_protocol.bl_memory_model_name().empty()) { + CircuitModelId bl_memory_model = openfpga_arch.circuit_lib.model(openfpga_arch.config_protocol.bl_memory_model_name()); + /* Error out if the circuit model id is invalid */ + if (CircuitModelId::INVALID() == bl_memory_model) { + VTR_LOG("Invalid bl memory model name '%s' defined in !", + openfpga_arch.config_protocol.bl_memory_model_name().c_str()); + exit(1); + } + openfpga_arch.config_protocol.set_bl_memory_model(bl_memory_model); + } + + if (!openfpga_arch.config_protocol.wl_memory_model_name().empty()) { + CircuitModelId wl_memory_model = openfpga_arch.circuit_lib.model(openfpga_arch.config_protocol.wl_memory_model_name()); + /* Error out if the circuit model id is invalid */ + if (CircuitModelId::INVALID() == wl_memory_model) { + VTR_LOG("Invalid wl memory model name '%s' defined in !", + openfpga_arch.config_protocol.wl_memory_model_name().c_str()); + exit(1); + } + openfpga_arch.config_protocol.set_wl_memory_model(wl_memory_model); + } } /******************************************************************** diff --git a/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp b/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp index 1cbbb40c0..44edcbfc0 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -33,6 +33,73 @@ e_config_protocol_type string_to_config_protocol_type(const std::string& type_st return NUM_CONFIG_PROTOCOL_TYPES; } +/******************************************************************** + * Convert string to the enumerate of BL/WL protocol type + *******************************************************************/ +static +e_blwl_protocol_type string_to_blwl_protocol_type(const std::string& type_string) { + + for (size_t itype = 0; itype < NUM_BLWL_PROTOCOL_TYPES; ++itype) { + if (std::string(BLWL_PROTOCOL_TYPE_STRING[itype]) == type_string) { + return static_cast(itype); + } + } + + return NUM_BLWL_PROTOCOL_TYPES; +} + +/******************************************************************** + * Parse XML codes of a to an object of configuration protocol + *******************************************************************/ +static +void read_xml_bl_protocol(pugi::xml_node& xml_bl_protocol, + const pugiutil::loc_data& loc_data, + ConfigProtocol& config_protocol) { + /* Find the type of configuration protocol */ + const char* type_attr = get_attribute(xml_bl_protocol, "protocol", loc_data).value(); + /* Translate the type of design technology to enumerate */ + e_blwl_protocol_type blwl_protocol_type = string_to_blwl_protocol_type(std::string(type_attr)); + + if (NUM_BLWL_PROTOCOL_TYPES == blwl_protocol_type) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bl_protocol), + "Invalid 'protocol' attribute '%s'\n", + type_attr); + } + + config_protocol.set_bl_protocol_type(blwl_protocol_type); + + /* Find the memory model, only applicable to shift-registor protocol */ + if (BLWL_PROTOCOL_SHIFT_REGISTER == blwl_protocol_type) { + config_protocol.set_bl_memory_model_name(get_attribute(xml_bl_protocol, "circuit_model_name", loc_data).as_string()); + } +} + +/******************************************************************** + * Parse XML codes of a to an object of configuration protocol + *******************************************************************/ +static +void read_xml_wl_protocol(pugi::xml_node& xml_wl_protocol, + const pugiutil::loc_data& loc_data, + ConfigProtocol& config_protocol) { + /* Find the type of configuration protocol */ + const char* type_attr = get_attribute(xml_wl_protocol, "protocol", loc_data).value(); + /* Translate the type of design technology to enumerate */ + e_blwl_protocol_type blwl_protocol_type = string_to_blwl_protocol_type(std::string(type_attr)); + + if (NUM_BLWL_PROTOCOL_TYPES == blwl_protocol_type) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_wl_protocol), + "Invalid 'protocol' attribute '%s'\n", + type_attr); + } + + config_protocol.set_wl_protocol_type(blwl_protocol_type); + + /* Find the memory model, only applicable to shift-registor protocol */ + if (BLWL_PROTOCOL_SHIFT_REGISTER == blwl_protocol_type) { + config_protocol.set_wl_memory_model_name(get_attribute(xml_wl_protocol, "circuit_model_name", loc_data).as_string()); + } +} + /******************************************************************** * Parse XML codes of a to an object of configuration protocol *******************************************************************/ @@ -65,6 +132,15 @@ void read_xml_config_organization(pugi::xml_node& xml_config_orgz, "Invalid 'num_region=%d' definition. At least 1 region should be defined!\n", config_protocol.num_regions()); } + + /* Parse BL & WL protocols */ + if (config_protocol.type() == CONFIG_MEM_QL_MEMORY_BANK) { + pugi::xml_node xml_bl_protocol = get_single_child(xml_config_orgz, "bl", loc_data); + read_xml_bl_protocol(xml_bl_protocol, loc_data, config_protocol); + + pugi::xml_node xml_wl_protocol = get_single_child(xml_config_orgz, "wl", loc_data); + read_xml_wl_protocol(xml_wl_protocol, loc_data, config_protocol); + } } /******************************************************************** From 8c281a22b09a8ab2ef410147acc4afb727420a74 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 23 Sep 2021 14:39:16 -0700 Subject: [PATCH 074/229] [Engine] Add check codes to validate circuit models for BL/WL protocols --- openfpga/src/base/openfpga_read_arch.cpp | 5 +-- openfpga/src/utils/circuit_library_utils.cpp | 42 ++++++++++++++++---- openfpga/src/utils/circuit_library_utils.h | 7 ++-- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/openfpga/src/base/openfpga_read_arch.cpp b/openfpga/src/base/openfpga_read_arch.cpp index 25bfc3831..56d96f740 100644 --- a/openfpga/src/base/openfpga_read_arch.cpp +++ b/openfpga/src/base/openfpga_read_arch.cpp @@ -56,9 +56,8 @@ int read_arch(OpenfpgaContext& openfpga_context, return CMD_EXEC_FATAL_ERROR; } - if (false == check_configurable_memory_circuit_model(openfpga_context.arch().config_protocol.type(), - openfpga_context.arch().circuit_lib, - openfpga_context.arch().config_protocol.memory_model())) { + if (false == check_configurable_memory_circuit_model(openfpga_context.arch().config_protocol, + openfpga_context.arch().circuit_lib)) { return CMD_EXEC_FATAL_ERROR; } diff --git a/openfpga/src/utils/circuit_library_utils.cpp b/openfpga/src/utils/circuit_library_utils.cpp index fabdc05da..bb59a0601 100644 --- a/openfpga/src/utils/circuit_library_utils.cpp +++ b/openfpga/src/utils/circuit_library_utils.cpp @@ -280,22 +280,50 @@ std::vector find_circuit_library_unique_spice_netlists(const Circui * Advanced check if the circuit model of configurable memory * satisfy the needs of configuration protocol * - Configuration chain -based: we check if we have a CCFF model - * - Frame -based: we check if we have a SRAM model which has BL and WL - * + * - Flatten/Frame -based: we check if we have a SRAM model which has BL and WL + * - Memory bank: we check if we have a SRAM model. Also we need to check if we have valid CCFF models for BL/WL models (if selected) ***********************************************************************/ -bool check_configurable_memory_circuit_model(const e_config_protocol_type& config_protocol_type, - const CircuitLibrary& circuit_lib, - const CircuitModelId& config_mem_circuit_model) { +bool check_configurable_memory_circuit_model(const ConfigProtocol& config_protocol, + const CircuitLibrary& circuit_lib) { size_t num_err = 0; + CircuitModelId config_mem_circuit_model = config_protocol.memory_model(); - switch (config_protocol_type) { + switch (config_protocol.type()) { case CONFIG_MEM_SCAN_CHAIN: num_err = check_ccff_circuit_model_ports(circuit_lib, config_mem_circuit_model); break; + case CONFIG_MEM_QL_MEMORY_BANK: { + num_err = check_sram_circuit_model_ports(circuit_lib, + config_mem_circuit_model, + true); + /* Check circuit model for BL protocol */ + CircuitModelId bl_memory_model = config_protocol.bl_memory_model(); + if ( BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type() + && CircuitModelId::INVALID() == bl_memory_model) { + VTR_LOG_ERROR("Expect a valid CCFF circuit model for BL protocol"); + num_err++; + } + if (bl_memory_model) { + num_err += check_ccff_circuit_model_ports(circuit_lib, + bl_memory_model); + } + + /* Check circuit model for WL protocol */ + CircuitModelId wl_memory_model = config_protocol.wl_memory_model(); + if ( BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type() + && CircuitModelId::INVALID() == wl_memory_model) { + VTR_LOG_ERROR("Expect a valid CCFF circuit model for WL protocol"); + num_err++; + } + if (wl_memory_model) { + num_err += check_ccff_circuit_model_ports(circuit_lib, + wl_memory_model); + } + break; + } case CONFIG_MEM_STANDALONE: case CONFIG_MEM_MEMORY_BANK: - case CONFIG_MEM_QL_MEMORY_BANK: case CONFIG_MEM_FRAME_BASED: num_err = check_sram_circuit_model_ports(circuit_lib, config_mem_circuit_model, diff --git a/openfpga/src/utils/circuit_library_utils.h b/openfpga/src/utils/circuit_library_utils.h index 758af9689..fe5fb03f7 100644 --- a/openfpga/src/utils/circuit_library_utils.h +++ b/openfpga/src/utils/circuit_library_utils.h @@ -8,8 +8,8 @@ * Include header files that are required by function declaration *******************************************************************/ #include -#include "circuit_types.h" #include "circuit_library.h" +#include "config_protocol.h" /******************************************************************** * Function declaration @@ -41,9 +41,8 @@ std::vector find_circuit_library_unique_verilog_netlists(const Circ std::vector find_circuit_library_unique_spice_netlists(const CircuitLibrary& circuit_lib); -bool check_configurable_memory_circuit_model(const e_config_protocol_type& config_protocol_type, - const CircuitLibrary& circuit_lib, - const CircuitModelId& config_mem_circuit_model); +bool check_configurable_memory_circuit_model(const ConfigProtocol& config_protocol, + const CircuitLibrary& circuit_lib); CircuitPortId find_circuit_model_power_gate_en_port(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); From 7e27c0caf3945b86b69893567755118a7f47b714 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 23 Sep 2021 16:16:39 -0700 Subject: [PATCH 075/229] [Engine] Upgrading top-module fabric generation to support QL memory bank with flatten BL/WLs --- .../src/fabric/build_top_module_memory.cpp | 30 +---- .../fabric/build_top_module_memory_bank.cpp | 113 ++++++++++++++++++ .../src/fabric/build_top_module_memory_bank.h | 8 ++ 3 files changed, 122 insertions(+), 29 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index ca78f8e88..7c2252883 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -852,35 +852,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, break; } case CONFIG_MEM_QL_MEMORY_BANK: { - BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); - module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); - - /* BL address size is the largest among all the regions */ - size_t bl_addr_size = 0; - for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - bl_addr_size = std::max(bl_addr_size, find_mux_local_decoder_addr_size(num_config_bits[config_region].first)); - } - BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), bl_addr_size); - module_manager.add_port(module_id, bl_addr_port, ModuleManager::MODULE_INPUT_PORT); - - /* WL address size is the largest among all the regions */ - size_t wl_addr_size = 0; - for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - wl_addr_size = std::max(wl_addr_size, find_mux_local_decoder_addr_size(num_config_bits[config_region].second)); - } - BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); - module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); - - /* Optional: If we have WLR port, we should add a read-back port */ - if (!circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR).empty()) { - BasicPort readback_port(std::string(DECODER_READBACK_PORT_NAME), config_protocol.num_regions()); - module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT); - } - - /* Data input should be dependent on the number of configuration regions*/ - BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), config_protocol.num_regions()); - module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); - + add_top_module_ql_memory_bank_sram_ports(module_manager, module_id, circuit_lib, config_protocol, num_config_bits); break; } case CONFIG_MEM_SCAN_CHAIN: { diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 7c60a03d8..723d102d5 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -474,4 +474,117 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma } } +/******************************************************************** + * Add a list of ports that are used for SRAM configuration to the FPGA + * top-level module + * - Add ports for BL control circuitry: + * - Decoder + * - an enable signals + * - an BL address port + * - a data-in port + * - Flatten + * - BL ports + * - TODO: Shift registers + * - Head of shift register chain for BLs + * - Tail of shift register chain for BLs + * + * - Add ports for WL control circuitry: + * - Decoder + * - an WL address port + * - a Readback port (Optional, only needed when WLR is required) + * - Flatten + * - WL ports + * - WLR ports (Optional) + * - TODO: Shift registers + * - Head of shift register chain for WLs + * - Tail of shift register chain for WLs + * - a Readback port (Optional, only needed when WLR is required) + * + * @note In this memory decoders, the address size will be computed in a different way than the regular one + ********************************************************************/ +void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, + const ModuleId& module_id, + const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol, + const TopModuleNumConfigBits& num_config_bits) { + VTR_ASSERT_SAFE(CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()); + CircuitModelId sram_model = config_protocol.memory_model(); + + switch (config_protocol.bl_protocol_type()) { + case BLWL_PROTOCOL_DECODER: { + /* Add enable signals */ + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); + + /* BL address size is the largest among all the regions */ + size_t bl_addr_size = 0; + for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + bl_addr_size = std::max(bl_addr_size, find_mux_local_decoder_addr_size(num_config_bits[config_region].first)); + } + BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), bl_addr_size); + module_manager.add_port(module_id, bl_addr_port, ModuleManager::MODULE_INPUT_PORT); + + /* Data input should be dependent on the number of configuration regions*/ + BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), config_protocol.num_regions()); + module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); + break; + } + case BLWL_PROTOCOL_FLATTEN: { + /* BL size is the largest among all the regions */ + size_t bl_size = 0; + for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + bl_size = std::max(bl_size, num_config_bits[config_region].first); + } + BasicPort bl_port(std::string(MEMORY_BL_PORT_NAME), bl_size); + module_manager.add_port(module_id, bl_port, ModuleManager::MODULE_INPUT_PORT); + break; + } + case BLWL_PROTOCOL_SHIFT_REGISTER: { + /* TODO */ + break; + } + default: { + VTR_LOG_ERROR("Invalid BL protocol"); + exit(1); + } + } + + switch (config_protocol.wl_protocol_type()) { + case BLWL_PROTOCOL_DECODER: { + /* WL address size is the largest among all the regions */ + size_t wl_addr_size = 0; + for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + wl_addr_size = std::max(wl_addr_size, find_mux_local_decoder_addr_size(num_config_bits[config_region].second)); + } + BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); + module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); + + /* Optional: If we have WLR port, we should add a read-back port */ + if (!circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR).empty()) { + BasicPort readback_port(std::string(DECODER_READBACK_PORT_NAME), config_protocol.num_regions()); + module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT); + } + break; + } + case BLWL_PROTOCOL_FLATTEN: { + /* WL size is the largest among all the regions */ + size_t wl_size = 0; + for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + wl_size = std::max(wl_size, num_config_bits[config_region].first); + } + BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), wl_size); + module_manager.add_port(module_id, wl_port, ModuleManager::MODULE_INPUT_PORT); + break; + } + case BLWL_PROTOCOL_SHIFT_REGISTER: { + /* TODO */ + break; + } + default: { + VTR_LOG_ERROR("Invalid WL protocol"); + exit(1); + } + } +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_memory_bank.h b/openfpga/src/fabric/build_top_module_memory_bank.h index 69f4408ef..50e9567c9 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.h +++ b/openfpga/src/fabric/build_top_module_memory_bank.h @@ -10,6 +10,7 @@ #include "vtr_vector.h" #include "vtr_ndmatrix.h" #include "module_manager.h" +#include "config_protocol.h" #include "circuit_library.h" #include "decoder_library.h" #include "build_top_module_memory_utils.h" @@ -28,6 +29,13 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma const CircuitModelId& sram_model, const TopModuleNumConfigBits& num_config_bits); +void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, + const ModuleId& module_id, + const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol, + const TopModuleNumConfigBits& num_config_bits); + + } /* end namespace openfpga */ #endif From 18257b3fa1e3c9a859c59d0f8366bff149865f3f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Sep 2021 11:07:58 -0700 Subject: [PATCH 076/229] [Engine] Update BL/WL port addition for the top-level module in fabric generator --- openfpga/src/base/openfpga_naming.cpp | 9 +++++++++ openfpga/src/base/openfpga_naming.h | 4 ++++ .../fabric/build_top_module_memory_bank.cpp | 18 ++++++++---------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index 3dab1ca7f..c3fdd3aa8 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -813,6 +813,15 @@ std::string generate_sram_local_port_name(const CircuitLibrary& circuit_lib, return port_name; } +/********************************************************************* + * Generate the BL/WL port names for the top-level module of an FPGA fabric + * Each BL/WL bus drive a specific configuration region has an unique name + *********************************************************************/ +std::string generate_regional_blwl_port_name(const std::string& blwl_port_prefix, + const ConfigRegionId& region_id) { + return blwl_port_prefix + std::string("_config_region_") + std::to_string(size_t(region_id)); +} + /********************************************************************* * Generate the port name for the input bus of a routing multiplexer * This is very useful in Verilog code generation where the inputs of diff --git a/openfpga/src/base/openfpga_naming.h b/openfpga/src/base/openfpga_naming.h index 319e99a60..77a46e4a6 100644 --- a/openfpga/src/base/openfpga_naming.h +++ b/openfpga/src/base/openfpga_naming.h @@ -16,6 +16,7 @@ #include "circuit_library.h" #include "device_grid.h" #include "openfpga_port.h" +#include "module_manager_fwd.h" /******************************************************************** * Function declaration @@ -183,6 +184,9 @@ std::string generate_sram_local_port_name(const CircuitLibrary& circuit_lib, const e_config_protocol_type& sram_orgz_type, const e_circuit_model_port_type& port_type); +std::string generate_regional_blwl_port_name(const std::string& blwl_port_prefix, + const ConfigRegionId& region_id); + std::string generate_mux_input_bus_port_name(const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, const size_t& mux_size, diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 723d102d5..b5bd39b6f 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -530,13 +530,12 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, break; } case BLWL_PROTOCOL_FLATTEN: { - /* BL size is the largest among all the regions */ - size_t bl_size = 0; + /* Each region will have independent BLs */ for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - bl_size = std::max(bl_size, num_config_bits[config_region].first); + size_t bl_size = num_config_bits[config_region].first; + BasicPort bl_port(generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), config_region), bl_size); + module_manager.add_port(module_id, bl_port, ModuleManager::MODULE_INPUT_PORT); } - BasicPort bl_port(std::string(MEMORY_BL_PORT_NAME), bl_size); - module_manager.add_port(module_id, bl_port, ModuleManager::MODULE_INPUT_PORT); break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { @@ -567,13 +566,12 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, break; } case BLWL_PROTOCOL_FLATTEN: { - /* WL size is the largest among all the regions */ - size_t wl_size = 0; + /* Each region will have independent WLs */ for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - wl_size = std::max(wl_size, num_config_bits[config_region].first); + size_t wl_size = num_config_bits[config_region].first; + BasicPort wl_port(generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region), wl_size); + module_manager.add_port(module_id, wl_port, ModuleManager::MODULE_INPUT_PORT); } - BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), wl_size); - module_manager.add_port(module_id, wl_port, ModuleManager::MODULE_INPUT_PORT); break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { From be4c850d2d5f42d607aa79b96c310115afe1fe21 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Sep 2021 12:03:35 -0700 Subject: [PATCH 077/229] [Engine] Split the function to add BL/WL configuration bus connections for support flatten BL/WLs --- .../src/read_xml_config_protocol.cpp | 12 +- openfpga/src/fabric/build_top_module.cpp | 2 +- .../src/fabric/build_top_module_memory.cpp | 5 +- openfpga/src/fabric/build_top_module_memory.h | 1 - .../fabric/build_top_module_memory_bank.cpp | 312 ++++++++++++------ .../src/fabric/build_top_module_memory_bank.h | 2 +- 6 files changed, 219 insertions(+), 115 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp b/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp index 44edcbfc0..ebfe64782 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -135,11 +135,15 @@ void read_xml_config_organization(pugi::xml_node& xml_config_orgz, /* Parse BL & WL protocols */ if (config_protocol.type() == CONFIG_MEM_QL_MEMORY_BANK) { - pugi::xml_node xml_bl_protocol = get_single_child(xml_config_orgz, "bl", loc_data); - read_xml_bl_protocol(xml_bl_protocol, loc_data, config_protocol); + pugi::xml_node xml_bl_protocol = get_single_child(xml_config_orgz, "bl", loc_data, pugiutil::ReqOpt::OPTIONAL); + if (xml_bl_protocol) { + read_xml_bl_protocol(xml_bl_protocol, loc_data, config_protocol); + } - pugi::xml_node xml_wl_protocol = get_single_child(xml_config_orgz, "wl", loc_data); - read_xml_wl_protocol(xml_wl_protocol, loc_data, config_protocol); + pugi::xml_node xml_wl_protocol = get_single_child(xml_config_orgz, "wl", loc_data, pugiutil::ReqOpt::OPTIONAL); + if (xml_wl_protocol) { + read_xml_wl_protocol(xml_wl_protocol, loc_data, config_protocol); + } } } diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index add2ea30b..421b7198a 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -422,7 +422,7 @@ int build_top_module(ModuleManager& module_manager, if (0 < module_manager.configurable_children(top_module).size()) { add_top_module_nets_memory_config_bus(module_manager, decoder_lib, top_module, - circuit_lib, sram_model, + circuit_lib, config_protocol, circuit_lib.design_tech_type(sram_model), top_module_num_config_bits); } diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 7c2252883..42debe24f 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -1737,7 +1737,6 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, const TopModuleNumConfigBits& num_config_bits) { switch (config_protocol.type()) { @@ -1755,7 +1754,7 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, add_top_module_nets_cmos_memory_bank_config_bus(module_manager, decoder_lib, parent_module, num_config_bits); break; case CONFIG_MEM_QL_MEMORY_BANK: - add_top_module_nets_cmos_ql_memory_bank_config_bus(module_manager, decoder_lib, parent_module, circuit_lib, sram_model, num_config_bits); + add_top_module_nets_cmos_ql_memory_bank_config_bus(module_manager, decoder_lib, parent_module, circuit_lib, config_protocol, num_config_bits); break; case CONFIG_MEM_FRAME_BASED: add_top_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, parent_module, num_config_bits); @@ -1803,7 +1802,6 @@ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, const e_circuit_model_design_tech& mem_tech, const TopModuleNumConfigBits& num_config_bits) { @@ -1815,7 +1813,6 @@ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, add_top_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, parent_module, circuit_lib, - sram_model, config_protocol, num_config_bits); break; diff --git a/openfpga/src/fabric/build_top_module_memory.h b/openfpga/src/fabric/build_top_module_memory.h index 336125df0..7b6f9aa10 100644 --- a/openfpga/src/fabric/build_top_module_memory.h +++ b/openfpga/src/fabric/build_top_module_memory.h @@ -66,7 +66,6 @@ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const ModuleId& parent_module, const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, const e_circuit_model_design_tech& mem_tech, const TopModuleNumConfigBits& num_config_bits); diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index b5bd39b6f..a974fc736 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -31,13 +31,15 @@ namespace openfpga { /********************************************************************* - * Top-level function to add nets for quicklogic memory banks + * This function to add nets for quicklogic memory banks * Each configuration region has independent memory bank circuitry * - Find the number of BLs and WLs required for each region * - Create BL and WL decoders, and add them to decoder library * - Create nets to connect from top-level module inputs to inputs of decoders * - Create nets to connect from outputs of decoders to BL/WL of configurable children * + * @note this function only adds the BL configuration bus for decoders + * * Detailed schematic of how memory banks are connected in the top-level: * Consider a random Region X, local BL address lines are aligned to the LSB of the * top-level BL address lines @@ -120,12 +122,13 @@ namespace openfpga { * +---------+ * **********************************************************************/ -void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_manager, - DecoderLibrary& decoder_lib, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, - const TopModuleNumConfigBits& num_config_bits) { +static +void add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const TopModuleNumConfigBits& num_config_bits) { /* Find Enable port from the top-level module */ ModulePortId en_port = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort en_port_info = module_manager.module_port(top_module, en_port); @@ -137,26 +140,12 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma /* Data in port should match the number of configuration regions */ VTR_ASSERT(din_port_info.get_width() == module_manager.regions(top_module).size()); - /* Find readback port from the top-level module */ - ModulePortId readback_port = module_manager.find_module_port(top_module, std::string(DECODER_READBACK_PORT_NAME)); - BasicPort readback_port_info; - - /* Readback port if available, should be a 1-bit port */ - if (readback_port) { - readback_port_info = module_manager.module_port(top_module, readback_port); - VTR_ASSERT(readback_port_info.get_width() == 1); - } - /* Find BL and WL address port from the top-level module */ ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port); - ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); - BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port); - /* Find the top-level number of BLs and WLs required to access each memory bit */ size_t bl_addr_size = bl_addr_port_info.get_width(); - size_t wl_addr_size = wl_addr_port_info.get_width(); /* Each memory bank has a unified number of BL/WLs */ size_t num_bls = 0; @@ -164,11 +153,6 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma num_bls = std::max(num_bls, curr_config_bits.first); } - size_t num_wls = 0; - for (const auto& curr_config_bits : num_config_bits) { - num_wls = std::max(num_wls, curr_config_bits.second); - } - /* Create separated memory bank circuitry, i.e., BL/WL decoders for each region */ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { /************************************************************** @@ -199,34 +183,6 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma size_t curr_bl_decoder_instance_id = module_manager.num_instance(top_module, bl_decoder_module); module_manager.add_child_module(top_module, bl_decoder_module); - /************************************************************** - * Add the WL decoder module - * Search the decoder library - * If we find one, we use the module. - * Otherwise, we create one and add it to the decoder library - */ - DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls, - true, false, false, readback_port != ModulePortId::INVALID()); - if (DecoderId::INVALID() == wl_decoder_id) { - wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false, readback_port != ModulePortId::INVALID()); - } - VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id); - - /* Create a module if not existed yet */ - std::string wl_decoder_module_name = generate_memory_decoder_subckt_name(wl_addr_size, num_wls); - ModuleId wl_decoder_module = module_manager.find_module(wl_decoder_module_name); - if (ModuleId::INVALID() == wl_decoder_module) { - /* BL decoder has the same ports as the frame-based decoders - * We reuse it here - */ - wl_decoder_module = build_wl_memory_decoder_module(module_manager, - decoder_lib, - wl_decoder_id); - } - VTR_ASSERT(ModuleId::INVALID() != wl_decoder_module); - size_t curr_wl_decoder_instance_id = module_manager.num_instance(top_module, wl_decoder_module); - module_manager.add_child_module(top_module, wl_decoder_module); - /************************************************************** * Add module nets from the top module to BL decoder's inputs */ @@ -267,57 +223,15 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma /* Configure the net sink */ module_manager.add_module_net_sink(top_module, din_net, bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_din_port, bl_decoder_din_port_info.pins()[0]); - /************************************************************** - * Add module nets from the top module to WL decoder's inputs - */ - ModulePortId wl_decoder_en_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); - BasicPort wl_decoder_en_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_en_port); - - ModulePortId wl_decoder_addr_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); - BasicPort wl_decoder_addr_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_addr_port); - - ModulePortId wl_decoder_readback_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_READBACK_PORT_NAME)); - BasicPort wl_decoder_readback_port_info; - if (wl_decoder_readback_port) { - wl_decoder_readback_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_readback_port); - } - - /* Top module Enable port -> WL Decoder Enable port */ - add_module_bus_nets(module_manager, - top_module, - top_module, 0, en_port, - wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_en_port); - - /* Top module Address port -> WL Decoder Address port */ - add_module_bus_nets(module_manager, - top_module, - top_module, 0, wl_addr_port, - wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_addr_port); - - /* Top module readback port -> WL Decoder readback port */ - if (wl_decoder_readback_port) { - add_module_bus_nets(module_manager, - top_module, - top_module, 0, readback_port, - wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_readback_port); - } - /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric * The distribution is a matrix which contains the starting index of BL/WL for each column or row */ std::pair child_x_range = compute_memory_bank_regional_configurable_child_x_range(module_manager, top_module, config_region); - std::pair child_y_range = compute_memory_bank_regional_configurable_child_y_range(module_manager, top_module, config_region); - std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, config_region, circuit_lib, sram_model); - std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, - config_region, - circuit_lib, sram_model); - std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); - std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); /************************************************************** * Add nets from BL data out to each configurable child @@ -378,13 +292,148 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma } } + /************************************************************** + * Add the BL and WL decoders to the end of configurable children list + * Note: this MUST be done after adding all the module nets to other regular configurable children + */ + module_manager.add_configurable_child(top_module, bl_decoder_module, curr_bl_decoder_instance_id); + module_manager.add_configurable_child_to_region(top_module, + config_region, + bl_decoder_module, + curr_bl_decoder_instance_id, + module_manager.configurable_children(top_module).size() - 1); + } +} + +/********************************************************************* + * Top-level function to add nets for quicklogic memory banks + * Each configuration region has independent memory bank circuitry + * - Find the number of BLs and WLs required for each region + * - Create BL and WL decoders, and add them to decoder library + * - Create nets to connect from top-level module inputs to inputs of decoders + * - Create nets to connect from outputs of decoders to BL/WL of configurable children + * + * @note this function only adds the WL configuration bus for decoders + * + * @note see detailed explanation on the bus connection in function add_top_module_nets_cmos_ql_memory_bank_config_bus() + **********************************************************************/ +static +void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model, + const TopModuleNumConfigBits& num_config_bits) { + /* Find Enable port from the top-level module */ + ModulePortId en_port = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort en_port_info = module_manager.module_port(top_module, en_port); + + /* Find readback port from the top-level module */ + ModulePortId readback_port = module_manager.find_module_port(top_module, std::string(DECODER_READBACK_PORT_NAME)); + BasicPort readback_port_info; + + /* Readback port if available, should be a 1-bit port */ + if (readback_port) { + readback_port_info = module_manager.module_port(top_module, readback_port); + VTR_ASSERT(readback_port_info.get_width() == 1); + } + + /* Find BL and WL address port from the top-level module */ + ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port); + + /* Find the top-level number of BLs and WLs required to access each memory bit */ + size_t wl_addr_size = wl_addr_port_info.get_width(); + + /* Each memory bank has a unified number of BL/WLs */ + size_t num_wls = 0; + for (const auto& curr_config_bits : num_config_bits) { + num_wls = std::max(num_wls, curr_config_bits.second); + } + + /* Create separated memory bank circuitry, i.e., BL/WL decoders for each region */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + /************************************************************** + * Add the WL decoder module + * Search the decoder library + * If we find one, we use the module. + * Otherwise, we create one and add it to the decoder library + */ + DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls, + true, false, false, readback_port != ModulePortId::INVALID()); + if (DecoderId::INVALID() == wl_decoder_id) { + wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false, readback_port != ModulePortId::INVALID()); + } + VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id); + + /* Create a module if not existed yet */ + std::string wl_decoder_module_name = generate_memory_decoder_subckt_name(wl_addr_size, num_wls); + ModuleId wl_decoder_module = module_manager.find_module(wl_decoder_module_name); + if (ModuleId::INVALID() == wl_decoder_module) { + /* BL decoder has the same ports as the frame-based decoders + * We reuse it here + */ + wl_decoder_module = build_wl_memory_decoder_module(module_manager, + decoder_lib, + wl_decoder_id); + } + VTR_ASSERT(ModuleId::INVALID() != wl_decoder_module); + size_t curr_wl_decoder_instance_id = module_manager.num_instance(top_module, wl_decoder_module); + module_manager.add_child_module(top_module, wl_decoder_module); + + /************************************************************** + * Add module nets from the top module to WL decoder's inputs + */ + ModulePortId wl_decoder_en_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort wl_decoder_en_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_en_port); + + ModulePortId wl_decoder_addr_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME)); + BasicPort wl_decoder_addr_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_addr_port); + + ModulePortId wl_decoder_readback_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_READBACK_PORT_NAME)); + BasicPort wl_decoder_readback_port_info; + if (wl_decoder_readback_port) { + wl_decoder_readback_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_readback_port); + } + + /* Top module Enable port -> WL Decoder Enable port */ + add_module_bus_nets(module_manager, + top_module, + top_module, 0, en_port, + wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_en_port); + + /* Top module Address port -> WL Decoder Address port */ + add_module_bus_nets(module_manager, + top_module, + top_module, 0, wl_addr_port, + wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_addr_port); + + /* Top module readback port -> WL Decoder readback port */ + if (wl_decoder_readback_port) { + add_module_bus_nets(module_manager, + top_module, + top_module, 0, readback_port, + wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_readback_port); + } + + /************************************************************** + * Precompute the BLs and WLs distribution across the FPGA fabric + * The distribution is a matrix which contains the starting index of BL/WL for each column or row + */ + std::pair child_y_range = compute_memory_bank_regional_configurable_child_y_range(module_manager, top_module, config_region); + std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, + config_region, + circuit_lib, sram_model); + std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); + /************************************************************** * Add nets from WL data out to each configurable child */ ModulePortId wl_decoder_dout_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); BasicPort wl_decoder_dout_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_dout_port); - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + /* Note we skip the last child which is the bl decoder added */ + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size() - 1; ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; @@ -458,13 +507,6 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma * Add the BL and WL decoders to the end of configurable children list * Note: this MUST be done after adding all the module nets to other regular configurable children */ - module_manager.add_configurable_child(top_module, bl_decoder_module, curr_bl_decoder_instance_id); - module_manager.add_configurable_child_to_region(top_module, - config_region, - bl_decoder_module, - curr_bl_decoder_instance_id, - module_manager.configurable_children(top_module).size() - 1); - module_manager.add_configurable_child(top_module, wl_decoder_module, curr_wl_decoder_instance_id); module_manager.add_configurable_child_to_region(top_module, config_region, @@ -474,6 +516,68 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma } } +/********************************************************************* + * Top-level function to add nets for quicklogic memory banks + * - Each configuration region has independent memory bank circuitry + * - BL and WL may have different circuitry and wire connection, e.g., decoder, flatten or shift-registers + * - BL control circuitry + * - Decoder: Add a BL decoder; Connect enable, address and data-in (din) between top-level and decoders; Connect data ports between between the decoder and configurable child modules + * - Flatten: Connect BLs between the top-level port and configurable child modules + * - TODO: Shift registers: add blocks of shift register chain (could be multi-head); Connect shift register outputs to configurable child modules + * + * - WL control circuitry + * - Decoder: Add a WL decoder; Connect address ports between top-level and decoders; Connect data ports between the decoder and configurable child modules + * - Flatten: Connect BLs between the top-level port and configurable child modules + * - TODO: Shift registers: add blocks of shift register chain (could be multi-head); Connect shift register outputs to configurable child modules + ********************************************************************/ +void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_manager, + DecoderLibrary& decoder_lib, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol, + const TopModuleNumConfigBits& num_config_bits) { + VTR_ASSERT_SAFE(CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()); + CircuitModelId sram_model = config_protocol.memory_model(); + + switch (config_protocol.bl_protocol_type()) { + case BLWL_PROTOCOL_DECODER: { + add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus(module_manager, decoder_lib, top_module, circuit_lib, sram_model, num_config_bits); + break; + } + case BLWL_PROTOCOL_FLATTEN: { + //add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(module_manager, decoder_lib, top_module, circuit_lib, num_config_bits); + break; + } + case BLWL_PROTOCOL_SHIFT_REGISTER: { + /* TODO */ + break; + } + default: { + VTR_LOG_ERROR("Invalid BL protocol"); + exit(1); + } + } + + switch (config_protocol.wl_protocol_type()) { + case BLWL_PROTOCOL_DECODER: { + add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(module_manager, decoder_lib, top_module, circuit_lib, sram_model, num_config_bits); + break; + } + case BLWL_PROTOCOL_FLATTEN: { + //add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(module_manager, decoder_lib, top_module, circuit_lib, num_config_bits); + break; + } + case BLWL_PROTOCOL_SHIFT_REGISTER: { + /* TODO */ + break; + } + default: { + VTR_LOG_ERROR("Invalid WL protocol"); + exit(1); + } + } +} + /******************************************************************** * Add a list of ports that are used for SRAM configuration to the FPGA * top-level module diff --git a/openfpga/src/fabric/build_top_module_memory_bank.h b/openfpga/src/fabric/build_top_module_memory_bank.h index 50e9567c9..3d6acc255 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.h +++ b/openfpga/src/fabric/build_top_module_memory_bank.h @@ -26,7 +26,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma DecoderLibrary& decoder_lib, const ModuleId& top_module, const CircuitLibrary& circuit_lib, - const CircuitModelId& sram_model, + const ConfigProtocol& config_protocol, const TopModuleNumConfigBits& num_config_bits); void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, From 74ffc8578f7f7a43cb495bdc72504f8e3f992a37 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Sep 2021 15:05:25 -0700 Subject: [PATCH 078/229] [Engine] Upgraded fabric generator to support flatten BL/WL bus for memory banks --- .../fabric/build_top_module_memory_bank.cpp | 247 +++++++++++++++++- 1 file changed, 241 insertions(+), 6 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index a974fc736..55203d993 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -315,7 +315,7 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus(ModuleManager * * @note this function only adds the WL configuration bus for decoders * - * @note see detailed explanation on the bus connection in function add_top_module_nets_cmos_ql_memory_bank_config_bus() + * @note see detailed explanation on the bus connection in function add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus() **********************************************************************/ static void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager& module_manager, @@ -433,14 +433,17 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager BasicPort wl_decoder_dout_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_dout_port); /* Note we skip the last child which is the bl decoder added */ - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size() - 1; ++child_id) { + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; - /* Find the WL port */ + /* Find the WL port. If the child does not have WL port, bypass it. It is usually a decoder module */ ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME)); + if (!child_wl_port) { + continue; + } BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port); size_t cur_wl_index = 0; @@ -477,8 +480,11 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; - /* Find the WL port */ + /* Find the WLR port. If the child does not have WLR port, bypass it. It is usually a decoder module */ ModulePortId child_wlr_port = module_manager.find_module_port(child_module, std::string(MEMORY_WLR_PORT_NAME)); + if (!child_wlr_port) { + continue; + } BasicPort child_wlr_port_info = module_manager.module_port(child_module, child_wlr_port); size_t cur_wlr_index = 0; @@ -516,6 +522,229 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager } } +/********************************************************************* + * This function to add nets for quicklogic memory banks using flatten BLs and WLs + * Each configuration region has independent BL/WLs + * - Find the number of BLs and WLs required for each region + * - Create nets to connect from top-level module inputs to BL/WL of configurable children + * + * @note this function only adds the BL configuration bus + * + * Detailed schematic of each memory bank: + * @note The numbers are just made to show a simplified example, practical cases are more complicated! + * + * BL[0:9] BL[10:17] BL[18:22] + * | | | + * | | | + * WL[0:3]-->-----------+---------------+---- ... |------+--> + * | | | | | | + * | v | v | v + * | +-------+ | +-------+ | +------+ + * +-->| SRAM | +-->| SRAM | +->| SRAM | + * | | [0:8] | | | [0:5] | ... | | [0:7]| + * | +-------+ | +-------+ | +------+ + * | | | + * WL[4:14] -----------+--------------+--------- | -----+--> + * | | | | | | + * | v | v | v + * | +-------+ | +-------+ | +-------+ + * +-->| SRAM | | | SRAM | +->| SRAM | + * | | [0:80]| | | [0:63]| ... | | [0:31]| + * | +-------+ | +-------+ | +-------+ + * | | + * | ... ... ... | ... + * | | | + * WL[15:18] -----------+---------------+---- --- | -----+--> + * | | | | | | + * | v | v | v + * | +-------+ | +-------+ | +-------+ + * +-->| SRAM | +-->| SRAM | +->| SRAM | + * | |[0:5] | | | [0:8] | ... | | [0:2] | + * | +-------+ | +-------+ | +-------+ + * v v v + * WL[0:9] WL[0:7] WL[0:4] + * + **********************************************************************/ +static +void add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(ModuleManager& module_manager, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model) { + /* Create connections between BLs of top-level module and BLs of child modules for each region */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + /************************************************************** + * Precompute the BLs and WLs distribution across the FPGA fabric + * The distribution is a matrix which contains the starting index of BL/WL for each column or row + */ + std::pair child_x_range = compute_memory_bank_regional_configurable_child_x_range(module_manager, top_module, config_region); + std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, + config_region, + circuit_lib, sram_model); + std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); + + /************************************************************** + * Add BL nets from top module to each configurable child + * BL pins of top module are connected to the BL input pins of each PB/CB/SB + * For all the PB/CB/SB in the same column, they share the same set of BLs + * A quick example + * + * BL[i .. i + sqrt(N)] + * | + * | CLB[1][H] + * | +---------+ + * | | SRAM | + * +-->| [0..N] | + * | +---------+ + * | + * ... + * | CLB[1][1] + * | +---------+ + * | | SRAM | + * +-->| [0..N] | + * | +---------+ + * | + */ + ModulePortId top_module_bl_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), config_region)); + BasicPort top_module_bl_port_info = module_manager.module_port(top_module, top_module_bl_port); + + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the BL port */ + ModulePortId child_bl_port = module_manager.find_module_port(child_module, std::string(MEMORY_BL_PORT_NAME)); + BasicPort child_bl_port_info = module_manager.module_port(child_module, child_bl_port); + + size_t cur_bl_index = 0; + + for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { + size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index; + VTR_ASSERT(bl_pin_id < top_module_bl_port_info.pins().size()); + + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + top_module, 0, + top_module_bl_port, + top_module_bl_port_info.pins()[bl_pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_bl_port, sink_bl_pin); + + cur_bl_index++; + } + } + } +} + +/********************************************************************* + * Top-level function to add nets for quicklogic memory banks using flatten BL/WLs + * Each configuration region has independent BL/WLs + * - Find the number of BLs and WLs required for each region + * - Create nets to connect from top-level module inputs to BL/WL of configurable children + * + * @note this function only adds the WL configuration bus + * + * @note see detailed explanation on the bus connection in function add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus() + **********************************************************************/ +static +void add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(ModuleManager& module_manager, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model) { + /* Create connections between WLs of top-level module and WLs of child modules for each region */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + /************************************************************** + * Precompute the BLs and WLs distribution across the FPGA fabric + * The distribution is a matrix which contains the starting index of BL/WL for each column or row + */ + std::pair child_y_range = compute_memory_bank_regional_configurable_child_y_range(module_manager, top_module, config_region); + std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, + config_region, + circuit_lib, sram_model); + std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); + + /************************************************************** + * Add WL nets from top module to each configurable child + */ + ModulePortId top_module_wl_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region)); + BasicPort top_module_wl_port_info = module_manager.module_port(top_module, top_module_wl_port); + + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the WL port */ + ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME)); + BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port); + + size_t cur_wl_index = 0; + + for (const size_t& sink_wl_pin : child_wl_port_info.pins()) { + size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + cur_wl_index; + VTR_ASSERT(wl_pin_id < top_module_wl_port_info.pins().size()); + + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + top_module, 0, + top_module_wl_port, + top_module_wl_port_info.pins()[wl_pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_wl_port, sink_wl_pin); + + cur_wl_index++; + } + } + + /************************************************************** + * Optional: Add WLR nets from top module to each configurable child + */ + ModulePortId top_module_wlr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WLR_PORT_NAME), config_region)); + BasicPort top_module_wlr_port_info; + if (top_module_wlr_port) { + top_module_wlr_port_info = module_manager.module_port(top_module, top_module_wlr_port); + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the WL port */ + ModulePortId child_wlr_port = module_manager.find_module_port(child_module, std::string(MEMORY_WLR_PORT_NAME)); + BasicPort child_wlr_port_info = module_manager.module_port(child_module, child_wlr_port); + + size_t cur_wlr_index = 0; + + for (const size_t& sink_wlr_pin : child_wlr_port_info.pins()) { + size_t wlr_pin_id = wl_start_index_per_tile[coord.y()] + cur_wlr_index; + VTR_ASSERT(wlr_pin_id < top_module_wlr_port_info.pins().size()); + + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + top_module, 0, + top_module_wlr_port, + top_module_wlr_port_info.pins()[wlr_pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_wlr_port, sink_wlr_pin); + + cur_wlr_index++; + } + } + } + } +} + /********************************************************************* * Top-level function to add nets for quicklogic memory banks * - Each configuration region has independent memory bank circuitry @@ -545,7 +774,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma break; } case BLWL_PROTOCOL_FLATTEN: { - //add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(module_manager, decoder_lib, top_module, circuit_lib, num_config_bits); + add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(module_manager, top_module, circuit_lib, sram_model); break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { @@ -564,7 +793,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma break; } case BLWL_PROTOCOL_FLATTEN: { - //add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(module_manager, decoder_lib, top_module, circuit_lib, num_config_bits); + add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(module_manager, top_module, circuit_lib, sram_model); break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { @@ -675,6 +904,12 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, size_t wl_size = num_config_bits[config_region].first; BasicPort wl_port(generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region), wl_size); module_manager.add_port(module_id, wl_port, ModuleManager::MODULE_INPUT_PORT); + + /* Optional: If we have WLR port, we should add a read-back port */ + if (!circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR).empty()) { + BasicPort readback_port(std::string(MEMORY_WLR_PORT_NAME), config_protocol.num_regions()); + module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT); + } } break; } From 2de4a460a813987cdd60d68f1cc7def98a96767d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Sep 2021 15:15:32 -0700 Subject: [PATCH 079/229] [Engine] Rework the function that counts the number of configurable children for fabric key writer and bitstream generator --- openfpga/src/base/openfpga_build_fabric.cpp | 2 +- openfpga/src/fabric/fabric_key_writer.cpp | 4 ++-- openfpga/src/fabric/fabric_key_writer.h | 7 ++++--- .../src/fpga_bitstream/build_device_bitstream.cpp | 12 ++++++------ openfpga/src/utils/memory_utils.cpp | 15 +++++++++++---- openfpga/src/utils/memory_utils.h | 3 ++- 6 files changed, 26 insertions(+), 17 deletions(-) diff --git a/openfpga/src/base/openfpga_build_fabric.cpp b/openfpga/src/base/openfpga_build_fabric.cpp index 2c3f491f9..146520624 100644 --- a/openfpga/src/base/openfpga_build_fabric.cpp +++ b/openfpga/src/base/openfpga_build_fabric.cpp @@ -132,7 +132,7 @@ int build_fabric(OpenfpgaContext& openfpga_ctx, VTR_ASSERT(false == fkey_fname.empty()); curr_status = write_fabric_key_to_xml_file(openfpga_ctx.module_graph(), fkey_fname, - openfpga_ctx.arch().config_protocol.type(), + openfpga_ctx.arch().config_protocol, cmd_context.option_enable(cmd, opt_verbose)); /* If there is any error, final status cannot be overwritten by a success flag */ if (CMD_EXEC_SUCCESS != curr_status) { diff --git a/openfpga/src/fabric/fabric_key_writer.cpp b/openfpga/src/fabric/fabric_key_writer.cpp index d6bea0527..38cb599db 100644 --- a/openfpga/src/fabric/fabric_key_writer.cpp +++ b/openfpga/src/fabric/fabric_key_writer.cpp @@ -31,7 +31,7 @@ namespace openfpga { ***************************************************************************************/ int write_fabric_key_to_xml_file(const ModuleManager& module_manager, const std::string& fname, - const e_config_protocol_type& config_protocol_type, + const ConfigProtocol& config_protocol, const bool& verbose) { std::string timer_message = std::string("Write fabric key to XML file '") + fname + std::string("'"); @@ -71,7 +71,7 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager, /* Each configuration protocol has some child which should not be in the list. They are typically decoders */ size_t curr_region_num_config_child = module_manager.region_configurable_children(top_module, config_region).size(); - size_t num_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol_type, curr_region_num_config_child); + size_t num_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol, curr_region_num_config_child); curr_region_num_config_child -= num_child_to_skip; fabric_key.reserve_region_keys(fabric_region, curr_region_num_config_child); diff --git a/openfpga/src/fabric/fabric_key_writer.h b/openfpga/src/fabric/fabric_key_writer.h index 3062db15a..bdb860354 100644 --- a/openfpga/src/fabric/fabric_key_writer.h +++ b/openfpga/src/fabric/fabric_key_writer.h @@ -4,8 +4,9 @@ /******************************************************************** * Include header files that are required by function declaration *******************************************************************/ -#include "vpr_context.h" -#include "openfpga_context.h" +#include +#include "module_manager.h" +#include "config_protocol.h" /******************************************************************** * Function declaration @@ -16,7 +17,7 @@ namespace openfpga { int write_fabric_key_to_xml_file(const ModuleManager& module_manager, const std::string& fname, - const e_config_protocol_type& config_protocol_type, + const ConfigProtocol& config_protocol, const bool& verbose); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp index 1c81e2cb3..8c89c3aaf 100644 --- a/openfpga/src/fpga_bitstream/build_device_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/build_device_bitstream.cpp @@ -64,7 +64,7 @@ static size_t rec_estimate_device_bitstream_num_bits(const ModuleManager& module_manager, const ModuleId& top_module, const ModuleId& parent_module, - const e_config_protocol_type& config_protocol_type) { + const ConfigProtocol& config_protocol) { size_t num_bits = 0; /* If a child module has no configurable children, this is a leaf node @@ -85,13 +85,13 @@ size_t rec_estimate_device_bitstream_num_bits(const ModuleManager& module_manage if (parent_module == top_module) { for (const ConfigRegionId& config_region : module_manager.regions(parent_module)) { size_t curr_region_num_config_child = module_manager.region_configurable_children(parent_module, config_region).size(); - size_t num_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol_type, curr_region_num_config_child); + size_t num_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol, curr_region_num_config_child); curr_region_num_config_child -= num_child_to_skip; /* Visit all the children in a recursively way */ for (size_t ichild = 0; ichild < curr_region_num_config_child; ++ichild) { ModuleId child_module = module_manager.region_configurable_children(parent_module, config_region)[ichild]; - num_bits += rec_estimate_device_bitstream_num_bits(module_manager, top_module, child_module, config_protocol_type); + num_bits += rec_estimate_device_bitstream_num_bits(module_manager, top_module, child_module, config_protocol); } } } else { @@ -102,14 +102,14 @@ size_t rec_estimate_device_bitstream_num_bits(const ModuleManager& module_manage /* Frame-based configuration protocol will have 1 decoder * if there are more than 1 configurable children */ - if ( (CONFIG_MEM_FRAME_BASED == config_protocol_type) + if ( (CONFIG_MEM_FRAME_BASED == config_protocol.type()) && (2 <= num_configurable_children)) { num_configurable_children--; } for (size_t ichild = 0; ichild < num_configurable_children; ++ichild) { ModuleId child_module = module_manager.configurable_children(parent_module)[ichild]; - num_bits += rec_estimate_device_bitstream_num_bits(module_manager, top_module, child_module, config_protocol_type); + num_bits += rec_estimate_device_bitstream_num_bits(module_manager, top_module, child_module, config_protocol); } } @@ -157,7 +157,7 @@ BitstreamManager build_device_bitstream(const VprContext& vpr_ctx, size_t num_bits_to_reserve = rec_estimate_device_bitstream_num_bits(openfpga_ctx.module_graph(), top_module, top_module, - openfpga_ctx.arch().config_protocol.type()); + openfpga_ctx.arch().config_protocol); bitstream_manager.reserve_bits(num_bits_to_reserve); VTR_LOGV(verbose, "Reserved %lu configuration bits\n", num_bits_to_reserve); diff --git a/openfpga/src/utils/memory_utils.cpp b/openfpga/src/utils/memory_utils.cpp index e5e44b99c..71c2c60ef 100644 --- a/openfpga/src/utils/memory_utils.cpp +++ b/openfpga/src/utils/memory_utils.cpp @@ -429,13 +429,13 @@ size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type, return sram_port_size; } -size_t estimate_num_configurable_children_to_skip_by_config_protocol(e_config_protocol_type config_protocol_type, +size_t estimate_num_configurable_children_to_skip_by_config_protocol(const ConfigProtocol& config_protocol, size_t curr_region_num_config_child) { size_t num_child_to_skip = 0; /* Frame-based configuration protocol will have 1 decoder * if there are more than 1 configurable children */ - if ( (CONFIG_MEM_FRAME_BASED == config_protocol_type) + if ( (CONFIG_MEM_FRAME_BASED == config_protocol.type()) && (2 <= curr_region_num_config_child)) { num_child_to_skip = 1; } @@ -443,10 +443,17 @@ size_t estimate_num_configurable_children_to_skip_by_config_protocol(e_config_pr /* Memory configuration protocol will have 2 decoders * at the top-level */ - if (CONFIG_MEM_MEMORY_BANK == config_protocol_type - || CONFIG_MEM_QL_MEMORY_BANK == config_protocol_type) { + if (CONFIG_MEM_MEMORY_BANK == config_protocol.type() + || CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) { VTR_ASSERT(2 <= curr_region_num_config_child); num_child_to_skip = 2; + /* If flatten bus is used, BL/WL may not need decoders */ + if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { + num_child_to_skip--; + } + if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { + num_child_to_skip--; + } } return num_child_to_skip; diff --git a/openfpga/src/utils/memory_utils.h b/openfpga/src/utils/memory_utils.h index d34e5f0ce..bf092b81a 100644 --- a/openfpga/src/utils/memory_utils.h +++ b/openfpga/src/utils/memory_utils.h @@ -7,6 +7,7 @@ #include #include "openfpga_port.h" #include "circuit_types.h" +#include "config_protocol.h" #include "module_manager.h" /******************************************************************** @@ -46,7 +47,7 @@ size_t generate_pb_sram_port_size(const e_config_protocol_type sram_orgz_type, * (they are included in the list for bitstream generator usage) * The number of decoders depends on the type of configuration protocol. */ -size_t estimate_num_configurable_children_to_skip_by_config_protocol(e_config_protocol_type config_protocol_type, +size_t estimate_num_configurable_children_to_skip_by_config_protocol(const ConfigProtocol& config_protocol, size_t curr_region_num_config_child); } /* end namespace openfpga */ From f735c10b84cb6dfa21d41b084ec77cad30b50492 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Sep 2021 15:18:31 -0700 Subject: [PATCH 080/229] [Engine] Clear up compiler warnings --- libopenfpga/libopenfpgautil/src/openfpga_port.cpp | 5 ----- libopenfpga/libopenfpgautil/src/openfpga_port.h | 1 - 2 files changed, 6 deletions(-) diff --git a/libopenfpga/libopenfpgautil/src/openfpga_port.cpp b/libopenfpga/libopenfpgautil/src/openfpga_port.cpp index a68431739..570fdf603 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_port.cpp +++ b/libopenfpga/libopenfpgautil/src/openfpga_port.cpp @@ -51,11 +51,6 @@ BasicPort::BasicPort(const std::string& name, const size_t& width) { set_origin_port_width(-1); } -/* Copy constructor */ -BasicPort::BasicPort(const BasicPort& basic_port) { - set(basic_port); -} - /************************************************************************ * Accessors ***********************************************************************/ diff --git a/libopenfpga/libopenfpgautil/src/openfpga_port.h b/libopenfpga/libopenfpgautil/src/openfpga_port.h index 4779e2332..3df6d0efa 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_port.h +++ b/libopenfpga/libopenfpgautil/src/openfpga_port.h @@ -18,7 +18,6 @@ class BasicPort { BasicPort(const char* name, const size_t& width); BasicPort(const std::string& name, const size_t& lsb, const size_t& msb); BasicPort(const std::string& name, const size_t& width); - BasicPort(const BasicPort& basic_port); /* Copy constructor */ public: /* Overloaded operators */ bool operator== (const BasicPort& portA) const; bool operator< (const BasicPort& portA) const; From 5f7617b682cfefb7aa2f2ff08b74b12b3eb5035b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Sep 2021 15:18:50 -0700 Subject: [PATCH 081/229] [Engine] Clear up compiler warnings in circuit library --- libopenfpga/libarchopenfpga/src/circuit_library.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libopenfpga/libarchopenfpga/src/circuit_library.cpp b/libopenfpga/libarchopenfpga/src/circuit_library.cpp index 537a436bc..4195158d4 100644 --- a/libopenfpga/libarchopenfpga/src/circuit_library.cpp +++ b/libopenfpga/libarchopenfpga/src/circuit_library.cpp @@ -1170,7 +1170,7 @@ CircuitModelId CircuitLibrary::add_model(const enum e_circuit_model_type& type) /* Pass-gate-related parameters */ pass_gate_logic_model_names_.emplace_back(); - pass_gate_logic_model_ids_.emplace_back(); + pass_gate_logic_model_ids_.emplace_back(CircuitModelId::INVALID()); /* Delay information */ delay_types_.emplace_back(); From 025ee67bc7ddfe24b57cc61ca34ab381da28a1ea Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Sep 2021 15:20:43 -0700 Subject: [PATCH 082/229] [Engine] Clear up compiler warning in tileable rr_graph builder --- vpr/src/tileable_rr_graph/rr_chan.cpp | 6 ------ vpr/src/tileable_rr_graph/rr_chan.h | 1 - vpr/src/tileable_rr_graph/rr_gsb.cpp | 7 ------- vpr/src/tileable_rr_graph/rr_gsb.h | 1 - 4 files changed, 15 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_chan.cpp b/vpr/src/tileable_rr_graph/rr_chan.cpp index fc387a988..0aea3cee4 100644 --- a/vpr/src/tileable_rr_graph/rr_chan.cpp +++ b/vpr/src/tileable_rr_graph/rr_chan.cpp @@ -11,12 +11,6 @@ namespace openfpga { /************************************************************************ * Constructors ***********************************************************************/ -/* Copy Constructor */ -RRChan::RRChan(const RRChan& rr_chan) { - this->set(rr_chan); - return; -} - /* default constructor */ RRChan::RRChan() { type_ = NUM_RR_TYPES; diff --git a/vpr/src/tileable_rr_graph/rr_chan.h b/vpr/src/tileable_rr_graph/rr_chan.h index 3277bb173..d06d894ca 100644 --- a/vpr/src/tileable_rr_graph/rr_chan.h +++ b/vpr/src/tileable_rr_graph/rr_chan.h @@ -43,7 +43,6 @@ namespace openfpga { *******************************************************************/ class RRChan { public: /* Constructors */ - RRChan(const RRChan&); /* Copy Constructor */ RRChan(); public: /* Accessors */ t_rr_type get_type() const; diff --git a/vpr/src/tileable_rr_graph/rr_gsb.cpp b/vpr/src/tileable_rr_graph/rr_gsb.cpp index c0d8d4143..eff2ebf00 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.cpp +++ b/vpr/src/tileable_rr_graph/rr_gsb.cpp @@ -32,13 +32,6 @@ RRGSB::RRGSB() { opin_node_.clear(); } -/* Copy constructor */ -RRGSB::RRGSB(const RRGSB& src) { - /* Copy coordinate */ - this->set(src); - return; -} - /************************************************************************ * Accessors ***********************************************************************/ diff --git a/vpr/src/tileable_rr_graph/rr_gsb.h b/vpr/src/tileable_rr_graph/rr_gsb.h index a0d13ad4a..38465369d 100644 --- a/vpr/src/tileable_rr_graph/rr_gsb.h +++ b/vpr/src/tileable_rr_graph/rr_gsb.h @@ -52,7 +52,6 @@ namespace openfpga { *******************************************************************/ class RRGSB { public: /* Contructors */ - RRGSB(const RRGSB&);/* Copy constructor */ RRGSB();/* Default constructor */ public: /* Accessors */ /* Get the number of sides of this SB */ From a49e3fe57a1895254a1d55306694ec0383568e0e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Sep 2021 16:30:18 -0700 Subject: [PATCH 083/229] [FPGA-bitstream] Upgraded bitstream generator to support flatten BL/WLs for QL memory bank --- .../libopenfpgautil/src/openfpga_decode.cpp | 34 +++++++ .../libopenfpgautil/src/openfpga_decode.h | 3 + .../build_fabric_bitstream_memory_bank.cpp | 92 +++++++++++++++---- 3 files changed, 111 insertions(+), 18 deletions(-) diff --git a/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp b/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp index b4dae065f..d6a6d0463 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp +++ b/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp @@ -46,6 +46,40 @@ std::vector ito1hot_vec(const size_t& in_int, return ret; } +/******************************************************************** + * Convert an integer to an one-hot encoding character array + * For example: + * Input integer: 3 + * Binary length : 4 + * Output: + * index | 0 | 1 | 2 | 3 + * ret | 0 | 0 | 0 | 1 + * + * If you need all zero code, set the input integer same as the binary length + * For example: + * Input integer: 4 + * Binary length : 4 + * Output: + * index | 0 | 1 | 2 | 3 + * ret | 0 | 0 | 0 | 0 + * + ********************************************************************/ +std::vector ito1hot_charvec(const size_t& in_int, + const size_t& bin_len) { + /* Make sure we do not have any overflow! */ + VTR_ASSERT ( (in_int <= bin_len) ); + + /* Initialize */ + std::vector ret(bin_len, '0'); + + if (bin_len == in_int) { + return ret; /* all zero case */ + } + ret[in_int] = '1'; /* Keep a good sequence of bits */ + + return ret; +} + /******************************************************************** * Converter an integer to a binary vector * For example: diff --git a/libopenfpga/libopenfpgautil/src/openfpga_decode.h b/libopenfpga/libopenfpgautil/src/openfpga_decode.h index 2e92bb9f4..21568b0dc 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_decode.h +++ b/libopenfpga/libopenfpgautil/src/openfpga_decode.h @@ -22,6 +22,9 @@ constexpr char DONT_CARE_CHAR = 'x'; std::vector ito1hot_vec(const size_t& in_int, const size_t& bin_len); +std::vector ito1hot_charvec(const size_t& in_int, + const size_t& bin_len); + std::vector itobin_vec(const size_t& in_int, const size_t& bin_len); diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index 3e7f2e9cc..1a5479842 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -47,6 +47,7 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B const ModuleId& top_module, const ModuleId& parent_module, const ConfigRegionId& config_region, + const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, const size_t& bl_addr_size, @@ -101,6 +102,7 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, child_block, module_manager, top_module, child_module, config_region, + config_protocol, circuit_lib, sram_model, bl_addr_size, wl_addr_size, num_bls_cur_tile, bl_start_index_per_tile, @@ -143,6 +145,7 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, child_block, module_manager, top_module, child_module, config_region, + config_protocol, circuit_lib, sram_model, bl_addr_size, wl_addr_size, num_bls_cur_tile, bl_start_index_per_tile, @@ -166,13 +169,29 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B for (const ConfigBitId& config_bit : bitstream_manager.block_bits(parent_block)) { FabricBitId fabric_bit = fabric_bitstream.add_bit(config_bit); - /* Find BL address */ + /* The BL address to be decoded depends on the protocol + * - flatten BLs: use 1-hot decoding + * - BL decoders: fully encoded + * - Shift register: use 1-hot decoding + */ size_t cur_bl_index = bl_start_index_per_tile.at(tile_coord.x()) + cur_mem_index[tile_coord] % num_bls_cur_tile; - std::vector bl_addr_bits_vec = itobin_charvec(cur_bl_index, bl_addr_size); + std::vector bl_addr_bits_vec; + if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { + bl_addr_bits_vec = itobin_charvec(cur_bl_index, bl_addr_size); + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() + || BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { + bl_addr_bits_vec = ito1hot_charvec(cur_bl_index, bl_addr_size); + } /* Find WL address */ size_t cur_wl_index = wl_start_index_per_tile.at(tile_coord.y()) + std::floor(cur_mem_index[tile_coord] / num_bls_cur_tile); - std::vector wl_addr_bits_vec = itobin_charvec(cur_wl_index, wl_addr_size); + std::vector wl_addr_bits_vec; + if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { + wl_addr_bits_vec = itobin_charvec(cur_wl_index, wl_addr_size); + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type() + || BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { + wl_addr_bits_vec = ito1hot_charvec(cur_wl_index, wl_addr_size); + } /* Set BL address */ fabric_bitstream.set_bit_bl_address(fabric_bit, bl_addr_bits_vec); @@ -193,7 +212,7 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B /******************************************************************** * Main function to build a fabric-dependent bitstream - * by considering the configuration protocol types + * by considering the QuickLogic memory banks *******************************************************************/ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol& config_protocol, const CircuitLibrary& circuit_lib, @@ -205,13 +224,57 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol /* Ensure we are in the correct type of configuration protocol*/ VTR_ASSERT(config_protocol.type() == CONFIG_MEM_QL_MEMORY_BANK); - /* Find global BL address port size */ - ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); - BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port); + /* For different BL control protocol, the address ports are different + * - flatten BLs: the address port should be raw BL ports at top-level module. + * Due to each configuration region has separated BLs, the address port should be the one with largest size + * - BL decoders: the address port should be the BL address port at top-level module + * - Shift register: the address port size will be calculated by the total number of unique BLs per child module in each configuration region + * Due to each configuration region has separated BLs, the address port should be the one with largest size + */ + ModulePortId bl_addr_port; + BasicPort bl_addr_port_info; + if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { + bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port); + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + ModulePortId temp_bl_addr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), config_region)); + BasicPort temp_bl_addr_port_info = module_manager.module_port(top_module, temp_bl_addr_port); + if (!bl_addr_port || (temp_bl_addr_port_info.get_width() > bl_addr_port_info.get_width())) { + bl_addr_port = temp_bl_addr_port; + bl_addr_port_info = temp_bl_addr_port_info; + } + } + } else { + /* TODO */ + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); + } - /* Find global WL address port size */ - ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); - BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port); + /* For different WL control protocol, the address ports are different + * - flatten WLs: the address port should be raw WL ports at top-level module. + * Due to each configuration region has separated WLs, the address port should be the one with largest size + * - WL decoders: the address port should be the WL address port at top-level module + * - Shift register: the address port size will be calculated by the total number of unique WLs per child module in each configuration region + * Due to each configuration region has separated WLs, the address port should be the one with largest size + */ + ModulePortId wl_addr_port; + BasicPort wl_addr_port_info; + if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { + wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port); + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + ModulePortId temp_wl_addr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region)); + BasicPort temp_wl_addr_port_info = module_manager.module_port(top_module, temp_wl_addr_port); + if (!wl_addr_port || (temp_wl_addr_port_info.get_width() > wl_addr_port_info.get_width())) { + wl_addr_port = temp_wl_addr_port; + wl_addr_port_info = temp_wl_addr_port_info; + } + } + } else { + /* TODO */ + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()); + } /* Reserve bits before build-up */ fabric_bitstream.set_use_address(true); @@ -225,14 +288,6 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol /* Find port information for local BL and WL decoder in this region */ std::vector configurable_children = module_manager.region_configurable_children(top_module, config_region); VTR_ASSERT(2 <= configurable_children.size()); - ModuleId bl_decoder_module = configurable_children[configurable_children.size() - 2]; - ModuleId wl_decoder_module = configurable_children[configurable_children.size() - 1]; - - ModulePortId bl_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); - BasicPort bl_port_info = module_manager.module_port(bl_decoder_module, bl_port); - - ModulePortId wl_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); - BasicPort wl_port_info = module_manager.module_port(wl_decoder_module, wl_port); /* Build the bitstream for all the blocks in this region */ FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region(); @@ -262,6 +317,7 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(bitstream_manager, top_block, module_manager, top_module, top_module, config_region, + config_protocol, circuit_lib, config_protocol.memory_model(), bl_addr_port_info.get_width(), wl_addr_port_info.get_width(), From 8b72447dad067aba430c68b1a4ae19c993abfd55 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 24 Sep 2021 18:07:07 -0700 Subject: [PATCH 084/229] [FPA-Bistream] Updating fabric bitstream writer to organize bitstream for flatten BL/WLs --- .../libopenfpgautil/src/openfpga_decode.cpp | 13 ++++ .../libopenfpgautil/src/openfpga_decode.h | 12 ++++ .../write_text_fabric_bitstream.cpp | 61 ++++++++++++++++++- openfpga/src/utils/fabric_bitstream_utils.cpp | 41 ++++++++++++- openfpga/src/utils/fabric_bitstream_utils.h | 23 +++++++ 5 files changed, 148 insertions(+), 2 deletions(-) diff --git a/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp b/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp index d6a6d0463..2961f423b 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp +++ b/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp @@ -80,6 +80,19 @@ std::vector ito1hot_charvec(const size_t& in_int, return ret; } +std::string combine_two_1hot_str(const std::string& code1, + const std::string& code2) { + VTR_ASSERT(code1.length() == code2.length()); + std::string ret = code1; + for (size_t ichar = 0; ichar < code2.length(); ichar++) { + VTR_ASSERT('0' == code2[ichar] || '1' == code2[ichar]); + if ('1' == code2[ichar]) { + ret[ichar] = code2[ichar]; + } + } + return ret; +} + /******************************************************************** * Converter an integer to a binary vector * For example: diff --git a/libopenfpga/libopenfpgautil/src/openfpga_decode.h b/libopenfpga/libopenfpgautil/src/openfpga_decode.h index 21568b0dc..4798af856 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_decode.h +++ b/libopenfpga/libopenfpgautil/src/openfpga_decode.h @@ -25,6 +25,18 @@ std::vector ito1hot_vec(const size_t& in_int, std::vector ito1hot_charvec(const size_t& in_int, const size_t& bin_len); +/******************************************************************** + * @brief Combine to two 1-hot codes which are in string format + * Any unique '1' will be merged + * For example: + * Code 1: 001000110 + * Code 2: 010001001 + * Output: 011001111 + * @note This function requires two codes in the same length + ********************************************************************/ +std::string combine_two_1hot_str(const std::string& code1, + const std::string& code2); + std::vector itobin_vec(const size_t& in_int, const size_t& bin_len); diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 8b2daaf87..8130fb447 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -180,6 +180,45 @@ int write_memory_bank_fabric_bitstream_to_text_file(std::fstream& fp, return status; } +/******************************************************************** + * Write the fabric bitstream fitting a memory bank protocol + * to a plain text file + * + * Return: + * - 0 if succeed + * - 1 if critical errors occured + *******************************************************************/ +static +int write_memory_bank_flatten_fabric_bitstream_to_text_file(std::fstream& fp, + const FabricBitstream& fabric_bitstream) { + int status = 0; + + MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); + + /* The address sizes and data input sizes are the same across any element, + * just get it from the 1st element to save runtime + */ + size_t bl_addr_size = fabric_bits_by_addr.begin()->first.first.size(); + size_t wl_addr_size = fabric_bits_by_addr.begin()->first.second.size(); + + /* Output information about how to intepret the bitstream */ + fp << "// Bitstream length: " << fabric_bits_by_addr.size() << std::endl; + fp << "// Bitstream width (LSB -> MSB): "; + fp << ""; + fp << ""; + fp << std::endl; + + for (const auto& addr_din_pair : fabric_bits_by_addr) { + /* Write BL address code */ + fp << addr_din_pair.first.first; + /* Write WL address code */ + fp << addr_din_pair.first.second; + fp << std::endl; + } + + return status; +} + /******************************************************************** * Write the fabric bitstream fitting a frame-based protocol * to a plain text file @@ -306,7 +345,27 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage bitstream_manager, fabric_bitstream); break; - case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_QL_MEMORY_BANK: { + /* Bitstream organization depends on the BL/WL protocols + * - If BL uses decoders, we have to config each memory cell one by one. + * - If BL uses flatten, we can configure all the memory cells on the same row by enabling dedicated WL + * In such case, we will merge the BL data under the same WL address + * Fast configuration is NOT applicable in this case + * - if BL uses shift-register, TODO + */ + if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { + status = write_memory_bank_fabric_bitstream_to_text_file(fp, + apply_fast_configuration, + bit_value_to_skip, + fabric_bitstream); + } else { + VTR_ASSERT(BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type() + || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); + status = write_memory_bank_flatten_fabric_bitstream_to_text_file(fp, + fabric_bitstream); + } + break; + } case CONFIG_MEM_MEMORY_BANK: status = write_memory_bank_fabric_bitstream_to_text_file(fp, apply_fast_configuration, diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 52f81dcdb..4fb46f0cf 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -188,7 +188,7 @@ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBit } /******************************************************************** - * Reorganize the fabric bitstream for memory banks + * Reorganize the fabric bitstream for memory banks which use BL and WL decoders * by the same address across regions: * This is due to that the length of fabric bitstream could be different in each region. * Template: @@ -232,6 +232,45 @@ MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const Fa return fabric_bits_by_addr; } +MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream) { + /* Build the bitstream by each region, here we use (WL, BL) pairs when storing bitstreams */ + vtr::vector> fabric_bits_per_region; + fabric_bits_per_region.resize(fabric_bitstream.num_regions()); + for (const FabricBitRegionId& region : fabric_bitstream.regions()) { + for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { + /* Create string for BL address */ + std::string bl_addr_str; + for (const char& addr_bit : fabric_bitstream.bit_bl_address(bit_id)) { + bl_addr_str.push_back(addr_bit); + } + + /* Create string for WL address */ + std::string wl_addr_str; + for (const char& addr_bit : fabric_bitstream.bit_wl_address(bit_id)) { + wl_addr_str.push_back(addr_bit); + } + + /* Place the config bit */ + auto result = fabric_bits_per_region[region].find(wl_addr_str); + if (result == fabric_bits_per_region[region].end()) { + /* This is a new bit, resize the vector to the number of regions + * and deposit '0' to all the bits + */ + fabric_bits_per_region[region][wl_addr_str] = bl_addr_str; + } else { + VTR_ASSERT_SAFE(result != fabric_bits_per_region[region].end()); + result->second = combine_two_1hot_str(bl_addr_str, result->second); + } + } + } + + /* TODO: Combine the bitstream from different region into a unique one. Now we follow the convention: use (BL, WL) pairs */ + MemoryBankFlattenFabricBitstream fabric_bits; + + return fabric_bits; +} + + /******************************************************************** * For fast configuration, the number of bits to be skipped * the rule to skip any configuration bit should consider the whole data input values. diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index 4da8c3c92..ca23a5363 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -37,6 +37,29 @@ FrameFabricBitstream build_frame_based_fabric_bitstream_by_address(const FabricB size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip); +/******************************************************************** + * @ brief Reorganize the fabric bitstream for memory banks which use flatten or shift register to manipulate BL and WLs + * For each configuration region, we will merge BL address (which are 1-hot codes) under the same WL address + * + * Quick Example + * _ _ + * An example: + * 010_111 000_101 + * + * Note that all the BL/WLs across configuration regions are independent. We will combine them together + * Quick Example + * _ _ + * 001_010 000_000 + * 100_100 000_000 + * + * the bitstream will be merged as + * 101_110 000_000 + * + * @note the std::map may cause large memory footprint for large bitstream databases! + *******************************************************************/ +typedef std::map, std::vector> MemoryBankFlattenFabricBitstream; +MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream); + /* Alias to a specific organization of bitstreams for memory bank configuration protocol */ typedef std::map, std::vector> MemoryBankFabricBitstream; MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream); From 1a2a2a6e633d504beb9d3582351b74154bfa43e2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 Sep 2021 12:03:33 -0700 Subject: [PATCH 085/229] [FPGA-Bitstream] Relax fabric bitstream address check --- .../build_fabric_bitstream_memory_bank.cpp | 30 ++++++++++++++++--- .../src/fpga_bitstream/fabric_bitstream.cpp | 23 ++++++++++---- .../src/fpga_bitstream/fabric_bitstream.h | 9 ++++-- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index 1a5479842..09ae2e966 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -194,10 +194,10 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B } /* Set BL address */ - fabric_bitstream.set_bit_bl_address(fabric_bit, bl_addr_bits_vec); + fabric_bitstream.set_bit_bl_address(fabric_bit, bl_addr_bits_vec, true); /* Set WL address */ - fabric_bitstream.set_bit_wl_address(fabric_bit, wl_addr_bits_vec); + fabric_bitstream.set_bit_wl_address(fabric_bit, wl_addr_bits_vec, true); /* Set data input */ fabric_bitstream.set_bit_din(fabric_bit, bitstream_manager.bit_value(config_bit)); @@ -291,6 +291,28 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol /* Build the bitstream for all the blocks in this region */ FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region(); + + /* Find the BL/WL port (different region may have different sizes of BL/WLs) */ + ModulePortId cur_bl_addr_port; + if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { + cur_bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { + cur_bl_addr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), config_region)); + } else { + /* TODO */ + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); + } + + ModulePortId cur_wl_addr_port; + if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { + cur_wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { + cur_wl_addr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region)); + } else { + /* TODO */ + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()); + } + BasicPort cur_wl_addr_port_info = module_manager.module_port(top_module, cur_wl_addr_port); /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric @@ -319,8 +341,8 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol config_region, config_protocol, circuit_lib, config_protocol.memory_model(), - bl_addr_port_info.get_width(), - wl_addr_port_info.get_width(), + cur_bl_addr_port_info.get_width(), + cur_wl_addr_port_info.get_width(), temp_num_bls_cur_tile, bl_start_index_per_tile, temp_num_wls_cur_tile, wl_start_index_per_tile, temp_coord, diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index 785327661..ca3702a3e 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -139,24 +139,35 @@ FabricBitId FabricBitstream::add_bit(const ConfigBitId& config_bit_id) { } void FabricBitstream::set_bit_address(const FabricBitId& bit_id, - const std::vector& address) { + const std::vector& address, + const bool& tolerant_short_address) { VTR_ASSERT(true == valid_bit_id(bit_id)); VTR_ASSERT(true == use_address_); - VTR_ASSERT(address_length_ == address.size()); + if (tolerant_short_address) { + VTR_ASSERT(address_length_ => address.size()); + } else { + VTR_ASSERT(address_length_ == address.size()); + } bit_addresses_[bit_id] = address; } void FabricBitstream::set_bit_bl_address(const FabricBitId& bit_id, - const std::vector& address) { - set_bit_address(bit_id, address); + const std::vector& address, + const bool& tolerant_short_address) { + set_bit_address(bit_id, address, tolerant_short_address); } void FabricBitstream::set_bit_wl_address(const FabricBitId& bit_id, - const std::vector& address) { + const std::vector& address, + const bool& tolerant_short_address) { VTR_ASSERT(true == valid_bit_id(bit_id)); VTR_ASSERT(true == use_address_); VTR_ASSERT(true == use_wl_address_); - VTR_ASSERT(wl_address_length_ == address.size()); + if (tolerant_short_address) { + VTR_ASSERT(wl_address_length_ => address.size()); + } else { + VTR_ASSERT(wl_address_length_ == address.size()); + } bit_wl_addresses_[bit_id] = address; } diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.h b/openfpga/src/fpga_bitstream/fabric_bitstream.h index 028452a58..e46edb74f 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.h @@ -135,13 +135,16 @@ class FabricBitstream { FabricBitId add_bit(const ConfigBitId& config_bit_id); void set_bit_address(const FabricBitId& bit_id, - const std::vector& address); + const std::vector& address, + const bool& tolerant_short_address = false); void set_bit_bl_address(const FabricBitId& bit_id, - const std::vector& address); + const std::vector& address, + const bool& tolerant_short_address = false); void set_bit_wl_address(const FabricBitId& bit_id, - const std::vector& address); + const std::vector& address, + const bool& tolerant_short_address = false); void set_bit_din(const FabricBitId& bit_id, const char& din); From 386812777c563183eae0fe980e1d96dbe1618f2e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 Sep 2021 12:49:32 -0700 Subject: [PATCH 086/229] [FPGA-Bitstream] Upgraded bitstream writer to support flatten BL/WLs --- .../build_fabric_bitstream_memory_bank.cpp | 1 + .../src/fpga_bitstream/fabric_bitstream.cpp | 4 +- .../write_text_fabric_bitstream.cpp | 26 ++++++--- openfpga/src/utils/fabric_bitstream_utils.cpp | 56 ++++++++++++++++++- openfpga/src/utils/fabric_bitstream_utils.h | 3 +- 5 files changed, 78 insertions(+), 12 deletions(-) diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index 09ae2e966..d4befa8bb 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -302,6 +302,7 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol /* TODO */ VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); } + BasicPort cur_bl_addr_port_info = module_manager.module_port(top_module, cur_bl_addr_port); ModulePortId cur_wl_addr_port; if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index ca3702a3e..23530f627 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -144,7 +144,7 @@ void FabricBitstream::set_bit_address(const FabricBitId& bit_id, VTR_ASSERT(true == valid_bit_id(bit_id)); VTR_ASSERT(true == use_address_); if (tolerant_short_address) { - VTR_ASSERT(address_length_ => address.size()); + VTR_ASSERT(address_length_ >= address.size()); } else { VTR_ASSERT(address_length_ == address.size()); } @@ -164,7 +164,7 @@ void FabricBitstream::set_bit_wl_address(const FabricBitId& bit_id, VTR_ASSERT(true == use_address_); VTR_ASSERT(true == use_wl_address_); if (tolerant_short_address) { - VTR_ASSERT(wl_address_length_ => address.size()); + VTR_ASSERT(wl_address_length_ >= address.size()); } else { VTR_ASSERT(wl_address_length_ == address.size()); } diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 8130fb447..13ef05726 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -190,29 +190,40 @@ int write_memory_bank_fabric_bitstream_to_text_file(std::fstream& fp, *******************************************************************/ static int write_memory_bank_flatten_fabric_bitstream_to_text_file(std::fstream& fp, + const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream) { int status = 0; - MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream); + MemoryBankFlattenFabricBitstream fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, bit_value_to_skip); /* The address sizes and data input sizes are the same across any element, * just get it from the 1st element to save runtime */ - size_t bl_addr_size = fabric_bits_by_addr.begin()->first.first.size(); - size_t wl_addr_size = fabric_bits_by_addr.begin()->first.second.size(); + size_t bl_addr_size = 0; + for (const auto& bl_vec : fabric_bits.begin()->first) { + bl_addr_size += bl_vec.size(); + } + size_t wl_addr_size = 0; + for (const auto& wl_vec : fabric_bits.begin()->second) { + wl_addr_size += wl_vec.size(); + } /* Output information about how to intepret the bitstream */ - fp << "// Bitstream length: " << fabric_bits_by_addr.size() << std::endl; + fp << "// Bitstream length: " << fabric_bits.size() << std::endl; fp << "// Bitstream width (LSB -> MSB): "; fp << ""; fp << ""; fp << std::endl; - for (const auto& addr_din_pair : fabric_bits_by_addr) { + for (const auto& addr_pair : fabric_bits) { /* Write BL address code */ - fp << addr_din_pair.first.first; + for (const auto& bl_vec : addr_pair.first) { + fp << bl_vec; + } /* Write WL address code */ - fp << addr_din_pair.first.second; + for (const auto& wl_vec : addr_pair.second) { + fp << wl_vec; + } fp << std::endl; } @@ -362,6 +373,7 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage VTR_ASSERT(BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type() || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); status = write_memory_bank_flatten_fabric_bitstream_to_text_file(fp, + bit_value_to_skip, fabric_bitstream); } break; diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 4fb46f0cf..bd518c7b2 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -232,12 +232,17 @@ MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const Fa return fabric_bits_by_addr; } -MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream) { +MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream, + const bool& bit_value_to_skip) { /* Build the bitstream by each region, here we use (WL, BL) pairs when storing bitstreams */ vtr::vector> fabric_bits_per_region; fabric_bits_per_region.resize(fabric_bitstream.num_regions()); for (const FabricBitRegionId& region : fabric_bitstream.regions()) { for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { + /* Skip din because they should be pre-configured through programming reset/set */ + if ((fabric_bitstream.bit_din(bit_id) == '1') == bit_value_to_skip) { + continue; + } /* Create string for BL address */ std::string bl_addr_str; for (const char& addr_bit : fabric_bitstream.bit_bl_address(bit_id)) { @@ -264,8 +269,55 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons } } - /* TODO: Combine the bitstream from different region into a unique one. Now we follow the convention: use (BL, WL) pairs */ + /* Find all the keys for the hash tables containing bitstream of each region */ + vtr::vector> fabric_bits_per_region_keys; + fabric_bits_per_region_keys.resize(fabric_bitstream.num_regions()); + for (const FabricBitRegionId& region : fabric_bitstream.regions()) { + /* Pre-allocate memory, because the key size may be large */ + fabric_bits_per_region_keys[region].reserve(fabric_bits_per_region[region].size()); + for (const auto& pair : fabric_bits_per_region[region]) { + fabric_bits_per_region_keys[region].push_back(pair.first); + } + } + + /* Find the maxium key size */ + size_t max_key_size = 0; + for (const FabricBitRegionId& region : fabric_bitstream.regions()) { + max_key_size = std::max(max_key_size, fabric_bits_per_region_keys[region].size()); + } + + /* Find the BL/WL sizes per region; Pair convention is (BL, WL) + * The address sizes are the same across any element, + * just get it from the 1st element to save runtime + */ + vtr::vector> max_blwl_sizes_per_region; + max_blwl_sizes_per_region.resize(fabric_bitstream.num_regions()); + for (const FabricBitRegionId& region : fabric_bitstream.regions()) { + max_blwl_sizes_per_region[region].first = std::max(max_blwl_sizes_per_region[region].first, fabric_bits_per_region[region].begin()->second.size()); + max_blwl_sizes_per_region[region].second = std::max(max_blwl_sizes_per_region[region].second, fabric_bits_per_region[region].begin()->first.size()); + } + + /* Combine the bitstream from different region into a unique one. Now we follow the convention: use (BL, WL) pairs */ MemoryBankFlattenFabricBitstream fabric_bits; + for (size_t ikey = 0; ikey < max_key_size; ikey++) { + /* Prepare the final BL/WL vectors to be added to the bitstream database */ + std::vector cur_bl_vectors; + std::vector cur_wl_vectors; + for (const FabricBitRegionId& region : fabric_bitstream.regions()) { + /* If the key id is in bound for the key list in this region, find the BL and WL and add to the final bitstream database + * If the key id is out of bound for the key list in this region, we append an all-zero string for both BL and WLs + */ + if (ikey < fabric_bits_per_region_keys[region].size()) { + cur_wl_vectors.push_back(fabric_bits_per_region_keys[region][ikey]); + cur_bl_vectors.push_back(fabric_bits_per_region[region].at(fabric_bits_per_region_keys[region][ikey])); + } else { + cur_wl_vectors.push_back(std::string(max_blwl_sizes_per_region[region].second, '0')); + cur_bl_vectors.push_back(std::string(max_blwl_sizes_per_region[region].first, '0')); + } + } + /* Add the pair to std map */ + fabric_bits[cur_bl_vectors] = cur_wl_vectors; + } return fabric_bits; } diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index ca23a5363..cb3406347 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -58,7 +58,8 @@ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBit * @note the std::map may cause large memory footprint for large bitstream databases! *******************************************************************/ typedef std::map, std::vector> MemoryBankFlattenFabricBitstream; -MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream); +MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream, + const bool& bit_value_to_skip); /* Alias to a specific organization of bitstreams for memory bank configuration protocol */ typedef std::map, std::vector> MemoryBankFabricBitstream; From a56d1f4fdb27f211bb0e97746fe0f47d984774a6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 Sep 2021 17:49:15 -0700 Subject: [PATCH 087/229] [FPGA-Verilog] Upgraded testbench generator to support memory bank using flatten BL/WLs --- .../fpga_verilog/verilog_top_testbench.cpp | 14 +- .../verilog_top_testbench_memory_bank.cpp | 290 +++++++++++++++++- .../verilog_top_testbench_memory_bank.h | 9 + .../src/fpga_verilog/verilog_writer_utils.cpp | 28 +- .../src/fpga_verilog/verilog_writer_utils.h | 4 + 5 files changed, 333 insertions(+), 12 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index eb070690d..7f7f12790 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -229,6 +229,8 @@ void print_verilog_top_testbench_config_protocol_port(std::fstream& fp, print_verilog_top_testbench_config_chain_port(fp, module_manager, top_module); break; case CONFIG_MEM_QL_MEMORY_BANK: + print_verilog_top_testbench_ql_memory_bank_port(fp, module_manager, top_module, config_protocol); + break; case CONFIG_MEM_MEMORY_BANK: print_verilog_top_testbench_memory_bank_port(fp, module_manager, top_module); break; @@ -1111,7 +1113,10 @@ void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& f case CONFIG_MEM_FRAME_BASED: { ModulePortId en_port_id = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); - BasicPort en_port = module_manager.module_port(top_module, en_port_id); + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + if (en_port_id) { + en_port = module_manager.module_port(top_module, en_port_id); + } BasicPort en_register_port(std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); print_verilog_comment(fp, std::string("---- Generate enable signal waveform -----")); print_verilog_shifted_clock_stimuli(fp, en_register_port, @@ -1684,7 +1689,7 @@ void print_verilog_full_testbench_frame_decoder_bitstream(std::fstream& fp, static void print_verilog_full_testbench_bitstream(std::fstream& fp, const std::string& bitstream_file, - const e_config_protocol_type& config_protocol_type, + const ConfigProtocol& config_protocol, const bool& fast_configuration, const bool& bit_value_to_skip, const ModuleManager& module_manager, @@ -1693,7 +1698,7 @@ void print_verilog_full_testbench_bitstream(std::fstream& fp, const FabricBitstream& fabric_bitstream) { /* Branch on the type of configuration protocol */ - switch (config_protocol_type) { + switch (config_protocol.type()) { case CONFIG_MEM_STANDALONE: print_verilog_full_testbench_vanilla_bitstream(fp, bitstream_file, @@ -1719,6 +1724,7 @@ void print_verilog_full_testbench_bitstream(std::fstream& fp, break; case CONFIG_MEM_QL_MEMORY_BANK: print_verilog_full_testbench_ql_memory_bank_bitstream(fp, bitstream_file, + config_protocol, fast_configuration, bit_value_to_skip, module_manager, top_module, @@ -1998,7 +2004,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, /* load bitstream to FPGA fabric in a configuration phase */ print_verilog_full_testbench_bitstream(fp, bitstream_file, - config_protocol.type(), + config_protocol, apply_fast_configuration, bit_value_to_skip, module_manager, top_module, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index d2a286984..b39f8b1c1 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -36,13 +36,264 @@ /* begin namespace openfpga */ namespace openfpga { -void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp, - const std::string& bitstream_file, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const ModuleManager& module_manager, - const ModuleId& top_module, - const FabricBitstream& fabric_bitstream) { +void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigProtocol& config_protocol) { + /* Validate the file stream */ + valid_file_stream(fp); + + /* Print the address port for the Bit-Line decoder here */ + if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { + print_verilog_comment(fp, std::string("---- Address port for Bit-Line decoder -----")); + ModulePortId bl_addr_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_BL_ADDRESS_PORT_NAME)); + BasicPort bl_addr_port = module_manager.module_port(top_module, bl_addr_port_id); + + fp << generate_verilog_port(VERILOG_PORT_REG, bl_addr_port) << ";" << std::endl; + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { + print_verilog_comment(fp, std::string("---- Bit-Line ports -----")); + for (const ConfigRegionId& region : module_manager.regions(top_module)) { + ModulePortId bl_port_id = module_manager.find_module_port(top_module, + generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), region)); + BasicPort bl_port = module_manager.module_port(top_module, bl_port_id); + fp << generate_verilog_port(VERILOG_PORT_REG, bl_port) << ";" << std::endl; + } + } else { + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); + /* TODO */ + } + + /* Print the address port for the Word-Line decoder here */ + if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { + print_verilog_comment(fp, std::string("---- Address port for Word-Line decoder -----")); + ModulePortId wl_addr_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_WL_ADDRESS_PORT_NAME)); + BasicPort wl_addr_port = module_manager.module_port(top_module, wl_addr_port_id); + + fp << generate_verilog_port(VERILOG_PORT_REG, wl_addr_port) << ";" << std::endl; + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { + print_verilog_comment(fp, std::string("---- Word-Line ports -----")); + for (const ConfigRegionId& region : module_manager.regions(top_module)) { + ModulePortId wl_port_id = module_manager.find_module_port(top_module, + generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), region)); + BasicPort wl_port = module_manager.module_port(top_module, wl_port_id); + fp << generate_verilog_port(VERILOG_PORT_REG, wl_port) << ";" << std::endl; + } + } else { + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()); + /* TODO */ + } + + /* Print the data-input port: only available when BL has a decoder */ + if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { + print_verilog_comment(fp, std::string("---- Data input port for memory decoders -----")); + ModulePortId din_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_DATA_IN_PORT_NAME)); + BasicPort din_port = module_manager.module_port(top_module, din_port_id); + fp << generate_verilog_port(VERILOG_PORT_REG, din_port) << ";" << std::endl; + } + + /* Print the optional readback port for the decoder here */ + if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { + print_verilog_comment(fp, std::string("---- Readback port for memory decoders -----")); + ModulePortId readback_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_READBACK_PORT_NAME)); + if (readback_port_id) { + BasicPort readback_port = module_manager.module_port(top_module, readback_port_id); + fp << generate_verilog_port(VERILOG_PORT_WIRE, readback_port) << ";" << std::endl; + /* Disable readback in full testbenches */ + print_verilog_wire_constant_values(fp, readback_port, std::vector(readback_port.get_width(), 0)); + } + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { + print_verilog_comment(fp, std::string("---- Word line read ports -----")); + for (const ConfigRegionId& region : module_manager.regions(top_module)) { + ModulePortId wlr_port_id = module_manager.find_module_port(top_module, + generate_regional_blwl_port_name(std::string(MEMORY_WLR_PORT_NAME), region)); + if (wlr_port_id) { + BasicPort wlr_port = module_manager.module_port(top_module, wlr_port_id); + fp << generate_verilog_port(VERILOG_PORT_WIRE, wlr_port) << ";" << std::endl; + /* Disable readback in full testbenches */ + print_verilog_wire_constant_values(fp, wlr_port, std::vector(wlr_port.get_width(), 0)); + } + } + } + + /* Generate enable signal waveform here: + * which is a 90 degree phase shift than the programming clock + */ + print_verilog_comment(fp, std::string("---- Wire enable port of memory decoders -----")); + ModulePortId en_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + if (en_port_id) { + en_port = module_manager.module_port(top_module, en_port_id); + } + BasicPort en_register_port(std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); + + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); + + fp << generate_verilog_port(VERILOG_PORT_WIRE, en_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, en_register_port) << ";" << std::endl; + + write_tab_to_file(fp, 1); + fp << "assign "; + fp << generate_verilog_port(VERILOG_PORT_CONKT, en_port); + fp << "= "; + fp << "~" << generate_verilog_port(VERILOG_PORT_CONKT, en_register_port); + fp << " & "; + fp << "~" << generate_verilog_port(VERILOG_PORT_CONKT, config_done_port); + fp << ";" << std::endl; +} + +/* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */ +static +void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& fp, + const std::string& bitstream_file, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricBitstream& fabric_bitstream) { + /* Validate the file stream */ + valid_file_stream(fp); + + /* No fast configuration available in this configuration protocol. Give a warning */ + if (true == fast_configuration) { + VTR_LOG_WARN("Fast configuration is not available for flatten BL protocol"); + } + + /* Reorganize the fabric bitstream by the same address across regions */ + MemoryBankFlattenFabricBitstream fabric_bits_by_addr = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, + bit_value_to_skip); + + /* Feed address and data input pair one by one + * Note: the first cycle is reserved for programming reset + * We should give dummy values + */ + std::vector bl_ports; + for (const ConfigRegionId& region : module_manager.regions(top_module)) { + ModulePortId cur_bl_port_id = module_manager.find_module_port(top_module, + generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), region)); + bl_ports.push_back(module_manager.module_port(top_module, cur_bl_port_id)); + } + + std::vector wl_ports; + for (const ConfigRegionId& region : module_manager.regions(top_module)) { + ModulePortId cur_wl_port_id = module_manager.find_module_port(top_module, + generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), region)); + wl_ports.push_back(module_manager.module_port(top_module, cur_wl_port_id)); + } + + /* Calculate the total size of BL/WL ports */ + size_t bl_port_width = 0; + for (const BasicPort& bl_port : bl_ports) { + bl_port_width += bl_port.get_width(); + } + size_t wl_port_width = 0; + for (const BasicPort& wl_port : wl_ports) { + wl_port_width += wl_port.get_width(); + } + + std::vector initial_bl_values(bl_port_width, 0); + std::vector initial_wl_values(wl_port_width, 0); + + /* Define a constant for the bitstream length */ + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), fabric_bits_by_addr.size()); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), bl_port_width + wl_port_width); + + /* Declare local variables for bitstream loading in Verilog */ + print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + fp << "reg [0:`" << TOP_TB_BITSTREAM_WIDTH_VARIABLE << " - 1] "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << " - 1];"; + fp << std::endl; + + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; + + print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + fp << "initial begin" << std::endl; + fp << "\t"; + fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << std::endl; + + print_verilog_comment(fp, "----- Bit-Line Address port default input -----"); + fp << "\t"; + fp << generate_verilog_ports_constant_values(bl_ports, initial_bl_values); + fp << ";"; + fp << std::endl; + + print_verilog_comment(fp, "----- Word-Line Address port default input -----"); + fp << "\t"; + fp << generate_verilog_ports_constant_values(wl_ports, initial_wl_values); + fp << ";"; + fp << std::endl; + + fp << "\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " <= 0"; + fp << ";"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); + fp << "always"; + fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t"; + fp << "if ("; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " >= "; + fp << "`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE; + fp << ") begin"; + fp << std::endl; + + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); + fp << "\t\t"; + std::vector config_done_final_values(config_done_port.get_width(), 1); + fp << generate_verilog_port_constant_values(config_done_port, config_done_final_values, true); + fp << ";" << std::endl; + + fp << "\t"; + fp << "end else begin"; + fp << std::endl; + + std::vector blwl_ports = bl_ports; + blwl_ports.insert(blwl_ports.end(), wl_ports.begin(), wl_ports.end()); + fp << "\t\t"; + fp << generate_verilog_ports(blwl_ports); + fp << " <= "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[" << TOP_TB_BITSTREAM_INDEX_REG_NAME << "]"; + fp << ";" << std::endl; + + fp << "\t\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " <= "; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " + 1"; + fp << ";" << std::endl; + + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); +} + +/* Verilog codes to load bitstream from a bit file for memory bank using BL/WL decoders */ +static +void print_verilog_full_testbench_ql_memory_bank_decoder_bitstream(std::fstream& fp, + const std::string& bitstream_file, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricBitstream& fabric_bitstream) { /* Validate the file stream */ valid_file_stream(fp); @@ -172,4 +423,29 @@ void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp, print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); } +void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp, + const std::string& bitstream_file, + const ConfigProtocol& config_protocol, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricBitstream& fabric_bitstream) { + if ( (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) + && (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) ) { + print_verilog_full_testbench_ql_memory_bank_decoder_bitstream(fp, bitstream_file, + fast_configuration, + bit_value_to_skip, + module_manager, top_module, + fabric_bitstream); + } else if ( (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) + && (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) ) { + print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(fp, bitstream_file, + fast_configuration, + bit_value_to_skip, + module_manager, top_module, + fabric_bitstream); + } +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h index e82a956e2..87ddf3ac5 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h @@ -26,12 +26,21 @@ /* begin namespace openfpga */ namespace openfpga { +/** + * @brief Print local wires for memory bank configuration protocols + */ +void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigProtocol& config_protocol); + /** * @brief Print stimulus for a FPGA fabric with a memory bank configuration protocol * where configuration bits are programming in serial (one by one) */ void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp, const std::string& bitstream_file, + const ConfigProtocol& config_protocol, const bool& fast_configuration, const bool& bit_value_to_skip, const ModuleManager& module_manager, diff --git a/openfpga/src/fpga_verilog/verilog_writer_utils.cpp b/openfpga/src/fpga_verilog/verilog_writer_utils.cpp index 7d5c3dd77..4b5981eda 100644 --- a/openfpga/src/fpga_verilog/verilog_writer_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_writer_utils.cpp @@ -721,7 +721,7 @@ std::string generate_verilog_constant_values(const std::vector& const_va } /******************************************************************** - * Generate a verilog port with a deposite of constant values + * Generate a verilog port with a deposit of constant values ********************************************************************/ std::string generate_verilog_port_constant_values(const BasicPort& output_port, const std::vector& const_values, @@ -742,6 +742,32 @@ std::string generate_verilog_port_constant_values(const BasicPort& output_port, return port_str; } +/******************************************************************** + * Generate a list of verilog ports with a deposit of constant values + ********************************************************************/ +std::string generate_verilog_ports_constant_values(const std::vector& output_ports, + const std::vector& const_values, + const bool& is_register) { + std::string port_str; + + /* Must check: the port width matches */ + size_t total_width = 0; + for (const BasicPort& port : output_ports) { + total_width += port.get_width(); + } + VTR_ASSERT( const_values.size() == total_width ); + + port_str = generate_verilog_ports(output_ports); + if (is_register) { + port_str += " <= "; + } else { + VTR_ASSERT_SAFE(!is_register); + port_str += " = "; + } + port_str += generate_verilog_constant_values(const_values); + return port_str; +} + /******************************************************************** * Generate a wire connection, that assigns constant values to a * Verilog port diff --git a/openfpga/src/fpga_verilog/verilog_writer_utils.h b/openfpga/src/fpga_verilog/verilog_writer_utils.h index 09a5dba7a..67d60b7f1 100644 --- a/openfpga/src/fpga_verilog/verilog_writer_utils.h +++ b/openfpga/src/fpga_verilog/verilog_writer_utils.h @@ -111,6 +111,10 @@ std::string generate_verilog_port_constant_values(const BasicPort& output_port, const std::vector& const_values, const bool& is_register = false); +std::string generate_verilog_ports_constant_values(const std::vector& output_ports, + const std::vector& const_values, + const bool& is_register = false); + void print_verilog_wire_constant_values(std::fstream& fp, const BasicPort& output_port, const std::vector& const_values); From 3cf31f156597077b964e81a1b6e36df0dc51a61c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 Sep 2021 18:22:55 -0700 Subject: [PATCH 088/229] [Engine] Fixed bugs --- .../build_fabric_bitstream_memory_bank.cpp | 13 ++++++++----- .../fpga_bitstream/write_text_fabric_bitstream.cpp | 2 +- openfpga/src/utils/fabric_bitstream_utils.cpp | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index d4befa8bb..998b3960b 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -19,6 +19,7 @@ #include "decoder_library_utils.h" #include "bitstream_manager_utils.h" +#include "memory_utils.h" #include "memory_bank_utils.h" #include "build_fabric_bitstream_memory_bank.h" @@ -73,7 +74,9 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B std::vector configurable_children = module_manager.region_configurable_children(parent_module, config_region); VTR_ASSERT(2 <= configurable_children.size()); - size_t num_configurable_children = configurable_children.size() - 2; + size_t num_config_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol, + configurable_children.size()); + size_t num_configurable_children = configurable_children.size() - num_config_child_to_skip; /* Early exit if there is no configurable children */ if (0 == num_configurable_children) { @@ -179,7 +182,7 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { bl_addr_bits_vec = itobin_charvec(cur_bl_index, bl_addr_size); } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() - || BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { + || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { bl_addr_bits_vec = ito1hot_charvec(cur_bl_index, bl_addr_size); } @@ -189,15 +192,15 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { wl_addr_bits_vec = itobin_charvec(cur_wl_index, wl_addr_size); } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type() - || BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { + || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()) { wl_addr_bits_vec = ito1hot_charvec(cur_wl_index, wl_addr_size); } /* Set BL address */ - fabric_bitstream.set_bit_bl_address(fabric_bit, bl_addr_bits_vec, true); + fabric_bitstream.set_bit_bl_address(fabric_bit, bl_addr_bits_vec, BLWL_PROTOCOL_DECODER != config_protocol.bl_protocol_type()); /* Set WL address */ - fabric_bitstream.set_bit_wl_address(fabric_bit, wl_addr_bits_vec, true); + fabric_bitstream.set_bit_wl_address(fabric_bit, wl_addr_bits_vec, BLWL_PROTOCOL_DECODER != config_protocol.wl_protocol_type()); /* Set data input */ fabric_bitstream.set_bit_din(fabric_bit, bitstream_manager.bit_value(config_bit)); diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 13ef05726..e6c458b37 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -370,7 +370,7 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage bit_value_to_skip, fabric_bitstream); } else { - VTR_ASSERT(BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type() + VTR_ASSERT(BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); status = write_memory_bank_flatten_fabric_bitstream_to_text_file(fp, bit_value_to_skip, diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index bd518c7b2..c196429c3 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -240,7 +240,7 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons for (const FabricBitRegionId& region : fabric_bitstream.regions()) { for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { /* Skip din because they should be pre-configured through programming reset/set */ - if ((fabric_bitstream.bit_din(bit_id) == '1') == bit_value_to_skip) { + if (fabric_bitstream.bit_din(bit_id) == bit_value_to_skip) { continue; } /* Create string for BL address */ From e06ac1163010e552a754ecf1398a0ad6a0d731c8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 Sep 2021 19:21:16 -0700 Subject: [PATCH 089/229] [Engine] Bug fix --- openfpga/src/fabric/build_top_module_memory_bank.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 55203d993..63cf7ea77 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -901,13 +901,13 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, case BLWL_PROTOCOL_FLATTEN: { /* Each region will have independent WLs */ for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - size_t wl_size = num_config_bits[config_region].first; + size_t wl_size = num_config_bits[config_region].second; BasicPort wl_port(generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region), wl_size); module_manager.add_port(module_id, wl_port, ModuleManager::MODULE_INPUT_PORT); /* Optional: If we have WLR port, we should add a read-back port */ if (!circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR).empty()) { - BasicPort readback_port(std::string(MEMORY_WLR_PORT_NAME), config_protocol.num_regions()); + BasicPort readback_port(std::string(MEMORY_WLR_PORT_NAME), wl_size); module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT); } } From 29c351f5a45e1c40c1c512fd7fba3bf6e1ffceb0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 Sep 2021 19:34:21 -0700 Subject: [PATCH 090/229] [Engine] Bug fix in estimating the configuration cycles for Verilog testbench generator --- .../fpga_verilog/verilog_top_testbench.cpp | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 7f7f12790..4b0524308 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -810,7 +810,7 @@ void print_verilog_top_testbench_ports(std::fstream& fp, * Note that this will not applicable to configuration chain!!! *******************************************************************/ static -size_t calculate_num_config_clock_cycles(const e_config_protocol_type& sram_orgz_type, +size_t calculate_num_config_clock_cycles(const ConfigProtocol& config_protocol, const bool& fast_configuration, const bool& bit_value_to_skip, const BitstreamManager& bitstream_manager, @@ -821,7 +821,7 @@ size_t calculate_num_config_clock_cycles(const e_config_protocol_type& sram_orgz size_t num_config_clock_cycles = 1 + regional_bitstream_max_size; /* Branch on the type of configuration protocol */ - switch (sram_orgz_type) { + switch (config_protocol.type()) { case CONFIG_MEM_STANDALONE: /* We just need 1 clock cycle to load all the configuration bits * since all the ports are exposed at the top-level @@ -849,7 +849,25 @@ size_t calculate_num_config_clock_cycles(const e_config_protocol_type& sram_orgz 100. * ((float)num_config_clock_cycles / (float)(1 + regional_bitstream_max_size) - 1.)); } break; - case CONFIG_MEM_QL_MEMORY_BANK: + case CONFIG_MEM_QL_MEMORY_BANK: { + if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { + /* For fast configuration, we will skip all the zero data points */ + num_config_clock_cycles = 1 + build_memory_bank_fabric_bitstream_by_address(fabric_bitstream).size(); + if (true == fast_configuration) { + size_t full_num_config_clock_cycles = num_config_clock_cycles; + num_config_clock_cycles = 1 + find_memory_bank_fast_configuration_fabric_bitstream_size(fabric_bitstream, bit_value_to_skip); + VTR_LOG("Fast configuration reduces number of configuration clock cycles from %lu to %lu (compression_rate = %f%)\n", + full_num_config_clock_cycles, + num_config_clock_cycles, + 100. * ((float)num_config_clock_cycles / (float)full_num_config_clock_cycles - 1.)); + } + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { + num_config_clock_cycles = 1 + build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, bit_value_to_skip).size(); + } else if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { + /* TODO */ + } + break; + } case CONFIG_MEM_MEMORY_BANK: { /* For fast configuration, we will skip all the zero data points */ num_config_clock_cycles = 1 + build_memory_bank_fabric_bitstream_by_address(fabric_bitstream).size(); @@ -1922,7 +1940,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, } /* Estimate the number of configuration clock cycles */ - size_t num_config_clock_cycles = calculate_num_config_clock_cycles(config_protocol.type(), + size_t num_config_clock_cycles = calculate_num_config_clock_cycles(config_protocol, apply_fast_configuration, bit_value_to_skip, bitstream_manager, From 33e9b27cb80902984bbefb88c552c14aaf69114e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 Sep 2021 20:22:27 -0700 Subject: [PATCH 091/229] [Engine] Fixed a critical bug when building final bitstream, which may cause loss when merging BLs --- .../src/fpga_bitstream/write_text_fabric_bitstream.cpp | 8 ++++---- openfpga/src/utils/fabric_bitstream_utils.cpp | 7 ++----- openfpga/src/utils/fabric_bitstream_utils.h | 5 ++++- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index e6c458b37..ee1b3deda 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -200,11 +200,11 @@ int write_memory_bank_flatten_fabric_bitstream_to_text_file(std::fstream& fp, * just get it from the 1st element to save runtime */ size_t bl_addr_size = 0; - for (const auto& bl_vec : fabric_bits.begin()->first) { + for (const auto& bl_vec : fabric_bits.begin()->second) { bl_addr_size += bl_vec.size(); } size_t wl_addr_size = 0; - for (const auto& wl_vec : fabric_bits.begin()->second) { + for (const auto& wl_vec : fabric_bits.begin()->first) { wl_addr_size += wl_vec.size(); } @@ -217,11 +217,11 @@ int write_memory_bank_flatten_fabric_bitstream_to_text_file(std::fstream& fp, for (const auto& addr_pair : fabric_bits) { /* Write BL address code */ - for (const auto& bl_vec : addr_pair.first) { + for (const auto& bl_vec : addr_pair.second) { fp << bl_vec; } /* Write WL address code */ - for (const auto& wl_vec : addr_pair.second) { + for (const auto& wl_vec : addr_pair.first) { fp << wl_vec; } fp << std::endl; diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index c196429c3..2df7bcb23 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -258,9 +258,6 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons /* Place the config bit */ auto result = fabric_bits_per_region[region].find(wl_addr_str); if (result == fabric_bits_per_region[region].end()) { - /* This is a new bit, resize the vector to the number of regions - * and deposit '0' to all the bits - */ fabric_bits_per_region[region][wl_addr_str] = bl_addr_str; } else { VTR_ASSERT_SAFE(result != fabric_bits_per_region[region].end()); @@ -297,7 +294,7 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons max_blwl_sizes_per_region[region].second = std::max(max_blwl_sizes_per_region[region].second, fabric_bits_per_region[region].begin()->first.size()); } - /* Combine the bitstream from different region into a unique one. Now we follow the convention: use (BL, WL) pairs */ + /* Combine the bitstream from different region into a unique one. Now we follow the convention: use (WL, BL) pairs */ MemoryBankFlattenFabricBitstream fabric_bits; for (size_t ikey = 0; ikey < max_key_size; ikey++) { /* Prepare the final BL/WL vectors to be added to the bitstream database */ @@ -316,7 +313,7 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons } } /* Add the pair to std map */ - fabric_bits[cur_bl_vectors] = cur_wl_vectors; + fabric_bits[cur_wl_vectors] = cur_bl_vectors; } return fabric_bits; diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index cb3406347..ad14aef74 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -37,6 +37,10 @@ FrameFabricBitstream build_frame_based_fabric_bitstream_by_address(const FabricB size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip); +/* Must use (WL, BL) as pairs in the map!!! + * This is because BL data may not be unique while WL must be unique + */ +typedef std::map, std::vector> MemoryBankFlattenFabricBitstream; /******************************************************************** * @ brief Reorganize the fabric bitstream for memory banks which use flatten or shift register to manipulate BL and WLs * For each configuration region, we will merge BL address (which are 1-hot codes) under the same WL address @@ -57,7 +61,6 @@ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBit * * @note the std::map may cause large memory footprint for large bitstream databases! *******************************************************************/ -typedef std::map, std::vector> MemoryBankFlattenFabricBitstream; MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip); From f9bceff33a60b79680a61e314264e90fc2e48ba0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 25 Sep 2021 20:44:45 -0700 Subject: [PATCH 092/229] [Doc] Update documentation for the flatten BL/WL protocols --- docs/source/manual/arch_lang/config_protocol.rst | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/source/manual/arch_lang/config_protocol.rst b/docs/source/manual/arch_lang/config_protocol.rst index 087914c80..560dc77fa 100644 --- a/docs/source/manual/arch_lang/config_protocol.rst +++ b/docs/source/manual/arch_lang/config_protocol.rst @@ -40,6 +40,7 @@ Template - ``scan_chain`` requires a circuit model type of ``ccff`` - ``frame_based`` requires a circuit model type of ``sram`` - ``memory_bank`` requires a circuit model type of ``sram`` + - ``ql_memory_bank`` requires a circuit model type of ``sram`` - ``standalone`` requires a circuit model type of ``sram`` .. option:: num_regions="" @@ -148,18 +149,29 @@ Users can customized the number of memory banks to be used across the fabrics. B .. warning:: Please do NOT add inverted Bit-Line and Word-Line inputs. It is not supported yet! - QuickLogic Memory bank Example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following XML code describes a physical design friendly memory-bank circuitry to configure the core logic of FPGA, as illustrated in :numref:`fig_memory_bank`. It will use the circuit model defined in :numref:`fig_sram_blwl`. +The BL and WL protocols can be customized through the XML syntax ``bl`` and ``wl``. + +.. note:: If not specified, the BL/WL protocols will use decoders. + .. code-block:: xml - + + + + +.. option:: protocol="decoder|flatten" + + - ``decoder``: BLs or WLs are controlled by decoders with address lines. For BLs, the decoder includes an enable signal as well as a data input signal. This is the default option if not specified. + - ``flatten``: BLs or WLs are directly available at the FPGA fabric. In this way, all the configurable memorys on the same WL can be written through the BL signals in one clock cycle + .. note:: Memory-bank decoders does require a memory cell to have - two outputs (one regular and another inverted) From b0a97a7052f0c85e66d541f8ca465071c158f0d8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 27 Sep 2021 10:24:04 -0700 Subject: [PATCH 093/229] [Doc] Update doc about WLR usage for QL memory bank --- docs/source/manual/arch_lang/config_protocol.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/manual/arch_lang/config_protocol.rst b/docs/source/manual/arch_lang/config_protocol.rst index 560dc77fa..04b47d638 100644 --- a/docs/source/manual/arch_lang/config_protocol.rst +++ b/docs/source/manual/arch_lang/config_protocol.rst @@ -177,6 +177,7 @@ The BL and WL protocols can be customized through the XML syntax ``bl`` and ``wl - two outputs (one regular and another inverted) - a Bit-Line input to load the data - a Word-Line input to enable data write + - (optional) a Word-Line read input to enabe data readback .. warning:: Please do NOT add inverted Bit-Line and Word-Line inputs. It is not supported yet! From dae3554fd49cebe939a964ba62eca005cc754c71 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 11:27:49 -0700 Subject: [PATCH 094/229] [Test] Add a new test case for QL memory bank with flatten BL/WL buses using WLR signals --- .../config/task.conf | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr/config/task.conf new file mode 100644 index 000000000..6d474ea5e --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr/config/task.conf @@ -0,0 +1,44 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +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/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_use_wlr_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +bench1_top = or2 +bench1_chan_width = 300 + +bench2_top = and2_latch +bench2_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 811c898173f0e8a72b01351077fba7b948473f73 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 11:29:45 -0700 Subject: [PATCH 095/229] [Test] Add the QL mem flatten BL/WL with WLR test to basic regression tests --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index cc74b9a4a..b9067ce78 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -58,6 +58,7 @@ run-task basic_tests/full_testbench/ql_memory_bank --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_use_wlr --debug --show_thread_logs run-task basic_tests/full_testbench/multi_region_ql_memory_bank --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_flatten --debug --show_thread_logs +run-task basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr --debug --show_thread_logs echo -e "Testing testbenches without self checking features"; run-task basic_tests/full_testbench/full_testbench_without_self_checking --debug --show_thread_logs From 4aed045cdde64fa37d4f6bb9f5db8540a3dc6395 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 11:34:20 -0700 Subject: [PATCH 096/229] [Arch] Added a new example OpenFPGA architecture which uses WLR signal in ql memory bank with flatten BL/WLs --- .../k4_N4_40nm_qlbankflatten_wlr_openfpga.xml | 202 ++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_wlr_openfpga.xml diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_wlr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_wlr_openfpga.xml new file mode 100644 index 000000000..f786382f0 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_wlr_openfpga.xml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 4400dae108c2b5df5bcb3086432b20cf2191b47f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 11:40:25 -0700 Subject: [PATCH 097/229] [Test] Bug fix in the wrong arch name --- .../ql_memory_bank_flatten_use_wlr/config/task.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr/config/task.conf index 6d474ea5e..04e345775 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr/config/task.conf @@ -17,7 +17,7 @@ fpga_flow=yosys_vpr [OpenFPGA_SHELL] openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga -openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_use_wlr_openfpga.xml +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_wlr_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml openfpga_vpr_device_layout= openfpga_fast_configuration= From 0d72e115ace9e79301bd66c600646d1f98770b2d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 11:53:38 -0700 Subject: [PATCH 098/229] [Engine] Bug fix for the undriven WLR nets in top-level modules --- openfpga/src/fabric/build_top_module_memory_bank.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 63cf7ea77..188efd2f4 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -907,8 +907,8 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, /* Optional: If we have WLR port, we should add a read-back port */ if (!circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR).empty()) { - BasicPort readback_port(std::string(MEMORY_WLR_PORT_NAME), wl_size); - module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort wlr_port(generate_regional_blwl_port_name(std::string(MEMORY_WLR_PORT_NAME), config_region), wl_size); + module_manager.add_port(module_id, wlr_port, ModuleManager::MODULE_INPUT_PORT); } } break; From 6469ee30488e9947efe07466d1d370f3f1a7876e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 12:21:54 -0700 Subject: [PATCH 099/229] [HDL] Update DFF modules by adding custom cells required by shift registers in BL/WLs --- .../openfpga_cell_library/verilog/dff.v | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/openfpga_flow/openfpga_cell_library/verilog/dff.v b/openfpga_flow/openfpga_cell_library/verilog/dff.v index 2eb5765c9..35bea1ec8 100644 --- a/openfpga_flow/openfpga_cell_library/verilog/dff.v +++ b/openfpga_flow/openfpga_cell_library/verilog/dff.v @@ -437,3 +437,61 @@ assign Q = q_reg; assign QN = !Q; endmodule //End Of Module + +//----------------------------------------------------- +// Function : D-type flip-flop with +// - asynchronous active high reset +// @note This DFF is designed to drive BLs when shift registers are used +//----------------------------------------------------- +module BL_DFFRQ ( + input RST, // Reset input + input CK, // Clock Input + input SIN, // Data Input + output SOUT, // Q output + output BL // BL output +); +//------------Internal Variables-------- +reg q_reg; + +//-------------Code Starts Here--------- +always @ ( posedge CK or posedge RST) +if (RST) begin + q_reg <= 1'b0; +end else begin + q_reg <= SIN; +end + +assign SOUT = q_reg; +assign BL = q_reg; + +endmodule //End Of Module + +//----------------------------------------------------- +// Function : D-type flip-flop with +// - asynchronous active high reset +// @note This DFF is designed to drive WLs when shift registers are used +//----------------------------------------------------- +module WL_DFFRQ ( + input RST, // Reset input + input CK, // Clock Input + input SIN, // Data Input + output SOUT, // Q output + output WLW, // Drive WL write signals + output WLR // Drive WL read signals +); +//------------Internal Variables-------- +reg q_reg; + +//-------------Code Starts Here--------- +always @ ( posedge CK or posedge RST) +if (RST) begin + q_reg <= 1'b0; +end else begin + q_reg <= SIN; +end + +assign SOUT = q_reg; +assign WLW = q_reg; +assign WLR = 1'b0; // Use a constant output just for simple testing + +endmodule //End Of Module From 2ce2fb269ae88294d7e1b0c5e8399e0d00cf4b02 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 12:35:13 -0700 Subject: [PATCH 100/229] [HDL] Added a different FF model which is designed to drive WLW only --- .../openfpga_cell_library/verilog/dff.v | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/openfpga_flow/openfpga_cell_library/verilog/dff.v b/openfpga_flow/openfpga_cell_library/verilog/dff.v index 35bea1ec8..da641d785 100644 --- a/openfpga_flow/openfpga_cell_library/verilog/dff.v +++ b/openfpga_flow/openfpga_cell_library/verilog/dff.v @@ -472,6 +472,34 @@ endmodule //End Of Module // @note This DFF is designed to drive WLs when shift registers are used //----------------------------------------------------- module WL_DFFRQ ( + input RST, // Reset input + input CK, // Clock Input + input SIN, // Data Input + output SOUT, // Q output + output WLW // Drive WL write signals +); +//------------Internal Variables-------- +reg q_reg; + +//-------------Code Starts Here--------- +always @ ( posedge CK or posedge RST) +if (RST) begin + q_reg <= 1'b0; +end else begin + q_reg <= SIN; +end + +assign SOUT = q_reg; +assign WLW = q_reg; + +endmodule //End Of Module + +//----------------------------------------------------- +// Function : D-type flip-flop with +// - asynchronous active high reset +// @note This DFF is designed to drive WLs and WLRs when shift registers are used +//----------------------------------------------------- +module WLR_DFFRQ ( input RST, // Reset input input CK, // Clock Input input SIN, // Data Input From 4c04c0fbd7a00a827a3f677df6e87e0bff3d50e3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 12:35:42 -0700 Subject: [PATCH 101/229] [Arch] Reworked the example architecture for QL memory bank using shift register by using the latest HDL models --- .../k4_N4_40nm_qlbanksr_openfpga.xml | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml index 3e04af1c3..c07af9a10 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml @@ -165,21 +165,32 @@ - + - - - + + + + + + + + + + + + + + - - + + From 80232fc4590687e925ba24fc71aacf0adc574532 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 12:36:36 -0700 Subject: [PATCH 102/229] [Arch] Add a new example architecture for QL memory bank using WLR in shift registers --- .../k4_N4_40nm_qlbanksr_wlr_openfpga.xml | 225 ++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml new file mode 100644 index 000000000..9c8e0964c --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 0a2979d61652439b84d38cf43716ab89e3c1b817 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 14:20:35 -0700 Subject: [PATCH 103/229] [Engine] Update readarchopenfpga library by adding new syntax ``num_banks`` as well as update arch writer for BL/WL protocols --- .../libarchopenfpga/src/config_protocol.cpp | 26 +++++++++++++++++++ .../libarchopenfpga/src/config_protocol.h | 10 ++++++- .../src/read_xml_config_protocol.cpp | 12 +++++++-- .../src/write_xml_config_protocol.cpp | 17 ++++++++++-- 4 files changed, 60 insertions(+), 5 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/config_protocol.cpp b/libopenfpga/libarchopenfpga/src/config_protocol.cpp index 948046493..a5aa748e8 100644 --- a/libopenfpga/libarchopenfpga/src/config_protocol.cpp +++ b/libopenfpga/libarchopenfpga/src/config_protocol.cpp @@ -45,6 +45,10 @@ CircuitModelId ConfigProtocol::bl_memory_model() const { return bl_memory_model_; } +size_t ConfigProtocol::bl_num_banks() const { + return bl_num_banks_; +} + e_blwl_protocol_type ConfigProtocol::wl_protocol_type() const { return wl_protocol_type_; } @@ -57,6 +61,10 @@ CircuitModelId ConfigProtocol::wl_memory_model() const { return wl_memory_model_; } +size_t ConfigProtocol::wl_num_banks() const { + return wl_num_banks_; +} + /************************************************************************ * Public Mutators ***********************************************************************/ @@ -100,6 +108,15 @@ void ConfigProtocol::set_bl_memory_model(const CircuitModelId& memory_model) { bl_memory_model_ = memory_model; } +void ConfigProtocol::set_bl_num_banks(const size_t& num_banks) { + if (BLWL_PROTOCOL_SHIFT_REGISTER != bl_protocol_type_) { + VTR_LOG_ERROR("BL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[bl_protocol_type_]); + return; + } + bl_num_banks_ = num_banks; +} + + void ConfigProtocol::set_wl_protocol_type(const e_blwl_protocol_type& type) { if (CONFIG_MEM_QL_MEMORY_BANK != type_) { VTR_LOG_ERROR("WL protocol type is only applicable for configuration protocol '%d'", CONFIG_PROTOCOL_TYPE_STRING[type_]); @@ -123,3 +140,12 @@ void ConfigProtocol::set_wl_memory_model(const CircuitModelId& memory_model) { } wl_memory_model_ = memory_model; } + +void ConfigProtocol::set_wl_num_banks(const size_t& num_banks) { + if (BLWL_PROTOCOL_SHIFT_REGISTER != wl_protocol_type_) { + VTR_LOG_ERROR("WL protocol memory model is only applicable when '%d' is defined", BLWL_PROTOCOL_TYPE_STRING[wl_protocol_type_]); + return; + } + wl_num_banks_ = num_banks; +} + diff --git a/libopenfpga/libarchopenfpga/src/config_protocol.h b/libopenfpga/libarchopenfpga/src/config_protocol.h index 24de1ff47..79bda1a46 100644 --- a/libopenfpga/libarchopenfpga/src/config_protocol.h +++ b/libopenfpga/libarchopenfpga/src/config_protocol.h @@ -29,9 +29,11 @@ class ConfigProtocol { e_blwl_protocol_type bl_protocol_type() const; std::string bl_memory_model_name() const; CircuitModelId bl_memory_model() const; + size_t bl_num_banks() const; e_blwl_protocol_type wl_protocol_type() const; std::string wl_memory_model_name() const; CircuitModelId wl_memory_model() const; + size_t wl_num_banks() const; public: /* Public Mutators */ void set_type(const e_config_protocol_type& type); void set_memory_model_name(const std::string& memory_model_name); @@ -41,9 +43,11 @@ class ConfigProtocol { void set_bl_protocol_type(const e_blwl_protocol_type& type); void set_bl_memory_model_name(const std::string& memory_model_name); void set_bl_memory_model(const CircuitModelId& memory_model); + void set_bl_num_banks(const size_t& num_banks); void set_wl_protocol_type(const e_blwl_protocol_type& type); void set_wl_memory_model_name(const std::string& memory_model_name); void set_wl_memory_model(const CircuitModelId& memory_model); + void set_wl_num_banks(const size_t& num_banks); private: /* Internal data */ /* The type of configuration protocol. * In other words, it is about how to organize and access each configurable memory @@ -58,17 +62,21 @@ class ConfigProtocol { int num_regions_; /* BL & WL protocol: This is only applicable to memory-bank configuration protocols - * - type: defines which protocol to be used. By default, we consider decoders + * - type: defines which protocol to be used. By default, we consider decoders * - bl/wl_memory_model: defines the circuit model to be used when building shift register chains for BL/WL configuration. * It must be a valid CCFF circuit model. This is only applicable when shift-register protocol is selected * for BL or WL. + * - bl/wl_num_banks: defines the number of independent shift register chains (with separated head and tail ports) + * for a given BL protocol per configuration region */ e_blwl_protocol_type bl_protocol_type_ = BLWL_PROTOCOL_DECODER; std::string bl_memory_model_name_; CircuitModelId bl_memory_model_; + size_t bl_num_banks_; e_blwl_protocol_type wl_protocol_type_ = BLWL_PROTOCOL_DECODER; std::string wl_memory_model_name_; CircuitModelId wl_memory_model_; + size_t wl_num_banks_; }; #endif diff --git a/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp b/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp index ebfe64782..c84bbe93b 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -68,9 +68,13 @@ void read_xml_bl_protocol(pugi::xml_node& xml_bl_protocol, config_protocol.set_bl_protocol_type(blwl_protocol_type); - /* Find the memory model, only applicable to shift-registor protocol */ + /* only applicable to shift-registor protocol + * - Find the memory model to build shift register chains + * - Find the number of shift register chains for each protocol + */ if (BLWL_PROTOCOL_SHIFT_REGISTER == blwl_protocol_type) { config_protocol.set_bl_memory_model_name(get_attribute(xml_bl_protocol, "circuit_model_name", loc_data).as_string()); + config_protocol.set_bl_num_banks(get_attribute(xml_bl_protocol, "num_banks", loc_data).as_int(1)); } } @@ -94,9 +98,13 @@ void read_xml_wl_protocol(pugi::xml_node& xml_wl_protocol, config_protocol.set_wl_protocol_type(blwl_protocol_type); - /* Find the memory model, only applicable to shift-registor protocol */ + /* only applicable to shift-registor protocol + * - Find the memory model to build shift register chains + * - Find the number of shift register chains for each protocol + */ if (BLWL_PROTOCOL_SHIFT_REGISTER == blwl_protocol_type) { config_protocol.set_wl_memory_model_name(get_attribute(xml_wl_protocol, "circuit_model_name", loc_data).as_string()); + config_protocol.set_wl_num_banks(get_attribute(xml_wl_protocol, "num_banks", loc_data).as_int(1)); } } diff --git a/libopenfpga/libarchopenfpga/src/write_xml_config_protocol.cpp b/libopenfpga/libarchopenfpga/src/write_xml_config_protocol.cpp index 0f202bf04..7801049a3 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_config_protocol.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_config_protocol.cpp @@ -26,11 +26,24 @@ void write_xml_config_organization(std::fstream& fp, openfpga::check_file_stream(fname, fp); fp << "\t\t" << "" << "\n"; + + /* Output BL/WL protocols */ + fp << "\t\t\t" << "" << "\n"; + + fp << "\t\t\t" << "" << "\n"; + + fp << "\t" << "" << "\n"; } /******************************************************************** From afd03d7eb7b9fc8d23ddb124f21dac4696cb90ba Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 15:56:07 -0700 Subject: [PATCH 104/229] [Engine] Add more check codes for the CCFF circuit model used by BL/WL shift registers --- .../src/check_circuit_library.cpp | 96 +++++++++++++++++++ .../src/check_circuit_library.h | 6 ++ openfpga/src/utils/circuit_library_utils.cpp | 8 +- 3 files changed, 106 insertions(+), 4 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/check_circuit_library.cpp b/libopenfpga/libarchopenfpga/src/check_circuit_library.cpp index 689d1af6f..1a7eb60ed 100644 --- a/libopenfpga/libarchopenfpga/src/check_circuit_library.cpp +++ b/libopenfpga/libarchopenfpga/src/check_circuit_library.cpp @@ -326,6 +326,102 @@ size_t check_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib, return num_err; } +/************************************************************************ + * A function to check the port map of CCFF circuit model used to control BLs + * - Require 1 clock port + * - Require 1 input port as data input (to be driven by other CCFF in a chain) + * - Require 1 output port as data output (to drive other CCFF in a chain) + * - Require 1 BL port as data output / inout (to drive/driven by BLs) + ***********************************************************************/ +size_t check_bl_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model) { + size_t num_err = 0; + + /* Check the type of circuit model */ + VTR_ASSERT(CIRCUIT_MODEL_CCFF == circuit_lib.model_type(circuit_model)); + + /* Check if we have D, Set and Reset */ + /* We can have either 1 input which is D or 2 inputs which are D and scan input */ + size_t num_input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true).size(); + if (1 != num_input_ports) { + VTR_LOG_ERROR("Configuration flip-flop for BL shift register '%s' must have 1 %s port!\n", + circuit_lib.model_name(circuit_model).c_str(), + CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(CIRCUIT_MODEL_PORT_INPUT)]); + num_err++; + } + + num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, + CIRCUIT_MODEL_PORT_INPUT, + num_input_ports, 1, false); + /* Check if we have a clock */ + num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, + CIRCUIT_MODEL_PORT_CLOCK, + 1, 1, true); + + + /* Check if we have 1 output*/ + num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, + CIRCUIT_MODEL_PORT_OUTPUT, + 1, 1, false); + + /* Check if we have 1 bl port */ + num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, + CIRCUIT_MODEL_PORT_BL, + 1, 1, false); + + return num_err; +} + +/************************************************************************ + * A function to check the port map of CCFF circuit model used to control WLs + * - Require 1 clock port + * - Require 1 input port as data input (to be driven by other CCFF in a chain) + * - Require 1 output port as data output (to drive other CCFF in a chain) + * - Require 1 WL port as data output (to drive WLs) + * - Optionally require 1 WLR port as data output (to drive WLRs) + ***********************************************************************/ +size_t check_wl_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model) { + size_t num_err = 0; + + /* Check the type of circuit model */ + VTR_ASSERT(CIRCUIT_MODEL_CCFF == circuit_lib.model_type(circuit_model)); + + /* Check if we have D, Set and Reset */ + /* We can have either 1 input which is D or 2 inputs which are D and scan input */ + size_t num_input_ports = circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_INPUT, true).size(); + if (1 != num_input_ports) { + VTR_LOG_ERROR("Configuration flip-flop for WL shift register '%s' must have 1 %s port!\n", + circuit_lib.model_name(circuit_model).c_str(), + CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(CIRCUIT_MODEL_PORT_INPUT)]); + num_err++; + } + + num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, + CIRCUIT_MODEL_PORT_INPUT, + num_input_ports, 1, false); + /* Check if we have a clock */ + num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, + CIRCUIT_MODEL_PORT_CLOCK, + 1, 1, true); + + + /* Check if we have 1 output*/ + num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, + CIRCUIT_MODEL_PORT_OUTPUT, + 1, 1, false); + + /* Check if we have 1 wl port */ + if (0 < circuit_lib.model_ports_by_type(circuit_model, CIRCUIT_MODEL_PORT_WLR, true).size()) { + num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, + CIRCUIT_MODEL_PORT_WLR, + 1, 1, false); + } + + return num_err; +} + + /************************************************************************ * A function to check the port map of SRAM circuit model ***********************************************************************/ diff --git a/libopenfpga/libarchopenfpga/src/check_circuit_library.h b/libopenfpga/libarchopenfpga/src/check_circuit_library.h index a6690f60c..3d196d7c9 100644 --- a/libopenfpga/libarchopenfpga/src/check_circuit_library.h +++ b/libopenfpga/libarchopenfpga/src/check_circuit_library.h @@ -39,6 +39,12 @@ size_t check_ff_circuit_model_ports(const CircuitLibrary& circuit_lib, size_t check_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model); +size_t check_bl_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model); + +size_t check_wl_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib, + const CircuitModelId& circuit_model); + size_t check_sram_circuit_model_ports(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const bool& check_blwl); diff --git a/openfpga/src/utils/circuit_library_utils.cpp b/openfpga/src/utils/circuit_library_utils.cpp index bb59a0601..45eea879c 100644 --- a/openfpga/src/utils/circuit_library_utils.cpp +++ b/openfpga/src/utils/circuit_library_utils.cpp @@ -305,8 +305,8 @@ bool check_configurable_memory_circuit_model(const ConfigProtocol& config_protoc num_err++; } if (bl_memory_model) { - num_err += check_ccff_circuit_model_ports(circuit_lib, - bl_memory_model); + num_err += check_bl_ccff_circuit_model_ports(circuit_lib, + bl_memory_model); } /* Check circuit model for WL protocol */ @@ -317,8 +317,8 @@ bool check_configurable_memory_circuit_model(const ConfigProtocol& config_protoc num_err++; } if (wl_memory_model) { - num_err += check_ccff_circuit_model_ports(circuit_lib, - wl_memory_model); + num_err += check_wl_ccff_circuit_model_ports(circuit_lib, + wl_memory_model); } break; } From 834bdd2b0707847e082383792c56eb9a085b0669 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 17:29:03 -0700 Subject: [PATCH 105/229] [Engine] Updating fabric generator to support BL/WL shift registers. Still WIP --- .../src/openfpga_reserved_words.h | 8 + .../fabric/build_top_module_memory_bank.cpp | 277 +++++++++++++++++- openfpga/src/utils/memory_bank_utils.cpp | 32 ++ openfpga/src/utils/memory_bank_utils.h | 17 ++ 4 files changed, 331 insertions(+), 3 deletions(-) diff --git a/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h b/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h index af151a7a5..4d51a8f12 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h +++ b/libopenfpga/libopenfpgautil/src/openfpga_reserved_words.h @@ -13,10 +13,18 @@ namespace openfpga { /* Top-level module name */ constexpr char* FPGA_TOP_MODULE_NAME = "fpga_top"; +/* Configuration chain naming constant strings */ constexpr char* CONFIGURABLE_MEMORY_CHAIN_IN_NAME = "ccff_head"; constexpr char* CONFIGURABLE_MEMORY_CHAIN_OUT_NAME = "ccff_tail"; constexpr char* CONFIGURABLE_MEMORY_DATA_OUT_NAME = "mem_out"; constexpr char* CONFIGURABLE_MEMORY_INVERTED_DATA_OUT_NAME = "mem_outb"; +constexpr char* BL_SHIFT_REGISTER_CHAIN_HEAD_NAME = "bl_sr_head"; +constexpr char* BL_SHIFT_REGISTER_CHAIN_TAIL_NAME = "bl_sr_tail"; +constexpr char* BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME = "bl_sr_bl_out"; +constexpr char* WL_SHIFT_REGISTER_CHAIN_HEAD_NAME = "wl_sr_head"; +constexpr char* WL_SHIFT_REGISTER_CHAIN_TAIL_NAME = "wl_sr_tail"; +constexpr char* WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME = "wl_sr_wl_out"; +constexpr char* WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME = "wl_sr_wlr_out"; /* IO PORT */ /* Prefix of global input, output and inout ports of FPGA fabric */ diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 188efd2f4..d3711ba2a 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -30,6 +30,108 @@ /* begin namespace openfpga */ namespace openfpga { +/********************************************************************* + * BL shift register chain module organization + * + * +-------+ +-------+ +-------+ + * chain --->| CCFF |--->| CCFF |--->... --->| CCFF |---->chain + * input&clock | [0] | | [1] | | [N-1] | output + * +-------+ +-------+ +-------+ + * | | ... | config-memory output + * v v v + * +-----------------------------------------+ + * | BLs of configurable modules | + * + ********************************************************************/ +static +void build_bl_shift_register_chain_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const std::string& module_name, + const CircuitModelId& sram_model, + const size_t& num_mems) { + + /* Get the input ports from the SRAM */ + std::vector sram_input_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); + VTR_ASSERT(1 == sram_input_ports.size()); + + /* Get the output ports from the SRAM */ + std::vector sram_output_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + VTR_ASSERT(1 == sram_output_ports.size()); + + /* Get the BL ports from the SRAM */ + std::vector sram_bl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BL, true); + VTR_ASSERT(1 == sram_bl_ports.size()); + + /* Create a module and add to the module manager */ + ModuleId mem_module = module_manager.add_module(module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); + + /* Label module usage */ + module_manager.set_module_usage(mem_module, ModuleManager::MODULE_CONFIG); + + /* Add an input port, which is the head of configuration chain in the module */ + /* TODO: restriction!!! + * consider only the first input of the CCFF model as the D port, + * which will be connected to the head of the chain + */ + BasicPort chain_head_port(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME, + circuit_lib.port_size(sram_input_ports[0])); + module_manager.add_port(mem_module, chain_head_port, ModuleManager::MODULE_INPUT_PORT); + + /* Add an output port, which is the tail of configuration chain in the module */ + /* TODO: restriction!!! + * consider only the first output of the CCFF model as the Q port, + * which will be connected to the tail of the chain + */ + BasicPort chain_tail_port(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME, + circuit_lib.port_size(sram_output_ports[0])); + module_manager.add_port(mem_module, chain_tail_port, ModuleManager::MODULE_OUTPUT_PORT); + + /* Add the output ports to output BL signals */ + BasicPort chain_bl_port(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME, + num_mems); + module_manager.add_port(mem_module, chain_bl_port, ModuleManager::MODULE_OUTPUT_PORT); + + /* Find the sram module in the module manager */ + ModuleId sram_mem_module = module_manager.find_module(circuit_lib.model_name(sram_model)); + + /* Instanciate each submodule */ + for (size_t i = 0; i < num_mems; ++i) { + size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); + module_manager.add_child_module(mem_module, sram_mem_module); + module_manager.add_configurable_child(mem_module, sram_mem_module, sram_mem_instance); + + /* Build module nets to wire bl outputs of sram modules to BL outputs of memory module */ + for (size_t iport = 0; iport < num_bl_ports; ++iport) { + CircuitPortId child_module_output_port = sram_bl_ports[iport]; + std::string chain_output_port_name = std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME); + std::vector output_nets = add_module_output_nets_to_chain_mem_modules(module_manager, mem_module, + chan_output_port_name, circuit_lib, + child_module_output_port, + sram_mem_module, i, sram_mem_instance); + } + } + + /* Build module nets to wire the configuration chain */ + add_module_nets_to_cmos_memory_config_chain_module(module_manager, mem_module, + circuit_lib, sram_input_ports[0], sram_output_ports[0]); + + /* If there is a second input defined, + * add nets to short wire the 2nd inputs to the first inputs + */ + if (2 == sram_input_ports.size()) { + add_module_nets_to_cmos_memory_scan_chain_module(module_manager, mem_module, + circuit_lib, sram_input_ports[1], sram_output_ports[0]); + } + + /* Add global ports to the pb_module: + * This is a much easier job after adding sub modules (instances), + * we just need to find all the global ports from the child modules and build a list of it + */ + add_module_global_ports_from_child_modules(module_manager, mem_module); +} + + /********************************************************************* * This function to add nets for quicklogic memory banks * Each configuration region has independent memory bank circuitry @@ -640,6 +742,161 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(ModuleManager } } +/********************************************************************* + * This function to add nets for quicklogic memory banks using shift registers to manipulate BL/WLs + * Each configuration region has independent BL/WL shift register banks + * - Find the number of BLs and WLs required for each region + * - Find the number of BL and WL shift register chains required for each region + * - Create the module of shift register chain for each unique size + * - Create nets to connect from top-level module inputs to BL/WL shift register chains + * - Create nets to connect from BL/WL shift register chains to BL/WL of configurable children + * + * @note this function only adds the BL protocol + * + * Detailed schematic of each memory bank: + * @note The numbers are just made to show a simplified example, practical cases are more complicated! + * + * sr_clk sr_head sr_tail + * | | ^ + * v v | + * +-------------------------------------------------+ + * | Bit Line shift register chains | + * +-------------------------------------------------+ + * | | | + * +---------+ BL[0:9] BL[10:17] BL[18:22] + * | | | | | + * | | | | | + * | Word |--WL[0:3]-->-----------+---------------+---- ... |------+--> + * | | | | | | | | + * | Line | | v | v | v + * | | | +-------+ | +-------+ | +------+ + * | shift | +-->| SRAM | +-->| SRAM | +->| SRAM | + * | | | | [0:8] | | | [0:5] | ... | | [0:7]| + * | register| | +-------+ | +-------+ | +------+ + * | | | | | + * | chains |--WL[4:14] -----------+--------------+--------- | -----+--> + * | | | | | | | | + * | | | v | v | v + * | | | +-------+ | +-------+ | +-------+ + * | | +-->| SRAM | | | SRAM | +->| SRAM | + * | | | | [0:80]| | | [0:63]| ... | | [0:31]| + * | | | +-------+ | +-------+ | +-------+ + * | | | | + * | | | ... ... ... | ... + * | | | | | + * | |--WL[15:18] -----------+---------------+---- --- | -----+--> + * | | | | | | | | + * | | | v | v | v + * +---------+ | +-------+ | +-------+ | +-------+ + * +-->| SRAM | +-->| SRAM | +->| SRAM | + * | |[0:5] | | | [0:8] | ... | | [0:2] | + * | +-------+ | +-------+ | +-------+ + * v v v + * WL[0:9] WL[0:7] WL[0:4] + * + **********************************************************************/ +static +void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(ModuleManager& module_manager, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol) { + CircuitModelId sram_model = config_protocol.memory_model(); + CircuitModelId bl_memory_model = config_protocol.bl_memory_model(); + /* Find out the unique shift register chain sizes */ + std::vector unique_sr_sizes; + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + /* TODO: Need to find how to cut the BLs when there are multiple banks for shift registers in a region */ + size_t num_bls = compute_memory_bank_regional_num_bls(module_manager, top_module, + config_region, + circuit_lib, sram_model); + unique_sr_sizes.push_back(num_bls); + } + + /* TODO: Build submodules for shift register chains */ + //for (const size_t& sr_size : unique_sr_sizes) { + // std::string sr_module_name = generate_bl_shift_register_module_name(bl_memory_model, sr_size); + // ModuleId sr_bank_module = build_bl_shift_register_chain_module(module_manager, + // circuit_lib, + // sr_module_name, + // bl_memory_model, + // sr_size); + //} + + /* TODO: Instanciate the shift register chains in the top-level module */ + //module_manager.add_child_module(top_module, sr_bank_module); + + /* TODO: create connections between top-level module and the BL shift register banks */ + + /* Create connections between BLs of top-level module and BLs of child modules for each region */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + /************************************************************** + * Precompute the BLs and WLs distribution across the FPGA fabric + * The distribution is a matrix which contains the starting index of BL/WL for each column or row + */ + std::pair child_x_range = compute_memory_bank_regional_configurable_child_x_range(module_manager, top_module, config_region); + std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, + config_region, + circuit_lib, sram_model); + std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); + + /************************************************************** + * Add BL nets from top module to each configurable child + * BL pins of top module are connected to the BL input pins of each PB/CB/SB + * For all the PB/CB/SB in the same column, they share the same set of BLs + * A quick example + * + * BL[i .. i + sqrt(N)] + * | + * | CLB[1][H] + * | +---------+ + * | | SRAM | + * +-->| [0..N] | + * | +---------+ + * | + * ... + * | CLB[1][1] + * | +---------+ + * | | SRAM | + * +-->| [0..N] | + * | +---------+ + * | + */ + ModulePortId top_module_bl_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), config_region)); + BasicPort top_module_bl_port_info = module_manager.module_port(top_module, top_module_bl_port); + + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the BL port */ + ModulePortId child_bl_port = module_manager.find_module_port(child_module, std::string(MEMORY_BL_PORT_NAME)); + BasicPort child_bl_port_info = module_manager.module_port(child_module, child_bl_port); + + size_t cur_bl_index = 0; + + for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { + size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index; + VTR_ASSERT(bl_pin_id < top_module_bl_port_info.pins().size()); + + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + top_module, 0, + top_module_bl_port, + top_module_bl_port_info.pins()[bl_pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_bl_port, sink_bl_pin); + + cur_bl_index++; + } + } + } +} + /********************************************************************* * Top-level function to add nets for quicklogic memory banks using flatten BL/WLs * Each configuration region has independent BL/WLs @@ -778,7 +1035,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { - /* TODO */ + add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(module_manager, top_module, circuit_lib, config_protocol); break; } default: { @@ -872,7 +1129,14 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { - /* TODO */ + /* Each region will have independent shift register banks */ + for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + size_t num_heads = config_protocol.bl_num_banks(); + BasicPort blsr_head_port(generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), num_heads); + module_manager.add_port(module_id, blsr_head_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort blsr_tail_port(generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), num_heads); + module_manager.add_port(module_id, blsr_tail_port, ModuleManager::MODULE_INPUT_PORT); + } break; } default: { @@ -914,7 +1178,14 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { - /* TODO */ + /* Each region will have independent shift register banks */ + for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { + size_t num_heads = config_protocol.wl_num_banks(); + BasicPort wlsr_head_port(generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), num_heads); + module_manager.add_port(module_id, wlsr_head_port, ModuleManager::MODULE_INPUT_PORT); + BasicPort wlsr_tail_port(generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), num_heads); + module_manager.add_port(module_id, wlsr_tail_port, ModuleManager::MODULE_INPUT_PORT); + } break; } default: { diff --git a/openfpga/src/utils/memory_bank_utils.cpp b/openfpga/src/utils/memory_bank_utils.cpp index 66eb938f3..dcb224fc6 100644 --- a/openfpga/src/utils/memory_bank_utils.cpp +++ b/openfpga/src/utils/memory_bank_utils.cpp @@ -84,6 +84,22 @@ size_t find_module_ql_memory_bank_num_blwls(const ModuleManager& module_manager, return num_blwls; } +size_t compute_memory_bank_regional_num_bls(const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigRegionId& config_region, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model) { + size_t num_bls = 0; + + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + num_bls += find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_BL); + } + + return num_bls; +} + std::map compute_memory_bank_regional_bitline_numbers_per_tile(const ModuleManager& module_manager, const ModuleId& top_module, const ConfigRegionId& config_region, @@ -100,6 +116,22 @@ std::map compute_memory_bank_regional_bitline_numbers_per_tile(cons return num_bls_per_tile; } +size_t compute_memory_bank_regional_num_wls(const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigRegionId& config_region, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model) { + size_t num_wls = 0; + + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + num_wls += find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_WL); + } + + return num_wls; +} + std::map compute_memory_bank_regional_wordline_numbers_per_tile(const ModuleManager& module_manager, const ModuleId& top_module, const ConfigRegionId& config_region, diff --git a/openfpga/src/utils/memory_bank_utils.h b/openfpga/src/utils/memory_bank_utils.h index 237098927..730d19271 100644 --- a/openfpga/src/utils/memory_bank_utils.h +++ b/openfpga/src/utils/memory_bank_utils.h @@ -48,6 +48,14 @@ size_t find_module_ql_memory_bank_num_blwls(const ModuleManager& module_manager, const CircuitModelId& sram_model, const e_config_protocol_type& sram_orgz_type, const e_circuit_model_port_type& circuit_port_type); +/** + * @brief Precompute the total number of bit lines required by a specific configuration region + */ +size_t compute_memory_bank_regional_num_bls(const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigRegionId& config_region, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model); /** * @brief Precompute the number of bit lines required by each tile under a specific configuration region @@ -60,6 +68,15 @@ std::map compute_memory_bank_regional_bitline_numbers_per_tile(cons const ConfigRegionId& config_region, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model); +/** + * @brief Precompute the total number of word lines required by a specific configuration region + */ +size_t compute_memory_bank_regional_num_wls(const ModuleManager& module_manager, + const ModuleId& top_module, + const ConfigRegionId& config_region, + const CircuitLibrary& circuit_lib, + const CircuitModelId& sram_model); + /** * @brief Precompute the number of word lines required by each tile under a specific configuration region * @note From 7723e00e6c46e3b50b1e7e199ea782cecf7c73ca Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 22:49:24 -0700 Subject: [PATCH 106/229] [Engine] Adding the function that builds a shift register module for BL/WLs --- openfpga/src/base/openfpga_naming.cpp | 17 ++ openfpga/src/base/openfpga_naming.h | 6 + openfpga/src/fabric/build_memory_modules.cpp | 2 - openfpga/src/fabric/build_memory_modules.h | 16 + .../fabric/build_top_module_memory_bank.cpp | 282 ++++++++++++++++-- 5 files changed, 295 insertions(+), 28 deletions(-) diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index c3fdd3aa8..403ce4907 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -822,6 +822,23 @@ std::string generate_regional_blwl_port_name(const std::string& blwl_port_prefix return blwl_port_prefix + std::string("_config_region_") + std::to_string(size_t(region_id)); } +/********************************************************************* + * Generate the module name for a shift register chain which configures BLs + *********************************************************************/ +std::string generate_bl_shift_register_module_name(const std::string& memory_model_name, + const size_t& shift_register_size) { + return std::string("bl_shift_register_") + memory_model_name + std::string("_size") + std::to_string(shift_register_size); +} + +/********************************************************************* + * Generate the module name for a shift register chain which configures WLs + *********************************************************************/ +std::string generate_wl_shift_register_module_name(const std::string& memory_model_name, + const size_t& shift_register_size) { + return std::string("wl_shift_register_") + memory_model_name + std::string("_size") + std::to_string(shift_register_size); +} + + /********************************************************************* * Generate the port name for the input bus of a routing multiplexer * This is very useful in Verilog code generation where the inputs of diff --git a/openfpga/src/base/openfpga_naming.h b/openfpga/src/base/openfpga_naming.h index 77a46e4a6..3e159a663 100644 --- a/openfpga/src/base/openfpga_naming.h +++ b/openfpga/src/base/openfpga_naming.h @@ -187,6 +187,12 @@ std::string generate_sram_local_port_name(const CircuitLibrary& circuit_lib, std::string generate_regional_blwl_port_name(const std::string& blwl_port_prefix, const ConfigRegionId& region_id); +std::string generate_bl_shift_register_module_name(const std::string& memory_model_name, + const size_t& shift_register_size); + +std::string generate_wl_shift_register_module_name(const std::string& memory_model_name, + const size_t& shift_register_size); + std::string generate_mux_input_bus_port_name(const CircuitLibrary& circuit_lib, const CircuitModelId& mux_model, const size_t& mux_size, diff --git a/openfpga/src/fabric/build_memory_modules.cpp b/openfpga/src/fabric/build_memory_modules.cpp index a8f7fceb4..844369fa9 100644 --- a/openfpga/src/fabric/build_memory_modules.cpp +++ b/openfpga/src/fabric/build_memory_modules.cpp @@ -78,7 +78,6 @@ void add_module_input_nets_to_mem_modules(ModuleManager& module_manager, * pin of output port of the memory module, where W is the size of port * 3. It assumes fixed port name for output ports ********************************************************************/ -static std::vector add_module_output_nets_to_chain_mem_modules(ModuleManager& module_manager, const ModuleId& mem_module, const std::string& mem_module_output_name, @@ -162,7 +161,6 @@ void add_module_output_nets_to_mem_modules(ModuleManager& module_manager, * Do not use it to replace the * add_module_nets_cmos_memory_chain_config_bus() !!! *********************************************************************/ -static void add_module_nets_to_cmos_memory_config_chain_module(ModuleManager& module_manager, const ModuleId& parent_module, const CircuitLibrary& circuit_lib, diff --git a/openfpga/src/fabric/build_memory_modules.h b/openfpga/src/fabric/build_memory_modules.h index 3551426a2..6b6794d46 100644 --- a/openfpga/src/fabric/build_memory_modules.h +++ b/openfpga/src/fabric/build_memory_modules.h @@ -16,6 +16,22 @@ /* begin namespace openfpga */ namespace openfpga { +std::vector add_module_output_nets_to_chain_mem_modules(ModuleManager& module_manager, + const ModuleId& mem_module, + const std::string& mem_module_output_name, + const CircuitLibrary& circuit_lib, + const CircuitPortId& circuit_port, + const ModuleId& child_module, + const size_t& child_index, + const size_t& child_instance); + +void add_module_nets_to_cmos_memory_config_chain_module(ModuleManager& module_manager, + const ModuleId& parent_module, + const CircuitLibrary& circuit_lib, + const CircuitPortId& model_input_port, + const CircuitPortId& model_output_port); + + void build_memory_modules(ModuleManager& module_manager, DecoderLibrary& arch_decoder_lib, const MuxLibrary& mux_lib, diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index d3711ba2a..ae1a792fd 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -24,6 +24,7 @@ #include "decoder_library_utils.h" #include "module_manager_utils.h" #include "memory_bank_utils.h" +#include "build_memory_modules.h" #include "build_decoder_modules.h" #include "build_top_module_memory_bank.h" @@ -44,11 +45,11 @@ namespace openfpga { * ********************************************************************/ static -void build_bl_shift_register_chain_module(ModuleManager& module_manager, - const CircuitLibrary& circuit_lib, - const std::string& module_name, - const CircuitModelId& sram_model, - const size_t& num_mems) { +ModuleId build_bl_shift_register_chain_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const std::string& module_name, + const CircuitModelId& sram_model, + const size_t& num_mems) { /* Get the input ports from the SRAM */ std::vector sram_input_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); @@ -102,13 +103,12 @@ void build_bl_shift_register_chain_module(ModuleManager& module_manager, module_manager.add_configurable_child(mem_module, sram_mem_module, sram_mem_instance); /* Build module nets to wire bl outputs of sram modules to BL outputs of memory module */ - for (size_t iport = 0; iport < num_bl_ports; ++iport) { - CircuitPortId child_module_output_port = sram_bl_ports[iport]; + for (const auto& child_module_output_port : sram_bl_ports) { std::string chain_output_port_name = std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME); - std::vector output_nets = add_module_output_nets_to_chain_mem_modules(module_manager, mem_module, - chan_output_port_name, circuit_lib, - child_module_output_port, - sram_mem_module, i, sram_mem_instance); + add_module_output_nets_to_chain_mem_modules(module_manager, mem_module, + chain_output_port_name, circuit_lib, + child_module_output_port, + sram_mem_module, i, sram_mem_instance); } } @@ -116,21 +116,121 @@ void build_bl_shift_register_chain_module(ModuleManager& module_manager, add_module_nets_to_cmos_memory_config_chain_module(module_manager, mem_module, circuit_lib, sram_input_ports[0], sram_output_ports[0]); - /* If there is a second input defined, - * add nets to short wire the 2nd inputs to the first inputs + /* Add global ports to the pb_module: + * This is a much easier job after adding sub modules (instances), + * we just need to find all the global ports from the child modules and build a list of it */ - if (2 == sram_input_ports.size()) { - add_module_nets_to_cmos_memory_scan_chain_module(module_manager, mem_module, - circuit_lib, sram_input_ports[1], sram_output_ports[0]); + add_module_global_ports_from_child_modules(module_manager, mem_module); + + return mem_module; +} + +/********************************************************************* + * WL shift register chain module organization + * + * +-------+ +-------+ +-------+ + * chain --->| CCFF |--->| CCFF |--->... --->| CCFF |---->chain + * input&clock | [0] | | [1] | | [N-1] | output + * +-------+ +-------+ +-------+ + * | | ... | config-memory output + * v v v + * +-----------------------------------------+ + * | WL/WLRs of configurable modules | + * + ********************************************************************/ +static +ModuleId build_wl_shift_register_chain_module(ModuleManager& module_manager, + const CircuitLibrary& circuit_lib, + const std::string& module_name, + const CircuitModelId& sram_model, + const size_t& num_mems) { + + /* Get the input ports from the SRAM */ + std::vector sram_input_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true); + VTR_ASSERT(1 == sram_input_ports.size()); + + /* Get the output ports from the SRAM */ + std::vector sram_output_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, true); + VTR_ASSERT(1 == sram_output_ports.size()); + + /* Get the WL ports from the SRAM */ + std::vector sram_wl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WL, true); + VTR_ASSERT(1 == sram_wl_ports.size()); + + /* Get the optional WLR ports from the SRAM */ + std::vector sram_wlr_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR, true); + VTR_ASSERT(0 == sram_wlr_ports.size() || 1 == sram_wlr_ports.size()); + + /* Create a module and add to the module manager */ + ModuleId mem_module = module_manager.add_module(module_name); + VTR_ASSERT(true == module_manager.valid_module_id(mem_module)); + + /* Label module usage */ + module_manager.set_module_usage(mem_module, ModuleManager::MODULE_CONFIG); + + /* Add an input port, which is the head of configuration chain in the module */ + /* TODO: restriction!!! + * consider only the first input of the CCFF model as the D port, + * which will be connected to the head of the chain + */ + BasicPort chain_head_port(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME, + circuit_lib.port_size(sram_input_ports[0])); + module_manager.add_port(mem_module, chain_head_port, ModuleManager::MODULE_INPUT_PORT); + + /* Add an output port, which is the tail of configuration chain in the module */ + /* TODO: restriction!!! + * consider only the first output of the CCFF model as the Q port, + * which will be connected to the tail of the chain + */ + BasicPort chain_tail_port(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME, + circuit_lib.port_size(sram_output_ports[0])); + module_manager.add_port(mem_module, chain_tail_port, ModuleManager::MODULE_OUTPUT_PORT); + + /* Add the output ports to output BL signals */ + BasicPort chain_wl_port(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME, + num_mems); + module_manager.add_port(mem_module, chain_wl_port, ModuleManager::MODULE_OUTPUT_PORT); + + /* Find the sram module in the module manager */ + ModuleId sram_mem_module = module_manager.find_module(circuit_lib.model_name(sram_model)); + + /* Instanciate each submodule */ + for (size_t i = 0; i < num_mems; ++i) { + size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module); + module_manager.add_child_module(mem_module, sram_mem_module); + module_manager.add_configurable_child(mem_module, sram_mem_module, sram_mem_instance); + + /* Build module nets to wire wl outputs of sram modules to WL outputs of memory module */ + for (const auto& child_module_output_port : sram_wl_ports) { + std::string chain_output_port_name = std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME); + add_module_output_nets_to_chain_mem_modules(module_manager, mem_module, + chain_output_port_name, circuit_lib, + child_module_output_port, + sram_mem_module, i, sram_mem_instance); + } + + /* Build module nets to wire wlr outputs of sram modules to WLR outputs of memory module */ + for (const auto& child_module_output_port : sram_wlr_ports) { + std::string chain_output_port_name = std::string(WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME); + add_module_output_nets_to_chain_mem_modules(module_manager, mem_module, + chain_output_port_name, circuit_lib, + child_module_output_port, + sram_mem_module, i, sram_mem_instance); + } } + /* Build module nets to wire the configuration chain */ + add_module_nets_to_cmos_memory_config_chain_module(module_manager, mem_module, + circuit_lib, sram_input_ports[0], sram_output_ports[0]); + /* Add global ports to the pb_module: * This is a much easier job after adding sub modules (instances), * we just need to find all the global ports from the child modules and build a list of it */ add_module_global_ports_from_child_modules(module_manager, mem_module); -} + return mem_module; +} /********************************************************************* * This function to add nets for quicklogic memory banks @@ -813,14 +913,14 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module } /* TODO: Build submodules for shift register chains */ - //for (const size_t& sr_size : unique_sr_sizes) { - // std::string sr_module_name = generate_bl_shift_register_module_name(bl_memory_model, sr_size); - // ModuleId sr_bank_module = build_bl_shift_register_chain_module(module_manager, - // circuit_lib, - // sr_module_name, - // bl_memory_model, - // sr_size); - //} + for (const size_t& sr_size : unique_sr_sizes) { + std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), sr_size); + ModuleId sr_bank_module = build_bl_shift_register_chain_module(module_manager, + circuit_lib, + sr_module_name, + bl_memory_model, + sr_size); + } /* TODO: Instanciate the shift register chains in the top-level module */ //module_manager.add_child_module(top_module, sr_bank_module); @@ -1002,6 +1102,136 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(ModuleManager } } +/********************************************************************* + * Top-level function to add nets for quicklogic memory banks using shift registers to control BL/WLs + * + * @note this function only adds the WL configuration bus + * + * @note see detailed explanation on the bus connection in function add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus() + **********************************************************************/ +static +void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(ModuleManager& module_manager, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol) { + CircuitModelId sram_model = config_protocol.memory_model(); + CircuitModelId wl_memory_model = config_protocol.wl_memory_model(); + /* Find out the unique shift register chain sizes */ + std::vector unique_sr_sizes; + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + /* TODO: Need to find how to cut the BLs when there are multiple banks for shift registers in a region */ + size_t num_wls = compute_memory_bank_regional_num_wls(module_manager, top_module, + config_region, + circuit_lib, sram_model); + unique_sr_sizes.push_back(num_wls); + } + + /* TODO: Build submodules for shift register chains */ + for (const size_t& sr_size : unique_sr_sizes) { + std::string sr_module_name = generate_wl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), sr_size); + ModuleId sr_bank_module = build_wl_shift_register_chain_module(module_manager, + circuit_lib, + sr_module_name, + wl_memory_model, + sr_size); + } + + /* TODO: Instanciate the shift register chains in the top-level module */ + //module_manager.add_child_module(top_module, sr_bank_module); + + /* TODO: create connections between top-level module and the BL shift register banks */ + + /* Create connections between WLs of top-level module and WLs of child modules for each region */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + /************************************************************** + * Precompute the BLs and WLs distribution across the FPGA fabric + * The distribution is a matrix which contains the starting index of BL/WL for each column or row + */ + std::pair child_y_range = compute_memory_bank_regional_configurable_child_y_range(module_manager, top_module, config_region); + std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, + config_region, + circuit_lib, sram_model); + std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); + + /************************************************************** + * Add WL nets from top module to each configurable child + */ + ModulePortId top_module_wl_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region)); + BasicPort top_module_wl_port_info = module_manager.module_port(top_module, top_module_wl_port); + + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the WL port */ + ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME)); + BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port); + + size_t cur_wl_index = 0; + + for (const size_t& sink_wl_pin : child_wl_port_info.pins()) { + size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + cur_wl_index; + VTR_ASSERT(wl_pin_id < top_module_wl_port_info.pins().size()); + + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + top_module, 0, + top_module_wl_port, + top_module_wl_port_info.pins()[wl_pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_wl_port, sink_wl_pin); + + cur_wl_index++; + } + } + + /************************************************************** + * Optional: Add WLR nets from top module to each configurable child + */ + ModulePortId top_module_wlr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WLR_PORT_NAME), config_region)); + BasicPort top_module_wlr_port_info; + if (top_module_wlr_port) { + top_module_wlr_port_info = module_manager.module_port(top_module, top_module_wlr_port); + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; + + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the WL port */ + ModulePortId child_wlr_port = module_manager.find_module_port(child_module, std::string(MEMORY_WLR_PORT_NAME)); + BasicPort child_wlr_port_info = module_manager.module_port(child_module, child_wlr_port); + + size_t cur_wlr_index = 0; + + for (const size_t& sink_wlr_pin : child_wlr_port_info.pins()) { + size_t wlr_pin_id = wl_start_index_per_tile[coord.y()] + cur_wlr_index; + VTR_ASSERT(wlr_pin_id < top_module_wlr_port_info.pins().size()); + + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + top_module, 0, + top_module_wlr_port, + top_module_wlr_port_info.pins()[wlr_pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_wlr_port, sink_wlr_pin); + + cur_wlr_index++; + } + } + } + } +} + + /********************************************************************* * Top-level function to add nets for quicklogic memory banks * - Each configuration region has independent memory bank circuitry @@ -1054,7 +1284,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { - /* TODO */ + add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(module_manager, top_module, circuit_lib, config_protocol); break; } default: { From 5da8f1db735e935dec38f9a08d8d0baad74c387f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 28 Sep 2021 23:27:47 -0700 Subject: [PATCH 107/229] [Engine] Upgrading fabric generator to connect nets between top module and BL/WL shift register modules --- openfpga/src/fabric/build_top_module.cpp | 13 +- .../fabric/build_top_module_memory_bank.cpp | 121 +++++++++++++++++- 2 files changed, 121 insertions(+), 13 deletions(-) diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 421b7198a..4fc4c396f 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -341,12 +341,6 @@ int build_top_module(ModuleManager& module_manager, tile_direct, arch_direct); } - /* Add global ports to the pb_module: - * This is a much easier job after adding sub modules (instances), - * we just need to find all the global ports from the child modules and build a list of it - */ - add_module_global_ports_from_child_modules(module_manager, top_module); - /* Add global ports from grid ports that are defined as global in tile annotation */ status = add_top_module_global_ports_from_grid_modules(module_manager, top_module, tile_annotation, vpr_device_annotation, grids, grid_instance_ids); if (CMD_EXEC_FATAL_ERROR == status) { @@ -427,6 +421,13 @@ int build_top_module(ModuleManager& module_manager, top_module_num_config_bits); } + /* Add global ports to the top module: + * This is a much easier job after adding sub modules (instances), + * we just need to find all the global ports from the child modules and build a list of it + * @note This function is called after the add_top_module_nets_memory_config_bus() because it may add some sub modules + */ + add_module_global_ports_from_child_modules(module_manager, top_module); + return status; } diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index ae1a792fd..8b332e08d 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -912,7 +912,7 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module unique_sr_sizes.push_back(num_bls); } - /* TODO: Build submodules for shift register chains */ + /* Build submodules for shift register chains */ for (const size_t& sr_size : unique_sr_sizes) { std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), sr_size); ModuleId sr_bank_module = build_bl_shift_register_chain_module(module_manager, @@ -920,12 +920,65 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module sr_module_name, bl_memory_model, sr_size); + /* Instanciate the shift register chains in the top-level module */ + module_manager.add_child_module(top_module, sr_bank_module); } - /* TODO: Instanciate the shift register chains in the top-level module */ - //module_manager.add_child_module(top_module, sr_bank_module); + /* TODO: create connections between top-level module and the BL shift register banks + * - Connect the head port from top-level module to each shift register bank + * - Connect the tail port from each shift register bank to top-level module + */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + ModulePortId blsr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region)); + BasicPort blsr_head_port_info = module_manager.module_port(top_module, blsr_head_port); - /* TODO: create connections between top-level module and the BL shift register banks */ + for (const size_t& sr_size : unique_sr_sizes) { + std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), sr_size); + ModuleId child_sr_module = module_manager.find_module(sr_module_name); + ModulePortId child_blsr_head_port = module_manager.find_module_port(child_sr_module, std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME)); + BasicPort child_blsr_head_port_info = module_manager.module_port(child_sr_module, child_blsr_head_port); + for (size_t child_instance = 0; child_instance < module_manager.num_instance(top_module, child_sr_module); ++child_instance) { + for (const size_t& sink_pin : child_blsr_head_port_info.pins()) { + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + top_module, 0, + blsr_head_port, + blsr_head_port_info.pins()[sink_pin]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + child_sr_module, child_instance, child_blsr_head_port, sink_pin); + } + } + } + } + + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + ModulePortId blsr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region)); + BasicPort blsr_tail_port_info = module_manager.module_port(top_module, blsr_tail_port); + + for (const size_t& sr_size : unique_sr_sizes) { + std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), sr_size); + ModuleId child_sr_module = module_manager.find_module(sr_module_name); + ModulePortId child_blsr_tail_port = module_manager.find_module_port(child_sr_module, std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); + BasicPort child_blsr_tail_port_info = module_manager.module_port(child_sr_module, child_blsr_tail_port); + for (size_t child_instance = 0; child_instance < module_manager.num_instance(top_module, child_sr_module); ++child_instance) { + for (const size_t& sink_pin : child_blsr_tail_port_info.pins()) { + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + child_sr_module, child_instance, + child_blsr_tail_port, sink_pin); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + top_module, 0, + blsr_tail_port, blsr_tail_port_info.pins()[sink_pin]); + } + } + } + } /* Create connections between BLs of top-level module and BLs of child modules for each region */ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { @@ -1134,12 +1187,66 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module sr_module_name, wl_memory_model, sr_size); + /* Instanciate the shift register chains in the top-level module */ + module_manager.add_child_module(top_module, sr_bank_module); } - /* TODO: Instanciate the shift register chains in the top-level module */ - //module_manager.add_child_module(top_module, sr_bank_module); + /* TODO: create connections between top-level module and the WL shift register banks + * - Connect the head port from top-level module to each shift register bank + * - Connect the tail port from each shift register bank to top-level module + */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + ModulePortId wlsr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region)); + BasicPort wlsr_head_port_info = module_manager.module_port(top_module, wlsr_head_port); + + for (const size_t& sr_size : unique_sr_sizes) { + std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), sr_size); + ModuleId child_sr_module = module_manager.find_module(sr_module_name); + ModulePortId child_wlsr_head_port = module_manager.find_module_port(child_sr_module, std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME)); + BasicPort child_wlsr_head_port_info = module_manager.module_port(child_sr_module, child_wlsr_head_port); + for (size_t child_instance = 0; child_instance < module_manager.num_instance(top_module, child_sr_module); ++child_instance) { + for (const size_t& sink_pin : child_wlsr_head_port_info.pins()) { + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + top_module, 0, + wlsr_head_port, + wlsr_head_port_info.pins()[sink_pin]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + child_sr_module, child_instance, child_wlsr_head_port, sink_pin); + } + } + } + } + + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + ModulePortId wlsr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region)); + BasicPort wlsr_tail_port_info = module_manager.module_port(top_module, wlsr_tail_port); + + for (const size_t& sr_size : unique_sr_sizes) { + std::string sr_module_name = generate_wl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), sr_size); + ModuleId child_sr_module = module_manager.find_module(sr_module_name); + ModulePortId child_wlsr_tail_port = module_manager.find_module_port(child_sr_module, std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); + BasicPort child_wlsr_tail_port_info = module_manager.module_port(child_sr_module, child_wlsr_tail_port); + for (size_t child_instance = 0; child_instance < module_manager.num_instance(top_module, child_sr_module); ++child_instance) { + for (const size_t& sink_pin : child_wlsr_tail_port_info.pins()) { + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + child_sr_module, child_instance, + child_wlsr_tail_port, sink_pin); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + top_module, 0, + wlsr_tail_port, wlsr_tail_port_info.pins()[sink_pin]); + } + } + } + } - /* TODO: create connections between top-level module and the BL shift register banks */ /* Create connections between WLs of top-level module and WLs of child modules for each region */ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { From c5ae93f1778f1d3ffd28bc32e0b66fcef74565bd Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 29 Sep 2021 16:17:40 -0700 Subject: [PATCH 108/229] [Engine] Upgraded fabric generator to support shifter register banks in Quicklogic memory bank --- .../fabric/build_top_module_memory_bank.cpp | 662 +++++++++--------- .../memory_bank_shift_register_banks.cpp | 80 +++ .../fabric/memory_bank_shift_register_banks.h | 67 ++ 3 files changed, 468 insertions(+), 341 deletions(-) create mode 100644 openfpga/src/fabric/memory_bank_shift_register_banks.cpp create mode 100644 openfpga/src/fabric/memory_bank_shift_register_banks.h diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 8b332e08d..a6a0ca564 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -26,6 +26,7 @@ #include "memory_bank_utils.h" #include "build_memory_modules.h" #include "build_decoder_modules.h" +#include "memory_bank_shift_register_banks.h" #include "build_top_module_memory_bank.h" /* begin namespace openfpga */ @@ -842,214 +843,6 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(ModuleManager } } -/********************************************************************* - * This function to add nets for quicklogic memory banks using shift registers to manipulate BL/WLs - * Each configuration region has independent BL/WL shift register banks - * - Find the number of BLs and WLs required for each region - * - Find the number of BL and WL shift register chains required for each region - * - Create the module of shift register chain for each unique size - * - Create nets to connect from top-level module inputs to BL/WL shift register chains - * - Create nets to connect from BL/WL shift register chains to BL/WL of configurable children - * - * @note this function only adds the BL protocol - * - * Detailed schematic of each memory bank: - * @note The numbers are just made to show a simplified example, practical cases are more complicated! - * - * sr_clk sr_head sr_tail - * | | ^ - * v v | - * +-------------------------------------------------+ - * | Bit Line shift register chains | - * +-------------------------------------------------+ - * | | | - * +---------+ BL[0:9] BL[10:17] BL[18:22] - * | | | | | - * | | | | | - * | Word |--WL[0:3]-->-----------+---------------+---- ... |------+--> - * | | | | | | | | - * | Line | | v | v | v - * | | | +-------+ | +-------+ | +------+ - * | shift | +-->| SRAM | +-->| SRAM | +->| SRAM | - * | | | | [0:8] | | | [0:5] | ... | | [0:7]| - * | register| | +-------+ | +-------+ | +------+ - * | | | | | - * | chains |--WL[4:14] -----------+--------------+--------- | -----+--> - * | | | | | | | | - * | | | v | v | v - * | | | +-------+ | +-------+ | +-------+ - * | | +-->| SRAM | | | SRAM | +->| SRAM | - * | | | | [0:80]| | | [0:63]| ... | | [0:31]| - * | | | +-------+ | +-------+ | +-------+ - * | | | | - * | | | ... ... ... | ... - * | | | | | - * | |--WL[15:18] -----------+---------------+---- --- | -----+--> - * | | | | | | | | - * | | | v | v | v - * +---------+ | +-------+ | +-------+ | +-------+ - * +-->| SRAM | +-->| SRAM | +->| SRAM | - * | |[0:5] | | | [0:8] | ... | | [0:2] | - * | +-------+ | +-------+ | +-------+ - * v v v - * WL[0:9] WL[0:7] WL[0:4] - * - **********************************************************************/ -static -void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(ModuleManager& module_manager, - const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const ConfigProtocol& config_protocol) { - CircuitModelId sram_model = config_protocol.memory_model(); - CircuitModelId bl_memory_model = config_protocol.bl_memory_model(); - /* Find out the unique shift register chain sizes */ - std::vector unique_sr_sizes; - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - /* TODO: Need to find how to cut the BLs when there are multiple banks for shift registers in a region */ - size_t num_bls = compute_memory_bank_regional_num_bls(module_manager, top_module, - config_region, - circuit_lib, sram_model); - unique_sr_sizes.push_back(num_bls); - } - - /* Build submodules for shift register chains */ - for (const size_t& sr_size : unique_sr_sizes) { - std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), sr_size); - ModuleId sr_bank_module = build_bl_shift_register_chain_module(module_manager, - circuit_lib, - sr_module_name, - bl_memory_model, - sr_size); - /* Instanciate the shift register chains in the top-level module */ - module_manager.add_child_module(top_module, sr_bank_module); - } - - /* TODO: create connections between top-level module and the BL shift register banks - * - Connect the head port from top-level module to each shift register bank - * - Connect the tail port from each shift register bank to top-level module - */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - ModulePortId blsr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region)); - BasicPort blsr_head_port_info = module_manager.module_port(top_module, blsr_head_port); - - for (const size_t& sr_size : unique_sr_sizes) { - std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), sr_size); - ModuleId child_sr_module = module_manager.find_module(sr_module_name); - ModulePortId child_blsr_head_port = module_manager.find_module_port(child_sr_module, std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME)); - BasicPort child_blsr_head_port_info = module_manager.module_port(child_sr_module, child_blsr_head_port); - for (size_t child_instance = 0; child_instance < module_manager.num_instance(top_module, child_sr_module); ++child_instance) { - for (const size_t& sink_pin : child_blsr_head_port_info.pins()) { - /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - blsr_head_port, - blsr_head_port_info.pins()[sink_pin]); - VTR_ASSERT(ModuleNetId::INVALID() != net); - - /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - child_sr_module, child_instance, child_blsr_head_port, sink_pin); - } - } - } - } - - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - ModulePortId blsr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region)); - BasicPort blsr_tail_port_info = module_manager.module_port(top_module, blsr_tail_port); - - for (const size_t& sr_size : unique_sr_sizes) { - std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), sr_size); - ModuleId child_sr_module = module_manager.find_module(sr_module_name); - ModulePortId child_blsr_tail_port = module_manager.find_module_port(child_sr_module, std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); - BasicPort child_blsr_tail_port_info = module_manager.module_port(child_sr_module, child_blsr_tail_port); - for (size_t child_instance = 0; child_instance < module_manager.num_instance(top_module, child_sr_module); ++child_instance) { - for (const size_t& sink_pin : child_blsr_tail_port_info.pins()) { - /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - child_sr_module, child_instance, - child_blsr_tail_port, sink_pin); - VTR_ASSERT(ModuleNetId::INVALID() != net); - - /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - top_module, 0, - blsr_tail_port, blsr_tail_port_info.pins()[sink_pin]); - } - } - } - } - - /* Create connections between BLs of top-level module and BLs of child modules for each region */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - /************************************************************** - * Precompute the BLs and WLs distribution across the FPGA fabric - * The distribution is a matrix which contains the starting index of BL/WL for each column or row - */ - std::pair child_x_range = compute_memory_bank_regional_configurable_child_x_range(module_manager, top_module, config_region); - std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, - config_region, - circuit_lib, sram_model); - std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); - - /************************************************************** - * Add BL nets from top module to each configurable child - * BL pins of top module are connected to the BL input pins of each PB/CB/SB - * For all the PB/CB/SB in the same column, they share the same set of BLs - * A quick example - * - * BL[i .. i + sqrt(N)] - * | - * | CLB[1][H] - * | +---------+ - * | | SRAM | - * +-->| [0..N] | - * | +---------+ - * | - * ... - * | CLB[1][1] - * | +---------+ - * | | SRAM | - * +-->| [0..N] | - * | +---------+ - * | - */ - ModulePortId top_module_bl_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), config_region)); - BasicPort top_module_bl_port_info = module_manager.module_port(top_module, top_module_bl_port); - - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; - - /* Find the BL port */ - ModulePortId child_bl_port = module_manager.find_module_port(child_module, std::string(MEMORY_BL_PORT_NAME)); - BasicPort child_bl_port_info = module_manager.module_port(child_module, child_bl_port); - - size_t cur_bl_index = 0; - - for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { - size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index; - VTR_ASSERT(bl_pin_id < top_module_bl_port_info.pins().size()); - - /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - top_module_bl_port, - top_module_bl_port_info.pins()[bl_pin_id]); - VTR_ASSERT(ModuleNetId::INVALID() != net); - - /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_bl_port, sink_bl_pin); - - cur_bl_index++; - } - } - } -} - /********************************************************************* * Top-level function to add nets for quicklogic memory banks using flatten BL/WLs * Each configuration region has independent BL/WLs @@ -1155,6 +948,291 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(ModuleManager } } +/********************************************************************* + * This function to add nets for QuickLogic memory bank + * We build the net connects between the head ports of shift register banks + * and the head ports of top-level module + * @note This function is applicable to both BL and WL shift registers + **********************************************************************/ +static +void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_heads(ModuleManager& module_manager, + const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks, + const std::string& head_port_name) { + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + ModulePortId blsr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(head_port_name, config_region)); + BasicPort blsr_head_port_info = module_manager.module_port(top_module, blsr_head_port); + + for (size_t iinst = 0; iinst < sr_banks.shift_register_bank_modules(config_region).size(); ++iinst) { + ModuleId sr_bank_module = sr_banks.shift_register_bank_modules(config_region)[iinst]; + size_t sr_bank_instance = sr_banks.shift_register_bank_instances(config_region)[iinst]; + VTR_ASSERT(sr_bank_module); + + ModulePortId sr_module_head_port = module_manager.find_module_port(sr_bank_module, head_port_name); + BasicPort sr_module_head_port_info = module_manager.module_port(sr_bank_module, sr_module_head_port); + VTR_ASSERT(sr_module_head_port_info.get_width() == blsr_head_port_info.get_width()); + for (size_t ipin = 0; ipin < sr_module_head_port_info.pins().size(); ++ipin) { + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + top_module, 0, + blsr_head_port, + blsr_head_port_info.pins()[ipin]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + sr_bank_module, sr_bank_instance, sr_module_head_port, sr_module_head_port_info.pins()[ipin]); + } + } + } +} + +/********************************************************************* + * This function to add nets for QuickLogic memory bank + * We build the net connects between the head ports of shift register banks + * and the head ports of top-level module + * @note This function is applicable to both BL and WL shift registers + **********************************************************************/ +static +void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(ModuleManager& module_manager, + const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks, + const std::string& tail_port_name) { + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + ModulePortId blsr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(tail_port_name, config_region)); + BasicPort blsr_tail_port_info = module_manager.module_port(top_module, blsr_tail_port); + + for (size_t iinst = 0; iinst < sr_banks.shift_register_bank_modules(config_region).size(); ++iinst) { + ModuleId sr_bank_module = sr_banks.shift_register_bank_modules(config_region)[iinst]; + size_t sr_bank_instance = sr_banks.shift_register_bank_instances(config_region)[iinst]; + VTR_ASSERT(sr_bank_module); + + ModulePortId sr_module_tail_port = module_manager.find_module_port(sr_bank_module, tail_port_name); + BasicPort sr_module_tail_port_info = module_manager.module_port(sr_bank_module, sr_module_tail_port); + VTR_ASSERT(sr_module_tail_port_info.get_width() == blsr_tail_port_info.get_width()); + for (size_t ipin = 0; ipin < sr_module_tail_port_info.pins().size(); ++ipin) { + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + sr_bank_module, sr_bank_instance, + sr_module_tail_port, sr_module_tail_port_info.pins()[ipin]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + top_module, 0, + blsr_tail_port, blsr_tail_port_info.pins()[ipin]); + } + } + } +} + +/************************************************************** + * Add BL/WL nets from shift register module to each configurable child + * BL pins of shift register module are connected to the BL input pins of each PB/CB/SB + * For all the PB/CB/SB in the same column, they share the same set of BLs + * A quick example + * + * +-----------------------+ + * | Shift register chain | + * +-----------------------+ + * BL[i .. i + sqrt(N)] + * | + * | CLB[1][H] + * | +---------+ + * | | SRAM | + * +-->| [0..N] | + * | +---------+ + * | + * ... + * | CLB[1][1] + * | +---------+ + * | | SRAM | + * +-->| [0..N] | + * | +---------+ + * | + * @note optional BL/WL is applicable to WLR, which may not always exist + */ +static +void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleManager& module_manager, + const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks, + const std::string& blwl_port_name, + const bool& optional_blwl = false) { + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + for (size_t iinst = 0; iinst < sr_banks.shift_register_bank_modules(config_region).size(); ++iinst) { + ModuleId sr_bank_module = sr_banks.shift_register_bank_modules(config_region)[iinst]; + size_t sr_bank_instance = sr_banks.shift_register_bank_instances(config_region)[iinst]; + VTR_ASSERT(sr_bank_module); + + ModulePortId sr_module_blwl_port = module_manager.find_module_port(sr_bank_module, blwl_port_name); + if (!sr_module_blwl_port && !optional_blwl) { + continue; + } else { + VTR_ASSERT(sr_module_blwl_port); + } + BasicPort sr_module_blwl_port_info = module_manager.module_port(sr_bank_module, sr_module_blwl_port); + + size_t cur_sr_module_blwl_pin_id = 0; + + for (size_t sink_id = 0; sink_id < sr_banks.shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance).size(); ++sink_id) { + size_t child_id = sr_banks.shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the BL port */ + ModulePortId child_blwl_port = module_manager.find_module_port(child_module, blwl_port_name); + BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port); + + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + sr_bank_module, sr_bank_instance, + sr_module_blwl_port, + sr_module_blwl_port_info.pins()[cur_sr_module_blwl_pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + size_t sink_pin_id = sr_banks.shift_register_bank_sink_pin_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_blwl_port, sink_pin_id); + + cur_sr_module_blwl_pin_id++; + } + } + } +} + +/********************************************************************* + * This function to add nets for quicklogic memory banks using shift registers to manipulate BL/WLs + * Each configuration region has independent BL/WL shift register banks + * - Find the number of BLs and WLs required for each region + * - Find the number of BL and WL shift register chains required for each region + * - Create the module of shift register chain for each unique size + * - Create nets to connect from top-level module inputs to BL/WL shift register chains + * - Create nets to connect from BL/WL shift register chains to BL/WL of configurable children + * + * @note this function only adds the BL protocol + * + * Detailed schematic of each memory bank: + * @note The numbers are just made to show a simplified example, practical cases are more complicated! + * + * sr_clk sr_head sr_tail + * | | ^ + * v v | + * +-------------------------------------------------+ + * | Bit Line shift register chains | + * +-------------------------------------------------+ + * | | | + * +---------+ BL[0:9] BL[10:17] BL[18:22] + * | | | | | + * | | | | | + * | Word |--WL[0:3]-->-----------+---------------+---- ... |------+--> + * | | | | | | | | + * | Line | | v | v | v + * | | | +-------+ | +-------+ | +------+ + * | shift | +-->| SRAM | +-->| SRAM | +->| SRAM | + * | | | | [0:8] | | | [0:5] | ... | | [0:7]| + * | register| | +-------+ | +-------+ | +------+ + * | | | | | + * | chains |--WL[4:14] -----------+--------------+--------- | -----+--> + * | | | | | | | | + * | | | v | v | v + * | | | +-------+ | +-------+ | +-------+ + * | | +-->| SRAM | | | SRAM | +->| SRAM | + * | | | | [0:80]| | | [0:63]| ... | | [0:31]| + * | | | +-------+ | +-------+ | +-------+ + * | | | | + * | | | ... ... ... | ... + * | | | | | + * | |--WL[15:18] -----------+---------------+---- --- | -----+--> + * | | | | | | | | + * | | | v | v | v + * +---------+ | +-------+ | +-------+ | +-------+ + * +-->| SRAM | +-->| SRAM | +->| SRAM | + * | |[0:5] | | | [0:8] | ... | | [0:2] | + * | +-------+ | +-------+ | +-------+ + * v v v + * WL[0:9] WL[0:7] WL[0:4] + * + **********************************************************************/ +static +void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(ModuleManager& module_manager, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib, + const ConfigProtocol& config_protocol) { + CircuitModelId sram_model = config_protocol.memory_model(); + CircuitModelId bl_memory_model = config_protocol.bl_memory_model(); + /* Find out the unique shift register chain sizes */ + vtr::vector unique_sr_sizes; + unique_sr_sizes.resize(module_manager.regions(top_module).size()); + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + /* TODO: Need to find how to cut the BLs when there are multiple banks for shift registers in a region */ + size_t num_bls = compute_memory_bank_regional_num_bls(module_manager, top_module, + config_region, + circuit_lib, sram_model); + unique_sr_sizes[config_region] = num_bls; + } + + /* Build submodules for shift register chains */ + for (const size_t& sr_size : unique_sr_sizes) { + std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), sr_size); + build_bl_shift_register_chain_module(module_manager, + circuit_lib, + sr_module_name, + bl_memory_model, + sr_size); + } + + /* [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/ + MemoryBankShiftRegisterBanks sr_banks; + /* Instanciate the shift register chains in the top-level module */ + sr_banks.resize_regions(module_manager.regions(top_module).size()); + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), unique_sr_sizes[config_region]); + ModuleId sr_bank_module = module_manager.find_module(sr_module_name); + VTR_ASSERT(sr_bank_module); + + size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module); + module_manager.add_child_module(top_module, sr_bank_module); + + sr_banks.add_shift_register_instance(config_region, sr_bank_module, cur_inst); + + /************************************************************** + * Precompute the BLs and WLs distribution across the FPGA fabric + * The distribution is a matrix which contains the starting index of BL/WL for each column or row + */ + std::pair child_x_range = compute_memory_bank_regional_configurable_child_x_range(module_manager, top_module, config_region); + std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, + config_region, + circuit_lib, sram_model); + std::map bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile); + + for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + + /* Find the BL port */ + ModulePortId child_bl_port = module_manager.find_module_port(child_module, std::string(MEMORY_BL_PORT_NAME)); + BasicPort child_bl_port_info = module_manager.module_port(child_module, child_bl_port); + + for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { + sr_banks.add_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_bl_pin); + } + } + } + + /* Create connections between top-level module and the BL shift register banks + * - Connect the head port from top-level module to each shift register bank + * - Connect the tail port from each shift register bank to top-level module + */ + add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_heads(module_manager, top_module, sr_banks, + std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME)); + + add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(module_manager, top_module, sr_banks, + std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); + + /* Create connections between BLs of top-level module and BLs of child modules for each region */ + add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks, std::string(MEMORY_BL_PORT_NAME)); +} + /********************************************************************* * Top-level function to add nets for quicklogic memory banks using shift registers to control BL/WLs * @@ -1170,7 +1248,7 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module CircuitModelId sram_model = config_protocol.memory_model(); CircuitModelId wl_memory_model = config_protocol.wl_memory_model(); /* Find out the unique shift register chain sizes */ - std::vector unique_sr_sizes; + vtr::vector unique_sr_sizes; for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { /* TODO: Need to find how to cut the BLs when there are multiple banks for shift registers in a region */ size_t num_wls = compute_memory_bank_regional_num_wls(module_manager, top_module, @@ -1182,74 +1260,27 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module /* TODO: Build submodules for shift register chains */ for (const size_t& sr_size : unique_sr_sizes) { std::string sr_module_name = generate_wl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), sr_size); - ModuleId sr_bank_module = build_wl_shift_register_chain_module(module_manager, - circuit_lib, - sr_module_name, - wl_memory_model, - sr_size); - /* Instanciate the shift register chains in the top-level module */ + build_wl_shift_register_chain_module(module_manager, + circuit_lib, + sr_module_name, + wl_memory_model, + sr_size); + } + + /* [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/ + MemoryBankShiftRegisterBanks sr_banks; + /* Instanciate the shift register chains in the top-level module */ + sr_banks.resize_regions(module_manager.regions(top_module).size()); + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + std::string sr_module_name = generate_wl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), unique_sr_sizes[config_region]); + ModuleId sr_bank_module = module_manager.find_module(sr_module_name); + VTR_ASSERT(sr_bank_module); + + size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module); module_manager.add_child_module(top_module, sr_bank_module); - } - /* TODO: create connections between top-level module and the WL shift register banks - * - Connect the head port from top-level module to each shift register bank - * - Connect the tail port from each shift register bank to top-level module - */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - ModulePortId wlsr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region)); - BasicPort wlsr_head_port_info = module_manager.module_port(top_module, wlsr_head_port); + sr_banks.add_shift_register_instance(config_region, sr_bank_module, cur_inst); - for (const size_t& sr_size : unique_sr_sizes) { - std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), sr_size); - ModuleId child_sr_module = module_manager.find_module(sr_module_name); - ModulePortId child_wlsr_head_port = module_manager.find_module_port(child_sr_module, std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME)); - BasicPort child_wlsr_head_port_info = module_manager.module_port(child_sr_module, child_wlsr_head_port); - for (size_t child_instance = 0; child_instance < module_manager.num_instance(top_module, child_sr_module); ++child_instance) { - for (const size_t& sink_pin : child_wlsr_head_port_info.pins()) { - /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - wlsr_head_port, - wlsr_head_port_info.pins()[sink_pin]); - VTR_ASSERT(ModuleNetId::INVALID() != net); - - /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - child_sr_module, child_instance, child_wlsr_head_port, sink_pin); - } - } - } - } - - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - ModulePortId wlsr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region)); - BasicPort wlsr_tail_port_info = module_manager.module_port(top_module, wlsr_tail_port); - - for (const size_t& sr_size : unique_sr_sizes) { - std::string sr_module_name = generate_wl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), sr_size); - ModuleId child_sr_module = module_manager.find_module(sr_module_name); - ModulePortId child_wlsr_tail_port = module_manager.find_module_port(child_sr_module, std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); - BasicPort child_wlsr_tail_port_info = module_manager.module_port(child_sr_module, child_wlsr_tail_port); - for (size_t child_instance = 0; child_instance < module_manager.num_instance(top_module, child_sr_module); ++child_instance) { - for (const size_t& sink_pin : child_wlsr_tail_port_info.pins()) { - /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - child_sr_module, child_instance, - child_wlsr_tail_port, sink_pin); - VTR_ASSERT(ModuleNetId::INVALID() != net); - - /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - top_module, 0, - wlsr_tail_port, wlsr_tail_port_info.pins()[sink_pin]); - } - } - } - } - - - /* Create connections between WLs of top-level module and WLs of child modules for each region */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric * The distribution is a matrix which contains the starting index of BL/WL for each column or row @@ -1260,84 +1291,33 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module circuit_lib, sram_model); std::map wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile); - /************************************************************** - * Add WL nets from top module to each configurable child - */ - ModulePortId top_module_wl_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region)); - BasicPort top_module_wl_port_info = module_manager.module_port(top_module, top_module_wl_port); - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; - - /* Find the WL port */ + /* Find the BL port */ ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME)); BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port); - size_t cur_wl_index = 0; - for (const size_t& sink_wl_pin : child_wl_port_info.pins()) { - size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + cur_wl_index; - VTR_ASSERT(wl_pin_id < top_module_wl_port_info.pins().size()); - - /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - top_module_wl_port, - top_module_wl_port_info.pins()[wl_pin_id]); - VTR_ASSERT(ModuleNetId::INVALID() != net); - - /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_wl_port, sink_wl_pin); - - cur_wl_index++; - } - } - - /************************************************************** - * Optional: Add WLR nets from top module to each configurable child - */ - ModulePortId top_module_wlr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WLR_PORT_NAME), config_region)); - BasicPort top_module_wlr_port_info; - if (top_module_wlr_port) { - top_module_wlr_port_info = module_manager.module_port(top_module, top_module_wlr_port); - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; - - /* Find the WL port */ - ModulePortId child_wlr_port = module_manager.find_module_port(child_module, std::string(MEMORY_WLR_PORT_NAME)); - BasicPort child_wlr_port_info = module_manager.module_port(child_module, child_wlr_port); - - size_t cur_wlr_index = 0; - - for (const size_t& sink_wlr_pin : child_wlr_port_info.pins()) { - size_t wlr_pin_id = wl_start_index_per_tile[coord.y()] + cur_wlr_index; - VTR_ASSERT(wlr_pin_id < top_module_wlr_port_info.pins().size()); - - /* Create net */ - ModuleNetId net = create_module_source_pin_net(module_manager, top_module, - top_module, 0, - top_module_wlr_port, - top_module_wlr_port_info.pins()[wlr_pin_id]); - VTR_ASSERT(ModuleNetId::INVALID() != net); - - /* Add net sink */ - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_wlr_port, sink_wlr_pin); - - cur_wlr_index++; - } + sr_banks.add_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_wl_pin); } } } -} + /* Create connections between top-level module and the BL shift register banks + * - Connect the head port from top-level module to each shift register bank + * - Connect the tail port from each shift register bank to top-level module + */ + add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_heads(module_manager, top_module, sr_banks, + std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME)); + + add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(module_manager, top_module, sr_banks, + std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); + + /* Create connections between BLs of top-level module and BLs of child modules for each region */ + add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks, std::string(MEMORY_WL_PORT_NAME)); + add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks, std::string(MEMORY_WLR_PORT_NAME), true); +} /********************************************************************* * Top-level function to add nets for quicklogic memory banks diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp new file mode 100644 index 000000000..3b04dc330 --- /dev/null +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -0,0 +1,80 @@ +#include "memory_bank_shift_register_banks.h" + +/* begin namespace openfpga */ +namespace openfpga { + +std::vector MemoryBankShiftRegisterBanks::shift_register_bank_modules(const ConfigRegionId& region) const { + std::vector sr_bank_modules; + VTR_ASSERT(valid_region_id(region)); + for (const auto& pair : sr_instance_info_[region]) { + sr_bank_modules.push_back(pair.first); + } + return sr_bank_modules; +} + +std::vector MemoryBankShiftRegisterBanks::shift_register_bank_instances(const ConfigRegionId& region) const { + std::vector sr_bank_instances; + VTR_ASSERT(valid_region_id(region)); + for (const auto& pair : sr_instance_info_[region]) { + sr_bank_instances.push_back(pair.second); + } + return sr_bank_instances; +} + +std::vector MemoryBankShiftRegisterBanks::shift_register_bank_sink_child_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const { + VTR_ASSERT(valid_region_id(region)); + std::vector sink_child_ids; + + auto result = sr_instance_info_[region].find(std::make_pair(sr_module, sr_instance)); + /* Return an empty vector if not found */ + if (result != sr_instance_info_[region].end()) { + for (const auto& sink_child : result->second) { + sink_child_ids.push_back(sink_child.first); + } + } + return sink_child_ids; +} + +std::vector MemoryBankShiftRegisterBanks::shift_register_bank_sink_child_pin_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const { + VTR_ASSERT(valid_region_id(region)); + std::vector sink_child_pin_ids; + + auto result = sr_instance_info_[region].find(std::make_pair(sr_module, sr_instance)); + /* Return an empty vector if not found */ + if (result != sr_instance_info_[region].end()) { + for (const auto& sink_child : result->second) { + sink_child_pin_ids.push_back(sink_child.second); + } + } + return sink_child_pin_ids; +} + +void MemoryBankShiftRegisterBanks::resize_regions(const size_t& num_regions) { + sr_instance_info_.resize(num_regions); +} + +void MemoryBankShiftRegisterBanks::add_shift_register_instance(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) { + VTR_ASSERT(valid_region_id(region)); + sr_instance_info_[region][std::make_pair(sr_module, sr_instance)]; +} + +void MemoryBankShiftRegisterBanks::add_shift_register_sink_nodes(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_child_id, + const size_t& sink_child_pin_id) { + VTR_ASSERT(valid_region_id(region)); + sr_instance_info_[region][std::make_pair(sr_module, sr_instance)].push_back(std::make_pair(sink_child_id, sink_child_pin_id)); +} + +bool MemoryBankShiftRegisterBanks::valid_region_id(const ConfigRegionId& region) const { + return size_t(region) < sr_instance_info_.size(); +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h new file mode 100644 index 000000000..83d7c517d --- /dev/null +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -0,0 +1,67 @@ +#ifndef MEMORY_BANK_SHIFT_REGISTER_BANKS_H +#define MEMORY_BANK_SHIFT_REGISTER_BANKS_H + +#include +#include +#include "vtr_vector.h" +#include "module_manager.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/****************************************************************************** + * This files includes data structures that stores detailed information about + * shift register banks for each configuration region in the top-level module, including + * - Module id of each shift register bank + * - Instance id of each shift register bank + * - The connectivity of of each shift register bank to reconfigurable child under a configuration region + * - The ids of each child to be connected + * - The Bit Line (BL) or Word Line (WL) pin id of each child + + * @note This data structure is mainly used as a database for adding connections around shift register banks in top-level module + ******************************************************************************/ +class MemoryBankShiftRegisterBanks { + public: /* Accessors */ + /* @brief Return a list of modules of shift register banks under a specific configuration region of top-level module */ + std::vector shift_register_bank_modules(const ConfigRegionId& region) const; + + /* @brief Return a list of instances of shift register banks under a specific configuration region of top-level module */ + std::vector shift_register_bank_instances(const ConfigRegionId& region) const; + + /* @brief Return a list of ids of reconfigurable children for a given instance of shift register bank + * under a specific configuration region of top-level module + */ + std::vector shift_register_bank_sink_child_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const; + + /* @brief Return a list of BL/WL ids of reconfigurable children for a given instance of shift register bank + * under a specific configuration region of top-level module + */ + std::vector shift_register_bank_sink_pin_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const; + public: /* Mutators */ + void resize_regions(const size_t& num_regions); + + /* @brief Add the module id and instance id of a shift register under a specific configuration region of top-level module */ + void add_shift_register_instance(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance); + + /* @brief Add the module id and instance id of a shift register under a specific configuration region of top-level module */ + void add_shift_register_sink_nodes(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_child_id, + const size_t& sink_child_pin_id); + public: /* Validators */ + bool valid_region_id(const ConfigRegionId& region) const; + + private: /* Internal data */ + vtr::vector, std::vector>>> sr_instance_info_; +}; + +} /* end namespace openfpga */ + +#endif From ac6268d9aec616c642946313e5b929362a6fde88 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 29 Sep 2021 16:24:36 -0700 Subject: [PATCH 109/229] [Engine] Bug fix on compilation errors --- .../src/fabric/memory_bank_shift_register_banks.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index 3b04dc330..6956b22d2 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -1,3 +1,4 @@ +#include "vtr_assert.h" #include "memory_bank_shift_register_banks.h" /* begin namespace openfpga */ @@ -7,7 +8,7 @@ std::vector MemoryBankShiftRegisterBanks::shift_register_bank_modules( std::vector sr_bank_modules; VTR_ASSERT(valid_region_id(region)); for (const auto& pair : sr_instance_info_[region]) { - sr_bank_modules.push_back(pair.first); + sr_bank_modules.push_back(pair.first.first); } return sr_bank_modules; } @@ -16,7 +17,7 @@ std::vector MemoryBankShiftRegisterBanks::shift_register_bank_instances( std::vector sr_bank_instances; VTR_ASSERT(valid_region_id(region)); for (const auto& pair : sr_instance_info_[region]) { - sr_bank_instances.push_back(pair.second); + sr_bank_instances.push_back(pair.first.second); } return sr_bank_instances; } @@ -37,9 +38,9 @@ std::vector MemoryBankShiftRegisterBanks::shift_register_bank_sink_child return sink_child_ids; } -std::vector MemoryBankShiftRegisterBanks::shift_register_bank_sink_child_pin_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const { +std::vector MemoryBankShiftRegisterBanks::shift_register_bank_sink_pin_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const { VTR_ASSERT(valid_region_id(region)); std::vector sink_child_pin_ids; From 89a97d83bd1143403eb66f347b985d92434f7608 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 29 Sep 2021 16:28:06 -0700 Subject: [PATCH 110/229] [Test] Added a new test case for the shift register banks in QuickLogic memory banks --- .../config/task.conf | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register/config/task.conf new file mode 100644 index 000000000..ba36d7f4c --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register/config/task.conf @@ -0,0 +1,44 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +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/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +bench1_top = or2 +bench1_chan_width = 300 + +bench2_top = and2_latch +bench2_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 4926c323e72ec2713847e50eef3305b082a6e27d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 29 Sep 2021 16:32:29 -0700 Subject: [PATCH 111/229] [Engine] Bug fix due to the optional syntax ``num_bank`` were required in XML --- libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp b/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp index c84bbe93b..9a3a60336 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -74,7 +74,7 @@ void read_xml_bl_protocol(pugi::xml_node& xml_bl_protocol, */ if (BLWL_PROTOCOL_SHIFT_REGISTER == blwl_protocol_type) { config_protocol.set_bl_memory_model_name(get_attribute(xml_bl_protocol, "circuit_model_name", loc_data).as_string()); - config_protocol.set_bl_num_banks(get_attribute(xml_bl_protocol, "num_banks", loc_data).as_int(1)); + config_protocol.set_bl_num_banks(get_attribute(xml_bl_protocol, "num_banks", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(1)); } } @@ -104,7 +104,7 @@ void read_xml_wl_protocol(pugi::xml_node& xml_wl_protocol, */ if (BLWL_PROTOCOL_SHIFT_REGISTER == blwl_protocol_type) { config_protocol.set_wl_memory_model_name(get_attribute(xml_wl_protocol, "circuit_model_name", loc_data).as_string()); - config_protocol.set_wl_num_banks(get_attribute(xml_wl_protocol, "num_banks", loc_data).as_int(1)); + config_protocol.set_wl_num_banks(get_attribute(xml_wl_protocol, "num_banks", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(1)); } } From 41cc3757460820e4b889db4065caf03c837c25c8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 29 Sep 2021 16:34:40 -0700 Subject: [PATCH 112/229] [Arch] define default CCFF model in ql bank example architecture that uses shift registers --- openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml index c07af9a10..25f5261d9 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml @@ -165,7 +165,7 @@ - + From 8f0ae937bc77e870cb07a29ab7da8457e6f74d6a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 29 Sep 2021 16:57:49 -0700 Subject: [PATCH 113/229] [Engine] Upgraded fabric generator to support single shift register bank per configuration region for QuickLogic memory bank --- openfpga/src/fabric/build_memory_modules.cpp | 1 + openfpga/src/fabric/build_memory_modules.h | 7 - .../fabric/build_top_module_memory_bank.cpp | 149 ++++++++++++++++-- 3 files changed, 137 insertions(+), 20 deletions(-) diff --git a/openfpga/src/fabric/build_memory_modules.cpp b/openfpga/src/fabric/build_memory_modules.cpp index 844369fa9..fe6340a8f 100644 --- a/openfpga/src/fabric/build_memory_modules.cpp +++ b/openfpga/src/fabric/build_memory_modules.cpp @@ -161,6 +161,7 @@ void add_module_output_nets_to_mem_modules(ModuleManager& module_manager, * Do not use it to replace the * add_module_nets_cmos_memory_chain_config_bus() !!! *********************************************************************/ +static void add_module_nets_to_cmos_memory_config_chain_module(ModuleManager& module_manager, const ModuleId& parent_module, const CircuitLibrary& circuit_lib, diff --git a/openfpga/src/fabric/build_memory_modules.h b/openfpga/src/fabric/build_memory_modules.h index 6b6794d46..921b9fbd2 100644 --- a/openfpga/src/fabric/build_memory_modules.h +++ b/openfpga/src/fabric/build_memory_modules.h @@ -25,13 +25,6 @@ std::vector add_module_output_nets_to_chain_mem_modules(ModuleManag const size_t& child_index, const size_t& child_instance); -void add_module_nets_to_cmos_memory_config_chain_module(ModuleManager& module_manager, - const ModuleId& parent_module, - const CircuitLibrary& circuit_lib, - const CircuitPortId& model_input_port, - const CircuitPortId& model_output_port); - - void build_memory_modules(ModuleManager& module_manager, DecoderLibrary& arch_decoder_lib, const MuxLibrary& mux_lib, diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index a6a0ca564..db82870ad 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -32,6 +32,118 @@ /* begin namespace openfpga */ namespace openfpga { +/******************************************************************** + * Connect all the memory modules under the parent module in a chain + * + * +--------+ +--------+ +--------+ + * ccff_head --->| Memory |--->| Memory |--->... --->| Memory |----> ccff_tail + * | Module | | Module | | Module | + * | [0] | | [1] | | [N-1] | + * +--------+ +--------+ +--------+ + * For the 1st memory module: + * net source is the configuration chain head of the primitive module + * net sink is the configuration chain head of the next memory module + * + * For the rest of memory modules: + * net source is the configuration chain tail of the previous memory module + * net sink is the configuration chain head of the next memory module + * + * Note that: + * This function is designed for memory modules ONLY! + * Do not use it to replace the + * add_module_nets_cmos_memory_chain_config_bus() !!! + *********************************************************************/ +static +void add_module_nets_to_ql_memory_bank_shift_register_module(ModuleManager& module_manager, + const ModuleId& parent_module, + const CircuitLibrary& circuit_lib, + const CircuitPortId& model_input_port, + const CircuitPortId& model_output_port, + const std::string& chain_head_port_name, + const std::string& chain_tail_port_name) { + for (size_t mem_index = 0; mem_index < module_manager.configurable_children(parent_module).size(); ++mem_index) { + ModuleId net_src_module_id; + size_t net_src_instance_id; + ModulePortId net_src_port_id; + + ModuleId net_sink_module_id; + size_t net_sink_instance_id; + ModulePortId net_sink_port_id; + + if (0 == mem_index) { + /* Find the port name of configuration chain head */ + std::string src_port_name = chain_head_port_name; + net_src_module_id = parent_module; + net_src_instance_id = 0; + net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + + /* Find the port name of next memory module */ + std::string sink_port_name = circuit_lib.port_prefix(model_input_port); + net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + } else { + /* Find the port name of previous memory module */ + std::string src_port_name = circuit_lib.port_prefix(model_output_port); + net_src_module_id = module_manager.configurable_children(parent_module)[mem_index - 1]; + net_src_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index - 1]; + net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + + /* Find the port name of next memory module */ + std::string sink_port_name = circuit_lib.port_prefix(model_input_port); + net_sink_module_id = module_manager.configurable_children(parent_module)[mem_index]; + net_sink_instance_id = module_manager.configurable_child_instances(parent_module)[mem_index]; + net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + } + + /* Get the pin id for source port */ + BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + /* Get the pin id for sink port */ + BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); + /* Port sizes of source and sink should match */ + VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width()); + + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { + /* Create a net and add source and sink to it */ + ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]); + /* Add net sink */ + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + } + } + + /* For the last memory module: + * net source is the configuration chain tail of the previous memory module + * net sink is the configuration chain tail of the primitive module + */ + /* Find the port name of previous memory module */ + std::string src_port_name = circuit_lib.port_prefix(model_output_port); + ModuleId net_src_module_id = module_manager.configurable_children(parent_module).back(); + size_t net_src_instance_id = module_manager.configurable_child_instances(parent_module).back(); + ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); + + /* Find the port name of next memory module */ + std::string sink_port_name = chain_tail_port_name; + ModuleId net_sink_module_id = parent_module; + size_t net_sink_instance_id = 0; + ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name); + + /* Get the pin id for source port */ + BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id); + /* Get the pin id for sink port */ + BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id); + /* Port sizes of source and sink should match */ + VTR_ASSERT(net_src_port.get_width() == net_sink_port.get_width()); + + /* Create a net for each pin */ + for (size_t pin_id = 0; pin_id < net_src_port.pins().size(); ++pin_id) { + /* Create a net and add source and sink to it */ + ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[pin_id]); + /* Add net sink */ + module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[pin_id]); + } +} + /********************************************************************* * BL shift register chain module organization * @@ -114,8 +226,10 @@ ModuleId build_bl_shift_register_chain_module(ModuleManager& module_manager, } /* Build module nets to wire the configuration chain */ - add_module_nets_to_cmos_memory_config_chain_module(module_manager, mem_module, - circuit_lib, sram_input_ports[0], sram_output_ports[0]); + add_module_nets_to_ql_memory_bank_shift_register_module(module_manager, mem_module, + circuit_lib, sram_input_ports[0], sram_output_ports[0], + std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), + std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); /* Add global ports to the pb_module: * This is a much easier job after adding sub modules (instances), @@ -221,8 +335,10 @@ ModuleId build_wl_shift_register_chain_module(ModuleManager& module_manager, } /* Build module nets to wire the configuration chain */ - add_module_nets_to_cmos_memory_config_chain_module(module_manager, mem_module, - circuit_lib, sram_input_ports[0], sram_output_ports[0]); + add_module_nets_to_ql_memory_bank_shift_register_module(module_manager, mem_module, + circuit_lib, sram_input_ports[0], sram_output_ports[0], + std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), + std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); /* Add global ports to the pb_module: * This is a much easier job after adding sub modules (instances), @@ -1056,7 +1172,8 @@ static void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleManager& module_manager, const ModuleId& top_module, const MemoryBankShiftRegisterBanks& sr_banks, - const std::string& blwl_port_name, + const std::string& sr_blwl_port_name, + const std::string& child_blwl_port_name, const bool& optional_blwl = false) { for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { for (size_t iinst = 0; iinst < sr_banks.shift_register_bank_modules(config_region).size(); ++iinst) { @@ -1064,12 +1181,11 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan size_t sr_bank_instance = sr_banks.shift_register_bank_instances(config_region)[iinst]; VTR_ASSERT(sr_bank_module); - ModulePortId sr_module_blwl_port = module_manager.find_module_port(sr_bank_module, blwl_port_name); - if (!sr_module_blwl_port && !optional_blwl) { + ModulePortId sr_module_blwl_port = module_manager.find_module_port(sr_bank_module, sr_blwl_port_name); + if (!sr_module_blwl_port && optional_blwl) { continue; - } else { - VTR_ASSERT(sr_module_blwl_port); } + VTR_ASSERT(sr_module_blwl_port); BasicPort sr_module_blwl_port_info = module_manager.module_port(sr_bank_module, sr_module_blwl_port); size_t cur_sr_module_blwl_pin_id = 0; @@ -1080,7 +1196,7 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; /* Find the BL port */ - ModulePortId child_blwl_port = module_manager.find_module_port(child_module, blwl_port_name); + ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name); BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port); /* Create net */ @@ -1230,7 +1346,9 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); /* Create connections between BLs of top-level module and BLs of child modules for each region */ - add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks, std::string(MEMORY_BL_PORT_NAME)); + add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks, + std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME), + std::string(MEMORY_BL_PORT_NAME)); } /********************************************************************* @@ -1315,8 +1433,13 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); /* Create connections between BLs of top-level module and BLs of child modules for each region */ - add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks, std::string(MEMORY_WL_PORT_NAME)); - add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks, std::string(MEMORY_WLR_PORT_NAME), true); + add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks, + std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME), + std::string(MEMORY_WL_PORT_NAME)); + add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks, + std::string(WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME), + std::string(MEMORY_WLR_PORT_NAME), + true); } /********************************************************************* From b87b7a99c5d706f5ff756744778e1725640ae334 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 29 Sep 2021 20:21:46 -0700 Subject: [PATCH 114/229] [Engine] Add MemoryBankShiftRegisterBanks to openfpga context because their contents are required by netlist writers as well as bitstream generators --- openfpga/src/base/openfpga_build_fabric.cpp | 1 + openfpga/src/base/openfpga_context.h | 8 ++++++++ openfpga/src/fabric/build_device_module.cpp | 2 ++ openfpga/src/fabric/build_device_module.h | 1 + openfpga/src/fabric/build_top_module.cpp | 3 ++- openfpga/src/fabric/build_top_module.h | 2 ++ openfpga/src/fabric/build_top_module_memory.cpp | 6 +++++- openfpga/src/fabric/build_top_module_memory.h | 2 ++ openfpga/src/fabric/build_top_module_memory_bank.cpp | 11 +++++------ openfpga/src/fabric/build_top_module_memory_bank.h | 3 +++ .../src/fabric/memory_bank_shift_register_banks.h | 1 + 11 files changed, 32 insertions(+), 8 deletions(-) diff --git a/openfpga/src/base/openfpga_build_fabric.cpp b/openfpga/src/base/openfpga_build_fabric.cpp index 146520624..1caac7342 100644 --- a/openfpga/src/base/openfpga_build_fabric.cpp +++ b/openfpga/src/base/openfpga_build_fabric.cpp @@ -103,6 +103,7 @@ int build_fabric(OpenfpgaContext& openfpga_ctx, curr_status = build_device_module_graph(openfpga_ctx.mutable_module_graph(), openfpga_ctx.mutable_decoder_lib(), + openfpga_ctx.mutable_blwl_shift_register_banks(), const_cast(openfpga_ctx), g_vpr_ctx.device(), cmd_context.option_enable(cmd, opt_frame_view), diff --git a/openfpga/src/base/openfpga_context.h b/openfpga/src/base/openfpga_context.h index c85bf8607..dbb611fe6 100644 --- a/openfpga/src/base/openfpga_context.h +++ b/openfpga/src/base/openfpga_context.h @@ -23,6 +23,7 @@ #include "device_rr_gsb.h" #include "io_location_map.h" #include "fabric_global_port_info.h" +#include "memory_bank_shift_register_banks.h" /******************************************************************** * This file includes the declaration of the date structure @@ -65,6 +66,7 @@ class OpenfpgaContext : public Context { const openfpga::DeviceRRGSB& device_rr_gsb() const { return device_rr_gsb_; } const openfpga::MuxLibrary& mux_lib() const { return mux_lib_; } const openfpga::DecoderLibrary& decoder_lib() const { return decoder_lib_; } + const std::array& blwl_shift_register_banks() { return blwl_sr_banks_; } const openfpga::TileDirect& tile_direct() const { return tile_direct_; } const openfpga::ModuleManager& module_graph() const { return module_graph_; } const openfpga::FlowManager& flow_manager() const { return flow_manager_; } @@ -87,6 +89,7 @@ class OpenfpgaContext : public Context { openfpga::DeviceRRGSB& mutable_device_rr_gsb() { return device_rr_gsb_; } openfpga::MuxLibrary& mutable_mux_lib() { return mux_lib_; } openfpga::DecoderLibrary& mutable_decoder_lib() { return decoder_lib_; } + std::array& mutable_blwl_shift_register_banks() { return blwl_sr_banks_; } openfpga::TileDirect& mutable_tile_direct() { return tile_direct_; } openfpga::ModuleManager& mutable_module_graph() { return module_graph_; } openfpga::FlowManager& mutable_flow_manager() { return flow_manager_; } @@ -132,6 +135,11 @@ class OpenfpgaContext : public Context { /* Inner/inter-column/row tile direct connections */ openfpga::TileDirect tile_direct_; + /* Library of shift register banks that control BLs and WLs + * @note Only used when memory bank is used as configuration protocol + */ + std::array blwl_sr_banks_; + /* Fabric module graph */ openfpga::ModuleManager module_graph_; openfpga::IoLocationMap io_location_map_; diff --git a/openfpga/src/fabric/build_device_module.cpp b/openfpga/src/fabric/build_device_module.cpp index 4b39a5cee..3541616fc 100644 --- a/openfpga/src/fabric/build_device_module.cpp +++ b/openfpga/src/fabric/build_device_module.cpp @@ -31,6 +31,7 @@ namespace openfpga { *******************************************************************/ int build_device_module_graph(ModuleManager& module_manager, DecoderLibrary& decoder_lib, + std::array& blwl_sr_banks, const OpenfpgaContext& openfpga_ctx, const DeviceContext& vpr_device_ctx, const bool& frame_view, @@ -112,6 +113,7 @@ int build_device_module_graph(ModuleManager& module_manager, /* Build FPGA fabric top-level module */ status = build_top_module(module_manager, decoder_lib, + blwl_sr_banks, openfpga_ctx.arch().circuit_lib, openfpga_ctx.vpr_device_annotation(), vpr_device_ctx.grid, diff --git a/openfpga/src/fabric/build_device_module.h b/openfpga/src/fabric/build_device_module.h index 5d3215bb4..1cde17ba7 100644 --- a/openfpga/src/fabric/build_device_module.h +++ b/openfpga/src/fabric/build_device_module.h @@ -17,6 +17,7 @@ namespace openfpga { int build_device_module_graph(ModuleManager& module_manager, DecoderLibrary& decoder_lib, + std::array& blwl_sr_banks, const OpenfpgaContext& openfpga_ctx, const DeviceContext& vpr_device_ctx, const bool& frame_view, diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 4fc4c396f..c5b3aee45 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -283,6 +283,7 @@ vtr::Matrix add_top_module_connection_block_instances(ModuleManager& mod *******************************************************************/ int build_top_module(ModuleManager& module_manager, DecoderLibrary& decoder_lib, + std::array& blwl_sr_banks, const CircuitLibrary& circuit_lib, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, @@ -414,7 +415,7 @@ int build_top_module(ModuleManager& module_manager, * This is a one-shot addition that covers all the memory modules in this pb module! */ if (0 < module_manager.configurable_children(top_module).size()) { - add_top_module_nets_memory_config_bus(module_manager, decoder_lib, + add_top_module_nets_memory_config_bus(module_manager, decoder_lib, blwl_sr_banks, top_module, circuit_lib, config_protocol, circuit_lib.design_tech_type(sram_model), diff --git a/openfpga/src/fabric/build_top_module.h b/openfpga/src/fabric/build_top_module.h index d7e90a09f..3ddaea09a 100644 --- a/openfpga/src/fabric/build_top_module.h +++ b/openfpga/src/fabric/build_top_module.h @@ -19,6 +19,7 @@ #include "config_protocol.h" #include "module_manager.h" #include "fabric_key.h" +#include "memory_bank_shift_register_banks.h" /******************************************************************** * Function declaration @@ -29,6 +30,7 @@ namespace openfpga { int build_top_module(ModuleManager& module_manager, DecoderLibrary& decoder_lib, + std::array& blwl_sr_banks, const CircuitLibrary& circuit_lib, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 42debe24f..e48167970 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -1735,6 +1735,7 @@ void add_top_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_mana static void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, + std::array& blwl_sr_banks, const ModuleId& parent_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, @@ -1754,7 +1755,8 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, add_top_module_nets_cmos_memory_bank_config_bus(module_manager, decoder_lib, parent_module, num_config_bits); break; case CONFIG_MEM_QL_MEMORY_BANK: - add_top_module_nets_cmos_ql_memory_bank_config_bus(module_manager, decoder_lib, parent_module, circuit_lib, config_protocol, num_config_bits); + add_top_module_nets_cmos_ql_memory_bank_config_bus(module_manager, decoder_lib, blwl_sr_banks, + parent_module, circuit_lib, config_protocol, num_config_bits); break; case CONFIG_MEM_FRAME_BASED: add_top_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, parent_module, num_config_bits); @@ -1800,6 +1802,7 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, *******************************************************************/ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, + std::array& blwl_sr_banks, const ModuleId& parent_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, @@ -1811,6 +1814,7 @@ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, switch (mem_tech) { case CIRCUIT_MODEL_DESIGN_CMOS: add_top_module_nets_cmos_memory_config_bus(module_manager, decoder_lib, + blwl_sr_banks, parent_module, circuit_lib, config_protocol, diff --git a/openfpga/src/fabric/build_top_module_memory.h b/openfpga/src/fabric/build_top_module_memory.h index 7b6f9aa10..4819a56f6 100644 --- a/openfpga/src/fabric/build_top_module_memory.h +++ b/openfpga/src/fabric/build_top_module_memory.h @@ -18,6 +18,7 @@ #include "device_rr_gsb.h" #include "fabric_key.h" #include "config_protocol.h" +#include "memory_bank_shift_register_banks.h" #include "build_top_module_memory_utils.h" /******************************************************************** @@ -64,6 +65,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, + std::array& blwl_sr_banks, const ModuleId& parent_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index db82870ad..dd2bdf29b 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -1272,6 +1272,7 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan **********************************************************************/ static void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(ModuleManager& module_manager, + MemoryBankShiftRegisterBanks& sr_banks, const ModuleId& top_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol) { @@ -1298,8 +1299,6 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module sr_size); } - /* [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/ - MemoryBankShiftRegisterBanks sr_banks; /* Instanciate the shift register chains in the top-level module */ sr_banks.resize_regions(module_manager.regions(top_module).size()); for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { @@ -1360,6 +1359,7 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module **********************************************************************/ static void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(ModuleManager& module_manager, + MemoryBankShiftRegisterBanks& sr_banks, const ModuleId& top_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol) { @@ -1385,8 +1385,6 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module sr_size); } - /* [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/ - MemoryBankShiftRegisterBanks sr_banks; /* Instanciate the shift register chains in the top-level module */ sr_banks.resize_regions(module_manager.regions(top_module).size()); for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { @@ -1458,6 +1456,7 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module ********************************************************************/ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, + std::array& blwl_sr_banks, const ModuleId& top_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, @@ -1475,7 +1474,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { - add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(module_manager, top_module, circuit_lib, config_protocol); + add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(module_manager, blwl_sr_banks[0], top_module, circuit_lib, config_protocol); break; } default: { @@ -1494,7 +1493,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { - add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(module_manager, top_module, circuit_lib, config_protocol); + add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(module_manager, blwl_sr_banks[1], top_module, circuit_lib, config_protocol); break; } default: { diff --git a/openfpga/src/fabric/build_top_module_memory_bank.h b/openfpga/src/fabric/build_top_module_memory_bank.h index 3d6acc255..d3a3d2f77 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.h +++ b/openfpga/src/fabric/build_top_module_memory_bank.h @@ -7,12 +7,14 @@ #include #include +#include #include "vtr_vector.h" #include "vtr_ndmatrix.h" #include "module_manager.h" #include "config_protocol.h" #include "circuit_library.h" #include "decoder_library.h" +#include "memory_bank_shift_register_banks.h" #include "build_top_module_memory_utils.h" /******************************************************************** @@ -24,6 +26,7 @@ namespace openfpga { void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, + std::array& blwl_sr_banks, const ModuleId& top_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h index 83d7c517d..262508bad 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.h +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -59,6 +59,7 @@ class MemoryBankShiftRegisterBanks { bool valid_region_id(const ConfigRegionId& region) const; private: /* Internal data */ + /* [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/ vtr::vector, std::vector>>> sr_instance_info_; }; From f456c7e2360b6dd83a44c2dc2080399d4001e781 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 29 Sep 2021 20:34:25 -0700 Subject: [PATCH 115/229] [Engine] Add a new API to the MemoryBankShiftRegisterBank to access all the unique modules --- .../src/fabric/memory_bank_shift_register_banks.cpp | 13 +++++++++++++ .../src/fabric/memory_bank_shift_register_banks.h | 3 +++ 2 files changed, 16 insertions(+) diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index 6956b22d2..0d4902936 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -1,9 +1,22 @@ +#include #include "vtr_assert.h" #include "memory_bank_shift_register_banks.h" /* begin namespace openfpga */ namespace openfpga { +std::vector MemoryBankShiftRegisterBanks::shift_register_bank_unique_modules() const { + std::vector sr_bank_modules; + for (const auto& region : sr_instance_info_) { + for (const auto& pair : region) { + if (sr_bank_modules.end() == std::find(sr_bank_modules.begin(), sr_bank_modules.end(), pair.first.first)) { + sr_bank_modules.push_back(pair.first.first); + } + } + } + return sr_bank_modules; +} + std::vector MemoryBankShiftRegisterBanks::shift_register_bank_modules(const ConfigRegionId& region) const { std::vector sr_bank_modules; VTR_ASSERT(valid_region_id(region)); diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h index 262508bad..59c92fef7 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.h +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -22,6 +22,9 @@ namespace openfpga { ******************************************************************************/ class MemoryBankShiftRegisterBanks { public: /* Accessors */ + /* @brief Return a list of modules of unique shift register banks across all the regions */ + std::vector shift_register_bank_unique_modules() const; + /* @brief Return a list of modules of shift register banks under a specific configuration region of top-level module */ std::vector shift_register_bank_modules(const ConfigRegionId& region) const; From 2d4c200d58ca778bb1a401168c349830984efd0a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 29 Sep 2021 20:56:02 -0700 Subject: [PATCH 116/229] [FPGA-Verilog] Now FPGA-Verilog can output shift register bank netlists --- openfpga/src/base/openfpga_verilog.cpp | 1 + openfpga/src/fpga_verilog/verilog_api.cpp | 2 + openfpga/src/fpga_verilog/verilog_api.h | 2 + openfpga/src/fpga_verilog/verilog_constants.h | 1 + .../verilog_shift_register_banks.cpp | 81 +++++++++++++++++++ .../verilog_shift_register_banks.h | 29 +++++++ .../src/fpga_verilog/verilog_submodule.cpp | 14 +++- openfpga/src/fpga_verilog/verilog_submodule.h | 2 + 8 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp create mode 100644 openfpga/src/fpga_verilog/verilog_shift_register_banks.h diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index b912c518c..2f3dd892f 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -52,6 +52,7 @@ int write_fabric_verilog(OpenfpgaContext& openfpga_ctx, fpga_fabric_verilog(openfpga_ctx.mutable_module_graph(), openfpga_ctx.mutable_verilog_netlists(), + openfpga_ctx.blwl_shift_register_banks(), openfpga_ctx.arch().circuit_lib, openfpga_ctx.mux_lib(), openfpga_ctx.decoder_lib(), diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index b22de5920..8ac019781 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -55,6 +55,7 @@ namespace openfpga { ********************************************************************/ void fpga_fabric_verilog(ModuleManager &module_manager, NetlistManager &netlist_manager, + const std::array& blwl_sr_banks, const CircuitLibrary &circuit_lib, const MuxLibrary &mux_lib, const DecoderLibrary &decoder_lib, @@ -94,6 +95,7 @@ void fpga_fabric_verilog(ModuleManager &module_manager, * Without the modules in the module manager, core logic generation is not possible!!! */ print_verilog_submodule(module_manager, netlist_manager, + blwl_sr_banks, mux_lib, decoder_lib, circuit_lib, submodule_dir_path, options); diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index 934dc08f7..ef550c76d 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -23,6 +23,7 @@ #include "io_location_map.h" #include "fabric_global_port_info.h" #include "vpr_netlist_annotation.h" +#include "memory_bank_shift_register_banks.h" #include "fabric_verilog_options.h" #include "verilog_testbench_options.h" @@ -35,6 +36,7 @@ namespace openfpga { void fpga_fabric_verilog(ModuleManager& module_manager, NetlistManager& netlist_manager, + const std::array& blwl_sr_banks, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const DecoderLibrary& decoder_lib, diff --git a/openfpga/src/fpga_verilog/verilog_constants.h b/openfpga/src/fpga_verilog/verilog_constants.h index 639c1575a..3c164feee 100644 --- a/openfpga/src/fpga_verilog/verilog_constants.h +++ b/openfpga/src/fpga_verilog/verilog_constants.h @@ -26,6 +26,7 @@ constexpr char* MUXES_VERILOG_FILE_NAME = "muxes.v"; constexpr char* LOCAL_ENCODER_VERILOG_FILE_NAME = "local_encoder.v"; constexpr char* ARCH_ENCODER_VERILOG_FILE_NAME = "arch_encoder.v"; constexpr char* MEMORIES_VERILOG_FILE_NAME = "memories.v"; +constexpr char* SHIFT_REGISTER_BANKS_VERILOG_FILE_NAME = "shift_register_banks.v"; constexpr char* WIRES_VERILOG_FILE_NAME = "wires.v"; constexpr char* ESSENTIALS_VERILOG_FILE_NAME = "inv_buf_passgate.v"; constexpr char* CONFIG_PERIPHERAL_VERILOG_FILE_NAME = "config_peripherals.v"; diff --git a/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp b/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp new file mode 100644 index 000000000..4d629a0cb --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp @@ -0,0 +1,81 @@ +/********************************************************************* + * This file includes functions to generate Verilog submodules for + * the memories that are affiliated to multiplexers and other programmable + * circuit models, such as IOPADs, LUTs, etc. + ********************************************************************/ +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" + +/* Headers from openfpgautil library */ +#include "openfpga_digest.h" + +#include "mux_graph.h" +#include "module_manager.h" +#include "circuit_library_utils.h" +#include "mux_utils.h" + +#include "openfpga_naming.h" + +#include "verilog_constants.h" +#include "verilog_writer_utils.h" +#include "verilog_module_writer.h" +#include "verilog_shift_register_banks.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/********************************************************************* + * Generate Verilog modules for + * the shift register banks that are used to control BL/WLs + ********************************************************************/ +void print_verilog_submodule_shift_register_banks(const ModuleManager& module_manager, + NetlistManager& netlist_manager, + const std::array& blwl_sr_banks, + const std::string& submodule_dir, + const FabricVerilogOption& options) { + + /* Plug in with the mux subckt */ + std::string verilog_fname(submodule_dir + std::string(SHIFT_REGISTER_BANKS_VERILOG_FILE_NAME)); + + /* Create the file stream */ + std::fstream fp; + fp.open(verilog_fname, std::fstream::out | std::fstream::trunc); + + check_file_stream(verilog_fname.c_str(), fp); + + /* Print out debugging information for if the file is not opened/created properly */ + VTR_LOG("Writing Verilog netlist for shift register banks '%s' ...", + verilog_fname.c_str()); + + print_verilog_file_header(fp, "Shift register banks used in FPGA"); + + /* Create the memory circuits for the multiplexer */ + for (const auto& sr_bank : blwl_sr_banks) { + for (const ModuleId& sr_module : sr_bank.shift_register_bank_unique_modules()) { + VTR_ASSERT(true == module_manager.valid_module_id(sr_module)); + /* Write the module content in Verilog format */ + write_verilog_module_to_file(fp, module_manager, sr_module, + options.explicit_port_mapping(), + options.default_net_type()); + + /* Add an empty line as a splitter */ + fp << std::endl; + } + } + + /* Close the file stream */ + fp.close(); + + /* Add fname to the netlist name list */ + NetlistId nlist_id = netlist_manager.add_netlist(verilog_fname); + VTR_ASSERT(NetlistId::INVALID() != nlist_id); + netlist_manager.set_netlist_type(nlist_id, NetlistManager::SUBMODULE_NETLIST); + + VTR_LOG("Done\n"); +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_shift_register_banks.h b/openfpga/src/fpga_verilog/verilog_shift_register_banks.h new file mode 100644 index 000000000..2de1bedee --- /dev/null +++ b/openfpga/src/fpga_verilog/verilog_shift_register_banks.h @@ -0,0 +1,29 @@ +#ifndef VERILOG_SHIFT_REGISTER_BANKS_H +#define VERILOG_SHIFT_REGISTER_BANKS_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include + +#include "memory_bank_shift_register_banks.h" +#include "module_manager.h" +#include "netlist_manager.h" +#include "fabric_verilog_options.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void print_verilog_submodule_shift_register_banks(const ModuleManager& module_manager, + NetlistManager& netlist_manager, + const std::array& blwl_sr_banks, + const std::string& submodule_dir, + const FabricVerilogOption& options); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fpga_verilog/verilog_submodule.cpp b/openfpga/src/fpga_verilog/verilog_submodule.cpp index d2bca2aa9..0cb2c97a4 100644 --- a/openfpga/src/fpga_verilog/verilog_submodule.cpp +++ b/openfpga/src/fpga_verilog/verilog_submodule.cpp @@ -14,6 +14,7 @@ #include "verilog_lut.h" #include "verilog_wire.h" #include "verilog_memory.h" +#include "verilog_shift_register_banks.h" #include "verilog_writer_utils.h" #include "verilog_constants.h" @@ -33,6 +34,7 @@ namespace openfpga { ********************************************************************/ void print_verilog_submodule(ModuleManager& module_manager, NetlistManager& netlist_manager, + const std::array& blwl_sr_banks, const MuxLibrary& mux_lib, const DecoderLibrary& decoder_lib, const CircuitLibrary& circuit_lib, @@ -84,14 +86,22 @@ void print_verilog_submodule(ModuleManager& module_manager, submodule_dir, fpga_verilog_opts.default_net_type()); - /* 4. Memories */ + /* Memories */ print_verilog_submodule_memories(const_cast(module_manager), netlist_manager, mux_lib, circuit_lib, submodule_dir, fpga_verilog_opts); - /* 5. Dump template for all the modules */ + /* Shift register banks */ + print_verilog_submodule_shift_register_banks(const_cast(module_manager), + netlist_manager, + blwl_sr_banks, + submodule_dir, + fpga_verilog_opts); + + + /* Dump template for all the modules */ if (true == fpga_verilog_opts.print_user_defined_template()) { print_verilog_submodule_templates(const_cast(module_manager), circuit_lib, diff --git a/openfpga/src/fpga_verilog/verilog_submodule.h b/openfpga/src/fpga_verilog/verilog_submodule.h index 27bf7fdba..d25ec4844 100644 --- a/openfpga/src/fpga_verilog/verilog_submodule.h +++ b/openfpga/src/fpga_verilog/verilog_submodule.h @@ -8,6 +8,7 @@ #include "netlist_manager.h" #include "mux_library.h" #include "decoder_library.h" +#include "memory_bank_shift_register_banks.h" #include "fabric_verilog_options.h" /******************************************************************** @@ -19,6 +20,7 @@ namespace openfpga { void print_verilog_submodule(ModuleManager& module_manager, NetlistManager& netlist_manager, + const std::array& blwl_sr_banks, const MuxLibrary& mux_lib, const DecoderLibrary& decoder_lib, const CircuitLibrary& circuit_lib, From 4d8019b7c1c1d4b5020570ce041d069e5cca23e6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 29 Sep 2021 22:32:45 -0700 Subject: [PATCH 117/229] [FPGA-Bitstream] Bug fix in bitstream generator for shift-register-based memory bank --- .../build_fabric_bitstream_memory_bank.cpp | 24 ++++++++++++++----- openfpga/src/utils/memory_utils.cpp | 10 +++++--- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index 998b3960b..7742b9bf9 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -249,8 +249,12 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol } } } else { - /* TODO */ VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); + bl_addr_port_info.set_width(1); /* Deposit minimum width */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + size_t num_bls = compute_memory_bank_regional_num_bls(module_manager, top_module, config_region, circuit_lib, config_protocol.memory_model()); + bl_addr_port_info.set_width(std::max(num_bls, bl_addr_port_info.get_width())); + } } /* For different WL control protocol, the address ports are different @@ -275,8 +279,12 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol } } } else { - /* TODO */ VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()); + wl_addr_port_info.set_width(1); /* Deposit minimum width */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + size_t num_wls = compute_memory_bank_regional_num_wls(module_manager, top_module, config_region, circuit_lib, config_protocol.memory_model()); + wl_addr_port_info.set_width(std::max(num_wls, wl_addr_port_info.get_width())); + } } /* Reserve bits before build-up */ @@ -297,26 +305,30 @@ void build_module_fabric_dependent_bitstream_ql_memory_bank(const ConfigProtocol /* Find the BL/WL port (different region may have different sizes of BL/WLs) */ ModulePortId cur_bl_addr_port; + BasicPort cur_bl_addr_port_info; if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { cur_bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); + cur_bl_addr_port_info = module_manager.module_port(top_module, cur_bl_addr_port); } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { cur_bl_addr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), config_region)); + cur_bl_addr_port_info = module_manager.module_port(top_module, cur_bl_addr_port); } else { - /* TODO */ VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); + cur_bl_addr_port_info.set_width(compute_memory_bank_regional_num_bls(module_manager, top_module, config_region, circuit_lib, config_protocol.memory_model())); } - BasicPort cur_bl_addr_port_info = module_manager.module_port(top_module, cur_bl_addr_port); ModulePortId cur_wl_addr_port; + BasicPort cur_wl_addr_port_info; if (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) { cur_wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); + cur_wl_addr_port_info = module_manager.module_port(top_module, cur_wl_addr_port); } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { cur_wl_addr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region)); + cur_wl_addr_port_info = module_manager.module_port(top_module, cur_wl_addr_port); } else { - /* TODO */ VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()); + cur_wl_addr_port_info.set_width(compute_memory_bank_regional_num_wls(module_manager, top_module, config_region, circuit_lib, config_protocol.memory_model())); } - BasicPort cur_wl_addr_port_info = module_manager.module_port(top_module, cur_wl_addr_port); /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric diff --git a/openfpga/src/utils/memory_utils.cpp b/openfpga/src/utils/memory_utils.cpp index 71c2c60ef..8da43d02b 100644 --- a/openfpga/src/utils/memory_utils.cpp +++ b/openfpga/src/utils/memory_utils.cpp @@ -447,11 +447,15 @@ size_t estimate_num_configurable_children_to_skip_by_config_protocol(const Confi || CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) { VTR_ASSERT(2 <= curr_region_num_config_child); num_child_to_skip = 2; - /* If flatten bus is used, BL/WL may not need decoders */ - if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { + /* - If flatten bus is used, BL/WL may not need decoders + * - If shift registers are used, BL/WLs do not need decoders. And shift registers are not counted as configurable children + */ + if ( BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() + || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type() ) { num_child_to_skip--; } - if (BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type()) { + if ( BLWL_PROTOCOL_FLATTEN == config_protocol.wl_protocol_type() + || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type() ) { num_child_to_skip--; } } From 43c569b612fb54a3f1784cfbedc3f90720184602 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 30 Sep 2021 14:47:21 -0700 Subject: [PATCH 118/229] [FPGA-Bitstream] Encapusulate the data structur storing memory bank fabric bitstream for flatten BL/WL into an object --- .../memory_bank_flatten_fabric_bitstream.cpp | 50 +++++++++++++ .../memory_bank_flatten_fabric_bitstream.h | 49 +++++++++++++ .../write_text_fabric_bitstream.cpp | 70 ++++++++++++++----- openfpga/src/utils/fabric_bitstream_utils.cpp | 2 +- openfpga/src/utils/fabric_bitstream_utils.h | 5 +- 5 files changed, 155 insertions(+), 21 deletions(-) create mode 100644 openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.cpp create mode 100644 openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.h diff --git a/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.cpp new file mode 100644 index 000000000..110732b3d --- /dev/null +++ b/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.cpp @@ -0,0 +1,50 @@ +#include "memory_bank_flatten_fabric_bitstream.h" + +/* begin namespace openfpga */ +namespace openfpga { + +size_t MemoryBankFlattenFabricBitstream::size() const { + return bitstream_.size(); +} + +size_t MemoryBankFlattenFabricBitstream::bl_vector_size() const { + /* The address sizes and data input sizes are the same across any element, + * just get it from the 1st element to save runtime + */ + size_t bl_vec_size = 0; + for (const auto& bl_vec : bitstream_.begin()->second) { + bl_vec_size += bl_vec.size(); + } + return bl_vec_size; +} + +size_t MemoryBankFlattenFabricBitstream::wl_vector_size() const { + /* The address sizes and data input sizes are the same across any element, + * just get it from the 1st element to save runtime + */ + size_t wl_vec_size = 0; + for (const auto& wl_vec : bitstream_.begin()->first) { + wl_vec_size += wl_vec.size(); + } + return wl_vec_size; +} + +std::vector MemoryBankFlattenFabricBitstream::bl_vector(const std::vector& wl_vec) const { + return bitstream_.at(wl_vec); +} + +std::vector> MemoryBankFlattenFabricBitstream::wl_vectors() const { + std::vector> wl_vecs; + for (const auto& pair : bitstream_) { + wl_vecs.push_back(pair.first); + } + return wl_vecs; +} + +void MemoryBankFlattenFabricBitstream::add_blwl_vectors(const std::vector& bl_vec, + const std::vector& wl_vec) { + /* TODO: Add sanity check. Give a warning if the wl vector is already there */ + bitstream_[wl_vec] = bl_vec; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.h b/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.h new file mode 100644 index 000000000..4c5cf27a9 --- /dev/null +++ b/openfpga/src/fpga_bitstream/memory_bank_flatten_fabric_bitstream.h @@ -0,0 +1,49 @@ +#ifndef MEMORY_BANK_FLATTEN_FABRIC_BITSTREAM_H +#define MEMORY_BANK_FLATTEN_FABRIC_BITSTREAM_H + +#include +#include +#include +#include "vtr_vector.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/****************************************************************************** + * This files includes data structures that stores a downloadable format of fabric bitstream + * which is compatible with memory bank configuration protocol using flatten BL/WL buses + * @note This data structure is mainly used to output bitstream file for compatible protocols + ******************************************************************************/ +class MemoryBankFlattenFabricBitstream { + public: /* Accessors */ + /* @brief Return the length of bitstream */ + size_t size() const; + + /* @brief Return the BL address size */ + size_t bl_vector_size() const; + + /* @brief Return the WL address size */ + size_t wl_vector_size() const; + + /* @brief Return the BL vectors with a given WL key */ + std::vector bl_vector(const std::vector& wl_vec) const; + + /* @brief Return all the WL vectors in a downloaded sequence */ + std::vector> wl_vectors() const; + + public: /* Mutators */ + /* @brief add a pair of BL/WL vectors to the bitstream database */ + void add_blwl_vectors(const std::vector& bl_vec, + const std::vector& wl_vec); + public: /* Validators */ + private: /* Internal data */ + /* [(wl_bank0, wl_bank1, ...)] = [(bl_bank0, bl_bank1, ...)] + * Must use (WL, BL) as pairs in the map!!! + * This is because BL data may not be unique while WL must be unique + */ + std::map, std::vector> bitstream_; +}; + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index ee1b3deda..a25b5ad02 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -199,14 +199,8 @@ int write_memory_bank_flatten_fabric_bitstream_to_text_file(std::fstream& fp, /* The address sizes and data input sizes are the same across any element, * just get it from the 1st element to save runtime */ - size_t bl_addr_size = 0; - for (const auto& bl_vec : fabric_bits.begin()->second) { - bl_addr_size += bl_vec.size(); - } - size_t wl_addr_size = 0; - for (const auto& wl_vec : fabric_bits.begin()->first) { - wl_addr_size += wl_vec.size(); - } + size_t bl_addr_size = fabric_bits.bl_vector_size(); + size_t wl_addr_size = fabric_bits.wl_vector_size(); /* Output information about how to intepret the bitstream */ fp << "// Bitstream length: " << fabric_bits.size() << std::endl; @@ -215,14 +209,55 @@ int write_memory_bank_flatten_fabric_bitstream_to_text_file(std::fstream& fp, fp << ""; fp << std::endl; - for (const auto& addr_pair : fabric_bits) { + for (const auto& wl_vec : fabric_bits.wl_vectors()) { /* Write BL address code */ - for (const auto& bl_vec : addr_pair.second) { - fp << bl_vec; + for (const auto& bl_unit : fabric_bits.bl_vector(wl_vec)) { + fp << bl_unit; } /* Write WL address code */ - for (const auto& wl_vec : addr_pair.first) { - fp << wl_vec; + for (const auto& wl_unit : wl_vec) { + fp << wl_unit; + } + fp << std::endl; + } + + return status; +} + +/******************************************************************** + * Write the fabric bitstream fitting a memory bank protocol + * to a plain text file + * + * Return: + * - 0 if succeed + * - 1 if critical errors occured + *******************************************************************/ +static +int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream& fp, + const bool& bit_value_to_skip, + const FabricBitstream& fabric_bitstream) { + int status = 0; + + MemoryBankFlattenFabricBitstream fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, bit_value_to_skip); + + size_t bl_addr_size = fabric_bits.bl_vector_size(); + size_t wl_addr_size = fabric_bits.wl_vector_size(); + + /* Output information about how to intepret the bitstream */ + fp << "// Bitstream length: " << fabric_bits.size() << std::endl; + fp << "// Bitstream width (LSB -> MSB): "; + fp << ""; + fp << ""; + fp << std::endl; + + for (const auto& wl_vec : fabric_bits.wl_vectors()) { + /* Write BL address code */ + for (const auto& bl_unit : fabric_bits.bl_vector(wl_vec)) { + fp << bl_unit; + } + /* Write WL address code */ + for (const auto& wl_unit : wl_vec) { + fp << wl_unit; } fp << std::endl; } @@ -369,12 +404,15 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage apply_fast_configuration, bit_value_to_skip, fabric_bitstream); - } else { - VTR_ASSERT(BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() - || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); + } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { status = write_memory_bank_flatten_fabric_bitstream_to_text_file(fp, bit_value_to_skip, fabric_bitstream); + } else { + VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); + status = write_memory_bank_shift_register_fabric_bitstream_to_text_file(fp, + bit_value_to_skip, + fabric_bitstream); } break; } diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 2df7bcb23..b300919a4 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -313,7 +313,7 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons } } /* Add the pair to std map */ - fabric_bits[cur_wl_vectors] = cur_bl_vectors; + fabric_bits.add_blwl_vectors(cur_bl_vectors, cur_wl_vectors); } return fabric_bits; diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index ad14aef74..d21c9c12e 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -10,6 +10,7 @@ #include #include #include "bitstream_manager.h" +#include "memory_bank_flatten_fabric_bitstream.h" #include "fabric_bitstream.h" /******************************************************************** @@ -37,10 +38,6 @@ FrameFabricBitstream build_frame_based_fabric_bitstream_by_address(const FabricB size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip); -/* Must use (WL, BL) as pairs in the map!!! - * This is because BL data may not be unique while WL must be unique - */ -typedef std::map, std::vector> MemoryBankFlattenFabricBitstream; /******************************************************************** * @ brief Reorganize the fabric bitstream for memory banks which use flatten or shift register to manipulate BL and WLs * For each configuration region, we will merge BL address (which are 1-hot codes) under the same WL address From 4526133089e99694980c4c7fed040fdb9683ee1a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 30 Sep 2021 17:01:02 -0700 Subject: [PATCH 119/229] [FPGA-Bitstream] Add a new data structure that stores fabric bitstream for memory bank using shift registers --- ...y_bank_shift_register_fabric_bitstream.cpp | 77 +++++++++++++++ ...ory_bank_shift_register_fabric_bitstream.h | 93 +++++++++++++++++++ ...bank_shift_register_fabric_bitstream_fwd.h | 23 +++++ 3 files changed, 193 insertions(+) create mode 100644 openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp create mode 100644 openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h create mode 100644 openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream_fwd.h diff --git a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp new file mode 100644 index 000000000..06c3c4aea --- /dev/null +++ b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp @@ -0,0 +1,77 @@ +#include "vtr_assert.h" +#include "memory_bank_shift_register_fabric_bitstream.h" + +/* begin namespace openfpga */ +namespace openfpga { + +MemoryBankShiftRegisterFabricBitstream::word_range MemoryBankShiftRegisterFabricBitstream::words() const { + return vtr::make_range(bitstream_word_ids_.begin(), bitstream_word_ids_.end()); +} + +size_t MemoryBankShiftRegisterFabricBitstream::num_words() const { + return bitstream_word_ids_.size(); +} + +size_t MemoryBankShiftRegisterFabricBitstream::word_size() const { + /* For a fast runtime, we just inspect the last element + * It is the validator which should ensure all the words have a uniform size + */ + return bitstream_word_bls_[bitstream_word_ids_.back()].size(); +} + +size_t MemoryBankShiftRegisterFabricBitstream::bl_width() const { + /* For a fast runtime, we just inspect the last element + * It is the validator which should ensure all the words have a uniform size + */ + return bitstream_word_bls_[bitstream_word_ids_.back()].back().size(); +} + +size_t MemoryBankShiftRegisterFabricBitstream::wl_width() const { + /* For a fast runtime, we just inspect the last element + * It is the validator which should ensure all the words have a uniform size + */ + return bitstream_word_wls_[bitstream_word_ids_.back()].back().size(); +} + +std::vector MemoryBankShiftRegisterFabricBitstream::bl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const { + VTR_ASSERT(valid_word_id(word_id)); + return bitstream_word_bls_[word_id]; +} + +std::vector MemoryBankShiftRegisterFabricBitstream::wl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const { + VTR_ASSERT(valid_word_id(word_id)); + return bitstream_word_wls_[word_id]; +} + +MemoryBankShiftRegisterFabricBitstreamWordId MemoryBankShiftRegisterFabricBitstream::create_word() { + /* Create a new id*/ + MemoryBankShiftRegisterFabricBitstreamWordId word_id = MemoryBankShiftRegisterFabricBitstreamWordId(bitstream_word_ids_.size()); + /* Update the id list */ + bitstream_word_ids_.push_back(word_id); + + /* Initialize other attributes */ + bitstream_word_bls_.emplace_back(); + bitstream_word_wls_.emplace_back(); + + return word_id; +} + +void MemoryBankShiftRegisterFabricBitstream::add_bl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, + const std::string& bl_vec) { + VTR_ASSERT(valid_word_id(word_id)); + VTR_ASSERT(bl_vec.size() == bl_width()); + return bitstream_word_bls_[word_id].push_back(bl_vec); +} + +void MemoryBankShiftRegisterFabricBitstream::add_wl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, + const std::string& wl_vec) { + VTR_ASSERT(valid_word_id(word_id)); + VTR_ASSERT(wl_vec.size() == wl_width()); + return bitstream_word_wls_[word_id].push_back(wl_vec); +} + +bool MemoryBankShiftRegisterFabricBitstream::valid_word_id(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const { + return ( size_t(word_id) < bitstream_word_ids_.size() ) && ( word_id == bitstream_word_ids_[word_id] ); +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h new file mode 100644 index 000000000..b6355ccad --- /dev/null +++ b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h @@ -0,0 +1,93 @@ +#ifndef MEMORY_BANK_SHIFT_REGISTER_FABRIC_BITSTREAM_H +#define MEMORY_BANK_SHIFT_REGISTER_FABRIC_BITSTREAM_H + +#include +#include +#include +#include "vtr_vector.h" +#include "memory_bank_shift_register_fabric_bitstream_fwd.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/****************************************************************************** + * This files includes data structures that stores a downloadable format of fabric bitstream + * which is compatible with memory bank configuration protocol using shift register to control BL/WLs + * @note This data structure is mainly used to output bitstream file for compatible protocols + ******************************************************************************/ +class MemoryBankShiftRegisterFabricBitstream { + public: /* Types */ + typedef vtr::vector::const_iterator word_iterator; + /* Create range */ + typedef vtr::Range word_range; + + public: /* Accessors: aggregates */ + word_range words() const; + + public: /* Accessors */ + /* @brief Return the length of bitstream */ + size_t num_words() const; + + /* @brief Return the length of each word. All the word should have a uniform size */ + size_t word_size() const; + + /* @brief Return the width of each BL word, which is the number of heads through which a BL word can be loaded in parallel */ + size_t bl_width() const; + + /* @brief Return the width of each WL word, which is the number of heads through which a WL word can be loaded in parallel */ + size_t wl_width() const; + + /* @brief Return the BL vectors with a given word id*/ + std::vector bl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const; + + /* @brief Return the WL vectors in a given word id */ + std::vector wl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const; + + public: /* Mutators */ + /* @brief Create a new word */ + MemoryBankShiftRegisterFabricBitstreamWordId create_word(); + + /* @brief Add BLs to a given word */ + void add_bl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, + const std::string& bl_vec); + + /* @brief Add WLs to a given word */ + void add_wl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, + const std::string& wl_vec); + + public: /* Validators */ + bool valid_word_id(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const; + + private: /* Internal data */ + /* Organization of the bitstream + * + * ============= Begin of Word 1 ============== + * |<--No of -->|<-- No of -->| + * | BL heads | WL heads | + * 010101 .. 101 101110 .. 001 ---- + * ... ... ^ + * | + * max. shift register length per word + * | + * v + * 110001 .. 111 100100 .. 110 ---- + * ============= End of Word 1 ============== + * ============= Begin of Word 2 ============== + * 010101 .. 101 101110 .. 001 ---- + * ... ... ^ + * | + * max. shift register length per word + * | + * v + * 110001 .. 111 100100 .. 110 ---- + * ============= End of Word 2 ============== + * .... more words + */ + vtr::vector bitstream_word_ids_; + vtr::vector> bitstream_word_bls_; + vtr::vector> bitstream_word_wls_; +}; + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream_fwd.h b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream_fwd.h new file mode 100644 index 000000000..87c1ebad2 --- /dev/null +++ b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream_fwd.h @@ -0,0 +1,23 @@ +/************************************************** + * This file includes only declarations for + * the data structures for MemoryBankShiftRegisterFabricBitstream + * Please refer to memory_bank_shift_register_fabric_bitstream.h for more details + *************************************************/ +#ifndef MEMORY_BANK_SHIFT_REGISTER_FABRIC_BITSTREAM_FWD_H +#define MEMORY_BANK_SHIFT_REGISTER_FABRIC_BITSTREAM_FWD_H + +#include "vtr_strong_id.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/* Strong Ids for ModuleManager */ +struct memory_bank_shift_register_fabric_bitstream_word_id_tag; + +typedef vtr::StrongId MemoryBankShiftRegisterFabricBitstreamWordId; + +class MemoryBankShiftRegisterFabricBitstream; + +} /* end namespace openfpga */ + +#endif From 33972fc0ec11d73ec892ff852bd9f0ebfb98d8af Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 30 Sep 2021 21:05:41 -0700 Subject: [PATCH 120/229] [FPGA-Bitstream] Upgraded bitstream writer to support QuickLogic memory bank using shift registers --- .../fabric/build_top_module_memory_bank.cpp | 13 ++++- .../memory_bank_shift_register_banks.cpp | 49 ++++++++++------- .../fabric/memory_bank_shift_register_banks.h | 12 +++- ...y_bank_shift_register_fabric_bitstream.cpp | 12 +++- ...ory_bank_shift_register_fabric_bitstream.h | 3 + .../write_text_fabric_bitstream.cpp | 27 ++++----- openfpga/src/utils/fabric_bitstream_utils.cpp | 55 +++++++++++++++++++ openfpga/src/utils/fabric_bitstream_utils.h | 37 ++++++++++++- 8 files changed, 166 insertions(+), 42 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index dd2bdf29b..206a70728 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -1323,13 +1323,19 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; /* Find the BL port */ ModulePortId child_bl_port = module_manager.find_module_port(child_module, std::string(MEMORY_BL_PORT_NAME)); BasicPort child_bl_port_info = module_manager.module_port(child_module, child_bl_port); + size_t cur_bl_index = 0; + for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { + size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index; + sr_banks.add_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_bl_pin); + sr_banks.add_shift_register_sink_blwls(config_region, sr_bank_module, cur_inst, bl_pin_id); } } } @@ -1409,13 +1415,18 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - /* Find the BL port */ + size_t cur_wl_index = 0; + + /* Find the WL port */ ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME)); BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port); for (const size_t& sink_wl_pin : child_wl_port_info.pins()) { + size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + cur_wl_index; sr_banks.add_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_wl_pin); + sr_banks.add_shift_register_sink_blwls(config_region, sr_bank_module, cur_inst, wl_pin_id); } } } diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index 0d4902936..aac8989fe 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -7,7 +7,7 @@ namespace openfpga { std::vector MemoryBankShiftRegisterBanks::shift_register_bank_unique_modules() const { std::vector sr_bank_modules; - for (const auto& region : sr_instance_info_) { + for (const auto& region : sr_instance_sink_child_ids_) { for (const auto& pair : region) { if (sr_bank_modules.end() == std::find(sr_bank_modules.begin(), sr_bank_modules.end(), pair.first.first)) { sr_bank_modules.push_back(pair.first.first); @@ -20,7 +20,7 @@ std::vector MemoryBankShiftRegisterBanks::shift_register_bank_unique_m std::vector MemoryBankShiftRegisterBanks::shift_register_bank_modules(const ConfigRegionId& region) const { std::vector sr_bank_modules; VTR_ASSERT(valid_region_id(region)); - for (const auto& pair : sr_instance_info_[region]) { + for (const auto& pair : sr_instance_sink_child_ids_[region]) { sr_bank_modules.push_back(pair.first.first); } return sr_bank_modules; @@ -29,7 +29,7 @@ std::vector MemoryBankShiftRegisterBanks::shift_register_bank_modules( std::vector MemoryBankShiftRegisterBanks::shift_register_bank_instances(const ConfigRegionId& region) const { std::vector sr_bank_instances; VTR_ASSERT(valid_region_id(region)); - for (const auto& pair : sr_instance_info_[region]) { + for (const auto& pair : sr_instance_sink_child_ids_[region]) { sr_bank_instances.push_back(pair.first.second); } return sr_bank_instances; @@ -39,43 +39,41 @@ std::vector MemoryBankShiftRegisterBanks::shift_register_bank_sink_child const ModuleId& sr_module, const size_t& sr_instance) const { VTR_ASSERT(valid_region_id(region)); - std::vector sink_child_ids; - auto result = sr_instance_info_[region].find(std::make_pair(sr_module, sr_instance)); + auto result = sr_instance_sink_child_ids_[region].find(std::make_pair(sr_module, sr_instance)); /* Return an empty vector if not found */ - if (result != sr_instance_info_[region].end()) { - for (const auto& sink_child : result->second) { - sink_child_ids.push_back(sink_child.first); - } + if (result != sr_instance_sink_child_ids_[region].end()) { + return result->second; } - return sink_child_ids; + return std::vector(); } std::vector MemoryBankShiftRegisterBanks::shift_register_bank_sink_pin_ids(const ConfigRegionId& region, const ModuleId& sr_module, const size_t& sr_instance) const { VTR_ASSERT(valid_region_id(region)); - std::vector sink_child_pin_ids; - auto result = sr_instance_info_[region].find(std::make_pair(sr_module, sr_instance)); + auto result = sr_instance_sink_child_pin_ids_[region].find(std::make_pair(sr_module, sr_instance)); /* Return an empty vector if not found */ - if (result != sr_instance_info_[region].end()) { - for (const auto& sink_child : result->second) { - sink_child_pin_ids.push_back(sink_child.second); - } + if (result != sr_instance_sink_child_pin_ids_[region].end()) { + return result->second; } - return sink_child_pin_ids; + return std::vector(); } void MemoryBankShiftRegisterBanks::resize_regions(const size_t& num_regions) { - sr_instance_info_.resize(num_regions); + sr_instance_sink_child_ids_.resize(num_regions); + sr_instance_sink_child_pin_ids_.resize(num_regions); + sr_instance_sink_blwl_ids_.resize(num_regions); } void MemoryBankShiftRegisterBanks::add_shift_register_instance(const ConfigRegionId& region, const ModuleId& sr_module, const size_t& sr_instance) { VTR_ASSERT(valid_region_id(region)); - sr_instance_info_[region][std::make_pair(sr_module, sr_instance)]; + sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)]; + sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)]; + sr_instance_sink_blwl_ids_[region][std::make_pair(sr_module, sr_instance)]; } void MemoryBankShiftRegisterBanks::add_shift_register_sink_nodes(const ConfigRegionId& region, @@ -84,11 +82,20 @@ void MemoryBankShiftRegisterBanks::add_shift_register_sink_nodes(const ConfigReg const size_t& sink_child_id, const size_t& sink_child_pin_id) { VTR_ASSERT(valid_region_id(region)); - sr_instance_info_[region][std::make_pair(sr_module, sr_instance)].push_back(std::make_pair(sink_child_id, sink_child_pin_id)); + sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_id); + sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_pin_id); } +void MemoryBankShiftRegisterBanks::add_shift_register_sink_blwls(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_blwl_id) { + VTR_ASSERT(valid_region_id(region)); + sr_instance_sink_blwl_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_blwl_id); +} + bool MemoryBankShiftRegisterBanks::valid_region_id(const ConfigRegionId& region) const { - return size_t(region) < sr_instance_info_.size(); + return size_t(region) < sr_instance_sink_child_ids_.size(); } } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h index 59c92fef7..a145aca5e 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.h +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -52,18 +52,26 @@ class MemoryBankShiftRegisterBanks { const ModuleId& sr_module, const size_t& sr_instance); - /* @brief Add the module id and instance id of a shift register under a specific configuration region of top-level module */ + /* @brief Add the child id and pin id of BL/WL to which a shift register is connected to under a specific configuration region of top-level module */ void add_shift_register_sink_nodes(const ConfigRegionId& region, const ModuleId& sr_module, const size_t& sr_instance, const size_t& sink_child_id, const size_t& sink_child_pin_id); + + /* @brief Add the BL/WL id under a specific configuration region of top-level module to which a shift register is connected to */ + void add_shift_register_sink_blwls(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_blwl_id); public: /* Validators */ bool valid_region_id(const ConfigRegionId& region) const; private: /* Internal data */ /* [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/ - vtr::vector, std::vector>>> sr_instance_info_; + vtr::vector, std::vector>> sr_instance_sink_child_ids_; + vtr::vector, std::vector>> sr_instance_sink_child_pin_ids_; + vtr::vector, std::vector>> sr_instance_sink_blwl_ids_; }; } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp index 06c3c4aea..9d5f5fe63 100644 --- a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp @@ -43,6 +43,16 @@ std::vector MemoryBankShiftRegisterFabricBitstream::wl_vectors(cons return bitstream_word_wls_[word_id]; } +std::vector MemoryBankShiftRegisterFabricBitstream::blwl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const { + VTR_ASSERT(valid_word_id(word_id)); + std::vector blwl_vec = bitstream_word_bls_[word_id]; + VTR_ASSERT(blwl_vec.size() == bitstream_word_wls_[word_id].size()); + for (size_t iwl = 0; iwl < bitstream_word_wls_[word_id].size(); ++iwl) { + blwl_vec[iwl] += bitstream_word_wls_[word_id][iwl]; + } + return blwl_vec; +} + MemoryBankShiftRegisterFabricBitstreamWordId MemoryBankShiftRegisterFabricBitstream::create_word() { /* Create a new id*/ MemoryBankShiftRegisterFabricBitstreamWordId word_id = MemoryBankShiftRegisterFabricBitstreamWordId(bitstream_word_ids_.size()); @@ -59,14 +69,12 @@ MemoryBankShiftRegisterFabricBitstreamWordId MemoryBankShiftRegisterFabricBitstr void MemoryBankShiftRegisterFabricBitstream::add_bl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, const std::string& bl_vec) { VTR_ASSERT(valid_word_id(word_id)); - VTR_ASSERT(bl_vec.size() == bl_width()); return bitstream_word_bls_[word_id].push_back(bl_vec); } void MemoryBankShiftRegisterFabricBitstream::add_wl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id, const std::string& wl_vec) { VTR_ASSERT(valid_word_id(word_id)); - VTR_ASSERT(wl_vec.size() == wl_width()); return bitstream_word_wls_[word_id].push_back(wl_vec); } diff --git a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h index b6355ccad..1355a8274 100644 --- a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h @@ -43,6 +43,9 @@ class MemoryBankShiftRegisterFabricBitstream { /* @brief Return the WL vectors in a given word id */ std::vector wl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const; + /* @brief Return the pair of BL and WL vectors in a given word id */ + std::vector blwl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const; + public: /* Mutators */ /* @brief Create a new word */ MemoryBankShiftRegisterFabricBitstreamWordId create_word(); diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index a25b5ad02..3c6de650f 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -238,26 +238,23 @@ int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream& const FabricBitstream& fabric_bitstream) { int status = 0; - MemoryBankFlattenFabricBitstream fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, bit_value_to_skip); - - size_t bl_addr_size = fabric_bits.bl_vector_size(); - size_t wl_addr_size = fabric_bits.wl_vector_size(); + MemoryBankShiftRegisterFabricBitstream fabric_bits = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, bit_value_to_skip); /* Output information about how to intepret the bitstream */ - fp << "// Bitstream length: " << fabric_bits.size() << std::endl; + fp << "// Bitstream word count: " << fabric_bits.num_words() << std::endl; + fp << "// Bitstream word size: " << fabric_bits.word_size() << std::endl; fp << "// Bitstream width (LSB -> MSB): "; - fp << ""; - fp << ""; + fp << ""; + fp << ""; fp << std::endl; - for (const auto& wl_vec : fabric_bits.wl_vectors()) { - /* Write BL address code */ - for (const auto& bl_unit : fabric_bits.bl_vector(wl_vec)) { - fp << bl_unit; - } - /* Write WL address code */ - for (const auto& wl_unit : wl_vec) { - fp << wl_unit; + size_t word_cnt = 0; + + for (const auto& word : fabric_bits.words()) { + fp << "// Word " << word_cnt << std::endl; + /* Write BL/WL address code */ + for (const auto& blwl_vec : fabric_bits.blwl_vectors(word)) { + fp << blwl_vec; } fp << std::endl; } diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index b300919a4..6ad0017a7 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -319,6 +319,61 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons return fabric_bits; } +MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream, + //const std::array& blwl_sr_banks, + const bool& bit_value_to_skip) { + MemoryBankFlattenFabricBitstream raw_fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, bit_value_to_skip); + MemoryBankShiftRegisterFabricBitstream fabric_bits; + + /* Iterate over each word */ + for (const auto& wl_vec : raw_fabric_bits.wl_vectors()) { + std::vector bl_vec = raw_fabric_bits.bl_vector(wl_vec); + /* Find the max sizes of BL/WL bits, this determines the size of shift register chain */ + size_t max_blwl_sizes = 0; + for (const auto& bl_bits : bl_vec) { + max_blwl_sizes = std::max(max_blwl_sizes, bl_bits.size()); + } + for (const auto& wl_bits : wl_vec) { + max_blwl_sizes = std::max(max_blwl_sizes, wl_bits.size()); + } + /* Reshape the BL and WL vectors */ + std::vector reshaped_blwls(bl_vec.size() + wl_vec.size(), std::string(max_blwl_sizes, '0')); + size_t blwl_col_cnt = 0; + for (const auto& bl_bits : bl_vec) { + size_t offset = max_blwl_sizes - bl_vec.size(); + for (const char& bl_bit : bl_bits) { + reshaped_blwls[blwl_col_cnt][offset] = bl_bit; + offset++; + } + blwl_col_cnt++; + } + for (const auto& wl_bits : wl_vec) { + size_t offset = max_blwl_sizes - wl_vec.size(); + for (const char& wl_bit : wl_bits) { + reshaped_blwls[blwl_col_cnt][offset] = wl_bit; + offset++; + } + blwl_col_cnt++; + } + /* Add the word to final bitstream */ + MemoryBankShiftRegisterFabricBitstreamWordId word_id = fabric_bits.create_word(); + for (size_t irow = 0; irow < max_blwl_sizes; ++irow) { + std::string cur_bl_vec; + for (size_t icol = 0; icol < bl_vec.size(); ++icol) { + cur_bl_vec.push_back(reshaped_blwls[icol][irow]); + } + fabric_bits.add_bl_vectors(word_id, cur_bl_vec); + + std::string cur_wl_vec; + for (size_t icol = bl_vec.size(); icol < bl_vec.size() + wl_vec.size(); ++icol) { + cur_wl_vec.push_back(reshaped_blwls[icol][irow]); + } + fabric_bits.add_wl_vectors(word_id, cur_wl_vec); + } + } + + return fabric_bits; +} /******************************************************************** * For fast configuration, the number of bits to be skipped diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index d21c9c12e..9a97a078b 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -9,8 +9,11 @@ *******************************************************************/ #include #include +#include #include "bitstream_manager.h" #include "memory_bank_flatten_fabric_bitstream.h" +#include "memory_bank_shift_register_banks.h" +#include "memory_bank_shift_register_fabric_bitstream.h" #include "fabric_bitstream.h" /******************************************************************** @@ -39,7 +42,7 @@ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBit const bool& bit_value_to_skip); /******************************************************************** - * @ brief Reorganize the fabric bitstream for memory banks which use flatten or shift register to manipulate BL and WLs + * @ brief Reorganize the fabric bitstream for memory banks which use flatten BL and WLs * For each configuration region, we will merge BL address (which are 1-hot codes) under the same WL address * * Quick Example @@ -61,6 +64,38 @@ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBit MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip); +/******************************************************************** + * @ brief Reorganize the fabric bitstream for memory banks which use shift register to manipulate BL and WLs + * For each configuration region, we will merge BL address (which are 1-hot codes) under the same WL address + * + * Quick Example + * _ _ + * An example: + * 010_111 000_101 + * + * Note that all the BL/WLs across configuration regions are independent. We will combine them together + * Quick Example + * _ _ + * 001_010 000_000 + * 100_100 000_000 + * + * the bitstream will be merged as + * 101_110 000_000 + * + * Because that the BL/WL are loaded through shift registers (perhaps using multiple heads), the bitstream will be reorganized as + * Considering single head: + * + * _ _ + * 1_1 0_0 + * 0_1 0_0 + * 1_0 0_0 + * + * @note the std::map may cause large memory footprint for large bitstream databases! + *******************************************************************/ +MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream, + //const std::array& blwl_sr_banks, + const bool& bit_value_to_skip); + /* Alias to a specific organization of bitstreams for memory bank configuration protocol */ typedef std::map, std::vector> MemoryBankFabricBitstream; MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream); From 4bdff1554d182b8bffef546eea494dab91dce1d5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 30 Sep 2021 21:20:56 -0700 Subject: [PATCH 121/229] [Engine] Fixed a critical bug which cause BL/WL sharing in shift-register-based memory bank broken --- .../src/fabric/build_top_module_memory_bank.cpp | 4 ++-- openfpga/src/utils/memory_bank_utils.cpp | 17 ++++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 206a70728..0c646fa55 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -1199,6 +1199,8 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name); BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port); + cur_sr_module_blwl_pin_id = cur_sr_module_blwl_pin_id % sr_module_blwl_port_info.get_width(); + /* Create net */ ModuleNetId net = create_module_source_pin_net(module_manager, top_module, sr_bank_module, sr_bank_instance, @@ -1210,8 +1212,6 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan size_t sink_pin_id = sr_banks.shift_register_bank_sink_pin_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; module_manager.add_module_net_sink(top_module, net, child_module, child_instance, child_blwl_port, sink_pin_id); - - cur_sr_module_blwl_pin_id++; } } } diff --git a/openfpga/src/utils/memory_bank_utils.cpp b/openfpga/src/utils/memory_bank_utils.cpp index dcb224fc6..98f0ffca6 100644 --- a/openfpga/src/utils/memory_bank_utils.cpp +++ b/openfpga/src/utils/memory_bank_utils.cpp @@ -90,11 +90,10 @@ size_t compute_memory_bank_regional_num_bls(const ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model) { size_t num_bls = 0; - - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - num_bls += find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_BL); + std::map num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module, + config_region, circuit_lib, sram_model); + for (const auto& pair : num_bls_per_tile) { + num_bls += pair.second; } return num_bls; @@ -123,10 +122,10 @@ size_t compute_memory_bank_regional_num_wls(const ModuleManager& module_manager, const CircuitModelId& sram_model) { size_t num_wls = 0; - for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) { - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - vtr::Point coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id]; - num_wls += find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_WL); + std::map num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module, + config_region, circuit_lib, sram_model); + for (const auto& pair : num_wls_per_tile) { + num_wls += pair.second; } return num_wls; From 96828e456a5c4acdf32492462ec8501835462e58 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 30 Sep 2021 22:07:46 -0700 Subject: [PATCH 122/229] [FPGA-Bitstream] Fixed a critical bug which cause reshaping bitstream wrong --- .../write_text_fabric_bitstream.cpp | 5 +++-- openfpga/src/utils/fabric_bitstream_utils.cpp | 18 ++++++------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 3c6de650f..58e5fd5bb 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -244,7 +244,7 @@ int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream& fp << "// Bitstream word count: " << fabric_bits.num_words() << std::endl; fp << "// Bitstream word size: " << fabric_bits.word_size() << std::endl; fp << "// Bitstream width (LSB -> MSB): "; - fp << ""; + fp << ""; fp << ""; fp << std::endl; @@ -255,8 +255,9 @@ int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream& /* Write BL/WL address code */ for (const auto& blwl_vec : fabric_bits.blwl_vectors(word)) { fp << blwl_vec; + fp << std::endl; } - fp << std::endl; + word_cnt++; } return status; diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 6ad0017a7..d82d09ded 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -337,22 +337,16 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b max_blwl_sizes = std::max(max_blwl_sizes, wl_bits.size()); } /* Reshape the BL and WL vectors */ - std::vector reshaped_blwls(bl_vec.size() + wl_vec.size(), std::string(max_blwl_sizes, '0')); + std::vector reshaped_blwls(bl_vec.size() + wl_vec.size(), std::string()); size_t blwl_col_cnt = 0; for (const auto& bl_bits : bl_vec) { - size_t offset = max_blwl_sizes - bl_vec.size(); - for (const char& bl_bit : bl_bits) { - reshaped_blwls[blwl_col_cnt][offset] = bl_bit; - offset++; - } + reshaped_blwls[blwl_col_cnt].resize(max_blwl_sizes - bl_bits.size(), '0'); + reshaped_blwls[blwl_col_cnt] += bl_bits; blwl_col_cnt++; } for (const auto& wl_bits : wl_vec) { - size_t offset = max_blwl_sizes - wl_vec.size(); - for (const char& wl_bit : wl_bits) { - reshaped_blwls[blwl_col_cnt][offset] = wl_bit; - offset++; - } + reshaped_blwls[blwl_col_cnt].resize(max_blwl_sizes - wl_bits.size(), '0'); + reshaped_blwls[blwl_col_cnt] += wl_bits; blwl_col_cnt++; } /* Add the word to final bitstream */ @@ -362,7 +356,7 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b for (size_t icol = 0; icol < bl_vec.size(); ++icol) { cur_bl_vec.push_back(reshaped_blwls[icol][irow]); } - fabric_bits.add_bl_vectors(word_id, cur_bl_vec); + fabric_bits.add_bl_vectors(word_id, cur_bl_vec); std::string cur_wl_vec; for (size_t icol = bl_vec.size(); icol < bl_vec.size() + wl_vec.size(); ++icol) { From fa57117f5045ca19c5464303b8ffed55aeb1f887 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 10:19:51 -0700 Subject: [PATCH 123/229] [Arch] Update openfpga architecture examples by adding syntax to identify clocks used by shift registers --- .../openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml | 4 ++-- .../openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml index 25f5261d9..ce848d2e7 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml @@ -173,7 +173,7 @@ - + @@ -184,7 +184,7 @@ - + diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml index 9c8e0964c..43d716222 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml @@ -170,23 +170,23 @@ - + - + - + - + From 7b010ba0f4ebc713f3403876a58eacaf4bfd556f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 11:00:38 -0700 Subject: [PATCH 124/229] [Engine] Support programming shift register clock in XML syntax --- .../libarchopenfpga/src/circuit_library.cpp | 18 ++++++- .../libarchopenfpga/src/circuit_library.h | 4 ++ .../src/read_xml_circuit_library.cpp | 3 ++ .../src/read_xml_simulation_setting.cpp | 45 +++++++++++++++- .../src/simulation_setting.cpp | 54 +++++++++++++++++++ .../libarchopenfpga/src/simulation_setting.h | 11 ++++ .../src/write_xml_circuit_library.cpp | 4 ++ .../src/write_xml_simulation_setting.cpp | 19 +++++-- .../src/fabric/fabric_global_port_info.cpp | 12 +++++ openfpga/src/fabric/fabric_global_port_info.h | 4 ++ openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp | 2 +- .../fpga_verilog/verilog_testbench_utils.cpp | 2 +- .../fpga_verilog/verilog_top_testbench.cpp | 10 ++-- .../auto_shift_register_sim_openfpga.xml | 41 ++++++++++++++ 14 files changed, 217 insertions(+), 12 deletions(-) create mode 100644 openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml diff --git a/libopenfpga/libarchopenfpga/src/circuit_library.cpp b/libopenfpga/libarchopenfpga/src/circuit_library.cpp index 4195158d4..e6b1f248e 100644 --- a/libopenfpga/libarchopenfpga/src/circuit_library.cpp +++ b/libopenfpga/libarchopenfpga/src/circuit_library.cpp @@ -949,7 +949,6 @@ bool CircuitLibrary::port_is_config_enable(const CircuitPortId& circuit_port_id) return port_is_config_enable_[circuit_port_id]; } - /* Return a flag if the port is used during programming a FPGA in a circuit model */ bool CircuitLibrary::port_is_prog(const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ @@ -957,6 +956,13 @@ bool CircuitLibrary::port_is_prog(const CircuitPortId& circuit_port_id) const { return port_is_prog_[circuit_port_id]; } +/* Return a flag if the port is used by shift register in a circuit model */ +bool CircuitLibrary::port_is_shift_register(const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); + return port_is_shift_register_[circuit_port_id]; +} + /* Return which level the output port locates at a LUT multiplexing structure */ size_t CircuitLibrary::port_lut_frac_level(const CircuitPortId& circuit_port_id) const { /* validate the circuit_port_id */ @@ -1401,6 +1407,7 @@ CircuitPortId CircuitLibrary::add_model_port(const CircuitModelId& model_id, port_is_set_.push_back(false); port_is_config_enable_.push_back(false); port_is_prog_.push_back(false); + port_is_shift_register_.push_back(false); port_tri_state_model_names_.emplace_back(); port_tri_state_model_ids_.push_back(CircuitModelId::INVALID()); port_inv_model_names_.emplace_back(); @@ -1538,6 +1545,15 @@ void CircuitLibrary::set_port_is_prog(const CircuitPortId& circuit_port_id, return; } +/* Set the is_prog for a port of a circuit model */ +void CircuitLibrary::set_port_is_shift_register(const CircuitPortId& circuit_port_id, + const bool& is_shift_register) { + /* validate the circuit_port_id */ + VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); + port_is_shift_register_[circuit_port_id] = is_shift_register; + return; +} + /* Set the model_name for a port of a circuit model */ void CircuitLibrary::set_port_tri_state_model_name(const CircuitPortId& circuit_port_id, const std::string& model_name) { diff --git a/libopenfpga/libarchopenfpga/src/circuit_library.h b/libopenfpga/libarchopenfpga/src/circuit_library.h index d2feee52b..ffd2f1661 100644 --- a/libopenfpga/libarchopenfpga/src/circuit_library.h +++ b/libopenfpga/libarchopenfpga/src/circuit_library.h @@ -288,6 +288,7 @@ class CircuitLibrary { bool port_is_set(const CircuitPortId& circuit_port_id) const; bool port_is_config_enable(const CircuitPortId& circuit_port_id) const; bool port_is_prog(const CircuitPortId& circuit_port_id) const; + bool port_is_shift_register(const CircuitPortId& circuit_port_id) const; size_t port_lut_frac_level(const CircuitPortId& circuit_port_id) const; bool port_is_harden_lut_port(const CircuitPortId& circuit_port_id) const; std::vector port_lut_output_mask(const CircuitPortId& circuit_port_id) const; @@ -372,6 +373,8 @@ class CircuitLibrary { const bool& is_config_enable); void set_port_is_prog(const CircuitPortId& circuit_port_id, const bool& is_prog); + void set_port_is_shift_register(const CircuitPortId& circuit_port_id, + const bool& is_shift_register); void set_port_tri_state_model_name(const CircuitPortId& circuit_port_id, const std::string& model_name); void set_port_tri_state_model_id(const CircuitPortId& circuit_port_id, @@ -560,6 +563,7 @@ class CircuitLibrary { vtr::vector port_is_set_; vtr::vector port_is_config_enable_; vtr::vector port_is_prog_; + vtr::vector port_is_shift_register_; vtr::vector port_tri_state_model_names_; vtr::vector port_tri_state_model_ids_; vtr::vector port_inv_model_names_; diff --git a/libopenfpga/libarchopenfpga/src/read_xml_circuit_library.cpp b/libopenfpga/libarchopenfpga/src/read_xml_circuit_library.cpp index 4fc3ddbb4..0137f961b 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_circuit_library.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_circuit_library.cpp @@ -484,6 +484,9 @@ void read_xml_circuit_port(pugi::xml_node& xml_port, /* Identify if the port is in programming purpose, by default it is NOT */ circuit_lib.set_port_is_prog(port, get_attribute(xml_port, "is_prog", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + /* Identify if the port is in shift register purpose, by default it is NOT */ + circuit_lib.set_port_is_shift_register(port, get_attribute(xml_port, "is_shift_register", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + /* Identify if the port is to enable programming for FPGAs, by default it is NOT */ circuit_lib.set_port_is_config_enable(port, get_attribute(xml_port, "is_config_enable", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); diff --git a/libopenfpga/libarchopenfpga/src/read_xml_simulation_setting.cpp b/libopenfpga/libarchopenfpga/src/read_xml_simulation_setting.cpp index b9ea51859..a76f2f2ff 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_simulation_setting.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_simulation_setting.cpp @@ -36,7 +36,7 @@ e_sim_accuracy_type string_to_sim_accuracy_type(const std::string& type_string) } /******************************************************************** - * Parse XML codes of a line to an object of simulation setting + * Parse XML codes of a line under to an object of simulation setting *******************************************************************/ static void read_xml_operating_clock_override_setting(pugi::xml_node& xml_clock_override_setting, @@ -62,6 +62,40 @@ void read_xml_operating_clock_override_setting(pugi::xml_node& xml_clock_overrid sim_setting.set_clock_frequency(clock_id, get_attribute(xml_clock_override_setting, "frequency", loc_data).as_float(0.)); } +/******************************************************************** + * Parse XML codes of a line under to an object of simulation setting + *******************************************************************/ +static +void read_xml_programming_clock_override_setting(pugi::xml_node& xml_clock_override_setting, + const pugiutil::loc_data& loc_data, + openfpga::SimulationSetting& sim_setting) { + std::string clock_name = get_attribute(xml_clock_override_setting, "name", loc_data).as_string(); + + /* Create a new clock override object in the sim_setting object with the given name */ + SimulationClockId clock_id = sim_setting.create_clock(clock_name); + + /* Report if the clock creation failed, this is due to a conflicts in naming*/ + if (false == sim_setting.valid_clock_id(clock_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_clock_override_setting), + "Fail to create simulation clock '%s', it may share the same name as other simulation clock definition!\n", + clock_name.c_str()); + } + + /* Parse port information */ + openfpga::PortParser clock_port_parser(get_attribute(xml_clock_override_setting, "port", loc_data).as_string()); + sim_setting.set_clock_port(clock_id, clock_port_parser.port()); + + /* Parse frequency information */ + std::string clock_freq_str = get_attribute(xml_clock_override_setting, "frequency", loc_data).as_string(); + if (std::string("auto") != clock_freq_str) { + sim_setting.set_clock_frequency(clock_id, get_attribute(xml_clock_override_setting, "frequency", loc_data).as_float(0.)); + } + + sim_setting.set_clock_is_programming(clock_id, true); + + sim_setting.set_clock_is_shift_register(clock_id, get_attribute(xml_clock_override_setting, "is_shift_register", loc_data).as_bool(false)); +} + /******************************************************************** * Parse XML codes of a to an object of simulation setting *******************************************************************/ @@ -102,6 +136,15 @@ void read_xml_clock_setting(pugi::xml_node& xml_clock_setting, pugi::xml_node xml_programming_clock_setting = get_single_child(xml_clock_setting, "programming", loc_data); sim_setting.set_programming_clock_frequency(get_attribute(xml_programming_clock_setting, "frequency", loc_data).as_float(0.)); + + /* Iterate over multiple operating clock settings and parse one by one */ + for (pugi::xml_node xml_clock : xml_programming_clock_setting.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_clock.name() != std::string("clock")) { + bad_tag(xml_clock, loc_data, xml_programming_clock_setting, {"clock"}); + } + read_xml_programming_clock_override_setting(xml_clock, loc_data, sim_setting); + } } /******************************************************************** diff --git a/libopenfpga/libarchopenfpga/src/simulation_setting.cpp b/libopenfpga/libarchopenfpga/src/simulation_setting.cpp index 88b398441..92296fe8f 100644 --- a/libopenfpga/libarchopenfpga/src/simulation_setting.cpp +++ b/libopenfpga/libarchopenfpga/src/simulation_setting.cpp @@ -16,6 +16,36 @@ SimulationSetting::simulation_clock_range SimulationSetting::clocks() const { return vtr::make_range(clock_ids_.begin(), clock_ids_.end()); } +std::vector SimulationSetting::operating_clocks() const { + std::vector op_clks; + for (const SimulationClockId& clk : clocks()) { + if (!clock_is_programming(clk)) { + op_clks.push_back(clk); + } + } + return op_clks; +} + +std::vector SimulationSetting::programming_clocks() const { + std::vector prog_clks; + for (const SimulationClockId& clk : clocks()) { + if (clock_is_programming(clk)) { + prog_clks.push_back(clk); + } + } + return prog_clks; +} + +std::vector SimulationSetting::programming_shift_register_clocks() const { + std::vector prog_clks; + for (const SimulationClockId& clk : clocks()) { + if (clock_is_programming(clk) && clock_is_shift_register(clk)) { + prog_clks.push_back(clk); + } + } + return prog_clks; +} + /************************************************************************ * Constructors ***********************************************************************/ @@ -53,6 +83,16 @@ float SimulationSetting::clock_frequency(const SimulationClockId& clock_id) cons return clock_frequencies_[clock_id]; } +bool SimulationSetting::clock_is_programming(const SimulationClockId& clock_id) const { + VTR_ASSERT(valid_clock_id(clock_id)); + return clock_is_programming_[clock_id]; +} + +bool SimulationSetting::clock_is_shift_register(const SimulationClockId& clock_id) const { + VTR_ASSERT(valid_clock_id(clock_id)); + return clock_is_shift_register_[clock_id]; +} + bool SimulationSetting::auto_select_num_clock_cycles() const { return 0 == num_clock_cycles_; } @@ -157,6 +197,8 @@ SimulationClockId SimulationSetting::create_clock(const std::string& name) { clock_names_.push_back(name); clock_ports_.emplace_back(); clock_frequencies_.push_back(0.); + clock_is_programming_.push_back(false); + clock_is_shift_register_.push_back(false); /* Register in the name-to-id map */ clock_name2ids_[name] = clock_id; @@ -176,6 +218,18 @@ void SimulationSetting::set_clock_frequency(const SimulationClockId& clock_id, clock_frequencies_[clock_id] = frequency; } +void SimulationSetting::set_clock_is_programming(const SimulationClockId& clock_id, + const float& is_prog) { + VTR_ASSERT(valid_clock_id(clock_id)); + clock_is_programming_[clock_id] = is_prog; +} + +void SimulationSetting::set_clock_is_shift_register(const SimulationClockId& clock_id, + const float& is_sr) { + VTR_ASSERT(valid_clock_id(clock_id)); + clock_is_shift_register_[clock_id] = is_sr; +} + void SimulationSetting::set_num_clock_cycles(const size_t& num_clk_cycles) { num_clock_cycles_ = num_clk_cycles; } diff --git a/libopenfpga/libarchopenfpga/src/simulation_setting.h b/libopenfpga/libarchopenfpga/src/simulation_setting.h index 2447cfd3d..5625acdea 100644 --- a/libopenfpga/libarchopenfpga/src/simulation_setting.h +++ b/libopenfpga/libarchopenfpga/src/simulation_setting.h @@ -62,6 +62,9 @@ class SimulationSetting { SimulationSetting(); public: /* Accessors: aggregates */ simulation_clock_range clocks() const; + std::vector operating_clocks() const; + std::vector programming_clocks() const; + std::vector programming_shift_register_clocks() const; public: /* Public Accessors */ float default_operating_clock_frequency() const; float programming_clock_frequency() const; @@ -69,6 +72,8 @@ class SimulationSetting { std::string clock_name(const SimulationClockId& clock_id) const; BasicPort clock_port(const SimulationClockId& clock_id) const; float clock_frequency(const SimulationClockId& clock_id) const; + bool clock_is_programming(const SimulationClockId& clock_id) const; + bool clock_is_shift_register(const SimulationClockId& clock_id) const; bool auto_select_num_clock_cycles() const; size_t num_clock_cycles() const; float operating_clock_frequency_slack() const; @@ -102,6 +107,10 @@ class SimulationSetting { const BasicPort& port); void set_clock_frequency(const SimulationClockId& clock_id, const float& frequency); + void set_clock_is_programming(const SimulationClockId& clock_id, + const float& is_prog); + void set_clock_is_shift_register(const SimulationClockId& clock_id, + const float& is_sr); void set_num_clock_cycles(const size_t& num_clk_cycles); void set_operating_clock_frequency_slack(const float& op_clk_freq_slack); void set_simulation_temperature(const float& sim_temp); @@ -150,6 +159,8 @@ class SimulationSetting { vtr::vector clock_names_; vtr::vector clock_ports_; vtr::vector clock_frequencies_; + vtr::vector clock_is_programming_; + vtr::vector clock_is_shift_register_; /* Fast name-to-id lookup */ std::map clock_name2ids_; diff --git a/libopenfpga/libarchopenfpga/src/write_xml_circuit_library.cpp b/libopenfpga/libarchopenfpga/src/write_xml_circuit_library.cpp index f96780a92..a9314713d 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_circuit_library.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_circuit_library.cpp @@ -220,6 +220,10 @@ void write_xml_circuit_port(std::fstream& fp, write_xml_attribute(fp, "is_prog", "true"); } + if (true == circuit_lib.port_is_shift_register(port)) { + write_xml_attribute(fp, "is_shift_register", "true"); + } + if (true == circuit_lib.port_is_config_enable(port)) { write_xml_attribute(fp, "is_config_enable", "true"); } diff --git a/libopenfpga/libarchopenfpga/src/write_xml_simulation_setting.cpp b/libopenfpga/libarchopenfpga/src/write_xml_simulation_setting.cpp index dc68f1924..3f8129908 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_simulation_setting.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_simulation_setting.cpp @@ -41,7 +41,7 @@ void write_xml_clock_setting(std::fstream& fp, fp << ">" << "\n"; /* Output clock information one by one */ - for (const SimulationClockId& clock_id : sim_setting.clocks()) { + for (const SimulationClockId& clock_id : sim_setting.operating_clocks()) { fp << "\t\t\t" << "" << "\n"; - fp << "\t\t" << "" << "\n"; + fp << ">" << "\n"; + + /* Output clock information one by one */ + for (const SimulationClockId& clock_id : sim_setting.programming_clocks()) { + fp << "\t\t\t" << "" << "\n"; + } + + fp << "\t\t" << "" << "\n"; fp << "\t" << "" << "\n"; } diff --git a/openfpga/src/fabric/fabric_global_port_info.cpp b/openfpga/src/fabric/fabric_global_port_info.cpp index 08ea8444d..60ef72d94 100644 --- a/openfpga/src/fabric/fabric_global_port_info.cpp +++ b/openfpga/src/fabric/fabric_global_port_info.cpp @@ -50,6 +50,11 @@ bool FabricGlobalPortInfo::global_port_is_prog(const FabricGlobalPortId& global_ return global_port_is_prog_[global_port_id]; } +bool FabricGlobalPortInfo::global_port_is_shift_register(const FabricGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_is_shift_register_[global_port_id]; +} + bool FabricGlobalPortInfo::global_port_is_config_enable(const FabricGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_config_enable_[global_port_id]; @@ -77,6 +82,7 @@ FabricGlobalPortId FabricGlobalPortInfo::create_global_port(const ModulePortId& global_port_is_set_.push_back(false); global_port_is_reset_.push_back(false); global_port_is_prog_.push_back(false); + global_port_is_shift_register_.push_back(false); global_port_is_io_.push_back(false); global_port_is_config_enable_.push_back(false); global_port_default_values_.push_back(0); @@ -108,6 +114,12 @@ void FabricGlobalPortInfo::set_global_port_is_prog(const FabricGlobalPortId& glo global_port_is_prog_[global_port_id] = is_prog; } +void FabricGlobalPortInfo::set_global_port_is_shift_register(const FabricGlobalPortId& global_port_id, + const bool& is_shift_register) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_is_shift_register_[global_port_id] = is_shift_register; +} + void FabricGlobalPortInfo::set_global_port_is_config_enable(const FabricGlobalPortId& global_port_id, const bool& is_config_enable) { VTR_ASSERT(valid_global_port_id(global_port_id)); diff --git a/openfpga/src/fabric/fabric_global_port_info.h b/openfpga/src/fabric/fabric_global_port_info.h index 31c67583e..2521308d1 100644 --- a/openfpga/src/fabric/fabric_global_port_info.h +++ b/openfpga/src/fabric/fabric_global_port_info.h @@ -36,6 +36,7 @@ class FabricGlobalPortInfo { bool global_port_is_set(const FabricGlobalPortId& global_port_id) const; bool global_port_is_reset(const FabricGlobalPortId& global_port_id) const; bool global_port_is_prog(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_shift_register(const FabricGlobalPortId& global_port_id) const; bool global_port_is_config_enable(const FabricGlobalPortId& global_port_id) const; bool global_port_is_io(const FabricGlobalPortId& global_port_id) const; size_t global_port_default_value(const FabricGlobalPortId& global_port_id) const; @@ -52,6 +53,8 @@ class FabricGlobalPortInfo { const bool& is_reset); void set_global_port_is_prog(const FabricGlobalPortId& global_port_id, const bool& is_prog); + void set_global_port_is_shift_register(const FabricGlobalPortId& global_port_id, + const bool& is_shift_register); void set_global_port_is_config_enable(const FabricGlobalPortId& global_port_id, const bool& is_config_enable); void set_global_port_is_io(const FabricGlobalPortId& global_port_id, @@ -68,6 +71,7 @@ class FabricGlobalPortInfo { vtr::vector global_port_is_reset_; vtr::vector global_port_is_set_; vtr::vector global_port_is_prog_; + vtr::vector global_port_is_shift_register_; vtr::vector global_port_is_config_enable_; vtr::vector global_port_is_io_; vtr::vector global_port_default_values_; diff --git a/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp b/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp index 156f78ff1..28f0b9bbd 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp @@ -97,7 +97,7 @@ void print_pnr_sdc_global_clock_ports(std::fstream& fp, /* Should try to find a port defintion from simulation parameters * If found, it means that we need to use special clock name! */ - for (const SimulationClockId& sim_clock : sim_setting.clocks()) { + for (const SimulationClockId& sim_clock : sim_setting.operating_clocks()) { if (port_to_constrain == sim_setting.clock_port(sim_clock)) { clock_period = 1./sim_setting.clock_frequency(sim_clock); } diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp index 3542cdcfc..b47d06d1d 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp @@ -515,7 +515,7 @@ void print_verilog_testbench_clock_stimuli(std::fstream& fp, /* Skip all the unrelated pin constraints */ VTR_ASSERT(clock_port.get_name() == pin_constraints.net(pin_constraint)); /* Try to find which clock source is considered in simulation settings for this pin */ - for (const SimulationClockId& sim_clock_id : simulation_parameters.clocks()) { + for (const SimulationClockId& sim_clock_id : simulation_parameters.operating_clocks()) { if (pin_constraints.pin(pin_constraint) == simulation_parameters.clock_port(sim_clock_id)) { clk_freq_to_use = (0.5 / simulation_parameters.clock_frequency(sim_clock_id)) / VERILOG_SIM_TIMESCALE; } diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 4b0524308..f3c9fcc54 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -290,7 +290,7 @@ void print_verilog_top_testbench_global_clock_ports_stimuli(std::fstream& fp, /* Should try to find a port defintion from simulation parameters * If found, it means that we need to use special clock name! */ - for (const SimulationClockId& sim_clock : simulation_parameters.clocks()) { + for (const SimulationClockId& sim_clock : simulation_parameters.operating_clocks()) { if (global_port_to_connect == simulation_parameters.clock_port(sim_clock)) { stimuli_clock_port.set_name(generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock))); } @@ -640,7 +640,7 @@ void print_verilog_top_testbench_benchmark_clock_ports(std::fstream& fp, /* Skip all the unrelated pin constraints */ VTR_ASSERT(clock_port_name == pin_constraints.net(pin_constraint)); /* Try to find which clock source is considered in simulation settings for this pin */ - for (const SimulationClockId& sim_clock_id : simulation_parameters.clocks()) { + for (const SimulationClockId& sim_clock_id : simulation_parameters.operating_clocks()) { if (pin_constraints.pin(pin_constraint) == simulation_parameters.clock_port(sim_clock_id)) { std::string sim_clock_port_name = generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock_id)); clock_source_to_connect = BasicPort(sim_clock_port_name, 1); @@ -742,7 +742,7 @@ void print_verilog_top_testbench_ports(std::fstream& fp, fp << generate_verilog_port(VERILOG_PORT_REG, prog_clock_register_port) << ";" << std::endl; /* Multiple operating clocks based on the simulation settings */ - for (const SimulationClockId& sim_clock : simulation_parameters.clocks()) { + for (const SimulationClockId& sim_clock : simulation_parameters.operating_clocks()) { std::string sim_clock_port_name = generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock)); BasicPort sim_clock_port(sim_clock_port_name, 1); fp << generate_verilog_port(VERILOG_PORT_WIRE, sim_clock_port) << ";" << std::endl; @@ -1010,7 +1010,7 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp, fp << std::endl; /* Generate stimuli waveform for multiple user-defined operating clock signals */ - for (const SimulationClockId& sim_clock : simulation_parameters.clocks()) { + for (const SimulationClockId& sim_clock : simulation_parameters.operating_clocks()) { print_verilog_comment(fp, "----- Begin raw operating clock signal '" + simulation_parameters.clock_name(sim_clock) + "' generation -----"); std::string sim_clock_port_name = generate_top_testbench_clock_name(std::string(TOP_TB_OP_CLOCK_PORT_PREFIX), simulation_parameters.clock_name(sim_clock)); BasicPort sim_clock_port(sim_clock_port_name, 1); @@ -1935,7 +1935,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, float prog_clock_period = (1./simulation_parameters.programming_clock_frequency()); float default_op_clock_period = (1./simulation_parameters.default_operating_clock_frequency()); float max_op_clock_period = 0.; - for (const SimulationClockId& clock_id : simulation_parameters.clocks()) { + for (const SimulationClockId& clock_id : simulation_parameters.operating_clocks()) { max_op_clock_period = std::max(max_op_clock_period, (float)(1./simulation_parameters.clock_frequency(clock_id))); } diff --git a/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml b/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml new file mode 100644 index 000000000..9b7ffa365 --- /dev/null +++ b/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From dda147e234e45121490ad21de9aa3f61a8d0e891 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 11:04:23 -0700 Subject: [PATCH 125/229] [Flow] Add an example simulation setting file for defining programming shift register clocks --- .../ql_memory_bank_shift_register/config/task.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register/config/task.conf index ba36d7f4c..0e611c666 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register/config/task.conf @@ -18,7 +18,8 @@ fpga_flow=yosys_vpr [OpenFPGA_SHELL] openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml -openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml + openfpga_vpr_device_layout= openfpga_fast_configuration= From cf96d9ff01061bde5721b2623da20d7efe31858e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 11:05:31 -0700 Subject: [PATCH 126/229] [Engine] Add programming shift register clock to internal global port data structure --- openfpga/src/fabric/build_fabric_global_port_info.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga/src/fabric/build_fabric_global_port_info.cpp b/openfpga/src/fabric/build_fabric_global_port_info.cpp index 44a09d199..2c745493a 100644 --- a/openfpga/src/fabric/build_fabric_global_port_info.cpp +++ b/openfpga/src/fabric/build_fabric_global_port_info.cpp @@ -53,6 +53,7 @@ FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_m fabric_global_port_info.set_global_port_is_reset(fabric_port, circuit_lib.port_is_reset(global_port)); fabric_global_port_info.set_global_port_is_set(fabric_port, circuit_lib.port_is_set(global_port)); fabric_global_port_info.set_global_port_is_prog(fabric_port, circuit_lib.port_is_prog(global_port)); + fabric_global_port_info.set_global_port_is_shift_register(fabric_port, circuit_lib.port_is_shift_register(global_port)); fabric_global_port_info.set_global_port_is_config_enable(fabric_port, circuit_lib.port_is_config_enable(global_port)); fabric_global_port_info.set_global_port_default_value(fabric_port, circuit_lib.port_default_value(global_port)); } From 2bd2788e775cd30db3ab27393d8e293c17a00e46 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 11:23:40 -0700 Subject: [PATCH 127/229] [Engine] Upgrading testbench generator to support QuickLogic memory bank with shift registers --- .../verilog_top_testbench_memory_bank.cpp | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index b39f8b1c1..22c135743 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -61,7 +61,18 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, } } else { VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); - /* TODO */ + print_verilog_comment(fp, std::string("---- Bit-Line ports -----")); + for (const ConfigRegionId& region : module_manager.regions(top_module)) { + ModulePortId sr_head_port_id = module_manager.find_module_port(top_module, + generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), region)); + BasicPort sr_head_port = module_manager.module_port(top_module, sr_head_port_id); + fp << generate_verilog_port(VERILOG_PORT_REG, sr_head_port) << ";" << std::endl; + + ModulePortId sr_tail_port_id = module_manager.find_module_port(top_module, + generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME), region)); + BasicPort sr_tail_port = module_manager.module_port(top_module, sr_tail_port_id); + fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_tail_port) << ";" << std::endl; + } } /* Print the address port for the Word-Line decoder here */ @@ -82,7 +93,18 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, } } else { VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()); - /* TODO */ + print_verilog_comment(fp, std::string("---- Word-Line ports -----")); + for (const ConfigRegionId& region : module_manager.regions(top_module)) { + ModulePortId sr_head_port_id = module_manager.find_module_port(top_module, + generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), region)); + BasicPort sr_head_port = module_manager.module_port(top_module, sr_head_port_id); + fp << generate_verilog_port(VERILOG_PORT_REG, sr_head_port) << ";" << std::endl; + + ModulePortId sr_tail_port_id = module_manager.find_module_port(top_module, + generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME), region)); + BasicPort sr_tail_port = module_manager.module_port(top_module, sr_tail_port_id); + fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_tail_port) << ";" << std::endl; + } } /* Print the data-input port: only available when BL has a decoder */ From 4f7ab01bf51ffe6889f86b1e001aa126c1fbd78c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 15:47:13 -0700 Subject: [PATCH 128/229] [FPGA-Bitstream] Reworked the bitstream writer to dump BL/WL words separately --- ...y_bank_shift_register_fabric_bitstream.cpp | 19 ++-- ...ory_bank_shift_register_fabric_bitstream.h | 10 +- .../write_text_fabric_bitstream.cpp | 19 +++- openfpga/src/utils/fabric_bitstream_utils.cpp | 100 ++++++++++++------ 4 files changed, 94 insertions(+), 54 deletions(-) diff --git a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp index 9d5f5fe63..d758a9141 100644 --- a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.cpp @@ -12,13 +12,20 @@ size_t MemoryBankShiftRegisterFabricBitstream::num_words() const { return bitstream_word_ids_.size(); } -size_t MemoryBankShiftRegisterFabricBitstream::word_size() const { +size_t MemoryBankShiftRegisterFabricBitstream::bl_word_size() const { /* For a fast runtime, we just inspect the last element * It is the validator which should ensure all the words have a uniform size */ return bitstream_word_bls_[bitstream_word_ids_.back()].size(); } +size_t MemoryBankShiftRegisterFabricBitstream::wl_word_size() const { + /* For a fast runtime, we just inspect the last element + * It is the validator which should ensure all the words have a uniform size + */ + return bitstream_word_wls_[bitstream_word_ids_.back()].size(); +} + size_t MemoryBankShiftRegisterFabricBitstream::bl_width() const { /* For a fast runtime, we just inspect the last element * It is the validator which should ensure all the words have a uniform size @@ -43,16 +50,6 @@ std::vector MemoryBankShiftRegisterFabricBitstream::wl_vectors(cons return bitstream_word_wls_[word_id]; } -std::vector MemoryBankShiftRegisterFabricBitstream::blwl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const { - VTR_ASSERT(valid_word_id(word_id)); - std::vector blwl_vec = bitstream_word_bls_[word_id]; - VTR_ASSERT(blwl_vec.size() == bitstream_word_wls_[word_id].size()); - for (size_t iwl = 0; iwl < bitstream_word_wls_[word_id].size(); ++iwl) { - blwl_vec[iwl] += bitstream_word_wls_[word_id][iwl]; - } - return blwl_vec; -} - MemoryBankShiftRegisterFabricBitstreamWordId MemoryBankShiftRegisterFabricBitstream::create_word() { /* Create a new id*/ MemoryBankShiftRegisterFabricBitstreamWordId word_id = MemoryBankShiftRegisterFabricBitstreamWordId(bitstream_word_ids_.size()); diff --git a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h index 1355a8274..6016da15e 100644 --- a/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/memory_bank_shift_register_fabric_bitstream.h @@ -28,8 +28,11 @@ class MemoryBankShiftRegisterFabricBitstream { /* @brief Return the length of bitstream */ size_t num_words() const; - /* @brief Return the length of each word. All the word should have a uniform size */ - size_t word_size() const; + /* @brief Return the length of BL part of each word. All the word should have a uniform size */ + size_t bl_word_size() const; + + /* @brief Return the length of WL part of each word. All the word should have a uniform size */ + size_t wl_word_size() const; /* @brief Return the width of each BL word, which is the number of heads through which a BL word can be loaded in parallel */ size_t bl_width() const; @@ -43,9 +46,6 @@ class MemoryBankShiftRegisterFabricBitstream { /* @brief Return the WL vectors in a given word id */ std::vector wl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const; - /* @brief Return the pair of BL and WL vectors in a given word id */ - std::vector blwl_vectors(const MemoryBankShiftRegisterFabricBitstreamWordId& word_id) const; - public: /* Mutators */ /* @brief Create a new word */ MemoryBankShiftRegisterFabricBitstreamWordId create_word(); diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 58e5fd5bb..399abbf28 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -242,7 +242,8 @@ int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream& /* Output information about how to intepret the bitstream */ fp << "// Bitstream word count: " << fabric_bits.num_words() << std::endl; - fp << "// Bitstream word size: " << fabric_bits.word_size() << std::endl; + fp << "// Bitstream bl word size: " << fabric_bits.bl_word_size() << std::endl; + fp << "// Bitstream wl word size: " << fabric_bits.wl_word_size() << std::endl; fp << "// Bitstream width (LSB -> MSB): "; fp << ""; fp << ""; @@ -252,11 +253,21 @@ int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream& for (const auto& word : fabric_bits.words()) { fp << "// Word " << word_cnt << std::endl; - /* Write BL/WL address code */ - for (const auto& blwl_vec : fabric_bits.blwl_vectors(word)) { - fp << blwl_vec; + + /* Write BL address code */ + fp << "// BL part " << std::endl; + for (const auto& bl_vec : fabric_bits.bl_vectors(word)) { + fp << bl_vec; fp << std::endl; } + + /* Write WL address code */ + fp << "// WL part " << std::endl; + for (const auto& wl_vec : fabric_bits.wl_vectors(word)) { + fp << wl_vec; + fp << std::endl; + } + word_cnt++; } diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index d82d09ded..448dc02ba 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -319,6 +319,60 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons return fabric_bits; } +/******************************************************************** + * Reshape a list of vectors by aligning all of them to the last element + * For example: + * - Align vectors to the last element + * + * index ----------------------> + * vector 0: 000000001111101010 + * vector 1: 00000011010101 + * vector 2: 0010101111000110 + * + * - Fill void in each vector with desired bits (Here assume fill 'x' + * index ----------------------> + * vector 0: 000000001111101010 + * vector 1: xxxx00000011010101 + * vector 2: xx0010101111000110 + * + * - Rotate the array by 90 degree + * index -----------------------> + * vector 0: 0xx + * vector 1: 0xx + * ... + * vector N: 010 + * + *******************************************************************/ +static +std::vector reshape_bitstream_vectors_to_last_element(const std::vector& bitstream_vectors, + const char& default_bit_to_fill) { + /* Find the max sizes of BL bits, this determines the size of shift register chain */ + size_t max_vec_size = 0; + for (const auto& vec : bitstream_vectors) { + max_vec_size = std::max(max_vec_size, vec.size()); + } + /* Reshape the BL vectors */ + std::vector reshaped_vectors(bitstream_vectors.size(), std::string()); + size_t col_cnt = 0; + for (const auto& vec : bitstream_vectors) { + reshaped_vectors[col_cnt].resize(max_vec_size - vec.size(), default_bit_to_fill); + reshaped_vectors[col_cnt] += vec; + col_cnt++; + } + + /* Add the BL word to final bitstream */ + std::vector rotated_vectors; + for (size_t irow = 0; irow < max_vec_size; ++irow) { + std::string cur_vec; + for (size_t icol = 0; icol < reshaped_vectors.size(); ++icol) { + cur_vec.push_back(reshaped_vectors[icol][irow]); + } + rotated_vectors.push_back(cur_vec); + } + + return rotated_vectors; +} + MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream, //const std::array& blwl_sr_banks, const bool& bit_value_to_skip) { @@ -328,41 +382,19 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b /* Iterate over each word */ for (const auto& wl_vec : raw_fabric_bits.wl_vectors()) { std::vector bl_vec = raw_fabric_bits.bl_vector(wl_vec); - /* Find the max sizes of BL/WL bits, this determines the size of shift register chain */ - size_t max_blwl_sizes = 0; - for (const auto& bl_bits : bl_vec) { - max_blwl_sizes = std::max(max_blwl_sizes, bl_bits.size()); - } - for (const auto& wl_bits : wl_vec) { - max_blwl_sizes = std::max(max_blwl_sizes, wl_bits.size()); - } - /* Reshape the BL and WL vectors */ - std::vector reshaped_blwls(bl_vec.size() + wl_vec.size(), std::string()); - size_t blwl_col_cnt = 0; - for (const auto& bl_bits : bl_vec) { - reshaped_blwls[blwl_col_cnt].resize(max_blwl_sizes - bl_bits.size(), '0'); - reshaped_blwls[blwl_col_cnt] += bl_bits; - blwl_col_cnt++; - } - for (const auto& wl_bits : wl_vec) { - reshaped_blwls[blwl_col_cnt].resize(max_blwl_sizes - wl_bits.size(), '0'); - reshaped_blwls[blwl_col_cnt] += wl_bits; - blwl_col_cnt++; - } - /* Add the word to final bitstream */ - MemoryBankShiftRegisterFabricBitstreamWordId word_id = fabric_bits.create_word(); - for (size_t irow = 0; irow < max_blwl_sizes; ++irow) { - std::string cur_bl_vec; - for (size_t icol = 0; icol < bl_vec.size(); ++icol) { - cur_bl_vec.push_back(reshaped_blwls[icol][irow]); - } - fabric_bits.add_bl_vectors(word_id, cur_bl_vec); - std::string cur_wl_vec; - for (size_t icol = bl_vec.size(); icol < bl_vec.size() + wl_vec.size(); ++icol) { - cur_wl_vec.push_back(reshaped_blwls[icol][irow]); - } - fabric_bits.add_wl_vectors(word_id, cur_wl_vec); + MemoryBankShiftRegisterFabricBitstreamWordId word_id = fabric_bits.create_word(); + + std::vector reshaped_bl_vectors = reshape_bitstream_vectors_to_last_element(bl_vec, '0'); + /* Add the BL word to final bitstream */ + for (const auto& reshaped_bl_vec : reshaped_bl_vectors) { + fabric_bits.add_bl_vectors(word_id, reshaped_bl_vec); + } + + std::vector reshaped_wl_vectors = reshape_bitstream_vectors_to_last_element(wl_vec, '0'); + /* Add the BL word to final bitstream */ + for (const auto& reshaped_wl_vec : reshaped_wl_vectors) { + fabric_bits.add_wl_vectors(word_id, reshaped_wl_vec); } } From 9e5debabe1782a5c343b131c1b20e33243a4efd5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 16:23:38 -0700 Subject: [PATCH 129/229] [FPGA-Bitstream] Enable fast configuration for QuickLogic memory banks --- .../src/fpga_bitstream/write_text_fabric_bitstream.cpp | 8 ++++++-- openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 2 +- .../fpga_verilog/verilog_top_testbench_memory_bank.cpp | 1 + openfpga/src/utils/fabric_bitstream_utils.cpp | 8 +++++--- openfpga/src/utils/fabric_bitstream_utils.h | 2 ++ 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 399abbf28..257cb0e5b 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -190,11 +190,12 @@ int write_memory_bank_fabric_bitstream_to_text_file(std::fstream& fp, *******************************************************************/ static int write_memory_bank_flatten_fabric_bitstream_to_text_file(std::fstream& fp, + const bool& fast_configuration, const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream) { int status = 0; - MemoryBankFlattenFabricBitstream fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, bit_value_to_skip); + MemoryBankFlattenFabricBitstream fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip); /* The address sizes and data input sizes are the same across any element, * just get it from the 1st element to save runtime @@ -234,11 +235,12 @@ int write_memory_bank_flatten_fabric_bitstream_to_text_file(std::fstream& fp, *******************************************************************/ static int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream& fp, + const bool& fast_configuration, const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream) { int status = 0; - MemoryBankShiftRegisterFabricBitstream fabric_bits = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, bit_value_to_skip); + MemoryBankShiftRegisterFabricBitstream fabric_bits = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip); /* Output information about how to intepret the bitstream */ fp << "// Bitstream word count: " << fabric_bits.num_words() << std::endl; @@ -415,11 +417,13 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage fabric_bitstream); } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { status = write_memory_bank_flatten_fabric_bitstream_to_text_file(fp, + apply_fast_configuration, bit_value_to_skip, fabric_bitstream); } else { VTR_ASSERT(BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()); status = write_memory_bank_shift_register_fabric_bitstream_to_text_file(fp, + apply_fast_configuration, bit_value_to_skip, fabric_bitstream); } diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index f3c9fcc54..0ef3eebcb 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -862,7 +862,7 @@ size_t calculate_num_config_clock_cycles(const ConfigProtocol& config_protocol, 100. * ((float)num_config_clock_cycles / (float)full_num_config_clock_cycles - 1.)); } } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { - num_config_clock_cycles = 1 + build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, bit_value_to_skip).size(); + num_config_clock_cycles = 1 + build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip).size(); } else if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { /* TODO */ } diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 22c135743..7618cd510 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -187,6 +187,7 @@ void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& /* Reorganize the fabric bitstream by the same address across regions */ MemoryBankFlattenFabricBitstream fabric_bits_by_addr = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, + fast_configuration, bit_value_to_skip); /* Feed address and data input pair one by one diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 448dc02ba..e09a99672 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -233,14 +233,15 @@ MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const Fa } MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream, + const bool& fast_configuration, const bool& bit_value_to_skip) { /* Build the bitstream by each region, here we use (WL, BL) pairs when storing bitstreams */ vtr::vector> fabric_bits_per_region; fabric_bits_per_region.resize(fabric_bitstream.num_regions()); for (const FabricBitRegionId& region : fabric_bitstream.regions()) { for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { - /* Skip din because they should be pre-configured through programming reset/set */ - if (fabric_bitstream.bit_din(bit_id) == bit_value_to_skip) { + /* Only when fast configuration is required, skip din because they should be pre-configured through programming reset/set */ + if (fast_configuration && fabric_bitstream.bit_din(bit_id) == bit_value_to_skip) { continue; } /* Create string for BL address */ @@ -374,9 +375,10 @@ std::vector reshape_bitstream_vectors_to_last_element(const std::ve } MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream, + const bool& fast_configuration, //const std::array& blwl_sr_banks, const bool& bit_value_to_skip) { - MemoryBankFlattenFabricBitstream raw_fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, bit_value_to_skip); + MemoryBankFlattenFabricBitstream raw_fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip); MemoryBankShiftRegisterFabricBitstream fabric_bits; /* Iterate over each word */ diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index 9a97a078b..b45db0c0d 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -62,6 +62,7 @@ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBit * @note the std::map may cause large memory footprint for large bitstream databases! *******************************************************************/ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream, + const bool& fast_configuration, const bool& bit_value_to_skip); /******************************************************************** @@ -93,6 +94,7 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons * @note the std::map may cause large memory footprint for large bitstream databases! *******************************************************************/ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream, + const bool& fast_configuration, //const std::array& blwl_sr_banks, const bool& bit_value_to_skip); From ff6f7e80f6c19a0a4d0b9c23252b668019fc6d00 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 16:52:06 -0700 Subject: [PATCH 130/229] [Flow] Modify simulation setting example for QuickLogic memory bank using separated clks for BL and WL shift registers --- .../auto_shift_register_sim_openfpga.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml b/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml index 9b7ffa365..0f5c417ec 100644 --- a/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml +++ b/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml @@ -8,7 +8,8 @@ - + + From 7ba5d27ea7cb260ac383ca57ae72f727d68cbdda Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 17:02:35 -0700 Subject: [PATCH 131/229] [Arch] Reworked example architectures for QuickLogic memory bank using shift registers: Add write-enable signal to WL CCFF model --- openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml | 5 +++-- .../openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml index ce848d2e7..a21c0e522 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml @@ -173,7 +173,7 @@ - + @@ -184,7 +184,8 @@ - + + diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml index 43d716222..da0e46ded 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml @@ -174,7 +174,7 @@ - + @@ -186,7 +186,8 @@ - + + From 0b068201774ccec39ba1608fb1bee3995a2fc23a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 17:06:35 -0700 Subject: [PATCH 132/229] [HDL] Update the WL CCFF HDL modeling by adding Write-Enable signals --- openfpga_flow/openfpga_cell_library/verilog/dff.v | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/openfpga_cell_library/verilog/dff.v b/openfpga_flow/openfpga_cell_library/verilog/dff.v index da641d785..b03b2ba2d 100644 --- a/openfpga_flow/openfpga_cell_library/verilog/dff.v +++ b/openfpga_flow/openfpga_cell_library/verilog/dff.v @@ -475,6 +475,7 @@ module WL_DFFRQ ( input RST, // Reset input input CK, // Clock Input input SIN, // Data Input + input WEN, // Write-enable output SOUT, // Q output output WLW // Drive WL write signals ); @@ -490,7 +491,7 @@ end else begin end assign SOUT = q_reg; -assign WLW = q_reg; +assign WLW = WEN ? q_reg : 1'b0; endmodule //End Of Module @@ -503,6 +504,7 @@ module WLR_DFFRQ ( input RST, // Reset input input CK, // Clock Input input SIN, // Data Input + input WEN, // Write-enable output SOUT, // Q output output WLW, // Drive WL write signals output WLR // Drive WL read signals @@ -519,7 +521,7 @@ end else begin end assign SOUT = q_reg; -assign WLW = q_reg; +assign WLW = WEN ? q_reg : 1'b0; assign WLR = 1'b0; // Use a constant output just for simple testing endmodule //End Of Module From 977d81679dbf11c31639b52fc84b7c027bc88e73 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 17:23:10 -0700 Subject: [PATCH 133/229] [Engine] Upgrade check codes for WL CCFF --- .../src/check_circuit_library.cpp | 4 ++-- openfpga/src/base/openfpga_build_fabric.cpp | 1 + .../fabric/build_fabric_global_port_info.cpp | 10 ++++++++ .../fabric/build_fabric_global_port_info.h | 1 + .../src/fabric/fabric_global_port_info.cpp | 24 +++++++++++++++++++ openfpga/src/fabric/fabric_global_port_info.h | 8 +++++++ 6 files changed, 46 insertions(+), 2 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/check_circuit_library.cpp b/libopenfpga/libarchopenfpga/src/check_circuit_library.cpp index 1a7eb60ed..0964cc10a 100644 --- a/libopenfpga/libarchopenfpga/src/check_circuit_library.cpp +++ b/libopenfpga/libarchopenfpga/src/check_circuit_library.cpp @@ -400,10 +400,10 @@ size_t check_wl_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib, num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_INPUT, num_input_ports, 1, false); - /* Check if we have a clock */ + /* Check if we have two clock: 1 for write-enable, 1 for shift register */ num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model, CIRCUIT_MODEL_PORT_CLOCK, - 1, 1, true); + 2, 1, true); /* Check if we have 1 output*/ diff --git a/openfpga/src/base/openfpga_build_fabric.cpp b/openfpga/src/base/openfpga_build_fabric.cpp index 1caac7342..211048eb3 100644 --- a/openfpga/src/base/openfpga_build_fabric.cpp +++ b/openfpga/src/base/openfpga_build_fabric.cpp @@ -124,6 +124,7 @@ int build_fabric(OpenfpgaContext& openfpga_ctx, /* Build fabric global port information */ openfpga_ctx.mutable_fabric_global_port_info() = build_fabric_global_port_info(openfpga_ctx.module_graph(), + openfpga_ctx.arch().config_protocol, openfpga_ctx.arch().tile_annotations, openfpga_ctx.arch().circuit_lib); diff --git a/openfpga/src/fabric/build_fabric_global_port_info.cpp b/openfpga/src/fabric/build_fabric_global_port_info.cpp index 2c745493a..d439a7fdf 100644 --- a/openfpga/src/fabric/build_fabric_global_port_info.cpp +++ b/openfpga/src/fabric/build_fabric_global_port_info.cpp @@ -24,6 +24,7 @@ namespace openfpga { * and cache their port/pin index in the top-level module *******************************************************************/ FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_manager, + const ConfigProtocol& config_protocol, const TileAnnotation& tile_annotation, const CircuitLibrary& circuit_lib) { vtr::ScopedStartFinishTimer timer("Create global port info for top module"); @@ -56,6 +57,15 @@ FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_m fabric_global_port_info.set_global_port_is_shift_register(fabric_port, circuit_lib.port_is_shift_register(global_port)); fabric_global_port_info.set_global_port_is_config_enable(fabric_port, circuit_lib.port_is_config_enable(global_port)); fabric_global_port_info.set_global_port_default_value(fabric_port, circuit_lib.port_default_value(global_port)); + + /* Special for BL/WL shift register models: we should identify which clock belongs to BL and which clock belongs to WL */ + if (config_protocol.bl_memory_model() == circuit_lib.port_parent_model(global_port)) { + fabric_global_port_info.set_global_port_is_bl(fabric_port, true); + } + + if (config_protocol.wl_memory_model() == circuit_lib.port_parent_model(global_port)) { + fabric_global_port_info.set_global_port_is_wl(fabric_port, true); + } } /* Add the global ports from tile annotation */ diff --git a/openfpga/src/fabric/build_fabric_global_port_info.h b/openfpga/src/fabric/build_fabric_global_port_info.h index 5625d379f..6852a0249 100644 --- a/openfpga/src/fabric/build_fabric_global_port_info.h +++ b/openfpga/src/fabric/build_fabric_global_port_info.h @@ -19,6 +19,7 @@ namespace openfpga { FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_manager, + const ConfigProtocol& config_protocol, const TileAnnotation& tile_annotation, const CircuitLibrary& circuit_lib); diff --git a/openfpga/src/fabric/fabric_global_port_info.cpp b/openfpga/src/fabric/fabric_global_port_info.cpp index 60ef72d94..18108597d 100644 --- a/openfpga/src/fabric/fabric_global_port_info.cpp +++ b/openfpga/src/fabric/fabric_global_port_info.cpp @@ -55,6 +55,16 @@ bool FabricGlobalPortInfo::global_port_is_shift_register(const FabricGlobalPortI return global_port_is_shift_register_[global_port_id]; } +bool FabricGlobalPortInfo::global_port_is_bl(const FabricGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_is_bl_[global_port_id]; +} + +bool FabricGlobalPortInfo::global_port_is_wl(const FabricGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_is_wl_[global_port_id]; +} + bool FabricGlobalPortInfo::global_port_is_config_enable(const FabricGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_config_enable_[global_port_id]; @@ -83,6 +93,8 @@ FabricGlobalPortId FabricGlobalPortInfo::create_global_port(const ModulePortId& global_port_is_reset_.push_back(false); global_port_is_prog_.push_back(false); global_port_is_shift_register_.push_back(false); + global_port_is_bl_.push_back(false); + global_port_is_wl_.push_back(false); global_port_is_io_.push_back(false); global_port_is_config_enable_.push_back(false); global_port_default_values_.push_back(0); @@ -120,6 +132,18 @@ void FabricGlobalPortInfo::set_global_port_is_shift_register(const FabricGlobalP global_port_is_shift_register_[global_port_id] = is_shift_register; } +void FabricGlobalPortInfo::set_global_port_is_bl(const FabricGlobalPortId& global_port_id, + const bool& is_bl) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_is_bl_[global_port_id] = is_bl; +} + +void FabricGlobalPortInfo::set_global_port_is_wl(const FabricGlobalPortId& global_port_id, + const bool& is_wl) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_is_wl_[global_port_id] = is_wl; +} + void FabricGlobalPortInfo::set_global_port_is_config_enable(const FabricGlobalPortId& global_port_id, const bool& is_config_enable) { VTR_ASSERT(valid_global_port_id(global_port_id)); diff --git a/openfpga/src/fabric/fabric_global_port_info.h b/openfpga/src/fabric/fabric_global_port_info.h index 2521308d1..45f8f41cc 100644 --- a/openfpga/src/fabric/fabric_global_port_info.h +++ b/openfpga/src/fabric/fabric_global_port_info.h @@ -36,6 +36,8 @@ class FabricGlobalPortInfo { bool global_port_is_set(const FabricGlobalPortId& global_port_id) const; bool global_port_is_reset(const FabricGlobalPortId& global_port_id) const; bool global_port_is_prog(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_bl(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_wl(const FabricGlobalPortId& global_port_id) const; bool global_port_is_shift_register(const FabricGlobalPortId& global_port_id) const; bool global_port_is_config_enable(const FabricGlobalPortId& global_port_id) const; bool global_port_is_io(const FabricGlobalPortId& global_port_id) const; @@ -55,6 +57,10 @@ class FabricGlobalPortInfo { const bool& is_prog); void set_global_port_is_shift_register(const FabricGlobalPortId& global_port_id, const bool& is_shift_register); + void set_global_port_is_bl(const FabricGlobalPortId& global_port_id, + const bool& is_bl); + void set_global_port_is_wl(const FabricGlobalPortId& global_port_id, + const bool& is_wl); void set_global_port_is_config_enable(const FabricGlobalPortId& global_port_id, const bool& is_config_enable); void set_global_port_is_io(const FabricGlobalPortId& global_port_id, @@ -72,6 +78,8 @@ class FabricGlobalPortInfo { vtr::vector global_port_is_set_; vtr::vector global_port_is_prog_; vtr::vector global_port_is_shift_register_; + vtr::vector global_port_is_bl_; + vtr::vector global_port_is_wl_; vtr::vector global_port_is_config_enable_; vtr::vector global_port_is_io_; vtr::vector global_port_default_values_; From 477c1cd062015244ee7f4b6b02b7c324fc2ca941 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 17:38:26 -0700 Subject: [PATCH 134/229] [Engine] Fixed a critical bug which causes undriven BL/WLs between shift register banks and child modules at the top-level module --- .../fabric/build_top_module_memory_bank.cpp | 11 +++++--- .../memory_bank_shift_register_banks.cpp | 27 ++++++++++++++----- .../fabric/memory_bank_shift_register_banks.h | 18 +++++++++---- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 0c646fa55..031e0a8aa 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -1188,7 +1188,6 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan VTR_ASSERT(sr_module_blwl_port); BasicPort sr_module_blwl_port_info = module_manager.module_port(sr_bank_module, sr_module_blwl_port); - size_t cur_sr_module_blwl_pin_id = 0; for (size_t sink_id = 0; sink_id < sr_banks.shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance).size(); ++sink_id) { size_t child_id = sr_banks.shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; @@ -1199,7 +1198,7 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name); BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port); - cur_sr_module_blwl_pin_id = cur_sr_module_blwl_pin_id % sr_module_blwl_port_info.get_width(); + size_t cur_sr_module_blwl_pin_id = sr_banks.shift_register_bank_source_blwl_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; /* Create net */ ModuleNetId net = create_module_source_pin_net(module_manager, top_module, @@ -1335,7 +1334,9 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index; sr_banks.add_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_bl_pin); - sr_banks.add_shift_register_sink_blwls(config_region, sr_bank_module, cur_inst, bl_pin_id); + sr_banks.add_shift_register_source_blwls(config_region, sr_bank_module, cur_inst, bl_pin_id); + + cur_bl_index++; } } } @@ -1426,7 +1427,9 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module for (const size_t& sink_wl_pin : child_wl_port_info.pins()) { size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + cur_wl_index; sr_banks.add_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_wl_pin); - sr_banks.add_shift_register_sink_blwls(config_region, sr_bank_module, cur_inst, wl_pin_id); + sr_banks.add_shift_register_source_blwls(config_region, sr_bank_module, cur_inst, wl_pin_id); + + cur_wl_index++; } } } diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index aac8989fe..9dcd98cf3 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -61,10 +61,23 @@ std::vector MemoryBankShiftRegisterBanks::shift_register_bank_sink_pin_i return std::vector(); } +std::vector MemoryBankShiftRegisterBanks::shift_register_bank_source_blwl_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const { + VTR_ASSERT(valid_region_id(region)); + + auto result = sr_instance_source_blwl_ids_[region].find(std::make_pair(sr_module, sr_instance)); + /* Return an empty vector if not found */ + if (result != sr_instance_source_blwl_ids_[region].end()) { + return result->second; + } + return std::vector(); +} + void MemoryBankShiftRegisterBanks::resize_regions(const size_t& num_regions) { sr_instance_sink_child_ids_.resize(num_regions); sr_instance_sink_child_pin_ids_.resize(num_regions); - sr_instance_sink_blwl_ids_.resize(num_regions); + sr_instance_source_blwl_ids_.resize(num_regions); } void MemoryBankShiftRegisterBanks::add_shift_register_instance(const ConfigRegionId& region, @@ -73,7 +86,7 @@ void MemoryBankShiftRegisterBanks::add_shift_register_instance(const ConfigRegio VTR_ASSERT(valid_region_id(region)); sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)]; sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)]; - sr_instance_sink_blwl_ids_[region][std::make_pair(sr_module, sr_instance)]; + sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)]; } void MemoryBankShiftRegisterBanks::add_shift_register_sink_nodes(const ConfigRegionId& region, @@ -86,12 +99,12 @@ void MemoryBankShiftRegisterBanks::add_shift_register_sink_nodes(const ConfigReg sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_pin_id); } -void MemoryBankShiftRegisterBanks::add_shift_register_sink_blwls(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_blwl_id) { +void MemoryBankShiftRegisterBanks::add_shift_register_source_blwls(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_blwl_id) { VTR_ASSERT(valid_region_id(region)); - sr_instance_sink_blwl_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_blwl_id); + sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_blwl_id); } bool MemoryBankShiftRegisterBanks::valid_region_id(const ConfigRegionId& region) const { diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h index a145aca5e..6114f93d8 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.h +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -44,6 +44,14 @@ class MemoryBankShiftRegisterBanks { std::vector shift_register_bank_sink_pin_ids(const ConfigRegionId& region, const ModuleId& sr_module, const size_t& sr_instance) const; + + /* @brief Return a list of BL/WL ids of a given instance of shift register bank + * under a specific configuration region of top-level module + */ + std::vector shift_register_bank_source_blwl_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const; + public: /* Mutators */ void resize_regions(const size_t& num_regions); @@ -60,10 +68,10 @@ class MemoryBankShiftRegisterBanks { const size_t& sink_child_pin_id); /* @brief Add the BL/WL id under a specific configuration region of top-level module to which a shift register is connected to */ - void add_shift_register_sink_blwls(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_blwl_id); + void add_shift_register_source_blwls(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_blwl_id); public: /* Validators */ bool valid_region_id(const ConfigRegionId& region) const; @@ -71,7 +79,7 @@ class MemoryBankShiftRegisterBanks { /* [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/ vtr::vector, std::vector>> sr_instance_sink_child_ids_; vtr::vector, std::vector>> sr_instance_sink_child_pin_ids_; - vtr::vector, std::vector>> sr_instance_sink_blwl_ids_; + vtr::vector, std::vector>> sr_instance_source_blwl_ids_; }; } /* end namespace openfpga */ From 2de6be44d6edaff8d5efd020057fc2dc7ad183d8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 18:27:42 -0700 Subject: [PATCH 135/229] [Engine] Fixed a critical bug which causes bitstream wrong for QuickLogic memory bank when fast configuration is enabled --- openfpga/src/utils/fabric_bitstream_utils.cpp | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index e09a99672..8d66f300f 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -235,13 +235,34 @@ MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const Fa MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream, const bool& fast_configuration, const bool& bit_value_to_skip) { + /* If fast configuration is not enabled, we need all the wl address even some of them have all-zero BLs */ + if (!fast_configuration) { + vtr::vector> fabric_bits_per_region; + fabric_bits_per_region.resize(fabric_bitstream.num_regions()); + for (const FabricBitRegionId& region : fabric_bitstream.regions()) { + for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { + /* Create string for BL address */ + std::string bl_addr_str(fabric_bitstream.bit_bl_address(bit_id).size(), bit_value_to_skip); + + /* Create string for WL address */ + std::string wl_addr_str; + for (const char& addr_bit : fabric_bitstream.bit_wl_address(bit_id)) { + wl_addr_str.push_back(addr_bit); + } + + /* Deposit the config bit */ + fabric_bits_per_region[region][wl_addr_str] = bl_addr_str; + } + } + } + /* Build the bitstream by each region, here we use (WL, BL) pairs when storing bitstreams */ vtr::vector> fabric_bits_per_region; fabric_bits_per_region.resize(fabric_bitstream.num_regions()); for (const FabricBitRegionId& region : fabric_bitstream.regions()) { for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { - /* Only when fast configuration is required, skip din because they should be pre-configured through programming reset/set */ - if (fast_configuration && fabric_bitstream.bit_din(bit_id) == bit_value_to_skip) { + /* Skip din because they should be pre-configured through programming reset/set */ + if (fabric_bitstream.bit_din(bit_id) == bit_value_to_skip) { continue; } /* Create string for BL address */ From 198517a898447d8952ec1bed5c4b763d54188431 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 19:59:50 -0700 Subject: [PATCH 136/229] [FPGA-Bitstream] Bug fix on bitstream sequence for QuickLogic memory bank using shift registers --- openfpga/src/utils/fabric_bitstream_utils.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 8d66f300f..d888b378b 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -409,12 +409,16 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b MemoryBankShiftRegisterFabricBitstreamWordId word_id = fabric_bits.create_word(); std::vector reshaped_bl_vectors = reshape_bitstream_vectors_to_last_element(bl_vec, '0'); + /* Reverse the vector due to shift register nature: first-in first-out */ + std::reverse(reshaped_bl_vectors.begin(), reshaped_bl_vectors.end()); /* Add the BL word to final bitstream */ for (const auto& reshaped_bl_vec : reshaped_bl_vectors) { fabric_bits.add_bl_vectors(word_id, reshaped_bl_vec); } std::vector reshaped_wl_vectors = reshape_bitstream_vectors_to_last_element(wl_vec, '0'); + /* Reverse the vector due to shift register nature: first-in first-out */ + std::reverse(reshaped_wl_vectors.begin(), reshaped_wl_vectors.end()); /* Add the BL word to final bitstream */ for (const auto& reshaped_wl_vec : reshaped_wl_vectors) { fabric_bits.add_wl_vectors(word_id, reshaped_wl_vec); From f686dd1f60f50af3c9f0504e2c98b8c8df676d2c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 1 Oct 2021 23:12:38 -0700 Subject: [PATCH 137/229] [FPGA-Bitstream] Do not reverse for now. Previous solution looks correct --- openfpga/src/utils/fabric_bitstream_utils.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index d888b378b..8d66f300f 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -409,16 +409,12 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b MemoryBankShiftRegisterFabricBitstreamWordId word_id = fabric_bits.create_word(); std::vector reshaped_bl_vectors = reshape_bitstream_vectors_to_last_element(bl_vec, '0'); - /* Reverse the vector due to shift register nature: first-in first-out */ - std::reverse(reshaped_bl_vectors.begin(), reshaped_bl_vectors.end()); /* Add the BL word to final bitstream */ for (const auto& reshaped_bl_vec : reshaped_bl_vectors) { fabric_bits.add_bl_vectors(word_id, reshaped_bl_vec); } std::vector reshaped_wl_vectors = reshape_bitstream_vectors_to_last_element(wl_vec, '0'); - /* Reverse the vector due to shift register nature: first-in first-out */ - std::reverse(reshaped_wl_vectors.begin(), reshaped_wl_vectors.end()); /* Add the BL word to final bitstream */ for (const auto& reshaped_wl_vec : reshaped_wl_vectors) { fabric_bits.add_wl_vectors(word_id, reshaped_wl_vec); From 32fc0a1692c89273c7c9907b8b92fbe3951a8612 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 2 Oct 2021 17:25:27 -0700 Subject: [PATCH 138/229] [FPGA-Verilog] Upgrading verilog testbench generator for QuickLogic memory bank using BL/WL shift register --- .../verilog_top_testbench_memory_bank.cpp | 319 +++++++++++++++++- .../verilog_top_testbench_memory_bank.h | 9 + 2 files changed, 323 insertions(+), 5 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 7618cd510..b2fa8277b 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -36,6 +36,17 @@ /* begin namespace openfpga */ namespace openfpga { +constexpr char* TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME = "bl_sr_clock"; +constexpr char* TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME = "wl_sr_clock"; +constexpr char* TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME = "start_bl_sr"; +constexpr char* TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME = "start_wl_sr"; +constexpr char* TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME = "bl_sr_count"; +constexpr char* TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME = "wl_sr_count"; +constexpr char* TOP_TB_BITSTREAM_BL_HEAD_WIDTH_VARIABLE = "BITSTREAM_BL_HEAD_WIDTH"; +constexpr char* TOP_TB_BITSTREAM_WL_HEAD_WIDTH_VARIABLE = "BITSTREAM_WL_HEAD_WIDTH"; +constexpr char* TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE = "BITSTREAM_BL_WORD_SIZE"; +constexpr char* TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE = "BITSTREAM_WL_WORD_SIZE"; + void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, const ModuleManager& module_manager, const ModuleId& top_module, @@ -73,6 +84,12 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, BasicPort sr_tail_port = module_manager.module_port(top_module, sr_tail_port_id); fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_tail_port) << ";" << std::endl; } + + /* BL Shift register clock and registers */ + BasicPort sr_clock_port(std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); + fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_clock_port) << ";" << std::endl; + BasicPort sr_clock_register_port(std::string(std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); + fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_register_port) << ";" << std::endl; } /* Print the address port for the Word-Line decoder here */ @@ -105,6 +122,12 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, BasicPort sr_tail_port = module_manager.module_port(top_module, sr_tail_port_id); fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_tail_port) << ";" << std::endl; } + + /* WL Shift register clock and registers */ + BasicPort sr_clock_port(std::string(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); + fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_clock_port) << ";" << std::endl; + BasicPort sr_clock_register_port(std::string(std::string(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); + fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_register_port) << ";" << std::endl; } /* Print the data-input port: only available when BL has a decoder */ @@ -180,11 +203,6 @@ void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& /* Validate the file stream */ valid_file_stream(fp); - /* No fast configuration available in this configuration protocol. Give a warning */ - if (true == fast_configuration) { - VTR_LOG_WARN("Fast configuration is not available for flatten BL protocol"); - } - /* Reorganize the fabric bitstream by the same address across regions */ MemoryBankFlattenFabricBitstream fabric_bits_by_addr = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, @@ -308,6 +326,290 @@ void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); } +/* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */ +void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(std::fstream& fp, + const BasicPort& prog_clock_port, + const BasicPort& start_sr_port, + const BasicPort& sr_clock_port) { + /* Validate the file stream */ + valid_file_stream(fp); + + fp << "always"; + fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t"; + fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); + fp << ";" << std::endl; + + fp << "\t"; + fp << "while (" << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ") begin"; + fp << std::endl; + + fp << "\t\t"; + fp << "#0.05 "; + print_verilog_register_connection(fp, sr_clock_port, sr_clock_port, true); + fp << ";" << std::endl; + + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "\t"; + fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); + fp << ";" << std::endl; +} + +/* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */ +static +void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::fstream& fp, + const std::string& bitstream_file, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricBitstream& fabric_bitstream) { + /* Validate the file stream */ + valid_file_stream(fp); + + /* Reorganize the fabric bitstream by the same address across regions */ + MemoryBankShiftRegisterFabricBitstream fabric_bits_by_addr = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, + fast_configuration, + bit_value_to_skip); + + /* Feed address and data input pair one by one + * Note: the first cycle is reserved for programming reset + * We should give dummy values + */ + std::vector bl_head_ports; + for (const ConfigRegionId& region : module_manager.regions(top_module)) { + ModulePortId cur_bl_head_port_id = module_manager.find_module_port(top_module, + generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), region)); + bl_head_ports.push_back(module_manager.module_port(top_module, cur_bl_head_port_id)); + } + + std::vector wl_head_ports; + for (const ConfigRegionId& region : module_manager.regions(top_module)) { + ModulePortId cur_wl_head_port_id = module_manager.find_module_port(top_module, + generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), region)); + wl_head_ports.push_back(module_manager.module_port(top_module, cur_wl_head_port_id)); + } + + /* Calculate the total size of BL/WL ports */ + size_t bl_head_port_width = 0; + for (const BasicPort& bl_head_port : bl_head_ports) { + bl_head_port_width += bl_head_port.get_width(); + } + VTR_ASSERT(bl_head_port_width == fabric_bits_by_addr.bl_width()); + + size_t wl_head_port_width = 0; + for (const BasicPort& wl_head_port : wl_head_ports) { + wl_head_port_width += wl_head_port.get_width(); + } + VTR_ASSERT(wl_head_port_width == fabric_bits_by_addr.wl_width()); + + std::vector initial_bl_head_values(bl_head_port_width, 0); + std::vector initial_wl_head_values(wl_head_port_width, 0); + + /* Define a constant for the bitstream length */ + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_LENGTH_VARIABLE), fabric_bits_by_addr.num_words()); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WIDTH_VARIABLE), std::max(bl_head_port_width, wl_head_port_width)); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_BL_HEAD_WIDTH_VARIABLE), bl_head_port_width); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WL_HEAD_WIDTH_VARIABLE), wl_head_port_width); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE), fabric_bits_by_addr.bl_word_size()); + print_verilog_define_flag(fp, std::string(TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE), fabric_bits_by_addr.wl_word_size()); + + /* Declare local variables for bitstream loading in Verilog */ + print_verilog_comment(fp, "----- Virtual memory to store the bitstream from external file -----"); + fp << "reg [0:`" << TOP_TB_BITSTREAM_WIDTH_VARIABLE << " - 1] "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[0:`"; + fp << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "*(`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE; + fp << " + `"<< TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") - 1];"; + fp << std::endl; + + fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; + + /* Register to enable/disable bl/wl shift register clocks */ + BasicPort start_bl_sr_port(TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME, 1); + fp << generate_verilog_port(VERILOG_PORT_REG, start_bl_sr_port) << ";" << std::endl; + BasicPort start_wl_sr_port(TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME, 1); + fp << generate_verilog_port(VERILOG_PORT_REG, start_wl_sr_port) << ";" << std::endl; + + /* Register to count bl/wl shift register clocks */ + fp << "integer " << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" << std::endl; + fp << "integer " << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" << std::endl; + + print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); + fp << "initial begin" << std::endl; + fp << "\t"; + fp << "$readmemb(\"" << bitstream_file << "\", " << TOP_TB_BITSTREAM_MEM_REG_NAME << ");"; + fp << std::endl; + + print_verilog_comment(fp, "----- Bit-Line head port default input -----"); + fp << "\t"; + fp << generate_verilog_ports_constant_values(bl_head_ports, initial_bl_head_values); + fp << ";"; + fp << std::endl; + + print_verilog_comment(fp, "----- Word-Line head port default input -----"); + fp << "\t"; + fp << generate_verilog_ports_constant_values(wl_head_ports, initial_wl_head_values); + fp << ";"; + fp << std::endl; + + fp << "\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " <= 0"; + fp << ";"; + fp << std::endl; + + fp << "\t"; + fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 0), true); + fp << ";"; + fp << std::endl; + + fp << "\t"; + fp << generate_verilog_port_constant_values(start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 0), true); + fp << ";"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); + BasicPort bl_sr_clock_port(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); + BasicPort wl_sr_clock_port(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); + + print_verilog_comment(fp, "----- BL Shift register clock generator -----"); + print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, prog_clock_port, start_bl_sr_port, bl_sr_clock_port); + + print_verilog_comment(fp, "----- WL Shift register clock generator -----"); + print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, prog_clock_port, start_wl_sr_port, wl_sr_clock_port); + + print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); + fp << "always"; + fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " begin"; + fp << std::endl; + + /* Finished all the configuration words, raise the configuration done signal */ + fp << "\t"; + fp << "if ("; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " >= "; + fp << "`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE; + fp << ") begin"; + fp << std::endl; + + BasicPort config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); + fp << "\t\t"; + std::vector config_done_final_values(config_done_port.get_width(), 1); + fp << generate_verilog_port_constant_values(config_done_port, config_done_final_values, true); + fp << ";" << std::endl; + + fp << "\t"; + fp << "end else begin"; + fp << std::endl; + + /* When there are still configuration words to be load, start the BL and WL shift register clock */ + fp << "\t\t"; + fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 0), true); + fp << ";"; + fp << std::endl; + + fp << "\t\t"; + fp << generate_verilog_port_constant_values(start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 0), true); + fp << ";"; + fp << std::endl; + + fp << "\t\t"; + fp << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME << " = 0;"; + fp << std::endl; + + fp << "\t\t"; + fp << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME << " = 0;"; + fp << std::endl; + + fp << "\t\t"; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME; + fp << " <= "; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << " + 1"; + fp << ";" << std::endl; + + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + /* Load data to BL shift register chains */ + fp << "always"; + fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, bl_sr_clock_port) << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t\t"; + fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 0), true); + fp << std::endl; + + fp << "\t\t"; + fp << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME << " = 0;"; + fp << std::endl; + + fp << "\t"; + fp << "end else begin" << std::endl; + + fp << "\t\t"; + fp << generate_verilog_ports(bl_head_ports); + fp << " <= "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "["; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "*(`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << "+ `" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << ") + " << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME; + fp << "];" << std::endl; + + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + /* Load data to WL shift register chains */ + fp << "always"; + fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, wl_sr_clock_port) << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t\t"; + fp << generate_verilog_port_constant_values(start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 0), true); + fp << std::endl; + + fp << "\t\t"; + fp << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME << " = 0;"; + fp << std::endl; + + fp << "\t"; + fp << "end else begin" << std::endl; + + fp << "\t\t"; + fp << generate_verilog_ports(wl_head_ports); + fp << " <= "; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "["; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "*(`" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << "+ `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") + `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << " + " << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME; + fp << "];" << std::endl; + + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "end"; + fp << std::endl; + + print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); +} + + /* Verilog codes to load bitstream from a bit file for memory bank using BL/WL decoders */ static void print_verilog_full_testbench_ql_memory_bank_decoder_bitstream(std::fstream& fp, @@ -468,6 +770,13 @@ void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp, bit_value_to_skip, module_manager, top_module, fabric_bitstream); + } else if ( (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) + && (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()) ) { + print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(fp, bitstream_file, + fast_configuration, + bit_value_to_skip, + module_manager, top_module, + fabric_bitstream); } } diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h index 87ddf3ac5..194f0b86f 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h @@ -34,6 +34,15 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, const ModuleId& top_module, const ConfigProtocol& config_protocol); +/** + * @brief Generate the Verilog codes for a shift register clocks that controls BL/WL protocols + */ +void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(std::fstream& fp, + const BasicPort& prog_clock_port, + const BasicPort& start_sr_port, + const BasicPort& sr_clock_port); + + /** * @brief Print stimulus for a FPGA fabric with a memory bank configuration protocol * where configuration bits are programming in serial (one by one) From 54ec74d8d29f285f10f7c54e35914dcec46d9d40 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 2 Oct 2021 17:31:37 -0700 Subject: [PATCH 139/229] [FPGA-Verilog] Bug fix in code generator --- .../src/fpga_verilog/verilog_top_testbench_memory_bank.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index b2fa8277b..346f3b34b 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -350,7 +350,6 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator( fp << "\t\t"; fp << "#0.05 "; print_verilog_register_connection(fp, sr_clock_port, sr_clock_port, true); - fp << ";" << std::endl; fp << "\t"; fp << "end"; @@ -552,7 +551,7 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "\t\t"; fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 0), true); - fp << std::endl; + fp << ";" << std::endl; fp << "\t\t"; fp << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME << " = 0;"; @@ -583,7 +582,7 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "\t\t"; fp << generate_verilog_port_constant_values(start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 0), true); - fp << std::endl; + fp << ";" << std::endl; fp << "\t\t"; fp << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME << " = 0;"; From 76d58ebaa0177169006f55d96897363e2bf80f34 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 2 Oct 2021 21:48:10 -0700 Subject: [PATCH 140/229] [FPGA-Verilog] Move clock generator to generic stimuli and shift register clock period is auto tuned by programming clock period --- .../fpga_verilog/verilog_top_testbench.cpp | 16 +- .../verilog_top_testbench_memory_bank.cpp | 161 ++++++++++++------ .../verilog_top_testbench_memory_bank.h | 16 +- 3 files changed, 128 insertions(+), 65 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 0ef3eebcb..3a09db525 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -1112,21 +1112,30 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp, *******************************************************************/ static void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& fp, - const e_config_protocol_type& config_protocol_type, + const ConfigProtocol& config_protocol, const ModuleManager& module_manager, const ModuleId& top_module, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const FabricBitstream& fabric_bitstream, const float& prog_clock_period, const float& timescale) { /* Validate the file stream */ valid_file_stream(fp); /* Branch on the type of configuration protocol */ - switch (config_protocol_type) { + switch (config_protocol.type()) { case CONFIG_MEM_STANDALONE: break; case CONFIG_MEM_SCAN_CHAIN: break; case CONFIG_MEM_QL_MEMORY_BANK: + print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(fp, + config_protocol, + module_manager,top_module, + fast_configuration, bit_value_to_skip, fabric_bitstream, + prog_clock_period, timescale); + break; case CONFIG_MEM_MEMORY_BANK: case CONFIG_MEM_FRAME_BASED: { ModulePortId en_port_id = module_manager.find_module_port(top_module, @@ -1956,8 +1965,9 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, /* Generate stimuli for programming interface */ print_verilog_top_testbench_configuration_protocol_stimulus(fp, - config_protocol.type(), + config_protocol, module_manager, top_module, + fast_configuration, bit_value_to_skip, fabric_bitstream, prog_clock_period, VERILOG_SIM_TIMESCALE); diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 346f3b34b..607ad9d0e 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -87,9 +87,13 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, /* BL Shift register clock and registers */ BasicPort sr_clock_port(std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); - fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_clock_port) << ";" << std::endl; - BasicPort sr_clock_register_port(std::string(std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); - fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_register_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_port) << ";" << std::endl; + + /* Register to enable/disable bl/wl shift register clocks */ + BasicPort start_bl_sr_port(TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME, 1); + fp << generate_verilog_port(VERILOG_PORT_REG, start_bl_sr_port) << ";" << std::endl; + /* Register to count bl/wl shift register clocks */ + fp << "integer " << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" << std::endl; } /* Print the address port for the Word-Line decoder here */ @@ -125,9 +129,13 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, /* WL Shift register clock and registers */ BasicPort sr_clock_port(std::string(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); - fp << generate_verilog_port(VERILOG_PORT_WIRE, sr_clock_port) << ";" << std::endl; - BasicPort sr_clock_register_port(std::string(std::string(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); - fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_register_port) << ";" << std::endl; + fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_port) << ";" << std::endl; + + /* Register to enable/disable bl/wl shift register clocks */ + BasicPort start_wl_sr_port(TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME, 1); + fp << generate_verilog_port(VERILOG_PORT_REG, start_wl_sr_port) << ";" << std::endl; + /* Register to count bl/wl shift register clocks */ + fp << "integer " << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" << std::endl; } /* Print the data-input port: only available when BL has a decoder */ @@ -191,6 +199,94 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, fp << ";" << std::endl; } +/** + * @brief Generate the Verilog codes for a shift register clocks that controls BL/WL protocols + */ +static +void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(std::fstream& fp, + const BasicPort& prog_clock_port, + const BasicPort& start_sr_port, + const BasicPort& sr_clock_port, + const float& sr_clock_period) { + /* Validate the file stream */ + valid_file_stream(fp); + + fp << "always"; + fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t"; + fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); + fp << ";" << std::endl; + + fp << "\t"; + fp << "while (" << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ") begin"; + fp << std::endl; + + fp << "\t\t"; + fp << "#" << sr_clock_period << " "; + print_verilog_register_connection(fp, sr_clock_port, sr_clock_port, true); + + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "\t"; + fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); + fp << ";" << std::endl; +} + +void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp, + const ConfigProtocol& config_protocol, + const ModuleManager& module_manager, + const ModuleId& top_module, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const FabricBitstream& fabric_bitstream, + const float& prog_clock_period, + const float& timescale) { + ModulePortId en_port_id = module_manager.find_module_port(top_module, + std::string(DECODER_ENABLE_PORT_NAME)); + BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); + if (en_port_id) { + en_port = module_manager.module_port(top_module, en_port_id); + } + BasicPort en_register_port(std::string(en_port.get_name() + std::string(TOP_TB_CLOCK_REG_POSTFIX)), 1); + print_verilog_comment(fp, std::string("---- Generate enable signal waveform -----")); + print_verilog_shifted_clock_stimuli(fp, en_register_port, + 0.25 * prog_clock_period / timescale, + 0.5 * prog_clock_period / timescale, 0); + + /* Stimulus only for shift-register-based BL/WL protocols */ + BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); + BasicPort bl_sr_clock_port(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); + BasicPort wl_sr_clock_port(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); + BasicPort start_bl_sr_port(TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME, 1); + BasicPort start_wl_sr_port(TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME, 1); + + /* Reorganize the fabric bitstream by the same address across regions */ + if (CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) { + MemoryBankShiftRegisterFabricBitstream fabric_bits_by_addr = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, + fast_configuration, + bit_value_to_skip); + + /* TODO: Consider auto-tuned clock period for now */ + float bl_sr_clock_period = prog_clock_period / fabric_bits_by_addr.bl_width() / timescale; + float wl_sr_clock_period = prog_clock_period / fabric_bits_by_addr.wl_width() / timescale; + + if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { + print_verilog_comment(fp, "----- BL Shift register clock generator -----"); + print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, prog_clock_port, start_bl_sr_port, bl_sr_clock_port, 0.5 * bl_sr_clock_period); + } + + if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()) { + print_verilog_comment(fp, "----- WL Shift register clock generator -----"); + print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, prog_clock_port, start_wl_sr_port, wl_sr_clock_port, 0.5 * wl_sr_clock_period); + } + } +} + /* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */ static void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& fp, @@ -326,40 +422,6 @@ void print_verilog_full_testbench_ql_memory_bank_flatten_bitstream(std::fstream& print_verilog_comment(fp, "----- End bitstream loading during configuration phase -----"); } -/* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */ -void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(std::fstream& fp, - const BasicPort& prog_clock_port, - const BasicPort& start_sr_port, - const BasicPort& sr_clock_port) { - /* Validate the file stream */ - valid_file_stream(fp); - - fp << "always"; - fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; - fp << " begin"; - fp << std::endl; - - fp << "\t"; - fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); - fp << ";" << std::endl; - - fp << "\t"; - fp << "while (" << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ") begin"; - fp << std::endl; - - fp << "\t\t"; - fp << "#0.05 "; - print_verilog_register_connection(fp, sr_clock_port, sr_clock_port, true); - - fp << "\t"; - fp << "end"; - fp << std::endl; - - fp << "\t"; - fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); - fp << ";" << std::endl; -} - /* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */ static void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::fstream& fp, @@ -429,16 +491,6 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "reg [$clog2(`" << TOP_TB_BITSTREAM_LENGTH_VARIABLE << "):0] " << TOP_TB_BITSTREAM_INDEX_REG_NAME << ";" << std::endl; - /* Register to enable/disable bl/wl shift register clocks */ - BasicPort start_bl_sr_port(TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME, 1); - fp << generate_verilog_port(VERILOG_PORT_REG, start_bl_sr_port) << ";" << std::endl; - BasicPort start_wl_sr_port(TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME, 1); - fp << generate_verilog_port(VERILOG_PORT_REG, start_wl_sr_port) << ";" << std::endl; - - /* Register to count bl/wl shift register clocks */ - fp << "integer " << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" << std::endl; - fp << "integer " << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME << ";" << std::endl; - print_verilog_comment(fp, "----- Preload bitstream file to a virtual memory -----"); fp << "initial begin" << std::endl; fp << "\t"; @@ -462,6 +514,9 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << ";"; fp << std::endl; + BasicPort start_bl_sr_port(TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME, 1); + BasicPort start_wl_sr_port(TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME, 1); + fp << "\t"; fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 0), true); fp << ";"; @@ -480,12 +535,6 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f BasicPort bl_sr_clock_port(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); BasicPort wl_sr_clock_port(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); - print_verilog_comment(fp, "----- BL Shift register clock generator -----"); - print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, prog_clock_port, start_bl_sr_port, bl_sr_clock_port); - - print_verilog_comment(fp, "----- WL Shift register clock generator -----"); - print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, prog_clock_port, start_wl_sr_port, wl_sr_clock_port); - print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); fp << "always"; fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h index 194f0b86f..78e364a4c 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h @@ -35,13 +35,17 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, const ConfigProtocol& config_protocol); /** - * @brief Generate the Verilog codes for a shift register clocks that controls BL/WL protocols + * @brief Generate the Verilog codes that generate stimuli waveforms for BL/WL protocols */ -void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(std::fstream& fp, - const BasicPort& prog_clock_port, - const BasicPort& start_sr_port, - const BasicPort& sr_clock_port); - +void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp, + const ConfigProtocol& config_protocol, + const ModuleManager& module_manager, + const ModuleId& top_module, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const FabricBitstream& fabric_bitstream, + const float& prog_clock_period, + const float& timescale); /** * @brief Print stimulus for a FPGA fabric with a memory bank configuration protocol From fa7e1681371779551034c3f8cafe9a2d1aa424bf Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 2 Oct 2021 22:08:14 -0700 Subject: [PATCH 141/229] [FPGA-Verilog] Now testbench generator connects global shift register clocks to FPGA ports --- .../fpga_verilog/verilog_top_testbench.cpp | 10 +++++ .../verilog_top_testbench_memory_bank.cpp | 40 +++++++++++++++++++ .../verilog_top_testbench_memory_bank.h | 8 ++++ 3 files changed, 58 insertions(+) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 3a09db525..f3832fdc3 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -271,6 +271,11 @@ void print_verilog_top_testbench_global_clock_ports_stimuli(std::fstream& fp, /* Find the module port */ ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port); VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port)); + + /* Skip shift register clocks, they are handled in another way */ + if (true == fabric_global_port_info.global_port_is_shift_register(fabric_global_port)) { + continue; + } BasicPort stimuli_clock_port; if (true == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { @@ -563,6 +568,11 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, fabric_global_port_info, simulation_parameters); + print_verilog_top_testbench_global_shift_register_clock_ports_stimuli(fp, + module_manager, + top_module, + fabric_global_port_info); + print_verilog_top_testbench_global_config_done_ports_stimuli(fp, module_manager, top_module, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 607ad9d0e..816b7aebb 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -199,6 +199,46 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, fp << ";" << std::endl; } + +void print_verilog_top_testbench_global_shift_register_clock_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info) { + /* Validate the file stream */ + valid_file_stream(fp); + + /* Connect global clock ports to shift-register programming clock signal */ + for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { + /* Only care shift register clocks */ + if (false == fabric_global_port_info.global_port_is_clock(fabric_global_port) + || false == fabric_global_port_info.global_port_is_shift_register(fabric_global_port) + || false == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { + continue; + } + /* Find the module port */ + ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port); + VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port)); + + BasicPort stimuli_clock_port; + + if (true == fabric_global_port_info.global_port_is_bl(fabric_global_port)) { + stimuli_clock_port.set_name(std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME)); + stimuli_clock_port.set_width(1); + } else { + VTR_ASSERT(true == fabric_global_port_info.global_port_is_wl(fabric_global_port)); + stimuli_clock_port.set_name(std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME)); + stimuli_clock_port.set_width(1); + } + + for (const size_t& pin : module_manager.module_port(top_module, module_global_port).pins()) { + BasicPort global_port_to_connect(module_manager.module_port(top_module, module_global_port).get_name(), pin, pin); + print_verilog_wire_connection(fp, global_port_to_connect, + stimuli_clock_port, + 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); + } + } +} + /** * @brief Generate the Verilog codes for a shift register clocks that controls BL/WL protocols */ diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h index 78e364a4c..d4ebf3264 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h @@ -34,6 +34,14 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, const ModuleId& top_module, const ConfigProtocol& config_protocol); +/** + * @brief Generate the Verilog codes that connect shift register clock stimuli to FPGA ports + */ +void print_verilog_top_testbench_global_shift_register_clock_ports_stimuli(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info); + /** * @brief Generate the Verilog codes that generate stimuli waveforms for BL/WL protocols */ From 02af633acdc9158e7a24f1da486a831aa88250b7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 2 Oct 2021 22:14:15 -0700 Subject: [PATCH 142/229] [FPGA-Verilog] Fixed several bugs in testbench generator which caused iVerilog errors --- .../verilog_top_testbench_memory_bank.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 816b7aebb..1b00795cb 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -275,6 +275,9 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator( fp << "\t"; fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); fp << ";" << std::endl; + + fp << "end"; + fp << std::endl; } void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp, @@ -638,6 +641,14 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << " begin"; fp << std::endl; + fp << "\t"; + fp << "if ("; + fp << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME; + fp << " >= "; + fp << "`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE; + fp << ") begin"; + fp << std::endl; + fp << "\t\t"; fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 0), true); fp << ";" << std::endl; @@ -669,6 +680,14 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << " begin"; fp << std::endl; + fp << "\t"; + fp << "if ("; + fp << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME; + fp << " >= "; + fp << "`" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE; + fp << ") begin"; + fp << std::endl; + fp << "\t\t"; fp << generate_verilog_port_constant_values(start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 0), true); fp << ";" << std::endl; From 86e7c963f889e7f269feade7e5f955d034f6771a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 2 Oct 2021 22:19:20 -0700 Subject: [PATCH 143/229] [Arch] Bug fix for wrong XML syntax in QuickLogic memory bank example architecture files --- openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml index a21c0e522..803512e5d 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml @@ -173,7 +173,7 @@ - + @@ -185,7 +185,7 @@ - + From d453e6477dafc3befc9fc1216e5ba3a7d76c63ee Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 2 Oct 2021 22:32:57 -0700 Subject: [PATCH 144/229] [FPGA-Verilog] Bug fix --- .../verilog_top_testbench_memory_bank.cpp | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 1b00795cb..76151a8b2 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -315,8 +315,8 @@ void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus( bit_value_to_skip); /* TODO: Consider auto-tuned clock period for now */ - float bl_sr_clock_period = prog_clock_period / fabric_bits_by_addr.bl_width() / timescale; - float wl_sr_clock_period = prog_clock_period / fabric_bits_by_addr.wl_width() / timescale; + float bl_sr_clock_period = prog_clock_period / fabric_bits_by_addr.bl_word_size() / timescale; + float wl_sr_clock_period = prog_clock_period / fabric_bits_by_addr.wl_word_size() / timescale; if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { print_verilog_comment(fp, "----- BL Shift register clock generator -----"); @@ -605,12 +605,12 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f /* When there are still configuration words to be load, start the BL and WL shift register clock */ fp << "\t\t"; - fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 1), true); fp << ";"; fp << std::endl; fp << "\t\t"; - fp << generate_verilog_port_constant_values(start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 0), true); + fp << generate_verilog_port_constant_values(start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 1), true); fp << ";"; fp << std::endl; @@ -664,9 +664,14 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << generate_verilog_ports(bl_head_ports); fp << " <= "; fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "["; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "*(`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << "+ `" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << ") + " << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "*(`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " + `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") + " << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME; fp << "];" << std::endl; + fp << "\t\t"; + fp << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME << " = "; + fp << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME << " + 1;"; + fp << std::endl; + fp << "\t"; fp << "end"; fp << std::endl; @@ -703,9 +708,14 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << generate_verilog_ports(wl_head_ports); fp << " <= "; fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "["; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "*(`" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << "+ `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") + `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << " + " << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "*(`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " + `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") + `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << " + " << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME; fp << "];" << std::endl; + fp << "\t\t"; + fp << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME << " = "; + fp << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME << " + 1;"; + fp << std::endl; + fp << "\t"; fp << "end"; fp << std::endl; From 3eb601531a4f4712f9a7ce2955600b58e9ca9cca Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 2 Oct 2021 23:39:53 -0700 Subject: [PATCH 145/229] [FPGA-Verilog] Many bug fixes --- .../verilog_top_testbench_memory_bank.cpp | 26 ++++++++++--------- openfpga/src/utils/fabric_bitstream_utils.cpp | 14 ++++++---- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 76151a8b2..a750ff68b 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -226,7 +226,7 @@ void print_verilog_top_testbench_global_shift_register_clock_ports_stimuli(std:: stimuli_clock_port.set_width(1); } else { VTR_ASSERT(true == fabric_global_port_info.global_port_is_wl(fabric_global_port)); - stimuli_clock_port.set_name(std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME)); + stimuli_clock_port.set_name(std::string(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME)); stimuli_clock_port.set_width(1); } @@ -244,7 +244,6 @@ void print_verilog_top_testbench_global_shift_register_clock_ports_stimuli(std:: */ static void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(std::fstream& fp, - const BasicPort& prog_clock_port, const BasicPort& start_sr_port, const BasicPort& sr_clock_port, const float& sr_clock_period) { @@ -252,7 +251,7 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator( valid_file_stream(fp); fp << "always"; - fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, prog_clock_port) << ")"; + fp << " @(posedge " << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ")"; fp << " begin"; fp << std::endl; @@ -314,18 +313,21 @@ void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus( fast_configuration, bit_value_to_skip); - /* TODO: Consider auto-tuned clock period for now */ - float bl_sr_clock_period = prog_clock_period / fabric_bits_by_addr.bl_word_size() / timescale; - float wl_sr_clock_period = prog_clock_period / fabric_bits_by_addr.wl_word_size() / timescale; + /* TODO: Consider auto-tuned clock period for now: + * - the BL/WL shift register clock only works in the second half of the programming clock period + * - add 2 idle clocks to avoid racing between programming clock and shift register clocks at edge + */ + float bl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.bl_word_size() + 2) / timescale; + float wl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.wl_word_size() + 2) / timescale; if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { print_verilog_comment(fp, "----- BL Shift register clock generator -----"); - print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, prog_clock_port, start_bl_sr_port, bl_sr_clock_port, 0.5 * bl_sr_clock_period); + print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, start_bl_sr_port, bl_sr_clock_port, bl_sr_clock_period); } if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()) { print_verilog_comment(fp, "----- WL Shift register clock generator -----"); - print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, prog_clock_port, start_wl_sr_port, wl_sr_clock_port, 0.5 * wl_sr_clock_period); + print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, start_wl_sr_port, wl_sr_clock_port, wl_sr_clock_period); } } } @@ -663,8 +665,8 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "\t\t"; fp << generate_verilog_ports(bl_head_ports); fp << " <= "; - fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "["; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "*(`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " + `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") + " << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[("; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "-1)*(`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " + `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") + " << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME; fp << "];" << std::endl; fp << "\t\t"; @@ -707,8 +709,8 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "\t\t"; fp << generate_verilog_ports(wl_head_ports); fp << " <= "; - fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "["; - fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "*(`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " + `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") + `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << " + " << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME; + fp << TOP_TB_BITSTREAM_MEM_REG_NAME << "[("; + fp << TOP_TB_BITSTREAM_INDEX_REG_NAME << "-1)*(`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " + `" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << ") + `" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " + " << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME; fp << "];" << std::endl; fp << "\t\t"; diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 8d66f300f..31163efcc 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -366,8 +366,8 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons * *******************************************************************/ static -std::vector reshape_bitstream_vectors_to_last_element(const std::vector& bitstream_vectors, - const char& default_bit_to_fill) { +std::vector reshape_bitstream_vectors_to_first_element(const std::vector& bitstream_vectors, + const char& default_bit_to_fill) { /* Find the max sizes of BL bits, this determines the size of shift register chain */ size_t max_vec_size = 0; for (const auto& vec : bitstream_vectors) { @@ -377,8 +377,8 @@ std::vector reshape_bitstream_vectors_to_last_element(const std::ve std::vector reshaped_vectors(bitstream_vectors.size(), std::string()); size_t col_cnt = 0; for (const auto& vec : bitstream_vectors) { - reshaped_vectors[col_cnt].resize(max_vec_size - vec.size(), default_bit_to_fill); reshaped_vectors[col_cnt] += vec; + reshaped_vectors[col_cnt] += std::string(max_vec_size - vec.size(), default_bit_to_fill); col_cnt++; } @@ -408,13 +408,17 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b MemoryBankShiftRegisterFabricBitstreamWordId word_id = fabric_bits.create_word(); - std::vector reshaped_bl_vectors = reshape_bitstream_vectors_to_last_element(bl_vec, '0'); + std::vector reshaped_bl_vectors = reshape_bitstream_vectors_to_first_element(bl_vec, '0'); + /* Reverse the vectors due to the shift register chain nature: first-in first-out */ + //std::reverse(reshaped_bl_vectors.begin(), reshaped_bl_vectors.end()); /* Add the BL word to final bitstream */ for (const auto& reshaped_bl_vec : reshaped_bl_vectors) { fabric_bits.add_bl_vectors(word_id, reshaped_bl_vec); } - std::vector reshaped_wl_vectors = reshape_bitstream_vectors_to_last_element(wl_vec, '0'); + std::vector reshaped_wl_vectors = reshape_bitstream_vectors_to_first_element(wl_vec, '0'); + /* Reverse the vectors due to the shift register chain nature: first-in first-out */ + //std::reverse(reshaped_wl_vectors.begin(), reshaped_wl_vectors.end()); /* Add the BL word to final bitstream */ for (const auto& reshaped_wl_vec : reshaped_wl_vectors) { fabric_bits.add_wl_vectors(word_id, reshaped_wl_vec); From 756b4c7dc8b574416b884c18fd0bb53f887b3a5c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 3 Oct 2021 12:11:20 -0700 Subject: [PATCH 146/229] [FPGA-Verilog] Bug fix in estimating the simulation period for QuickLogic memory bank using BL/WL shift registers --- openfpga/src/fpga_verilog/verilog_top_testbench.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index f3832fdc3..f8477df5f 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -874,7 +874,7 @@ size_t calculate_num_config_clock_cycles(const ConfigProtocol& config_protocol, } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type()) { num_config_clock_cycles = 1 + build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip).size(); } else if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { - /* TODO */ + num_config_clock_cycles = 1 + build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip).size(); } break; } From 28904ff526e2b73fae3d74fa3b745fd97831d451 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 3 Oct 2021 12:31:58 -0700 Subject: [PATCH 147/229] [Engine] Bug fix on wrong port type for shift register chains --- openfpga/src/fabric/build_top_module_memory_bank.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 031e0a8aa..dd3dceafb 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -1588,7 +1588,7 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, BasicPort blsr_head_port(generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), num_heads); module_manager.add_port(module_id, blsr_head_port, ModuleManager::MODULE_INPUT_PORT); BasicPort blsr_tail_port(generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), num_heads); - module_manager.add_port(module_id, blsr_tail_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, blsr_tail_port, ModuleManager::MODULE_OUTPUT_PORT); } break; } @@ -1637,7 +1637,7 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, BasicPort wlsr_head_port(generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), num_heads); module_manager.add_port(module_id, wlsr_head_port, ModuleManager::MODULE_INPUT_PORT); BasicPort wlsr_tail_port(generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), num_heads); - module_manager.add_port(module_id, wlsr_tail_port, ModuleManager::MODULE_INPUT_PORT); + module_manager.add_port(module_id, wlsr_tail_port, ModuleManager::MODULE_OUTPUT_PORT); } break; } From 2badcb58f2d9090331b8d19d1abfa3f093cbcca7 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 3 Oct 2021 16:04:47 -0700 Subject: [PATCH 148/229] [FPGA-Verilog] Fixed a critical bug in verilog testbench generator for QL memory bank using BL/WL register which causes misalignment in shift register loading --- .../src/fpga_verilog/verilog_top_testbench_memory_bank.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index a750ff68b..5482b0454 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -647,7 +647,7 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "if ("; fp << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME; fp << " >= "; - fp << "`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE; + fp << "`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " - 1"; fp << ") begin"; fp << std::endl; @@ -691,7 +691,7 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "if ("; fp << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME; fp << " >= "; - fp << "`" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE; + fp << "`" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << " - 1"; fp << ") begin"; fp << std::endl; From 06b018cfe7f15b3200ece0d653abf5c2c4f22f89 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 3 Oct 2021 16:05:33 -0700 Subject: [PATCH 149/229] [FPGA-Bitstream] Reverse bitstream for shift register due to its FIFO nature --- openfpga/src/utils/fabric_bitstream_utils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 31163efcc..cc14dfe84 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -410,7 +410,7 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b std::vector reshaped_bl_vectors = reshape_bitstream_vectors_to_first_element(bl_vec, '0'); /* Reverse the vectors due to the shift register chain nature: first-in first-out */ - //std::reverse(reshaped_bl_vectors.begin(), reshaped_bl_vectors.end()); + std::reverse(reshaped_bl_vectors.begin(), reshaped_bl_vectors.end()); /* Add the BL word to final bitstream */ for (const auto& reshaped_bl_vec : reshaped_bl_vectors) { fabric_bits.add_bl_vectors(word_id, reshaped_bl_vec); @@ -418,7 +418,7 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b std::vector reshaped_wl_vectors = reshape_bitstream_vectors_to_first_element(wl_vec, '0'); /* Reverse the vectors due to the shift register chain nature: first-in first-out */ - //std::reverse(reshaped_wl_vectors.begin(), reshaped_wl_vectors.end()); + std::reverse(reshaped_wl_vectors.begin(), reshaped_wl_vectors.end()); /* Add the BL word to final bitstream */ for (const auto& reshaped_wl_vec : reshaped_wl_vectors) { fabric_bits.add_wl_vectors(word_id, reshaped_wl_vec); From 7f75c2b619e80a2328d6c1a856a1174c29033209 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 3 Oct 2021 16:06:44 -0700 Subject: [PATCH 150/229] [Test] Deploy shift register -based QL memory bank test case to basic regression test --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index b9067ce78..09c4d7f10 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -59,6 +59,7 @@ run-task basic_tests/full_testbench/ql_memory_bank_use_wlr --debug --show_thread run-task basic_tests/full_testbench/multi_region_ql_memory_bank --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_flatten --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr --debug --show_thread_logs +run-task basic_tests/full_testbench/ql_memory_bank_shift_register --debug --show_thread_logs echo -e "Testing testbenches without self checking features"; run-task basic_tests/full_testbench/full_testbench_without_self_checking --debug --show_thread_logs From a01fa7c28297076a1d8da4aa5cd591444dd27f41 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 4 Oct 2021 12:09:42 -0700 Subject: [PATCH 151/229] [Doc] Add figures and text to explain the difference between the XML syntax for QuickLogic memory bank --- .../manual/arch_lang/config_protocol.rst | 35 +- .../arch_lang/figures/memory_bank_decoder.svg | 2449 +++++++++++++++ .../arch_lang/figures/memory_bank_flatten.svg | 2440 +++++++++++++++ .../figures/memory_bank_shift_register.svg | 2770 +++++++++++++++++ 4 files changed, 7691 insertions(+), 3 deletions(-) create mode 100644 docs/source/manual/arch_lang/figures/memory_bank_decoder.svg create mode 100644 docs/source/manual/arch_lang/figures/memory_bank_flatten.svg create mode 100644 docs/source/manual/arch_lang/figures/memory_bank_shift_register.svg diff --git a/docs/source/manual/arch_lang/config_protocol.rst b/docs/source/manual/arch_lang/config_protocol.rst index 04b47d638..9b5cfe3ef 100644 --- a/docs/source/manual/arch_lang/config_protocol.rst +++ b/docs/source/manual/arch_lang/config_protocol.rst @@ -167,10 +167,39 @@ The BL and WL protocols can be customized through the XML syntax ``bl`` and ``wl -.. option:: protocol="decoder|flatten" +.. option:: protocol="decoder|flatten|shift_register" - - ``decoder``: BLs or WLs are controlled by decoders with address lines. For BLs, the decoder includes an enable signal as well as a data input signal. This is the default option if not specified. - - ``flatten``: BLs or WLs are directly available at the FPGA fabric. In this way, all the configurable memorys on the same WL can be written through the BL signals in one clock cycle + - ``decoder``: BLs or WLs are controlled by decoders with address lines. For BLs, the decoder includes an enable signal as well as a data input signal. This is the default option if not specified. See an illustrative example in :numref:`fig_memory_bank_decoder_based`. + - ``flatten``: BLs or WLs are directly available at the FPGA fabric. In this way, all the configurable memorys on the same WL can be written through the BL signals in one clock cycle. See an illustrative example in :numref:`fig_memory_bank_flatten`. + - ``shift_register``: BLs or WLs are controlled by shift register chains. The BL/WLs are programming each time the shift register chains are fully loaded. See an illustrative example in :numref:`fig_memory_bank_shift_register`. + +.. _fig_memory_bank_decoder_based: + +.. figure:: figures/memory_bank_decoder.svg + :scale: 30% + :alt: map to buried treasure + + Example of (a) a memory organization using address decoders; (b) single memory bank across the fabric; and (c) multiple memory banks across the fabric. + + +.. _fig_memory_bank_flatten: + +.. figure:: figures/memory_bank_flatten.svg + :scale: 30% + :alt: map to buried treasure + + Example of (a) a memory organization with direct access to BL/WL signals; (b) single memory bank across the fabric; and (c) multiple memory banks across the fabric. + +.. _fig_memory_bank_shift_register: + +.. figure:: figures/memory_bank_shift_register.svg + :scale: 30% + :alt: map to buried treasure + + Example of (a) a memory organization using shift register chains to control BL/WLs; (b) single memory bank across the fabric; and (c) multiple memory banks across the fabric. + + +.. note:: The flip-flop for WL shift register requires an enable signal to gate WL signals when loading WL shift registers .. note:: Memory-bank decoders does require a memory cell to have diff --git a/docs/source/manual/arch_lang/figures/memory_bank_decoder.svg b/docs/source/manual/arch_lang/figures/memory_bank_decoder.svg new file mode 100644 index 000000000..d392fe785 --- /dev/null +++ b/docs/source/manual/arch_lang/figures/memory_bank_decoder.svg @@ -0,0 +1,2449 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Produced by OmniGraffle 7.18.5\n2021-10-04 18:57:28 +0000 + + decoder-based + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + out + + + + + + out + + + + + + + + + + + + + + + + + + + GND + + + + + V + DD + + + + + GND + + + + + V + DD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WL + + + + + + + + + + + + + + + + BL + + + + + + + + + + + + + + + + WL + + + + + + + + + + + + + + + + + + + + + + BL + + + + + + + + + + + + + + + + + + + + + + Cell + 0 + + + + + + + + + + + + + Cell + 3 + + + + + + + + + + + + + Cell + 6 + + + + + + + + + + + + + Cell + 1 + + + + + + + + + + + + + Cell + 4 + + + + + + + + + + + + + Cell + 7 + + + + + + + + + + + + + Cell + 2 + + + + + + + + + + + + + Cell + 5 + + + + + + + + + + + + + Cell + 8 + + + + + + + + + + + + + + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + + + + Bit Lines (BL) + + + + + Word Lines (WL) + + + + + + + Column Decoder + + + + + + + + + + + + + Row Decoder + + + + + SRAM Cell + + + + + ... + + + + + ... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Single Memory + Bank + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Memory + Bank A + + + + + + + Memory + Bank B + + + + + + + Memory + Bank C + + + + + + + Memory + Bank D + + + + + + + + + + + (a) + + + + + (b) + + + + + (c) + + + + + diff --git a/docs/source/manual/arch_lang/figures/memory_bank_flatten.svg b/docs/source/manual/arch_lang/figures/memory_bank_flatten.svg new file mode 100644 index 000000000..c7c87c656 --- /dev/null +++ b/docs/source/manual/arch_lang/figures/memory_bank_flatten.svg @@ -0,0 +1,2440 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Produced by OmniGraffle 7.18.5\n2021-10-04 18:57:28 +0000 + + flatten + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + out + + + + + + out + + + + + + + + + + + + + + + + + + + GND + + + + + V + DD + + + + + GND + + + + + V + DD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WL + + + + + + + + + + + + + + + + BL + + + + + + + + + + + + + + + + WL + + + + + + + + + + + + + + + + + + + + + + BL + + + + + + + + + + + + + + + + + + + + + + Cell + 0 + + + + + + + + + + + + + Cell + 3 + + + + + + + + + + + + + Cell + 6 + + + + + + + + + + + + + Cell + 1 + + + + + + + + + + + + + Cell + 4 + + + + + + + + + + + + + Cell + 7 + + + + + + + + + + + + + Cell + 2 + + + + + + + + + + + + + Cell + 5 + + + + + + + + + + + + + Cell + 8 + + + + + + + + + + + + + + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + + + + Bit Lines (BL) Bus [0 .. x] + + + + + Word Lines (WL) Bus [0 .. y] + + + + + + + + + + + SRAM Cell + + + + + ... + + + + + ... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Single Memory + Bank + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Memory + Bank A + + + + + + + Memory + Bank B + + + + + + + Memory + Bank C + + + + + + + Memory + Bank D + + + + + + + + + + + (a) + + + + + (b) + + + + + (c) + + + + + diff --git a/docs/source/manual/arch_lang/figures/memory_bank_shift_register.svg b/docs/source/manual/arch_lang/figures/memory_bank_shift_register.svg new file mode 100644 index 000000000..04ab9fe34 --- /dev/null +++ b/docs/source/manual/arch_lang/figures/memory_bank_shift_register.svg @@ -0,0 +1,2770 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Produced by OmniGraffle 7.18.5\n2021-10-04 18:57:28 +0000 + + shift-register-based + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + out + + + + + + out + + + + + + + + + + + + + + + + + + + GND + + + + + V + DD + + + + + GND + + + + + V + DD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WL + + + + + + + + + + + + + + + + BL + + + + + + + + + + + + + + + + WL + + + + + + + + + + + + + + + + + + + + + + BL + + + + + + + + + + + + + + + + + + + + + + Cell + 0 + + + + + + + + + + + + + Cell + 3 + + + + + + + + + + + + + Cell + 6 + + + + + + + + + + + + + Cell + 1 + + + + + + + + + + + + + Cell + 4 + + + + + + + + + + + + + Cell + 7 + + + + + + + + + + + + + Cell + 2 + + + + + + + + + + + + + Cell + 5 + + + + + + + + + + + + + Cell + 8 + + + + + + + + + + + + + + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + + + + Bit Lines (BL) + + + + + Word Lines (WL) + + + + + + + BL Shift Register Chains + + + + + + + + + + + + + WL Shift Register Chains + + + + + SRAM Cell + + + + + ... + + + + + ... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Single Memory + Bank + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + Tile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Memory + Bank A + + + + + + + Memory + Bank B + + + + + + + Memory + Bank C + + + + + + + Memory + Bank D + + + + + + + + + + + (a) + + + + + (b) + + + + + (c) + + + + + sf_chain + + + + + + + + + + FF + + + + + D + + + + + CLK + + + + + + + + + + + + + + + + + + + + + Q + + + + + BL/ + WL + + + + + + + + + FF + + + + + D + + + + + CLK + + + + + + + + + + + + + + + + + + + + + Q + + + + + BL/ + WL + + + + + + + + + FF + + + + + D + + + + + CLK + + + + + + + + + + + + + + + + + + + + + Q + + + + + BL/ + WL + + + + + + + + + + + + + + + + + + + + + Clk + + + + + Head + + + + + + + + + + + + + + + + + + + + + + + + + + FF + + + + + D + + + + + CLK + + + + + + + + + + + + + + + + + + + + + Q + + + + + BL/ + WL + + + + + + + + + … + + + + + + + + + + + + Tail + + + + + + + + + + + + + + + + + + + + + BL/WL[0] + + + + + BL/WL[1] + + + + + BL/WL[2] + + + + + BL/WL[n] + + + + + + + + BL/WL signals + + + + + Shift Register Chain + + + + + + + + From 9a7e0f761aeb806f8b0313fc825120c8f10c28a9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 4 Oct 2021 12:29:49 -0700 Subject: [PATCH 152/229] [Doc] Add fabric bitstream file format for QL memory bank --- .../manual/file_formats/fabric_bitstream.rst | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/docs/source/manual/file_formats/fabric_bitstream.rst b/docs/source/manual/file_formats/fabric_bitstream.rst index 2def5d269..6cd8085de 100644 --- a/docs/source/manual/file_formats/fabric_bitstream.rst +++ b/docs/source/manual/file_formats/fabric_bitstream.rst @@ -65,6 +65,112 @@ The information depends on the type of configuration procotol. .. note:: When there are multiple configuration regions, each ```` may consist of multiple bits. For example, ``0110`` represents the bits for 4 configuration regions, where the 4 digits correspond to the bits from region ``0, 1, 2, 3`` respectively. +.. option:: ql_memory_bank using decoders + + Multiple lines will be included, each of which is organized as . + The size of address line and data input bits are shown as a comment in the bitstream file, which eases the development of bitstream downloader. + For example + + .. code-block:: verilog + + // Bitstream width (LSB -> MSB): + + The first part represents the Bit-Line address. + The second part represents the Word-Line address. + The third part represents the configuration bit. + For example + + .. code-block:: xml + + + + ... + + + .. note:: When there are multiple configuration regions, each ```` may consist of multiple bits. For example, ``0110`` represents the bits for 4 configuration regions, where the 4 digits correspond to the bits from region ``0, 1, 2, 3`` respectively. + +.. option:: ql_memory_bank using flatten BL and WLs + + Multiple lines will be included, each of which is organized as . + The size of data are shown as a comment in the bitstream file, which eases the development of bitstream downloader. + For example + + .. code-block:: verilog + + // Bitstream width (LSB -> MSB): + + The first part represents the Bit-Line data from multiple configuration regions. + The second part represents the Word-Line data from multiple configuration regions. + For example + + .. code-block:: xml + + + + ... + + + .. note:: The WL data of region is one-hot. + +.. option:: ql_memory_bank using shift registers + + Multiple lines will be included, each of which is organized as or . + The size of data are shown as a comment in the bitstream file, which eases the development of bitstream downloader. + For example + + .. code-block:: verilog + + // Bitstream word count: 36 + // Bitstream bl word size: 39 + // Bitstream wl word size: 37 + // Bitstream width (LSB -> MSB): + + The bitstream data are organized by words. Each word consists of two parts, BL data to be loaded to BL shift register chains and WL data to be loaded to WL shift register chains + For example + + .. code-block:: xml + + // Word 0 + // BL Part + ---- + ^ + | + ... BL word size + | + v + ---- + // Word 0 + // WL Part + ---- + ^ + | + ... WL word size + | + v + ---- + // Word 1 + // BL Part + ---- + ^ + | + ... BL word size + | + v + ---- + // Word 1 + // WL Part + ---- + ^ + | + ... WL word size + | + v + ---- + ... // More words + + .. note:: The BL/WL data may be multi-bit, while each bit corresponds to a configuration region + .. note:: The WL data of region is one-hot. + .. option:: frame_based Multiple lines will be included, each of which is organized as ``
``. From fa1908511d717f61070596906b49d112ed0a7b32 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 4 Oct 2021 16:36:20 -0700 Subject: [PATCH 153/229] [Test] Added a new test case to validate QuickLogic memory using shift registers with WLR control --- .../config/task.conf | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register_use_wlr/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register_use_wlr/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register_use_wlr/config/task.conf new file mode 100644 index 000000000..56dee6c68 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register_use_wlr/config/task.conf @@ -0,0 +1,45 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +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/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml + +openfpga_vpr_device_layout= +openfpga_fast_configuration= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +bench1_top = or2 +bench1_chan_width = 300 + +bench2_top = and2_latch +bench2_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 13c31cb89cb37f4f6192067356a94add3f073180 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 4 Oct 2021 16:37:49 -0700 Subject: [PATCH 154/229] [Test] Deploy the qlbanksr_wlr to basic regression tests --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index 09c4d7f10..0b7a3dc95 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -60,6 +60,7 @@ run-task basic_tests/full_testbench/multi_region_ql_memory_bank --debug --show_t run-task basic_tests/full_testbench/ql_memory_bank_flatten --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_shift_register --debug --show_thread_logs +run-task basic_tests/full_testbench/ql_memory_bank_shift_register_use_wlr --debug --show_thread_logs echo -e "Testing testbenches without self checking features"; run-task basic_tests/full_testbench/full_testbench_without_self_checking --debug --show_thread_logs From fbef22b49425bc65b0b7b2e0d762b5d6d62201b4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 4 Oct 2021 16:39:53 -0700 Subject: [PATCH 155/229] [Arch] Bug fix in the example architecture for QL memory bank using WLR and shift registers --- .../openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml index da0e46ded..d78c980e5 100644 --- a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_wlr_openfpga.xml @@ -166,11 +166,11 @@ - + - + @@ -181,7 +181,7 @@ - + From 3efd6840a81931a7e208d46a8f1665305a9a03e0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 4 Oct 2021 16:58:01 -0700 Subject: [PATCH 156/229] [Engine] Bug fix for missing WLR ports in auto-generated shift register banks --- openfpga/src/fabric/build_top_module_memory_bank.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index dd3dceafb..18accc9bb 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -301,11 +301,18 @@ ModuleId build_wl_shift_register_chain_module(ModuleManager& module_manager, circuit_lib.port_size(sram_output_ports[0])); module_manager.add_port(mem_module, chain_tail_port, ModuleManager::MODULE_OUTPUT_PORT); - /* Add the output ports to output BL signals */ + /* Add the output ports to output BL/WL signals */ BasicPort chain_wl_port(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME, num_mems); module_manager.add_port(mem_module, chain_wl_port, ModuleManager::MODULE_OUTPUT_PORT); + /* Add the output ports to output WLR signals */ + if (!sram_wlr_ports.empty()) { + BasicPort chain_wlr_port(WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME, + num_mems); + module_manager.add_port(mem_module, chain_wlr_port, ModuleManager::MODULE_OUTPUT_PORT); + } + /* Find the sram module in the module manager */ ModuleId sram_mem_module = module_manager.find_module(circuit_lib.model_name(sram_model)); From d2859ca1c87122a5687a0882a79307316a58327f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 10:56:20 -0700 Subject: [PATCH 157/229] [Arch] Add an example architecture for multi-region QuickLogic memory bank using shift registers --- ...N4_40nm_multi_region_qlbanksr_openfpga.xml | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_qlbanksr_openfpga.xml diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_qlbanksr_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_qlbanksr_openfpga.xml new file mode 100644 index 000000000..8fc83b95e --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_qlbanksr_openfpga.xml @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 52569f808e1a078db34a479f2849dbb10a5c2c5b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 10:57:33 -0700 Subject: [PATCH 158/229] [Test] Added a test case for QuickLogic memory bank using shift registers in multiple region --- .../config/task.conf | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/full_testbench/multi_region_ql_memory_bank_shift_register/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_ql_memory_bank_shift_register/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_ql_memory_bank_shift_register/config/task.conf new file mode 100644 index 000000000..4683a6e19 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_ql_memory_bank_shift_register/config/task.conf @@ -0,0 +1,36 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +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/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_qlbanksr_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml +openfpga_vpr_device_layout=--device 2x2 +openfpga_fast_configuration= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 492db50efe486fd63bfe27cec23aa5ea0590ee64 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 10:59:26 -0700 Subject: [PATCH 159/229] [Test] Deploy the new test to basic regression tests --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index 0b7a3dc95..5ddc5af76 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -61,6 +61,7 @@ run-task basic_tests/full_testbench/ql_memory_bank_flatten --debug --show_thread run-task basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_shift_register --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_shift_register_use_wlr --debug --show_thread_logs +run-task basic_tests/full_testbench/multi_region_ql_memory_bank_shift_register --debug --show_thread_logs echo -e "Testing testbenches without self checking features"; run-task basic_tests/full_testbench/full_testbench_without_self_checking --debug --show_thread_logs From b21f212031ddfe766e1d226ebc4c307e6d22935c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 11:39:53 -0700 Subject: [PATCH 160/229] [Test] Replace the multi-region test with the fabric key test because the mutli region of shift-register bank is sensitive to the correctness of fabric key --- .../regression_test_scripts/basic_reg_test.sh | 2 +- .../config/task.conf | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) rename openfpga_flow/tasks/basic_tests/{full_testbench/multi_region_ql_memory_bank_shift_register => fabric_key/load_external_key_multi_region_qlbanksr_fpga}/config/task.conf (72%) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index 5ddc5af76..c593994d8 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -61,7 +61,6 @@ run-task basic_tests/full_testbench/ql_memory_bank_flatten --debug --show_thread run-task basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_shift_register --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_shift_register_use_wlr --debug --show_thread_logs -run-task basic_tests/full_testbench/multi_region_ql_memory_bank_shift_register --debug --show_thread_logs echo -e "Testing testbenches without self checking features"; run-task basic_tests/full_testbench/full_testbench_without_self_checking --debug --show_thread_logs @@ -96,6 +95,7 @@ run-task basic_tests/fabric_key/load_external_key_cc_fpga --debug --show_thread_ run-task basic_tests/fabric_key/load_external_key_multi_region_cc_fpga --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key_qlbank_fpga --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga --debug --show_thread_logs +run-task basic_tests/fabric_key/load_external_key_multi_region_qlbanksr_fpga --debug --show_thread_logs echo -e "Testing K4 series FPGA"; echo -e "Testing K4N4 with facturable LUTs"; diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_ql_memory_bank_shift_register/config/task.conf b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_multi_region_qlbanksr_fpga/config/task.conf similarity index 72% rename from openfpga_flow/tasks/basic_tests/full_testbench/multi_region_ql_memory_bank_shift_register/config/task.conf rename to openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_multi_region_qlbanksr_fpga/config/task.conf index 4683a6e19..53330396b 100644 --- a/openfpga_flow/tasks/basic_tests/full_testbench/multi_region_ql_memory_bank_shift_register/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_multi_region_qlbanksr_fpga/config/task.conf @@ -13,24 +13,27 @@ power_analysis = true spice_output=false verilog_output=true timeout_each_job = 20*60 -fpga_flow=yosys_vpr +fpga_flow=vpr_blif [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_multi_region_qlbanksr_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml -openfpga_vpr_device_layout=--device 2x2 -openfpga_fast_configuration= +external_fabric_key_file=${PATH:OPENFPGA_PATH}/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbanksr_sample_key.xml +openfpga_vpr_device_layout=2x2 [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml [BENCHMARKS] -bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif [SYNTHESIS_PARAM] bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v bench0_chan_width = 300 [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= From 80fd1efd6198f0109cfdfc8bdf6f7290be4fa2e9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 11:46:58 -0700 Subject: [PATCH 161/229] [Test] Add an example test key for multi-region QuickLogic memory bank using shift registers --- ...4_2x2_multi_region_qlbanksr_sample_key.xml | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbanksr_sample_key.xml diff --git a/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbanksr_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbanksr_sample_key.xml new file mode 100644 index 000000000..0b96c1930 --- /dev/null +++ b/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbanksr_sample_key.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ff339312f63607f8a8d7d28acb5f48021f685e01 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 11:55:10 -0700 Subject: [PATCH 162/229] [Doc] Update documentation about the limitations of multi-region configuration protocols --- docs/source/manual/arch_lang/config_protocol.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/source/manual/arch_lang/config_protocol.rst b/docs/source/manual/arch_lang/config_protocol.rst index 9b5cfe3ef..1c124ddc0 100644 --- a/docs/source/manual/arch_lang/config_protocol.rst +++ b/docs/source/manual/arch_lang/config_protocol.rst @@ -47,7 +47,12 @@ Template Specify the number of configuration regions to be used across the fabrics. By default, it will be only 1 configuration region. Each configuration region contains independent configuration protocols, but the whole fabric should employ the same type of configuration protocols. For example, an FPGA fabric consists of 4 configuration regions, each of which includes a configuration chain. The more configuration chain to be used, the fast configuration runtime will be, but at the cost of more I/Os in the FPGA fabrics. The organization of each configurable region can be customized through the fabric key (see details in :ref:`fabric_key`). - .. warning:: Currently, multiple configuration regions is not applicable to ``standalone`` configuration protocol. + .. warning:: Currently, multiple configuration regions is not applicable to + + - ``standalone`` configuration protocol. + - ``ql_memory_bank`` configuration protocol when BL/WL protocol ``flatten`` is selected + + .. note:: For ``ql_memory_bank`` configuration protocol when BL/WL protocol ``shift_register`` is selected, different configuration regions **cannot** share any WLs on the same row! In such case, the default fabric key may not work. Strongly recommend to craft your own fabric key based on your configuration region plannning! Configuration Chain Example From 3d062872def7e3a744f0bf0d1a257b6c2154111d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 14:08:01 -0700 Subject: [PATCH 163/229] [Lib] Upgrade openfpga arch parser to error out for unsupported configuration protocol settings --- .../libarchopenfpga/src/read_xml_config_protocol.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp b/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp index 9a3a60336..0472b7d73 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_config_protocol.cpp @@ -152,6 +152,12 @@ void read_xml_config_organization(pugi::xml_node& xml_config_orgz, if (xml_wl_protocol) { read_xml_wl_protocol(xml_wl_protocol, loc_data, config_protocol); } + + /* Throw an execption if the BL/WL protocols are different. We currently do not support it! */ + if (config_protocol.bl_protocol_type() != config_protocol.wl_protocol_type()) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_config_orgz), + "Expect same type of protocol for both BL and WL! Other combinations are not supported yet\n"); + } } } From fdd75c4ec85845b0029d8e2ef31f39f70aa94e07 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 17:54:07 -0700 Subject: [PATCH 164/229] [FPGA-Bitstream] Enable don't care bit to be outputted in bitstream file for QuickLogic memory banks --- .../write_text_fabric_bitstream.cpp | 4 ++-- openfpga/src/utils/fabric_bitstream_utils.cpp | 18 ++++++++++-------- openfpga/src/utils/fabric_bitstream_utils.h | 6 ++++-- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 257cb0e5b..8c2226876 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -195,7 +195,7 @@ int write_memory_bank_flatten_fabric_bitstream_to_text_file(std::fstream& fp, const FabricBitstream& fabric_bitstream) { int status = 0; - MemoryBankFlattenFabricBitstream fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip); + MemoryBankFlattenFabricBitstream fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip, 'x'); /* The address sizes and data input sizes are the same across any element, * just get it from the 1st element to save runtime @@ -240,7 +240,7 @@ int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream& const FabricBitstream& fabric_bitstream) { int status = 0; - MemoryBankShiftRegisterFabricBitstream fabric_bits = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip); + MemoryBankShiftRegisterFabricBitstream fabric_bits = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip, 'x'); /* Output information about how to intepret the bitstream */ fp << "// Bitstream word count: " << fabric_bits.num_words() << std::endl; diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index cc14dfe84..814666c9b 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -234,7 +234,8 @@ MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const Fa MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream, const bool& fast_configuration, - const bool& bit_value_to_skip) { + const bool& bit_value_to_skip, + const char& dont_care_bit) { /* If fast configuration is not enabled, we need all the wl address even some of them have all-zero BLs */ if (!fast_configuration) { vtr::vector> fabric_bits_per_region; @@ -324,14 +325,14 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons std::vector cur_wl_vectors; for (const FabricBitRegionId& region : fabric_bitstream.regions()) { /* If the key id is in bound for the key list in this region, find the BL and WL and add to the final bitstream database - * If the key id is out of bound for the key list in this region, we append an all-zero string for both BL and WLs + * If the key id is out of bound for the key list in this region, we append an all-'x' string for both BL and WLs */ if (ikey < fabric_bits_per_region_keys[region].size()) { cur_wl_vectors.push_back(fabric_bits_per_region_keys[region][ikey]); cur_bl_vectors.push_back(fabric_bits_per_region[region].at(fabric_bits_per_region_keys[region][ikey])); } else { - cur_wl_vectors.push_back(std::string(max_blwl_sizes_per_region[region].second, '0')); - cur_bl_vectors.push_back(std::string(max_blwl_sizes_per_region[region].first, '0')); + cur_wl_vectors.push_back(std::string(max_blwl_sizes_per_region[region].second, dont_care_bit)); + cur_bl_vectors.push_back(std::string(max_blwl_sizes_per_region[region].first, dont_care_bit)); } } /* Add the pair to std map */ @@ -398,8 +399,9 @@ std::vector reshape_bitstream_vectors_to_first_element(const std::v MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream, const bool& fast_configuration, //const std::array& blwl_sr_banks, - const bool& bit_value_to_skip) { - MemoryBankFlattenFabricBitstream raw_fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip); + const bool& bit_value_to_skip, + const char& dont_care_bit) { + MemoryBankFlattenFabricBitstream raw_fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip, dont_care_bit); MemoryBankShiftRegisterFabricBitstream fabric_bits; /* Iterate over each word */ @@ -408,7 +410,7 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b MemoryBankShiftRegisterFabricBitstreamWordId word_id = fabric_bits.create_word(); - std::vector reshaped_bl_vectors = reshape_bitstream_vectors_to_first_element(bl_vec, '0'); + std::vector reshaped_bl_vectors = reshape_bitstream_vectors_to_first_element(bl_vec, dont_care_bit); /* Reverse the vectors due to the shift register chain nature: first-in first-out */ std::reverse(reshaped_bl_vectors.begin(), reshaped_bl_vectors.end()); /* Add the BL word to final bitstream */ @@ -416,7 +418,7 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b fabric_bits.add_bl_vectors(word_id, reshaped_bl_vec); } - std::vector reshaped_wl_vectors = reshape_bitstream_vectors_to_first_element(wl_vec, '0'); + std::vector reshaped_wl_vectors = reshape_bitstream_vectors_to_first_element(wl_vec, dont_care_bit); /* Reverse the vectors due to the shift register chain nature: first-in first-out */ std::reverse(reshaped_wl_vectors.begin(), reshaped_wl_vectors.end()); /* Add the BL word to final bitstream */ diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index b45db0c0d..ff822802e 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -63,7 +63,8 @@ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBit *******************************************************************/ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(const FabricBitstream& fabric_bitstream, const bool& fast_configuration, - const bool& bit_value_to_skip); + const bool& bit_value_to_skip, + const char& dont_care_bit = 'x'); /******************************************************************** * @ brief Reorganize the fabric bitstream for memory banks which use shift register to manipulate BL and WLs @@ -96,7 +97,8 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream, const bool& fast_configuration, //const std::array& blwl_sr_banks, - const bool& bit_value_to_skip); + const bool& bit_value_to_skip, + const char& dont_care_bit = 'x'); /* Alias to a specific organization of bitstreams for memory bank configuration protocol */ typedef std::map, std::vector> MemoryBankFabricBitstream; From ad54c8547e236e720cb82a8e9e711a5810b3c415 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 18:54:02 -0700 Subject: [PATCH 165/229] [FPGA-Bitstream] Added an option to ``write_fabric_bitstream`` command to enable outputting don't care bits in bitstream files --- openfpga/src/base/openfpga_bitstream.cpp | 2 ++ .../src/base/openfpga_bitstream_command.cpp | 3 +++ .../write_text_fabric_bitstream.cpp | 26 ++++++++++++++----- .../write_text_fabric_bitstream.h | 1 + 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/openfpga/src/base/openfpga_bitstream.cpp b/openfpga/src/base/openfpga_bitstream.cpp index 315f647bc..ea390ae08 100644 --- a/openfpga/src/base/openfpga_bitstream.cpp +++ b/openfpga/src/base/openfpga_bitstream.cpp @@ -94,6 +94,7 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx, CommandOptionId opt_file = cmd.option("file"); CommandOptionId opt_file_format = cmd.option("format"); CommandOptionId opt_fast_config = cmd.option("fast_configuration"); + CommandOptionId opt_keep_dont_care_bits = cmd.option("keep_dont_care_bits"); /* Write fabric bitstream if required */ int status = CMD_EXEC_SUCCESS; @@ -125,6 +126,7 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx, openfpga_ctx.fabric_global_port_info(), cmd_context.option_value(cmd, opt_file), cmd_context.option_enable(cmd, opt_fast_config), + cmd_context.option_enable(cmd, opt_keep_dont_care_bits), cmd_context.option_enable(cmd, opt_verbose)); } diff --git a/openfpga/src/base/openfpga_bitstream_command.cpp b/openfpga/src/base/openfpga_bitstream_command.cpp index a59d19adf..0ebb10d58 100644 --- a/openfpga/src/base/openfpga_bitstream_command.cpp +++ b/openfpga/src/base/openfpga_bitstream_command.cpp @@ -154,6 +154,9 @@ ShellCommandId add_openfpga_write_fabric_bitstream_command(openfpga::Shell Date: Tue, 5 Oct 2021 18:58:47 -0700 Subject: [PATCH 166/229] [FPGA-Bitstream] Bug fix in wrong option name --- openfpga/src/base/openfpga_bitstream_command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga/src/base/openfpga_bitstream_command.cpp b/openfpga/src/base/openfpga_bitstream_command.cpp index 0ebb10d58..fcf431890 100644 --- a/openfpga/src/base/openfpga_bitstream_command.cpp +++ b/openfpga/src/base/openfpga_bitstream_command.cpp @@ -155,7 +155,7 @@ ShellCommandId add_openfpga_write_fabric_bitstream_command(openfpga::Shell Date: Tue, 5 Oct 2021 18:59:33 -0700 Subject: [PATCH 167/229] [Test] Add new tests to validate the correctness of bitstream files with don't care bits --- .../config/task.conf | 44 ++++++++++++++++++ .../config/task.conf | 45 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 openfpga_flow/tasks/fpga_bitstream/ql_memory_bank_flatten_dont_care_bit/config/task.conf create mode 100644 openfpga_flow/tasks/fpga_bitstream/ql_memory_bank_shift_register_dont_care_bit/config/task.conf diff --git a/openfpga_flow/tasks/fpga_bitstream/ql_memory_bank_flatten_dont_care_bit/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/ql_memory_bank_flatten_dont_care_bit/config/task.conf new file mode 100644 index 000000000..bcaad37ce --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/ql_memory_bank_flatten_dont_care_bit/config/task.conf @@ -0,0 +1,44 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +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/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml +openfpga_vpr_device_layout= +openfpga_fast_configuration=--keep_dont_care_bits + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +bench1_top = or2 +bench1_chan_width = 300 + +bench2_top = and2_latch +bench2_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/tasks/fpga_bitstream/ql_memory_bank_shift_register_dont_care_bit/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/ql_memory_bank_shift_register_dont_care_bit/config/task.conf new file mode 100644 index 000000000..9974313fd --- /dev/null +++ b/openfpga_flow/tasks/fpga_bitstream/ql_memory_bank_shift_register_dont_care_bit/config/task.conf @@ -0,0 +1,45 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +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/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml + +openfpga_vpr_device_layout= +openfpga_fast_configuration=--keep_dont_care_bits + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +bench1_top = or2 +bench1_chan_width = 300 + +bench2_top = and2_latch +bench2_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 064ac478f363c384d5c16b9dad167dce0a06e8c6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 19:01:03 -0700 Subject: [PATCH 168/229] [Test] Deploy news test to fpga-bitstream regression tests --- .../regression_test_scripts/fpga_bitstream_reg_test.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh index 58858e0b9..9fa5001b2 100755 --- a/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_bitstream_reg_test.sh @@ -32,3 +32,7 @@ run-task fpga_bitstream/write_io_mapping --debug --show_thread_logs echo -e "Testing report bitstream distribution to file"; run-task fpga_bitstream/report_bitstream_distribution/default_depth --debug --show_thread_logs run-task fpga_bitstream/report_bitstream_distribution/custom_depth --debug --show_thread_logs + +echo -e "Testing bitstream file with don't care bits"; +run-task fpga_bitstream/dont_care_bits/ql_memory_bank_flatten --debug --show_thread_logs +run-task fpga_bitstream/dont_care_bits/ql_memory_bank_shift_register --debug --show_thread_logs From 50604e4589ea9081b489ccc5b2b34301250d27b5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 19:02:43 -0700 Subject: [PATCH 169/229] [Test] move test cases --- .../ql_memory_bank_flatten}/config/task.conf | 0 .../ql_memory_bank_shift_register}/config/task.conf | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename openfpga_flow/tasks/fpga_bitstream/{ql_memory_bank_flatten_dont_care_bit => dont_care_bits/ql_memory_bank_flatten}/config/task.conf (100%) rename openfpga_flow/tasks/fpga_bitstream/{ql_memory_bank_shift_register_dont_care_bit => dont_care_bits/ql_memory_bank_shift_register}/config/task.conf (100%) diff --git a/openfpga_flow/tasks/fpga_bitstream/ql_memory_bank_flatten_dont_care_bit/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_flatten/config/task.conf similarity index 100% rename from openfpga_flow/tasks/fpga_bitstream/ql_memory_bank_flatten_dont_care_bit/config/task.conf rename to openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_flatten/config/task.conf diff --git a/openfpga_flow/tasks/fpga_bitstream/ql_memory_bank_shift_register_dont_care_bit/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_shift_register/config/task.conf similarity index 100% rename from openfpga_flow/tasks/fpga_bitstream/ql_memory_bank_shift_register_dont_care_bit/config/task.conf rename to openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_shift_register/config/task.conf From 4add9781d5d59e9e60cbadc280d20e81975f6f83 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 19:13:50 -0700 Subject: [PATCH 170/229] [Script] Add a new openfpga shell script for don't care bits outputting --- ...nch_dont_care_bits_example_script.openfpga | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 openfpga_flow/openfpga_shell_scripts/write_full_testbench_dont_care_bits_example_script.openfpga diff --git a/openfpga_flow/openfpga_shell_scripts/write_full_testbench_dont_care_bits_example_script.openfpga b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_dont_care_bits_example_script.openfpga new file mode 100644 index 000000000..88e97bcbc --- /dev/null +++ b/openfpga_flow/openfpga_shell_scripts/write_full_testbench_dont_care_bits_example_script.openfpga @@ -0,0 +1,74 @@ +# Run VPR for the 'and' design +#--write_rr_graph example_rr_graph.xml +vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route ${OPENFPGA_VPR_DEVICE_LAYOUT} + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ${OPENFPGA_ARCH_FILE} + +# Read OpenFPGA simulation settings +read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE} + +# Annotate the OpenFPGA architecture to VPR data base +# to debug use --verbose options +link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to clustering nets based on routing results +pb_pin_fixup --verbose + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing #--verbose + +# Write the fabric hierarchy of module graph to a file +# This is used by hierarchical PnR flows +write_fabric_hierarchy --file ./fabric_hierarchy.txt + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write fabric-dependent bitstream +write_fabric_bitstream --file fabric_bitstream.bit --format plain_text ${OPENFPGA_FAST_CONFIGURATION} --keep_dont_care_bits + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --explicit_port_mapping --bitstream fabric_bitstream.bit ${OPENFPGA_FAST_CONFIGURATION} + +# Write the SDC files for PnR backend +# - Turn on every options here +write_pnr_sdc --file ./SDC + +# Write SDC to disable timing for configure ports +write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file ./SDC_analysis + +# Finish and exit OpenFPGA +exit + +# Note : +# To run verification at the end of the flow maintain source in ./SRC directory From f74ea5d39acc47b0b053c1040e928bb8682e8ff6 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 19:14:44 -0700 Subject: [PATCH 171/229] [Test] Use the new openfpga shell script in don't care bit tests --- .../dont_care_bits/ql_memory_bank_flatten/config/task.conf | 2 +- .../ql_memory_bank_shift_register/config/task.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_flatten/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_flatten/config/task.conf index bcaad37ce..dbd1c3db8 100644 --- a/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_flatten/config/task.conf +++ b/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_flatten/config/task.conf @@ -16,7 +16,7 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_dont_care_bits_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml openfpga_vpr_device_layout= diff --git a/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_shift_register/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_shift_register/config/task.conf index 9974313fd..1bb51ba34 100644 --- a/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_shift_register/config/task.conf +++ b/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_shift_register/config/task.conf @@ -16,7 +16,7 @@ timeout_each_job = 20*60 fpga_flow=yosys_vpr [OpenFPGA_SHELL] -openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_dont_care_bits_example_script.openfpga openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml From 189ade6c1e8c11c6524df6e8329d4fce900238c0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 19:17:34 -0700 Subject: [PATCH 172/229] [Test] Bug fix --- .../dont_care_bits/ql_memory_bank_flatten/config/task.conf | 2 +- .../ql_memory_bank_shift_register/config/task.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_flatten/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_flatten/config/task.conf index dbd1c3db8..791a8150e 100644 --- a/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_flatten/config/task.conf +++ b/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_flatten/config/task.conf @@ -20,7 +20,7 @@ openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scrip openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbankflatten_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml openfpga_vpr_device_layout= -openfpga_fast_configuration=--keep_dont_care_bits +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml diff --git a/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_shift_register/config/task.conf b/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_shift_register/config/task.conf index 1bb51ba34..30f89b9b9 100644 --- a/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_shift_register/config/task.conf +++ b/openfpga_flow/tasks/fpga_bitstream/dont_care_bits/ql_memory_bank_shift_register/config/task.conf @@ -21,7 +21,7 @@ openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_ openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml openfpga_vpr_device_layout= -openfpga_fast_configuration=--keep_dont_care_bits +openfpga_fast_configuration= [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From 03bcf6dee5a8054eb6e85c7e5183d9d56faa9953 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 5 Oct 2021 19:23:42 -0700 Subject: [PATCH 173/229] [Doc] Update documenation for the new option ``--keep_dont_care_bits`` --- .../openfpga_commands/fpga_bitstream_commands.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst index 12c4d8ff5..bf66e4b09 100644 --- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst +++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_bitstream_commands.rst @@ -77,6 +77,9 @@ write_fabric_bitstream .. note:: If both reset and set ports are defined in the circuit modeling for programming, OpenFPGA will pick the one that will bring largest benefit in speeding up configuration. + .. option:: --keep_dont_care_bits + + Keep don't care bits (``x``) in the outputted bitstream file. This is only applicable to plain text file format. If not enabled, the don't care bits are converted to either logic ``0`` or ``1``. .. option:: --verbose From 82ed6b177b3405eee0f80d246046f886048a5980 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 6 Oct 2021 11:39:28 -0700 Subject: [PATCH 174/229] [FPGA-Verilog] Now consider clock constraints for BL/WL shift registers --- .../fpga_verilog/verilog_top_testbench.cpp | 53 +++++++----- .../verilog_top_testbench_memory_bank.cpp | 84 ++++++++++++++++--- .../verilog_top_testbench_memory_bank.h | 19 +++-- 3 files changed, 116 insertions(+), 40 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index f8477df5f..f45e84c9d 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -11,6 +11,9 @@ #include "vtr_assert.h" #include "vtr_time.h" +/* Headers from openfpgashell library */ +#include "command_exit_codes.h" + /* Headers from openfpgautil library */ #include "openfpga_port.h" #include "openfpga_digest.h" @@ -1121,15 +1124,16 @@ void print_verilog_top_testbench_generic_stimulus(std::fstream& fp, * 1. the enable signal *******************************************************************/ static -void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& fp, - const ConfigProtocol& config_protocol, - const ModuleManager& module_manager, - const ModuleId& top_module, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const FabricBitstream& fabric_bitstream, - const float& prog_clock_period, - const float& timescale) { +int print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& fp, + const ConfigProtocol& config_protocol, + const SimulationSetting& sim_settings, + const ModuleManager& module_manager, + const ModuleId& top_module, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const FabricBitstream& fabric_bitstream, + const float& prog_clock_period, + const float& timescale) { /* Validate the file stream */ valid_file_stream(fp); @@ -1140,11 +1144,11 @@ void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& f case CONFIG_MEM_SCAN_CHAIN: break; case CONFIG_MEM_QL_MEMORY_BANK: - print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(fp, - config_protocol, - module_manager,top_module, - fast_configuration, bit_value_to_skip, fabric_bitstream, - prog_clock_period, timescale); + return print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(fp, + config_protocol, sim_settings, + module_manager, top_module, + fast_configuration, bit_value_to_skip, fabric_bitstream, + prog_clock_period, timescale); break; case CONFIG_MEM_MEMORY_BANK: case CONFIG_MEM_FRAME_BASED: { @@ -1166,6 +1170,8 @@ void print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& f "Invalid SRAM organization type!\n"); exit(1); } + + return CMD_EXEC_SUCCESS; } /******************************************************************** @@ -1974,12 +1980,17 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, VERILOG_SIM_TIMESCALE); /* Generate stimuli for programming interface */ - print_verilog_top_testbench_configuration_protocol_stimulus(fp, - config_protocol, - module_manager, top_module, - fast_configuration, bit_value_to_skip, fabric_bitstream, - prog_clock_period, - VERILOG_SIM_TIMESCALE); + int status = CMD_EXEC_SUCCESS; + status = print_verilog_top_testbench_configuration_protocol_stimulus(fp, + config_protocol, simulation_parameters, + module_manager, top_module, + fast_configuration, bit_value_to_skip, fabric_bitstream, + prog_clock_period, + VERILOG_SIM_TIMESCALE); + + if (status == CMD_EXEC_FATAL_ERROR) { + return status; + } /* Identify the stimulus for global reset/set for programming purpose: * - If only reset port is seen we turn on Reset @@ -2124,7 +2135,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, /* Close the file stream */ fp.close(); - return 0; + return status; } diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 5482b0454..da48da8b8 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -11,7 +11,11 @@ #include "vtr_assert.h" #include "vtr_time.h" +/* Headers from openfpgashell library */ +#include "command_exit_codes.h" + /* Headers from openfpgautil library */ +#include "openfpga_scale.h" #include "openfpga_port.h" #include "openfpga_digest.h" @@ -279,15 +283,48 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator( fp << std::endl; } -void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp, - const ConfigProtocol& config_protocol, - const ModuleManager& module_manager, - const ModuleId& top_module, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const FabricBitstream& fabric_bitstream, - const float& prog_clock_period, - const float& timescale) { +/** + * @brief Update the clock period of shift register chain by considering the constraints from simulation settings + * - If the frequency is lower than the pre-computed bound, we should error out! Shift register chain cannot load the data completely + * - If the frequency is higher than the pre-computed bound, we use the contrained frequency + * @param sr_clock_port is the clock port which expect constraints + * @param sr_clock_period is the pre-constrained clock period. It is also the final clock period which will be return (if updated) + */ +static +int constrain_blwl_shift_register_clock_period_from_simulation_settings(const SimulationSetting& sim_settings, + const BasicPort& sr_clock_port, + const float& timescale, + float& sr_clock_period) { + for (const SimulationClockId& sim_clk : sim_settings.programming_shift_register_clocks()) { + /* Bypass all the clocks which does not match */ + if (sim_settings.clock_port(sim_clk) == sr_clock_port) { + if (sr_clock_period > 0.5 * (1 / sim_settings.clock_frequency(sim_clk)) / timescale) { + VTR_LOG_ERROR("Constrained clock frequency for BL shift registers is lower than the minimum requirement (%g %s[Hz])! Shift register chain cannot load data completely!\n", + 1. / (2. * sr_clock_period) / 1e6, + time_unit_to_string(1e6).c_str()); + return CMD_EXEC_FATAL_ERROR; + } else { + sr_clock_period = 0.5 * (1. / sim_settings.clock_frequency(sim_clk)) / timescale; + VTR_LOG("Will use constrained clock frequency (=%g %s[Hz]) for %s.\n", + sim_settings.clock_frequency(sim_clk) / 1e6, + time_unit_to_string(1e6).c_str(), + sr_clock_port.get_name().c_str()); + } + } + } + return CMD_EXEC_SUCCESS; +} + +int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp, + const ConfigProtocol& config_protocol, + const SimulationSetting& sim_settings, + const ModuleManager& module_manager, + const ModuleId& top_module, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const FabricBitstream& fabric_bitstream, + const float& prog_clock_period, + const float& timescale) { ModulePortId en_port_id = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); @@ -313,13 +350,38 @@ void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus( fast_configuration, bit_value_to_skip); - /* TODO: Consider auto-tuned clock period for now: + /* Compute the auto-tuned clock period first, this is the lower bound of the shift register clock periods: * - the BL/WL shift register clock only works in the second half of the programming clock period * - add 2 idle clocks to avoid racing between programming clock and shift register clocks at edge */ float bl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.bl_word_size() + 2) / timescale; float wl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.wl_word_size() + 2) / timescale; + VTR_LOG("Precomputed clock frequency (=%g %s[Hz]) for %s.\n", + 1. / (2. * bl_sr_clock_period) / 1e6, + time_unit_to_string(1e6).c_str(), + bl_sr_clock_port.get_name().c_str()); + + VTR_LOG("Precomputed clock frequency (=%g %s[Hz]) for %s.\n", + 1. / (2. * wl_sr_clock_period) / 1e6, + time_unit_to_string(1e6).c_str(), + wl_sr_clock_port.get_name().c_str()); + + + if (CMD_EXEC_FATAL_ERROR == constrain_blwl_shift_register_clock_period_from_simulation_settings(sim_settings, + bl_sr_clock_port, + timescale, + bl_sr_clock_period)) { + return CMD_EXEC_FATAL_ERROR; + } + + if (CMD_EXEC_FATAL_ERROR == constrain_blwl_shift_register_clock_period_from_simulation_settings(sim_settings, + wl_sr_clock_port, + timescale, + wl_sr_clock_period)) { + return CMD_EXEC_FATAL_ERROR; + } + if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { print_verilog_comment(fp, "----- BL Shift register clock generator -----"); print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, start_bl_sr_port, bl_sr_clock_port, bl_sr_clock_period); @@ -330,6 +392,8 @@ void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus( print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, start_wl_sr_port, wl_sr_clock_port, wl_sr_clock_period); } } + + return CMD_EXEC_SUCCESS; } /* Verilog codes to load bitstream from a bit file for memory bank using flatten BL/WLs */ diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h index d4ebf3264..e3a4edc7e 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h @@ -45,15 +45,16 @@ void print_verilog_top_testbench_global_shift_register_clock_ports_stimuli(std:: /** * @brief Generate the Verilog codes that generate stimuli waveforms for BL/WL protocols */ -void print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp, - const ConfigProtocol& config_protocol, - const ModuleManager& module_manager, - const ModuleId& top_module, - const bool& fast_configuration, - const bool& bit_value_to_skip, - const FabricBitstream& fabric_bitstream, - const float& prog_clock_period, - const float& timescale); +int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(std::fstream& fp, + const ConfigProtocol& config_protocol, + const SimulationSetting& sim_settings, + const ModuleManager& module_manager, + const ModuleId& top_module, + const bool& fast_configuration, + const bool& bit_value_to_skip, + const FabricBitstream& fabric_bitstream, + const float& prog_clock_period, + const float& timescale); /** * @brief Print stimulus for a FPGA fabric with a memory bank configuration protocol From fcb5470baa44694a058bb414d04b94b748baee47 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 6 Oct 2021 11:48:23 -0700 Subject: [PATCH 175/229] [Lib] Add validator to check if a clock is constrained in simulation settings --- libopenfpga/libarchopenfpga/src/simulation_setting.cpp | 4 ++++ libopenfpga/libarchopenfpga/src/simulation_setting.h | 2 ++ .../src/fpga_verilog/verilog_top_testbench_memory_bank.cpp | 3 +-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/simulation_setting.cpp b/libopenfpga/libarchopenfpga/src/simulation_setting.cpp index 92296fe8f..ebbc50fc6 100644 --- a/libopenfpga/libarchopenfpga/src/simulation_setting.cpp +++ b/libopenfpga/libarchopenfpga/src/simulation_setting.cpp @@ -328,5 +328,9 @@ bool SimulationSetting::valid_clock_id(const SimulationClockId& clock_id) const return ( size_t(clock_id) < clock_ids_.size() ) && ( clock_id == clock_ids_[clock_id] ); } +bool SimulationSetting::constrained_clock(const SimulationClockId& clock_id) const { + VTR_ASSERT(valid_clock_id(clock_id)); + return 0. != clock_frequencies_[clock_id]; +} } /* namespace openfpga ends */ diff --git a/libopenfpga/libarchopenfpga/src/simulation_setting.h b/libopenfpga/libarchopenfpga/src/simulation_setting.h index 5625acdea..532380b26 100644 --- a/libopenfpga/libarchopenfpga/src/simulation_setting.h +++ b/libopenfpga/libarchopenfpga/src/simulation_setting.h @@ -139,6 +139,8 @@ class SimulationSetting { public: /* Public Validators */ bool valid_signal_threshold(const float& threshold) const; bool valid_clock_id(const SimulationClockId& clock_id) const; + /** @brief Validate if a given clock is constrained or not */ + bool constrained_clock(const SimulationClockId& clock_id) const; private: /* Internal data */ /* Operating clock frequency: the default clock frequency to be applied to users' implemetation on FPGA * This will be stored in the x() part of vtr::Point diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index da48da8b8..718e1688a 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -297,7 +297,7 @@ int constrain_blwl_shift_register_clock_period_from_simulation_settings(const Si float& sr_clock_period) { for (const SimulationClockId& sim_clk : sim_settings.programming_shift_register_clocks()) { /* Bypass all the clocks which does not match */ - if (sim_settings.clock_port(sim_clk) == sr_clock_port) { + if (sim_settings.clock_port(sim_clk) == sr_clock_port && sim_settings.constrained_clock(sim_clk)) { if (sr_clock_period > 0.5 * (1 / sim_settings.clock_frequency(sim_clk)) / timescale) { VTR_LOG_ERROR("Constrained clock frequency for BL shift registers is lower than the minimum requirement (%g %s[Hz])! Shift register chain cannot load data completely!\n", 1. / (2. * sr_clock_period) / 1e6, @@ -367,7 +367,6 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s time_unit_to_string(1e6).c_str(), wl_sr_clock_port.get_name().c_str()); - if (CMD_EXEC_FATAL_ERROR == constrain_blwl_shift_register_clock_period_from_simulation_settings(sim_settings, bl_sr_clock_port, timescale, From bf473f50f8f618e97b84407c52dfd73d9a906e8a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 6 Oct 2021 11:55:57 -0700 Subject: [PATCH 176/229] [FPGA-Verilog] Correct bugs in logging clock frequencies --- .../libopenfpgautil/src/openfpga_scale.cpp | 4 ++-- .../libopenfpgautil/src/openfpga_scale.h | 2 +- .../verilog_top_testbench_memory_bank.cpp | 22 +++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libopenfpga/libopenfpgautil/src/openfpga_scale.cpp b/libopenfpga/libopenfpgautil/src/openfpga_scale.cpp index 66364501d..222d1c41b 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_scale.cpp +++ b/libopenfpga/libopenfpgautil/src/openfpga_scale.cpp @@ -84,7 +84,7 @@ std::string unit_to_string(const float& unit) { * Convert numeric time unit to string * e.g. 1e-12 -> ps *******************************************************************/ -std::string time_unit_to_string(const float& unit) { +std::string time_unit_to_string(const float& unit, const std::string& postfix) { /* For larger than 1 unit, we do not accept */ if (1e6 < unit) { VTR_LOGF_ERROR(__FILE__, __LINE__, @@ -93,7 +93,7 @@ std::string time_unit_to_string(const float& unit) { exit(1); } - return unit_to_string(unit) + std::string("s"); + return unit_to_string(unit) + postfix; } /******************************************************************** diff --git a/libopenfpga/libopenfpgautil/src/openfpga_scale.h b/libopenfpga/libopenfpgautil/src/openfpga_scale.h index 197923548..f10abcca6 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_scale.h +++ b/libopenfpga/libopenfpgautil/src/openfpga_scale.h @@ -18,7 +18,7 @@ bool same_float_number(const float& a, std::string unit_to_string(const float& unit); -std::string time_unit_to_string(const float& unit); +std::string time_unit_to_string(const float& unit, const std::string& postfix = "s"); float string_to_unit(const std::string& scale); diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 718e1688a..12fc89139 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -299,15 +299,15 @@ int constrain_blwl_shift_register_clock_period_from_simulation_settings(const Si /* Bypass all the clocks which does not match */ if (sim_settings.clock_port(sim_clk) == sr_clock_port && sim_settings.constrained_clock(sim_clk)) { if (sr_clock_period > 0.5 * (1 / sim_settings.clock_frequency(sim_clk)) / timescale) { - VTR_LOG_ERROR("Constrained clock frequency for BL shift registers is lower than the minimum requirement (%g %s[Hz])! Shift register chain cannot load data completely!\n", - 1. / (2. * sr_clock_period) / 1e6, - time_unit_to_string(1e6).c_str()); + VTR_LOG_ERROR("Constrained clock frequency for BL shift registers is lower than the minimum requirement (%g %s)! Shift register chain cannot load data completely!\n", + 1. / (2. * sr_clock_period * timescale) / 1e6, + time_unit_to_string(1e6, "Hz").c_str()); return CMD_EXEC_FATAL_ERROR; } else { sr_clock_period = 0.5 * (1. / sim_settings.clock_frequency(sim_clk)) / timescale; - VTR_LOG("Will use constrained clock frequency (=%g %s[Hz]) for %s.\n", + VTR_LOG("Will use constrained clock frequency (=%g %s) for %s.\n", sim_settings.clock_frequency(sim_clk) / 1e6, - time_unit_to_string(1e6).c_str(), + time_unit_to_string(1e6, "Hz").c_str(), sr_clock_port.get_name().c_str()); } } @@ -357,14 +357,14 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s float bl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.bl_word_size() + 2) / timescale; float wl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.wl_word_size() + 2) / timescale; - VTR_LOG("Precomputed clock frequency (=%g %s[Hz]) for %s.\n", - 1. / (2. * bl_sr_clock_period) / 1e6, - time_unit_to_string(1e6).c_str(), + VTR_LOG("Precomputed clock frequency (=%g %s) for %s.\n", + 1. / (2. * bl_sr_clock_period * timescale) / 1e6, + time_unit_to_string(1e6, "Hz").c_str(), bl_sr_clock_port.get_name().c_str()); - VTR_LOG("Precomputed clock frequency (=%g %s[Hz]) for %s.\n", - 1. / (2. * wl_sr_clock_period) / 1e6, - time_unit_to_string(1e6).c_str(), + VTR_LOG("Precomputed clock frequency (=%g %s) for %s.\n", + 1. / (2. * wl_sr_clock_period * timescale) / 1e6, + time_unit_to_string(1e6, "Hz").c_str(), wl_sr_clock_port.get_name().c_str()); if (CMD_EXEC_FATAL_ERROR == constrain_blwl_shift_register_clock_period_from_simulation_settings(sim_settings, From 169bb5fa45f5aacfaa4ed55c3c01fd66df4eda21 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 6 Oct 2021 11:58:50 -0700 Subject: [PATCH 177/229] [Script] Add an example simulation setting file with a fixed clock frequency for shift registers --- .../fixed_shift_register_sim_openfpga.xml | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 openfpga_flow/openfpga_simulation_settings/fixed_shift_register_sim_openfpga.xml diff --git a/openfpga_flow/openfpga_simulation_settings/fixed_shift_register_sim_openfpga.xml b/openfpga_flow/openfpga_simulation_settings/fixed_shift_register_sim_openfpga.xml new file mode 100644 index 000000000..740e00a1c --- /dev/null +++ b/openfpga_flow/openfpga_simulation_settings/fixed_shift_register_sim_openfpga.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From b98a8ec71829d341c3d3c02eed95961f304b95f3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 6 Oct 2021 12:09:26 -0700 Subject: [PATCH 178/229] [Test] Added the dedicated test case for fixed shift register clock frequency --- .../config/task.conf | 0 .../config/task.conf | 45 +++++++++++++++++++ 2 files changed, 45 insertions(+) rename openfpga_flow/tasks/basic_tests/fixed_simulation_settings/{ => fixed_operating_clock_freq}/config/task.conf (100%) create mode 100644 openfpga_flow/tasks/basic_tests/fixed_simulation_settings/fixed_shift_register_clock_freq/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/fixed_simulation_settings/config/task.conf b/openfpga_flow/tasks/basic_tests/fixed_simulation_settings/fixed_operating_clock_freq/config/task.conf similarity index 100% rename from openfpga_flow/tasks/basic_tests/fixed_simulation_settings/config/task.conf rename to openfpga_flow/tasks/basic_tests/fixed_simulation_settings/fixed_operating_clock_freq/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/fixed_simulation_settings/fixed_shift_register_clock_freq/config/task.conf b/openfpga_flow/tasks/basic_tests/fixed_simulation_settings/fixed_shift_register_clock_freq/config/task.conf new file mode 100644 index 000000000..2e4a821ec --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/fixed_simulation_settings/fixed_shift_register_clock_freq/config/task.conf @@ -0,0 +1,45 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +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/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_shift_register_sim_openfpga.xml + +openfpga_vpr_device_layout= +openfpga_fast_configuration= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +bench1_top = or2 +bench1_chan_width = 300 + +bench2_top = and2_latch +bench2_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 554018449eae53fb8cefd37c0bd4f1006cab0035 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 6 Oct 2021 12:10:37 -0700 Subject: [PATCH 179/229] [Test] Update regression test script --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index c593994d8..5381920fe 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -83,7 +83,8 @@ echo -e "Testing separated Verilog fabric netlists and testbench locations"; run-task basic_tests/custom_fabric_netlist_location --debug --show_thread_logs echo -e "Testing user-defined simulation settings: clock frequency and number of cycles"; -run-task basic_tests/fixed_simulation_settings --debug --show_thread_logs +run-task basic_tests/fixed_simulation_settings/fixed_operating_clock_freq --debug --show_thread_logs +run-task basic_tests/fixed_simulation_settings/fixed_shift_register_clock_freq --debug --show_thread_logs echo -e "Testing Secured FPGA fabrics"; run-task basic_tests/fabric_key/generate_vanilla_key --debug --show_thread_logs From a1eaacf5a81b905f4e0198739dea106f99751b3c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 6 Oct 2021 12:12:15 -0700 Subject: [PATCH 180/229] [Test] Reduce the number of benchmarks in the test for fixed shift register clock frequency --- .../fixed_shift_register_clock_freq/config/task.conf | 9 --------- 1 file changed, 9 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/fixed_simulation_settings/fixed_shift_register_clock_freq/config/task.conf b/openfpga_flow/tasks/basic_tests/fixed_simulation_settings/fixed_shift_register_clock_freq/config/task.conf index 2e4a821ec..7a75ee299 100644 --- a/openfpga_flow/tasks/basic_tests/fixed_simulation_settings/fixed_shift_register_clock_freq/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/fixed_simulation_settings/fixed_shift_register_clock_freq/config/task.conf @@ -28,18 +28,9 @@ arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml [BENCHMARKS] bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v -bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v -bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v [SYNTHESIS_PARAM] bench0_top = and2 -bench0_chan_width = 300 - -bench1_top = or2 -bench1_chan_width = 300 - -bench2_top = and2_latch -bench2_chan_width = 300 [SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] end_flow_with_test= From dc5aedc39327dddcd247ffa91ad369be5a13b220 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 6 Oct 2021 13:36:35 -0700 Subject: [PATCH 181/229] [Script] Correct naming for clocks in shifter register chain defined in simulation setting files --- .../fixed_shift_register_sim_openfpga.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/openfpga_simulation_settings/fixed_shift_register_sim_openfpga.xml b/openfpga_flow/openfpga_simulation_settings/fixed_shift_register_sim_openfpga.xml index 740e00a1c..a3b5b88de 100644 --- a/openfpga_flow/openfpga_simulation_settings/fixed_shift_register_sim_openfpga.xml +++ b/openfpga_flow/openfpga_simulation_settings/fixed_shift_register_sim_openfpga.xml @@ -8,8 +8,8 @@ - - + + From 27153bbc899cba16d92ecdd5e735e828b569b13c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 6 Oct 2021 13:38:51 -0700 Subject: [PATCH 182/229] [FPGA-Verilog] Bug fix in matching shift register clocks between verilog ports and simulation setting definition --- .../src/fpga_verilog/verilog_top_testbench_memory_bank.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 12fc89139..9f12362b5 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -297,7 +297,7 @@ int constrain_blwl_shift_register_clock_period_from_simulation_settings(const Si float& sr_clock_period) { for (const SimulationClockId& sim_clk : sim_settings.programming_shift_register_clocks()) { /* Bypass all the clocks which does not match */ - if (sim_settings.clock_port(sim_clk) == sr_clock_port && sim_settings.constrained_clock(sim_clk)) { + if (sim_settings.clock_name(sim_clk) == sr_clock_port.get_name() && sim_settings.constrained_clock(sim_clk)) { if (sr_clock_period > 0.5 * (1 / sim_settings.clock_frequency(sim_clk)) / timescale) { VTR_LOG_ERROR("Constrained clock frequency for BL shift registers is lower than the minimum requirement (%g %s)! Shift register chain cannot load data completely!\n", 1. / (2. * sr_clock_period * timescale) / 1e6, @@ -310,6 +310,7 @@ int constrain_blwl_shift_register_clock_period_from_simulation_settings(const Si time_unit_to_string(1e6, "Hz").c_str(), sr_clock_port.get_name().c_str()); } + break; } } return CMD_EXEC_SUCCESS; From 40b589dc6d843539eaa91061c898a4b90fe71ddd Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 6 Oct 2021 13:50:33 -0700 Subject: [PATCH 183/229] [Doc] Update documentation about the clock definition for programming clocks in simulation settings --- .../manual/arch_lang/simulation_setting.rst | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/docs/source/manual/arch_lang/simulation_setting.rst b/docs/source/manual/arch_lang/simulation_setting.rst index 32c5a3ebf..d480f4160 100644 --- a/docs/source/manual/arch_lang/simulation_setting.rst +++ b/docs/source/manual/arch_lang/simulation_setting.rst @@ -14,7 +14,10 @@ General organization is as follows ... - + + + ... + @@ -61,7 +64,10 @@ We should the full syntax in the code block below and then provide details on ea ... - + + + ... + Operating clock setting @@ -121,6 +127,22 @@ Programming clocks are defined under the XML node ```` Specify the frequency of the programming clock using an absolute value in the unit of ``[Hz]`` This frequency is used in testbenches for programming phase simulation. +.. option:: + +- ``name="`` + Specify a unique name for a clock signal. The name should match a reserved word of programming clock, i.e., ``bl_sr_clock`` and ``wl_sr_clock``. + + .. note:: The ``bl_sr_clock`` represents the clock signal driving the BL shift register chains, while the ``wl_sr_clock`` represents the clock signal driving the WL shift register chains + +- ``port="`` + Specify the clock port which the clock signal should be applied to. The clock port must be a valid clock port defined in OpenFPGA architecture description. Explicit index is required, e.g., ``clk[1:1]``. Otherwise, default index ``0`` will be considered, e.g., ``clk`` will be translated as ``clk[0:0]``. + +- ``frequency="auto|`` + Specify frequency of a clock signal in the unit of ``[Hz]``. If ``auto`` is used, the programming clock frequency will be inferred by OpenFPGA. + +- ``is_shift_register="`` + Specify if this clock signal is used to drive shift register chains in BL/WL protocols + .. note:: Programming clock frequency is typically much slower than the operating clock and strongly depends on the process technology. Suggest to characterize the speed of your configuration protocols before specifying a value! Simulator Option From 8aa2647878601bb43aa70f1e7ebd2360b81e9e15 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 6 Oct 2021 16:49:01 -0700 Subject: [PATCH 184/229] [Script] Bug fix in slow clock frequency in shift register chain contraints --- .../fixed_shift_register_sim_openfpga.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/openfpga_simulation_settings/fixed_shift_register_sim_openfpga.xml b/openfpga_flow/openfpga_simulation_settings/fixed_shift_register_sim_openfpga.xml index a3b5b88de..0687db6cf 100644 --- a/openfpga_flow/openfpga_simulation_settings/fixed_shift_register_sim_openfpga.xml +++ b/openfpga_flow/openfpga_simulation_settings/fixed_shift_register_sim_openfpga.xml @@ -7,7 +7,7 @@ - + From 54a8809b3c633b87411380c076c276d19c12e7ee Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 6 Oct 2021 16:49:28 -0700 Subject: [PATCH 185/229] [FPGA-Verilog] Bug fix in computing clock frequency for shift register chains --- .../src/fpga_verilog/verilog_top_testbench_memory_bank.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 9f12362b5..c933cc939 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -298,8 +298,10 @@ int constrain_blwl_shift_register_clock_period_from_simulation_settings(const Si for (const SimulationClockId& sim_clk : sim_settings.programming_shift_register_clocks()) { /* Bypass all the clocks which does not match */ if (sim_settings.clock_name(sim_clk) == sr_clock_port.get_name() && sim_settings.constrained_clock(sim_clk)) { - if (sr_clock_period > 0.5 * (1 / sim_settings.clock_frequency(sim_clk)) / timescale) { - VTR_LOG_ERROR("Constrained clock frequency for BL shift registers is lower than the minimum requirement (%g %s)! Shift register chain cannot load data completely!\n", + if (1. / (2. * sr_clock_period * timescale) > sim_settings.clock_frequency(sim_clk)) { + VTR_LOG_ERROR("Constrained clock frequency (=%g %s) for BL shift registers is lower than the minimum requirement (=%g %s)! Shift register chain cannot load data completely!\n", + sim_settings.clock_frequency(sim_clk) / 1e6, + time_unit_to_string(1e6, "Hz").c_str(), 1. / (2. * sr_clock_period * timescale) / 1e6, time_unit_to_string(1e6, "Hz").c_str()); return CMD_EXEC_FATAL_ERROR; From 9693a269eea1ecd4e1a5ab290bbf910360241bd2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 7 Oct 2021 11:31:16 -0700 Subject: [PATCH 186/229] [FPGA-Bitstream] Now dont' care bits are truelly seen in single-chain and flatten QuickLogic memory bank --- .../libopenfpgautil/src/openfpga_decode.cpp | 19 ++++++++++++---- .../libopenfpgautil/src/openfpga_decode.h | 22 ++++++++++++++----- .../build_fabric_bitstream_memory_bank.cpp | 2 +- .../write_text_fabric_bitstream.cpp | 4 ++-- openfpga/src/utils/fabric_bitstream_utils.cpp | 17 +++++++------- 5 files changed, 44 insertions(+), 20 deletions(-) diff --git a/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp b/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp index 2961f423b..bc45e9682 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp +++ b/libopenfpga/libopenfpgautil/src/openfpga_decode.cpp @@ -65,12 +65,13 @@ std::vector ito1hot_vec(const size_t& in_int, * ********************************************************************/ std::vector ito1hot_charvec(const size_t& in_int, - const size_t& bin_len) { + const size_t& bin_len, + const char& default_bit) { /* Make sure we do not have any overflow! */ VTR_ASSERT ( (in_int <= bin_len) ); /* Initialize */ - std::vector ret(bin_len, '0'); + std::vector ret(bin_len, default_bit); if (bin_len == in_int) { return ret; /* all zero case */ @@ -80,13 +81,23 @@ std::vector ito1hot_charvec(const size_t& in_int, return ret; } +void replace_str_bits(std::string& str_to_convert, + const char& bit_in_place, + const char& bit_to_replace) { + for (char& bit : str_to_convert) { + if (bit_in_place == bit) { + bit = bit_to_replace; + } + } +} + std::string combine_two_1hot_str(const std::string& code1, const std::string& code2) { VTR_ASSERT(code1.length() == code2.length()); std::string ret = code1; for (size_t ichar = 0; ichar < code2.length(); ichar++) { - VTR_ASSERT('0' == code2[ichar] || '1' == code2[ichar]); - if ('1' == code2[ichar]) { + VTR_ASSERT('0' == code2[ichar] || '1' == code2[ichar] || 'x' == code2[ichar]); + if ('1' == code2[ichar] || '0' == code2[ichar]) { ret[ichar] = code2[ichar]; } } diff --git a/libopenfpga/libopenfpgautil/src/openfpga_decode.h b/libopenfpga/libopenfpgautil/src/openfpga_decode.h index 4798af856..92dcf0667 100644 --- a/libopenfpga/libopenfpgautil/src/openfpga_decode.h +++ b/libopenfpga/libopenfpgautil/src/openfpga_decode.h @@ -23,15 +23,27 @@ std::vector ito1hot_vec(const size_t& in_int, const size_t& bin_len); std::vector ito1hot_charvec(const size_t& in_int, - const size_t& bin_len); + const size_t& bin_len, + const char& default_bit = '0'); + +/** @brief Replace the characters in a string with a given replacement + * @param str_to_convert the input and output string + * @param bit_in_place the charater to be replaced + * @param bit_to_replace the charater to replace the bit_in_place + */ +void replace_str_bits(std::string& str_to_convert, + const char& bit_in_place, + const char& bit_to_replace); /******************************************************************** * @brief Combine to two 1-hot codes which are in string format - * Any unique '1' will be merged + * Any unique '1' or '0' will be merged + * @note Where there are both '0' or '1' in the code1 and code2, + * code2 bits will overwrite * For example: - * Code 1: 001000110 - * Code 2: 010001001 - * Output: 011001111 + * Code 1: xx1x0x110 + * Code 2: 01xx01xx1 + * Output: 011x01111 * @note This function requires two codes in the same length ********************************************************************/ std::string combine_two_1hot_str(const std::string& code1, diff --git a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp index 7742b9bf9..96833b984 100644 --- a/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp +++ b/openfpga/src/fpga_bitstream/build_fabric_bitstream_memory_bank.cpp @@ -183,7 +183,7 @@ void rec_build_module_fabric_dependent_ql_memory_bank_regional_bitstream(const B bl_addr_bits_vec = itobin_charvec(cur_bl_index, bl_addr_size); } else if (BLWL_PROTOCOL_FLATTEN == config_protocol.bl_protocol_type() || BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { - bl_addr_bits_vec = ito1hot_charvec(cur_bl_index, bl_addr_size); + bl_addr_bits_vec = ito1hot_charvec(cur_bl_index, bl_addr_size, DONT_CARE_CHAR); } /* Find WL address */ diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 110cbdb34..51be3783a 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -419,8 +419,8 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage * - If BL uses decoders, we have to config each memory cell one by one. * - If BL uses flatten, we can configure all the memory cells on the same row by enabling dedicated WL * In such case, we will merge the BL data under the same WL address - * Fast configuration is NOT applicable in this case - * - if BL uses shift-register, TODO + * Fast configuration is applicable when a row of BLs are all zeros/ones while we have a global reset/set for all the memory cells + * - if BL uses shift-register, same as the flatten. */ if (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) { status = write_memory_bank_fabric_bitstream_to_text_file(fp, diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 814666c9b..a4f676b81 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -236,14 +236,14 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons const bool& fast_configuration, const bool& bit_value_to_skip, const char& dont_care_bit) { - /* If fast configuration is not enabled, we need all the wl address even some of them have all-zero BLs */ + /* If fast configuration is not enabled, we need all the wl address even some of them have all-dont-care-bits BLs */ if (!fast_configuration) { vtr::vector> fabric_bits_per_region; fabric_bits_per_region.resize(fabric_bitstream.num_regions()); for (const FabricBitRegionId& region : fabric_bitstream.regions()) { for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { - /* Create string for BL address */ - std::string bl_addr_str(fabric_bitstream.bit_bl_address(bit_id).size(), bit_value_to_skip); + /* Create string for BL address with complete don't care bits */ + std::string bl_addr_str(fabric_bitstream.bit_bl_address(bit_id).size(), dont_care_bit); /* Create string for WL address */ std::string wl_addr_str; @@ -262,16 +262,17 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons fabric_bits_per_region.resize(fabric_bitstream.num_regions()); for (const FabricBitRegionId& region : fabric_bitstream.regions()) { for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) { - /* Skip din because they should be pre-configured through programming reset/set */ - if (fabric_bitstream.bit_din(bit_id) == bit_value_to_skip) { - continue; - } /* Create string for BL address */ std::string bl_addr_str; for (const char& addr_bit : fabric_bitstream.bit_bl_address(bit_id)) { bl_addr_str.push_back(addr_bit); } + /* If this bit should be programmed to 0, convert the 1s in BL to 0s */ + if (fabric_bitstream.bit_din(bit_id) == bit_value_to_skip) { + replace_str_bits(bl_addr_str, '1', '0'); + } + /* Create string for WL address */ std::string wl_addr_str; for (const char& addr_bit : fabric_bitstream.bit_wl_address(bit_id)) { @@ -284,7 +285,7 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons fabric_bits_per_region[region][wl_addr_str] = bl_addr_str; } else { VTR_ASSERT_SAFE(result != fabric_bits_per_region[region].end()); - result->second = combine_two_1hot_str(bl_addr_str, result->second); + result->second = combine_two_1hot_str(result->second, bl_addr_str); } } } From a15798a4e1891f44ea305617f3230e9c862e7dc8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 7 Oct 2021 14:42:21 -0700 Subject: [PATCH 187/229] [Lib] Upgrade fabric key data structure to support shift register bank definitions --- libopenfpga/libfabrickey/src/fabric_key.cpp | 70 +++++++++++++++++++ libopenfpga/libfabrickey/src/fabric_key.h | 43 ++++++++++++ libopenfpga/libfabrickey/src/fabric_key_fwd.h | 4 ++ 3 files changed, 117 insertions(+) diff --git a/libopenfpga/libfabrickey/src/fabric_key.cpp b/libopenfpga/libfabrickey/src/fabric_key.cpp index d15c86e56..bd61a3103 100644 --- a/libopenfpga/libfabrickey/src/fabric_key.cpp +++ b/libopenfpga/libfabrickey/src/fabric_key.cpp @@ -27,6 +27,16 @@ FabricKey::fabric_region_range FabricKey::regions() const { return vtr::make_range(region_ids_.begin(), region_ids_.end()); } +FabricKey::fabric_bit_line_bank_range FabricKey::bl_banks(const FabricRegionId& region_id) const { + VTR_ASSERT(valid_region_id(region_id)); + return vtr::make_range(bl_bank_ids_[region_id].begin(), bl_bank_ids_[region_id].end()); +} + +FabricKey::fabric_word_line_bank_range FabricKey::wl_banks(const FabricRegionId& region_id) const { + VTR_ASSERT(valid_region_id(region_id)); + return vtr::make_range(wl_bank_ids_[region_id].begin(), wl_bank_ids_[region_id].end()); +} + /************************************************************************ * Public Accessors : Basic data query ***********************************************************************/ @@ -64,6 +74,16 @@ bool FabricKey::empty() const { return 0 == key_ids_.size(); } +std::vector FabricKey::bl_bank_data_ports(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const { + VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); + return bl_bank_data_ports_[region_id][bank_id]; +} + +std::vector FabricKey::wl_bank_data_ports(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const { + VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); + return wl_bank_data_ports_[region_id][bank_id]; +} + /************************************************************************ * Public Mutators ***********************************************************************/ @@ -178,6 +198,42 @@ void FabricKey::set_key_coordinate(const FabricKeyId& key_id, key_coordinates_[key_id] = coord; } +FabricBitLineBankId FabricKey::create_bl_shift_register_bank(const FabricRegionId& region_id) { + VTR_ASSERT(valid_region_id(region_id)); + + /* Create a new id */ + FabricBitLineBankId bank = FabricBitLineBankId(bl_bank_ids_[region_id].size()); + bl_bank_ids_[region_id].push_back(bank); + bl_bank_data_ports_[region_id].emplace_back(); + + return bank; +} + +void FabricKey::add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id, + const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port) { + VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); + bl_bank_data_ports_[region_id][bank_id].push_back(data_port); +} + +FabricWordLineBankId FabricKey::create_wl_shift_register_bank(const FabricRegionId& region_id) { + VTR_ASSERT(valid_region_id(region_id)); + + /* Create a new id */ + FabricWordLineBankId bank = FabricWordLineBankId(wl_bank_ids_[region_id].size()); + wl_bank_ids_[region_id].push_back(bank); + wl_bank_data_ports_[region_id].emplace_back(); + + return bank; +} + +void FabricKey::add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id, + const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port) { + VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); + wl_bank_data_ports_[region_id][bank_id].push_back(data_port); +} + /************************************************************************ * Internal invalidators/validators ***********************************************************************/ @@ -193,3 +249,17 @@ bool FabricKey::valid_key_id(const FabricKeyId& key_id) const { bool FabricKey::valid_key_coordinate(const vtr::Point& coord) const { return coord.x() > -1 && coord.y() > -1; } + +bool FabricKey::valid_bl_bank_id(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const { + if (!valid_region_id(region_id)) { + return false; + } + return ( size_t(bank_id) < bl_bank_ids_[region_id].size() ) && ( bank_id == bl_bank_ids_[region_id][bank_id] ); +} + +bool FabricKey::valid_wl_bank_id(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const { + if (!valid_region_id(region_id)) { + return false; + } + return ( size_t(bank_id) < wl_bank_ids_[region_id].size() ) && ( bank_id == wl_bank_ids_[region_id][bank_id] ); +} diff --git a/libopenfpga/libfabrickey/src/fabric_key.h b/libopenfpga/libfabrickey/src/fabric_key.h index 6e9025f9e..2ce6db061 100644 --- a/libopenfpga/libfabrickey/src/fabric_key.h +++ b/libopenfpga/libfabrickey/src/fabric_key.h @@ -12,6 +12,9 @@ #include "vtr_vector.h" #include "vtr_geometry.h" +/* Headers from openfpgautil library */ +#include "openfpga_port.h" + #include "fabric_key_fwd.h" /******************************************************************** @@ -38,14 +41,20 @@ class FabricKey { public: /* Types */ typedef vtr::vector::const_iterator fabric_key_iterator; typedef vtr::vector::const_iterator fabric_region_iterator; + typedef vtr::vector::const_iterator fabric_bit_line_bank_iterator; + typedef vtr::vector::const_iterator fabric_word_line_bank_iterator; /* Create range */ typedef vtr::Range fabric_region_range; typedef vtr::Range fabric_key_range; + typedef vtr::Range fabric_bit_line_bank_range; + typedef vtr::Range fabric_word_line_bank_range; public: /* Constructors */ FabricKey(); public: /* Accessors: aggregates */ fabric_key_range keys() const; fabric_region_range regions() const; + fabric_bit_line_bank_range bl_banks(const FabricRegionId& region_id) const; + fabric_word_line_bank_range wl_banks(const FabricRegionId& region_id) const; public: /* Public Accessors: Basic data query */ /* Access all the keys of a region */ std::vector region_keys(const FabricRegionId& region_id) const; @@ -65,6 +74,12 @@ class FabricKey { /* Check if there are any keys */ bool empty() const; + /* Return a list of data ports which will be driven by a BL shift register bank */ + std::vector bl_bank_data_ports(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const; + + /* Return a list of data ports which will be driven by a WL shift register bank */ + std::vector wl_bank_data_ports(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const; + public: /* Public Mutators: model-related */ /* Reserve a number of regions to be memory efficent */ @@ -100,11 +115,29 @@ class FabricKey { void set_key_coordinate(const FabricKeyId& key_id, const vtr::Point& coord); + /* Create a new shift register bank for BLs and return an id */ + FabricBitLineBankId create_bl_shift_register_bank(const FabricRegionId& region_id); + + /* Add a data port to a given BL shift register bank */ + void add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id, + const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port); + + /* Create a new shift register bank for WLs and return an id */ + FabricWordLineBankId create_wl_shift_register_bank(const FabricRegionId& region_id); + + /* Add a data port to a given WL shift register bank */ + void add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id, + const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port); + public: /* Public invalidators/validators */ bool valid_region_id(const FabricRegionId& region_id) const; bool valid_key_id(const FabricKeyId& key_id) const; /* Identify if key coordinate is acceptable to fabric key convention */ bool valid_key_coordinate(const vtr::Point& coord) const; + bool valid_bl_bank_id(const FabricRegionId& region_id, const FabricBitLineBankId& bank_id) const; + bool valid_wl_bank_id(const FabricRegionId& region_id, const FabricWordLineBankId& bank_id) const; private: /* Internal data */ /* Unique ids for each region */ vtr::vector region_ids_; @@ -129,6 +162,16 @@ class FabricKey { /* Optional alias for each key, with which a key can also be represented */ vtr::vector key_alias_; + + /* Unique ids for each BL shift register bank */ + vtr::vector> bl_bank_ids_; + /* Data ports to be connected to each BL shift register bank */ + vtr::vector>> bl_bank_data_ports_; + + /* Unique ids for each WL shift register bank */ + vtr::vector> wl_bank_ids_; + /* Data ports to be connected to each WL shift register bank */ + vtr::vector>> wl_bank_data_ports_; }; #endif diff --git a/libopenfpga/libfabrickey/src/fabric_key_fwd.h b/libopenfpga/libfabrickey/src/fabric_key_fwd.h index 249093fd2..7309daa23 100644 --- a/libopenfpga/libfabrickey/src/fabric_key_fwd.h +++ b/libopenfpga/libfabrickey/src/fabric_key_fwd.h @@ -14,9 +14,13 @@ struct fabric_region_id_tag; struct fabric_key_id_tag; +struct fabric_bit_line_bank_id_tag; +struct fabric_word_line_bank_id_tag; typedef vtr::StrongId FabricRegionId; typedef vtr::StrongId FabricKeyId; +typedef vtr::StrongId FabricBitLineBankId; +typedef vtr::StrongId FabricWordLineBankId; /* Short declaration of class */ class FabricKey; From eddafb42c83e3e8134017331094551776f3a852f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 7 Oct 2021 15:38:42 -0700 Subject: [PATCH 188/229] [Lib] Upgrade parser for fabric key to support shift register banks --- libopenfpga/libfabrickey/src/fabric_key.cpp | 12 ++ libopenfpga/libfabrickey/src/fabric_key.h | 4 + .../libfabrickey/src/read_xml_fabric_key.cpp | 139 ++++++++++++++++-- 3 files changed, 144 insertions(+), 11 deletions(-) diff --git a/libopenfpga/libfabrickey/src/fabric_key.cpp b/libopenfpga/libfabrickey/src/fabric_key.cpp index bd61a3103..f17f3deaa 100644 --- a/libopenfpga/libfabrickey/src/fabric_key.cpp +++ b/libopenfpga/libfabrickey/src/fabric_key.cpp @@ -198,6 +198,18 @@ void FabricKey::set_key_coordinate(const FabricKeyId& key_id, key_coordinates_[key_id] = coord; } +void FabricKey::reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) { + VTR_ASSERT(valid_region_id(region_id)); + bl_bank_ids_[region_id].reserve(num_banks); + bl_bank_data_ports_[region_id].reserve(num_banks); +} + +void FabricKey::reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) { + VTR_ASSERT(valid_region_id(region_id)); + wl_bank_ids_[region_id].reserve(num_banks); + wl_bank_data_ports_[region_id].reserve(num_banks); +} + FabricBitLineBankId FabricKey::create_bl_shift_register_bank(const FabricRegionId& region_id) { VTR_ASSERT(valid_region_id(region_id)); diff --git a/libopenfpga/libfabrickey/src/fabric_key.h b/libopenfpga/libfabrickey/src/fabric_key.h index 2ce6db061..45569f269 100644 --- a/libopenfpga/libfabrickey/src/fabric_key.h +++ b/libopenfpga/libfabrickey/src/fabric_key.h @@ -115,6 +115,10 @@ class FabricKey { void set_key_coordinate(const FabricKeyId& key_id, const vtr::Point& coord); + /* Reserve a number of banks to be memory efficent */ + void reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks); + void reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks); + /* Create a new shift register bank for BLs and return an id */ FabricBitLineBankId create_bl_shift_register_bank(const FabricRegionId& region_id); diff --git a/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp b/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp index 1c42b07bb..15fc61fe1 100644 --- a/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp +++ b/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp @@ -13,6 +13,10 @@ #include "vtr_assert.h" #include "vtr_time.h" +/* Headers from openfpga util library */ +#include "openfpga_tokenizer.h" +#include "openfpga_port_parser.h" + /* Headers from libarchfpga */ #include "arch_error.h" #include "read_xml_util.h" @@ -70,6 +74,114 @@ void read_xml_region_key(pugi::xml_node& xml_component_key, } } +/******************************************************************** + * Parse XML codes of a under to an object of FabricKey + *******************************************************************/ +static +void read_xml_region_bl_shift_register_bank(pugi::xml_node& xml_bank, + const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, + const FabricRegionId& fabric_region) { + /* Find the id of the bank */ + FabricBitLineBankId bank_id = FabricBitLineBankId(get_attribute(xml_bank, "id", loc_data).as_int()); + + if (!fabric_key.valid_bl_bank_id(fabric_region, bank_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bank), + "Invalid 'id' attribute '%lu' (in total %lu BL banks)!\n", + size_t(bank_id), + fabric_key.bl_banks(fabric_region).size()); + } + + VTR_ASSERT_SAFE(true == fabric_key.valid_bl_bank_id(fabric_region, bank_id)); + + /* Parse the ports */ + std::string data_ports = get_attribute(xml_bank, "range", loc_data).as_string(); + /* Split with ',' if we have multiple ports */ + openfpga::StringToken tokenizer(data_ports); + for (const std::string& data_port : tokenizer.split(',')) { + openfpga::PortParser data_port_parser(data_port); + fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, bank_id, data_port_parser.port()); + } +} + +/******************************************************************** + * Parse XML codes of a to an object of FabricKey + *******************************************************************/ +static +void read_xml_region_bl_shift_register_banks(pugi::xml_node& xml_bl_bank, + const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, + const FabricRegionId& fabric_region) { + size_t num_banks = count_children(xml_bl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL); + fabric_key.reserve_bl_shift_register_banks(fabric_region, num_banks); + + for (size_t ibank = 0; ibank < num_banks; ++ibank) { + fabric_key.create_bl_shift_register_bank(fabric_region); + } + + for (pugi::xml_node xml_bank : xml_bl_bank.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_bank.name() != std::string("bank")) { + bad_tag(xml_bank, loc_data, xml_bl_bank, {"bank"}); + } + read_xml_region_bl_shift_register_bank(xml_bank, loc_data, fabric_key, fabric_region); + } +} + +/******************************************************************** + * Parse XML codes of a under to an object of FabricKey + *******************************************************************/ +static +void read_xml_region_wl_shift_register_bank(pugi::xml_node& xml_bank, + const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, + const FabricRegionId& fabric_region) { + /* Find the id of the bank */ + FabricWordLineBankId bank_id = FabricWordLineBankId(get_attribute(xml_bank, "id", loc_data).as_int()); + + if (!fabric_key.valid_wl_bank_id(fabric_region, bank_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bank), + "Invalid 'id' attribute '%lu' (in total %lu WL banks)!\n", + size_t(bank_id), + fabric_key.wl_banks(fabric_region).size()); + } + + VTR_ASSERT_SAFE(true == fabric_key.valid_wl_bank_id(fabric_region, bank_id)); + + /* Parse the ports */ + std::string data_ports = get_attribute(xml_bank, "range", loc_data).as_string(); + /* Split with ',' if we have multiple ports */ + openfpga::StringToken tokenizer(data_ports); + for (const std::string& data_port : tokenizer.split(',')) { + openfpga::PortParser data_port_parser(data_port); + fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, bank_id, data_port_parser.port()); + } +} + +/******************************************************************** + * Parse XML codes of a to an object of FabricKey + *******************************************************************/ +static +void read_xml_region_wl_shift_register_banks(pugi::xml_node& xml_wl_bank, + const pugiutil::loc_data& loc_data, + FabricKey& fabric_key, + const FabricRegionId& fabric_region) { + size_t num_banks = count_children(xml_wl_bank, "bank", loc_data, pugiutil::ReqOpt::OPTIONAL); + fabric_key.reserve_wl_shift_register_banks(fabric_region, num_banks); + + for (size_t ibank = 0; ibank < num_banks; ++ibank) { + fabric_key.create_wl_shift_register_bank(fabric_region); + } + + for (pugi::xml_node xml_bank : xml_wl_bank.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_bank.name() != std::string("bank")) { + bad_tag(xml_bank, loc_data, xml_wl_bank, {"bank"}); + } + read_xml_region_wl_shift_register_bank(xml_bank, loc_data, fabric_key, fabric_region); + } +} + /******************************************************************** * Parse XML codes of a to an object of FabricKey *******************************************************************/ @@ -88,20 +200,25 @@ void read_xml_fabric_region(pugi::xml_node& xml_region, VTR_ASSERT_SAFE(true == fabric_key.valid_region_id(region_id)); /* Reserve memory space for the keys in the region */ - size_t num_keys = std::distance(xml_region.children().begin(), xml_region.children().end()); + size_t num_keys = count_children(xml_region, "key", loc_data, pugiutil::ReqOpt::OPTIONAL); fabric_key.reserve_region_keys(region_id, num_keys); - for (pugi::xml_node xml_key : xml_region.children()) { - /* Error out if the XML child has an invalid name! */ - if (xml_key.name() != std::string("key")) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_region), - "Unexpected child '%s' in region '%lu', Region XML node can only contain keys!\n", - xml_key.name(), - size_t(region_id)); - } - /* Parse the key for this region */ - read_xml_region_key(xml_key, loc_data, fabric_key, region_id); + /* Parse the key for this region */ + if (0 < num_keys) { + pugi::xml_node xml_key = get_first_child(xml_region, "key", loc_data); + while (xml_key) { + read_xml_region_key(xml_key, loc_data, fabric_key, region_id); + xml_key = xml_key.next_sibling(xml_key.name()); + } } + + /* Parse the BL shift register bank for this region */ + pugi::xml_node xml_bl_bank = get_single_child(xml_region, "bl_shift_register_banks", loc_data, pugiutil::ReqOpt::OPTIONAL); + read_xml_region_bl_shift_register_banks(xml_bl_bank, loc_data, fabric_key, region_id); + + /* Parse the WL shift register bank for this region */ + pugi::xml_node xml_wl_bank = get_single_child(xml_region, "wl_shift_register_banks", loc_data, pugiutil::ReqOpt::OPTIONAL); + read_xml_region_wl_shift_register_banks(xml_wl_bank, loc_data, fabric_key, region_id); } /******************************************************************** From 92eebd9abbbeb672afb8ffa1d990693b4cb9ccac Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 7 Oct 2021 17:05:35 -0700 Subject: [PATCH 189/229] [Lib] Upgrade fabric key writer to support the BL/WL shift register banks --- .../libfabrickey/src/write_xml_fabric_key.cpp | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp b/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp index aa38c8140..ffd64ea54 100644 --- a/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp +++ b/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp @@ -63,6 +63,106 @@ int write_xml_fabric_component_key(std::fstream& fp, return 0; } +/******************************************************************** + * A writer to output a BL shift register bank description to XML format + * + * Return 0 if successful + * Return 1 if there are more serious bugs in the architecture + * Return 2 if fail when creating files + *******************************************************************/ +static +int write_xml_fabric_bl_shift_register_banks(std::fstream& fp, + const FabricKey& fabric_key, + const FabricRegionId& region) { + /* Validate the file stream */ + if (false == openfpga::valid_file_stream(fp)) { + return 2; + } + + /* If we have an empty bank, we just skip it */ + if (0 == fabric_key.bl_banks(region).size()) { + return 0; + } + + /* Write the root node */ + openfpga::write_tab_to_file(fp, 2); + fp << "" << "\n"; + + for (const auto& bank : fabric_key.bl_banks(region)) { + openfpga::write_tab_to_file(fp, 3); + fp << "" << "\n"; + } + + openfpga::write_tab_to_file(fp, 2); + fp << "" << "\n"; + + return 0; +} + +/******************************************************************** + * A writer to output a WL shift register bank description to XML format + * + * Return 0 if successful + * Return 1 if there are more serious bugs in the architecture + * Return 2 if fail when creating files + *******************************************************************/ +static +int write_xml_fabric_wl_shift_register_banks(std::fstream& fp, + const FabricKey& fabric_key, + const FabricRegionId& region) { + /* Validate the file stream */ + if (false == openfpga::valid_file_stream(fp)) { + return 2; + } + + /* If we have an empty bank, we just skip it */ + if (0 == fabric_key.wl_banks(region).size()) { + return 0; + } + + /* Write the root node */ + openfpga::write_tab_to_file(fp, 2); + fp << "" << "\n"; + + for (const auto& bank : fabric_key.wl_banks(region)) { + openfpga::write_tab_to_file(fp, 3); + fp << "" << "\n"; + } + + openfpga::write_tab_to_file(fp, 2); + fp << "" << "\n"; + + return 0; +} + /******************************************************************** * A writer to output a fabric key to XML format * @@ -93,6 +193,10 @@ int write_xml_fabric_key(const char* fname, openfpga::write_tab_to_file(fp, 1); fp << "\n"; + /* Write shift register banks */ + write_xml_fabric_bl_shift_register_banks(fp, fabric_key, region); + write_xml_fabric_wl_shift_register_banks(fp, fabric_key, region); + /* Write component by component */ for (const FabricKeyId& key : fabric_key.region_keys(region)) { err_code = write_xml_fabric_component_key(fp, fabric_key, key); From f7484d4323d683f9c93ecc86d4eec650bc496260 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 8 Oct 2021 10:42:18 -0700 Subject: [PATCH 190/229] [Engine] Update the key memory data structure to contain shift register bank general information --- .../memory_bank_shift_register_banks.cpp | 121 ++++++++++++++++++ .../fabric/memory_bank_shift_register_banks.h | 53 ++++++++ 2 files changed, 174 insertions(+) diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index 9dcd98cf3..9854585b9 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -5,6 +5,54 @@ /* begin namespace openfpga */ namespace openfpga { +std::vector MemoryBankShiftRegisterBanks::bl_bank_unique_sizes(const ConfigRegionId& region_id) const { + std::vector unique_sizes; + for (const auto& bank_id : bl_banks(region_id)) { + size_t cur_bank_size = bl_bank_size(region_id, bank_id); + if (unique_sizes.end() == std::find(unique_sizes.begin(), unique_sizes.end(), cur_bank_size)) { + unique_sizes.push_back(cur_bank_size); + } + } + return unique_sizes; +} + +size_t MemoryBankShiftRegisterBanks::bl_bank_size(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { + size_t cur_bank_size = 0; + for (const auto& data_port : bl_bank_data_ports(region_id, bank_id)) { + cur_bank_size += data_port.get_width(); + } + return cur_bank_size; +} + +FabricKey::fabric_bit_line_bank_range MemoryBankShiftRegisterBanks::bl_banks(const ConfigRegionId& region_id) const { + VTR_ASSERT(valid_region_id(region_id)); + return vtr::make_range(bl_bank_ids_[region_id].begin(), bl_bank_ids_[region_id].end()); +} + +std::vector MemoryBankShiftRegisterBanks::wl_bank_unique_sizes(const ConfigRegionId& region_id) const { + std::vector unique_sizes; + for (const auto& bank_id : wl_banks(region_id)) { + size_t cur_bank_size = wl_bank_size(region_id, bank_id); + if (unique_sizes.end() == std::find(unique_sizes.begin(), unique_sizes.end(), cur_bank_size)) { + unique_sizes.push_back(cur_bank_size); + } + } + return unique_sizes; +} + +size_t MemoryBankShiftRegisterBanks::wl_bank_size(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const { + size_t cur_bank_size = 0; + for (const auto& data_port : wl_bank_data_ports(region_id, bank_id)) { + cur_bank_size += data_port.get_width(); + } + return cur_bank_size; +} + +FabricKey::fabric_word_line_bank_range MemoryBankShiftRegisterBanks::wl_banks(const ConfigRegionId& region_id) const { + VTR_ASSERT(valid_region_id(region_id)); + return vtr::make_range(wl_bank_ids_[region_id].begin(), wl_bank_ids_[region_id].end()); +} + std::vector MemoryBankShiftRegisterBanks::shift_register_bank_unique_modules() const { std::vector sr_bank_modules; for (const auto& region : sr_instance_sink_child_ids_) { @@ -74,6 +122,16 @@ std::vector MemoryBankShiftRegisterBanks::shift_register_bank_source_blw return std::vector(); } +std::vector MemoryBankShiftRegisterBanks::bl_bank_data_ports(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { + VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); + return bl_bank_data_ports_[region_id][bank_id]; +} + +std::vector MemoryBankShiftRegisterBanks::wl_bank_data_ports(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const { + VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); + return wl_bank_data_ports_[region_id][bank_id]; +} + void MemoryBankShiftRegisterBanks::resize_regions(const size_t& num_regions) { sr_instance_sink_child_ids_.resize(num_regions); sr_instance_sink_child_pin_ids_.resize(num_regions); @@ -107,8 +165,71 @@ void MemoryBankShiftRegisterBanks::add_shift_register_source_blwls(const ConfigR sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_blwl_id); } +void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks) { + VTR_ASSERT(valid_region_id(region_id)); + bl_bank_ids_[region_id].reserve(num_banks); + bl_bank_data_ports_[region_id].reserve(num_banks); +} + +void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks) { + VTR_ASSERT(valid_region_id(region_id)); + wl_bank_ids_[region_id].reserve(num_banks); + wl_bank_data_ports_[region_id].reserve(num_banks); +} + +FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank(const ConfigRegionId& region_id) { + VTR_ASSERT(valid_region_id(region_id)); + + /* Create a new id */ + FabricBitLineBankId bank = FabricBitLineBankId(bl_bank_ids_[region_id].size()); + bl_bank_ids_[region_id].push_back(bank); + bl_bank_data_ports_[region_id].emplace_back(); + + return bank; +} + +void MemoryBankShiftRegisterBanks::add_data_port_to_bl_shift_register_bank(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port) { + VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); + bl_bank_data_ports_[region_id][bank_id].push_back(data_port); +} + +FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank(const ConfigRegionId& region_id) { + VTR_ASSERT(valid_region_id(region_id)); + + /* Create a new id */ + FabricWordLineBankId bank = FabricWordLineBankId(wl_bank_ids_[region_id].size()); + wl_bank_ids_[region_id].push_back(bank); + wl_bank_data_ports_[region_id].emplace_back(); + + return bank; +} + +void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port) { + VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); + wl_bank_data_ports_[region_id][bank_id].push_back(data_port); +} + + bool MemoryBankShiftRegisterBanks::valid_region_id(const ConfigRegionId& region) const { return size_t(region) < sr_instance_sink_child_ids_.size(); } +bool MemoryBankShiftRegisterBanks::valid_bl_bank_id(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { + if (!valid_region_id(region_id)) { + return false; + } + return ( size_t(bank_id) < bl_bank_ids_[region_id].size() ) && ( bank_id == bl_bank_ids_[region_id][bank_id] ); +} + +bool MemoryBankShiftRegisterBanks::valid_wl_bank_id(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const { + if (!valid_region_id(region_id)) { + return false; + } + return ( size_t(bank_id) < wl_bank_ids_[region_id].size() ) && ( bank_id == wl_bank_ids_[region_id][bank_id] ); +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h index 6114f93d8..56da677b2 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.h +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -4,6 +4,7 @@ #include #include #include "vtr_vector.h" +#include "fabric_key.h" #include "module_manager.h" /* begin namespace openfpga */ @@ -21,7 +22,28 @@ namespace openfpga { * @note This data structure is mainly used as a database for adding connections around shift register banks in top-level module ******************************************************************************/ class MemoryBankShiftRegisterBanks { + public: /* Accessors: aggregates */ + FabricKey::fabric_bit_line_bank_range bl_banks(const ConfigRegionId& region_id) const; + FabricKey::fabric_word_line_bank_range wl_banks(const ConfigRegionId& region_id) const; public: /* Accessors */ + /* @brief Return a list of unique sizes of shift register banks for BL protocol */ + std::vector bl_bank_unique_sizes(const ConfigRegionId& region_id) const; + + /* @brief Return the size of a BL shift register bank */ + size_t bl_bank_size(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; + + /* @brief Return a list of data ports which will be driven by a BL shift register bank */ + std::vector bl_bank_data_ports(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; + + /* @brief Return a list of unique sizes of shift register banks for WL protocol */ + std::vector wl_bank_unique_sizes(const ConfigRegionId& region_id) const; + + /* @brief Return the size of a WL shift register bank */ + size_t wl_bank_size(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; + + /* @brief Return a list of data ports which will be driven by a WL shift register bank */ + std::vector wl_bank_data_ports(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; + /* @brief Return a list of modules of unique shift register banks across all the regions */ std::vector shift_register_bank_unique_modules() const; @@ -72,10 +94,41 @@ class MemoryBankShiftRegisterBanks { const ModuleId& sr_module, const size_t& sr_instance, const size_t& sink_blwl_id); + + /* Reserve a number of banks to be memory efficent */ + void reserve_bl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks); + void reserve_wl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks); + + /* Create a new shift register bank for BLs and return an id */ + FabricBitLineBankId create_bl_shift_register_bank(const ConfigRegionId& region_id); + + /* Add a data port to a given BL shift register bank */ + void add_data_port_to_bl_shift_register_bank(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port); + + /* Create a new shift register bank for WLs and return an id */ + FabricWordLineBankId create_wl_shift_register_bank(const ConfigRegionId& region_id); + + /* Add a data port to a given WL shift register bank */ + void add_data_port_to_wl_shift_register_bank(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port); + public: /* Validators */ bool valid_region_id(const ConfigRegionId& region) const; + bool valid_bl_bank_id(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; + bool valid_wl_bank_id(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; private: /* Internal data */ + /* General information about the BL shift register bank */ + vtr::vector> bl_bank_ids_; + vtr::vector>> bl_bank_data_ports_; + + /* General information about the WL shift register bank */ + vtr::vector> wl_bank_ids_; + vtr::vector>> wl_bank_data_ports_; + /* [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/ vtr::vector, std::vector>> sr_instance_sink_child_ids_; vtr::vector, std::vector>> sr_instance_sink_child_pin_ids_; From 8f5f30792fa4aebed93fe510ea9f1e9c4d7a1a43 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 8 Oct 2021 15:25:37 -0700 Subject: [PATCH 191/229] [Engine] Now the MemoryBankShiftRegisterBanks data structure combines both BL/WL data structures as the unified interface --- openfpga/src/base/openfpga_context.h | 6 +- openfpga/src/fabric/build_device_module.cpp | 2 +- openfpga/src/fabric/build_device_module.h | 2 +- openfpga/src/fabric/build_top_module.cpp | 2 +- openfpga/src/fabric/build_top_module.h | 2 +- .../src/fabric/build_top_module_memory.cpp | 4 +- openfpga/src/fabric/build_top_module_memory.h | 2 +- .../fabric/build_top_module_memory_bank.cpp | 119 ++++++++--- .../src/fabric/build_top_module_memory_bank.h | 2 +- .../memory_bank_shift_register_banks.cpp | 186 ++++++++++++++---- .../fabric/memory_bank_shift_register_banks.h | 128 ++++++++---- openfpga/src/fpga_verilog/verilog_api.cpp | 2 +- openfpga/src/fpga_verilog/verilog_api.h | 2 +- .../verilog_shift_register_banks.cpp | 31 +-- .../verilog_shift_register_banks.h | 2 +- .../src/fpga_verilog/verilog_submodule.cpp | 2 +- openfpga/src/fpga_verilog/verilog_submodule.h | 2 +- openfpga/src/utils/fabric_bitstream_utils.cpp | 2 +- openfpga/src/utils/fabric_bitstream_utils.h | 2 +- 19 files changed, 370 insertions(+), 130 deletions(-) diff --git a/openfpga/src/base/openfpga_context.h b/openfpga/src/base/openfpga_context.h index dbb611fe6..3719a2fa7 100644 --- a/openfpga/src/base/openfpga_context.h +++ b/openfpga/src/base/openfpga_context.h @@ -66,7 +66,7 @@ class OpenfpgaContext : public Context { const openfpga::DeviceRRGSB& device_rr_gsb() const { return device_rr_gsb_; } const openfpga::MuxLibrary& mux_lib() const { return mux_lib_; } const openfpga::DecoderLibrary& decoder_lib() const { return decoder_lib_; } - const std::array& blwl_shift_register_banks() { return blwl_sr_banks_; } + const openfpga::MemoryBankShiftRegisterBanks& blwl_shift_register_banks() { return blwl_sr_banks_; } const openfpga::TileDirect& tile_direct() const { return tile_direct_; } const openfpga::ModuleManager& module_graph() const { return module_graph_; } const openfpga::FlowManager& flow_manager() const { return flow_manager_; } @@ -89,7 +89,7 @@ class OpenfpgaContext : public Context { openfpga::DeviceRRGSB& mutable_device_rr_gsb() { return device_rr_gsb_; } openfpga::MuxLibrary& mutable_mux_lib() { return mux_lib_; } openfpga::DecoderLibrary& mutable_decoder_lib() { return decoder_lib_; } - std::array& mutable_blwl_shift_register_banks() { return blwl_sr_banks_; } + openfpga::MemoryBankShiftRegisterBanks& mutable_blwl_shift_register_banks() { return blwl_sr_banks_; } openfpga::TileDirect& mutable_tile_direct() { return tile_direct_; } openfpga::ModuleManager& mutable_module_graph() { return module_graph_; } openfpga::FlowManager& mutable_flow_manager() { return flow_manager_; } @@ -138,7 +138,7 @@ class OpenfpgaContext : public Context { /* Library of shift register banks that control BLs and WLs * @note Only used when memory bank is used as configuration protocol */ - std::array blwl_sr_banks_; + openfpga::MemoryBankShiftRegisterBanks blwl_sr_banks_; /* Fabric module graph */ openfpga::ModuleManager module_graph_; diff --git a/openfpga/src/fabric/build_device_module.cpp b/openfpga/src/fabric/build_device_module.cpp index 3541616fc..53ae7f3fc 100644 --- a/openfpga/src/fabric/build_device_module.cpp +++ b/openfpga/src/fabric/build_device_module.cpp @@ -31,7 +31,7 @@ namespace openfpga { *******************************************************************/ int build_device_module_graph(ModuleManager& module_manager, DecoderLibrary& decoder_lib, - std::array& blwl_sr_banks, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const OpenfpgaContext& openfpga_ctx, const DeviceContext& vpr_device_ctx, const bool& frame_view, diff --git a/openfpga/src/fabric/build_device_module.h b/openfpga/src/fabric/build_device_module.h index 1cde17ba7..1c21fd069 100644 --- a/openfpga/src/fabric/build_device_module.h +++ b/openfpga/src/fabric/build_device_module.h @@ -17,7 +17,7 @@ namespace openfpga { int build_device_module_graph(ModuleManager& module_manager, DecoderLibrary& decoder_lib, - std::array& blwl_sr_banks, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const OpenfpgaContext& openfpga_ctx, const DeviceContext& vpr_device_ctx, const bool& frame_view, diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index c5b3aee45..1bd5dc703 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -283,7 +283,7 @@ vtr::Matrix add_top_module_connection_block_instances(ModuleManager& mod *******************************************************************/ int build_top_module(ModuleManager& module_manager, DecoderLibrary& decoder_lib, - std::array& blwl_sr_banks, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const CircuitLibrary& circuit_lib, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, diff --git a/openfpga/src/fabric/build_top_module.h b/openfpga/src/fabric/build_top_module.h index 3ddaea09a..c1b3a6f93 100644 --- a/openfpga/src/fabric/build_top_module.h +++ b/openfpga/src/fabric/build_top_module.h @@ -30,7 +30,7 @@ namespace openfpga { int build_top_module(ModuleManager& module_manager, DecoderLibrary& decoder_lib, - std::array& blwl_sr_banks, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const CircuitLibrary& circuit_lib, const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index e48167970..9da2a3641 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -1735,7 +1735,7 @@ void add_top_module_nets_cmos_memory_frame_config_bus(ModuleManager& module_mana static void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, - std::array& blwl_sr_banks, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const ModuleId& parent_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, @@ -1802,7 +1802,7 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager, *******************************************************************/ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, - std::array& blwl_sr_banks, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const ModuleId& parent_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, diff --git a/openfpga/src/fabric/build_top_module_memory.h b/openfpga/src/fabric/build_top_module_memory.h index 4819a56f6..be4589490 100644 --- a/openfpga/src/fabric/build_top_module_memory.h +++ b/openfpga/src/fabric/build_top_module_memory.h @@ -65,7 +65,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, - std::array& blwl_sr_banks, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const ModuleId& parent_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 18accc9bb..e58ab9b4c 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -1086,9 +1086,25 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_heads(ModuleMan ModulePortId blsr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(head_port_name, config_region)); BasicPort blsr_head_port_info = module_manager.module_port(top_module, blsr_head_port); - for (size_t iinst = 0; iinst < sr_banks.shift_register_bank_modules(config_region).size(); ++iinst) { - ModuleId sr_bank_module = sr_banks.shift_register_bank_modules(config_region)[iinst]; - size_t sr_bank_instance = sr_banks.shift_register_bank_instances(config_region)[iinst]; + size_t num_sr_bank_modules; + if (std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME) == head_port_name) { + num_sr_bank_modules = sr_banks.bl_shift_register_bank_modules(config_region).size(); + } else { + VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME) == head_port_name); + num_sr_bank_modules = sr_banks.wl_shift_register_bank_modules(config_region).size(); + } + for (size_t iinst = 0; iinst < num_sr_bank_modules; ++iinst) { + ModuleId sr_bank_module; + size_t sr_bank_instance; + if (std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME) == head_port_name) { + sr_bank_module = sr_banks.bl_shift_register_bank_modules(config_region)[iinst]; + sr_bank_instance = sr_banks.bl_shift_register_bank_instances(config_region)[iinst]; + } else { + VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME) == head_port_name); + sr_bank_module = sr_banks.wl_shift_register_bank_modules(config_region)[iinst]; + sr_bank_instance = sr_banks.wl_shift_register_bank_instances(config_region)[iinst]; + } + VTR_ASSERT(sr_bank_module); ModulePortId sr_module_head_port = module_manager.find_module_port(sr_bank_module, head_port_name); @@ -1125,10 +1141,24 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(ModuleMan ModulePortId blsr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(tail_port_name, config_region)); BasicPort blsr_tail_port_info = module_manager.module_port(top_module, blsr_tail_port); - for (size_t iinst = 0; iinst < sr_banks.shift_register_bank_modules(config_region).size(); ++iinst) { - ModuleId sr_bank_module = sr_banks.shift_register_bank_modules(config_region)[iinst]; - size_t sr_bank_instance = sr_banks.shift_register_bank_instances(config_region)[iinst]; - VTR_ASSERT(sr_bank_module); + size_t num_sr_bank_modules; + if (std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME) == tail_port_name) { + num_sr_bank_modules = sr_banks.bl_shift_register_bank_modules(config_region).size(); + } else { + VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME) == tail_port_name); + num_sr_bank_modules = sr_banks.wl_shift_register_bank_modules(config_region).size(); + } + for (size_t iinst = 0; iinst < num_sr_bank_modules; ++iinst) { + ModuleId sr_bank_module; + size_t sr_bank_instance; + if (std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME) == tail_port_name) { + sr_bank_module = sr_banks.bl_shift_register_bank_modules(config_region)[iinst]; + sr_bank_instance = sr_banks.bl_shift_register_bank_instances(config_region)[iinst]; + } else { + VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME) == tail_port_name); + sr_bank_module = sr_banks.wl_shift_register_bank_modules(config_region)[iinst]; + sr_bank_instance = sr_banks.wl_shift_register_bank_instances(config_region)[iinst]; + } ModulePortId sr_module_tail_port = module_manager.find_module_port(sr_bank_module, tail_port_name); BasicPort sr_module_tail_port_info = module_manager.module_port(sr_bank_module, sr_module_tail_port); @@ -1183,9 +1213,25 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan const std::string& child_blwl_port_name, const bool& optional_blwl = false) { for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - for (size_t iinst = 0; iinst < sr_banks.shift_register_bank_modules(config_region).size(); ++iinst) { - ModuleId sr_bank_module = sr_banks.shift_register_bank_modules(config_region)[iinst]; - size_t sr_bank_instance = sr_banks.shift_register_bank_instances(config_region)[iinst]; + size_t num_sr_bank_modules; + if (std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME) == sr_blwl_port_name) { + num_sr_bank_modules = sr_banks.bl_shift_register_bank_modules(config_region).size(); + } else { + VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME) == sr_blwl_port_name); + num_sr_bank_modules = sr_banks.wl_shift_register_bank_modules(config_region).size(); + } + for (size_t iinst = 0; iinst < num_sr_bank_modules; ++iinst) { + ModuleId sr_bank_module; + size_t sr_bank_instance; + if (std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME) == sr_blwl_port_name) { + sr_bank_module = sr_banks.bl_shift_register_bank_modules(config_region)[iinst]; + sr_bank_instance = sr_banks.bl_shift_register_bank_instances(config_region)[iinst]; + } else { + VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME) == sr_blwl_port_name); + sr_bank_module = sr_banks.wl_shift_register_bank_modules(config_region)[iinst]; + sr_bank_instance = sr_banks.wl_shift_register_bank_instances(config_region)[iinst]; + } + VTR_ASSERT(sr_bank_module); ModulePortId sr_module_blwl_port = module_manager.find_module_port(sr_bank_module, sr_blwl_port_name); @@ -1195,9 +1241,23 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan VTR_ASSERT(sr_module_blwl_port); BasicPort sr_module_blwl_port_info = module_manager.module_port(sr_bank_module, sr_module_blwl_port); + size_t num_sink_child_ids; + if (std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME) == sr_blwl_port_name) { + num_sink_child_ids = sr_banks.bl_shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance).size(); + } else { + VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME) == sr_blwl_port_name); + num_sink_child_ids = sr_banks.wl_shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance).size(); + } + + for (size_t sink_id = 0; sink_id < num_sink_child_ids; ++sink_id) { + size_t child_id; + if (std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME) == sr_blwl_port_name) { + child_id = sr_banks.bl_shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; + } else { + VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME) == sr_blwl_port_name); + child_id = sr_banks.wl_shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; + } - for (size_t sink_id = 0; sink_id < sr_banks.shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance).size(); ++sink_id) { - size_t child_id = sr_banks.shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; @@ -1205,7 +1265,13 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name); BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port); - size_t cur_sr_module_blwl_pin_id = sr_banks.shift_register_bank_source_blwl_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; + size_t cur_sr_module_blwl_pin_id; + if (std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME) == sr_blwl_port_name) { + cur_sr_module_blwl_pin_id = sr_banks.bl_shift_register_bank_source_blwl_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; + } else { + VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME) == sr_blwl_port_name); + cur_sr_module_blwl_pin_id = sr_banks.wl_shift_register_bank_source_blwl_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; + } /* Create net */ ModuleNetId net = create_module_source_pin_net(module_manager, top_module, @@ -1215,7 +1281,14 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - size_t sink_pin_id = sr_banks.shift_register_bank_sink_pin_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; + size_t sink_pin_id; + if (std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME) == sr_blwl_port_name) { + sink_pin_id = sr_banks.bl_shift_register_bank_sink_pin_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; + } else { + VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME) == sr_blwl_port_name); + sink_pin_id = sr_banks.wl_shift_register_bank_sink_pin_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; + } + module_manager.add_module_net_sink(top_module, net, child_module, child_instance, child_blwl_port, sink_pin_id); } @@ -1315,7 +1388,7 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module); module_manager.add_child_module(top_module, sr_bank_module); - sr_banks.add_shift_register_instance(config_region, sr_bank_module, cur_inst); + sr_banks.add_bl_shift_register_instance(config_region, sr_bank_module, cur_inst); /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric @@ -1340,8 +1413,8 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index; - sr_banks.add_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_bl_pin); - sr_banks.add_shift_register_source_blwls(config_region, sr_bank_module, cur_inst, bl_pin_id); + sr_banks.add_bl_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_bl_pin); + sr_banks.add_bl_shift_register_source_blwls(config_region, sr_bank_module, cur_inst, bl_pin_id); cur_bl_index++; } @@ -1409,7 +1482,7 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module); module_manager.add_child_module(top_module, sr_bank_module); - sr_banks.add_shift_register_instance(config_region, sr_bank_module, cur_inst); + sr_banks.add_wl_shift_register_instance(config_region, sr_bank_module, cur_inst); /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric @@ -1433,8 +1506,8 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module for (const size_t& sink_wl_pin : child_wl_port_info.pins()) { size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + cur_wl_index; - sr_banks.add_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_wl_pin); - sr_banks.add_shift_register_source_blwls(config_region, sr_bank_module, cur_inst, wl_pin_id); + sr_banks.add_wl_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_wl_pin); + sr_banks.add_wl_shift_register_source_blwls(config_region, sr_bank_module, cur_inst, wl_pin_id); cur_wl_index++; } @@ -1477,7 +1550,7 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module ********************************************************************/ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, - std::array& blwl_sr_banks, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const ModuleId& top_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, @@ -1495,7 +1568,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { - add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(module_manager, blwl_sr_banks[0], top_module, circuit_lib, config_protocol); + add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(module_manager, blwl_sr_banks, top_module, circuit_lib, config_protocol); break; } default: { @@ -1514,7 +1587,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma break; } case BLWL_PROTOCOL_SHIFT_REGISTER: { - add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(module_manager, blwl_sr_banks[1], top_module, circuit_lib, config_protocol); + add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(module_manager, blwl_sr_banks, top_module, circuit_lib, config_protocol); break; } default: { diff --git a/openfpga/src/fabric/build_top_module_memory_bank.h b/openfpga/src/fabric/build_top_module_memory_bank.h index d3a3d2f77..5617271df 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.h +++ b/openfpga/src/fabric/build_top_module_memory_bank.h @@ -26,7 +26,7 @@ namespace openfpga { void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_manager, DecoderLibrary& decoder_lib, - std::array& blwl_sr_banks, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const ModuleId& top_module, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index 9854585b9..43278f2f5 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -53,9 +53,9 @@ FabricKey::fabric_word_line_bank_range MemoryBankShiftRegisterBanks::wl_banks(co return vtr::make_range(wl_bank_ids_[region_id].begin(), wl_bank_ids_[region_id].end()); } -std::vector MemoryBankShiftRegisterBanks::shift_register_bank_unique_modules() const { +std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_unique_modules() const { std::vector sr_bank_modules; - for (const auto& region : sr_instance_sink_child_ids_) { + for (const auto& region : bl_sr_instance_sink_child_ids_) { for (const auto& pair : region) { if (sr_bank_modules.end() == std::find(sr_bank_modules.begin(), sr_bank_modules.end(), pair.first.first)) { sr_bank_modules.push_back(pair.first.first); @@ -65,58 +65,127 @@ std::vector MemoryBankShiftRegisterBanks::shift_register_bank_unique_m return sr_bank_modules; } -std::vector MemoryBankShiftRegisterBanks::shift_register_bank_modules(const ConfigRegionId& region) const { +std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_modules(const ConfigRegionId& region) const { std::vector sr_bank_modules; VTR_ASSERT(valid_region_id(region)); - for (const auto& pair : sr_instance_sink_child_ids_[region]) { + for (const auto& pair : bl_sr_instance_sink_child_ids_[region]) { sr_bank_modules.push_back(pair.first.first); } return sr_bank_modules; } -std::vector MemoryBankShiftRegisterBanks::shift_register_bank_instances(const ConfigRegionId& region) const { +std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_instances(const ConfigRegionId& region) const { std::vector sr_bank_instances; VTR_ASSERT(valid_region_id(region)); - for (const auto& pair : sr_instance_sink_child_ids_[region]) { + for (const auto& pair : bl_sr_instance_sink_child_ids_[region]) { sr_bank_instances.push_back(pair.first.second); } return sr_bank_instances; } -std::vector MemoryBankShiftRegisterBanks::shift_register_bank_sink_child_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const { +std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const { VTR_ASSERT(valid_region_id(region)); - auto result = sr_instance_sink_child_ids_[region].find(std::make_pair(sr_module, sr_instance)); + auto result = bl_sr_instance_sink_child_ids_[region].find(std::make_pair(sr_module, sr_instance)); /* Return an empty vector if not found */ - if (result != sr_instance_sink_child_ids_[region].end()) { + if (result != bl_sr_instance_sink_child_ids_[region].end()) { return result->second; } return std::vector(); } -std::vector MemoryBankShiftRegisterBanks::shift_register_bank_sink_pin_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const { +std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_pin_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const { VTR_ASSERT(valid_region_id(region)); - auto result = sr_instance_sink_child_pin_ids_[region].find(std::make_pair(sr_module, sr_instance)); + auto result = bl_sr_instance_sink_child_pin_ids_[region].find(std::make_pair(sr_module, sr_instance)); /* Return an empty vector if not found */ - if (result != sr_instance_sink_child_pin_ids_[region].end()) { + if (result != bl_sr_instance_sink_child_pin_ids_[region].end()) { return result->second; } return std::vector(); } -std::vector MemoryBankShiftRegisterBanks::shift_register_bank_source_blwl_ids(const ConfigRegionId& region, +std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_source_blwl_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const { + VTR_ASSERT(valid_region_id(region)); + + auto result = bl_sr_instance_source_blwl_ids_[region].find(std::make_pair(sr_module, sr_instance)); + /* Return an empty vector if not found */ + if (result != bl_sr_instance_source_blwl_ids_[region].end()) { + return result->second; + } + return std::vector(); +} + +std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_unique_modules() const { + std::vector sr_bank_modules; + for (const auto& region : wl_sr_instance_sink_child_ids_) { + for (const auto& pair : region) { + if (sr_bank_modules.end() == std::find(sr_bank_modules.begin(), sr_bank_modules.end(), pair.first.first)) { + sr_bank_modules.push_back(pair.first.first); + } + } + } + return sr_bank_modules; +} + +std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_modules(const ConfigRegionId& region) const { + std::vector sr_bank_modules; + VTR_ASSERT(valid_region_id(region)); + for (const auto& pair : wl_sr_instance_sink_child_ids_[region]) { + sr_bank_modules.push_back(pair.first.first); + } + return sr_bank_modules; +} + +std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_instances(const ConfigRegionId& region) const { + std::vector sr_bank_instances; + VTR_ASSERT(valid_region_id(region)); + for (const auto& pair : wl_sr_instance_sink_child_ids_[region]) { + sr_bank_instances.push_back(pair.first.second); + } + return sr_bank_instances; +} + +std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const { + VTR_ASSERT(valid_region_id(region)); + + auto result = wl_sr_instance_sink_child_ids_[region].find(std::make_pair(sr_module, sr_instance)); + /* Return an empty vector if not found */ + if (result != wl_sr_instance_sink_child_ids_[region].end()) { + return result->second; + } + return std::vector(); +} + +std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_pin_ids(const ConfigRegionId& region, const ModuleId& sr_module, const size_t& sr_instance) const { VTR_ASSERT(valid_region_id(region)); - auto result = sr_instance_source_blwl_ids_[region].find(std::make_pair(sr_module, sr_instance)); + auto result = wl_sr_instance_sink_child_pin_ids_[region].find(std::make_pair(sr_module, sr_instance)); /* Return an empty vector if not found */ - if (result != sr_instance_source_blwl_ids_[region].end()) { + if (result != wl_sr_instance_sink_child_pin_ids_[region].end()) { + return result->second; + } + return std::vector(); +} + +std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_source_blwl_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const { + VTR_ASSERT(valid_region_id(region)); + + auto result = wl_sr_instance_source_blwl_ids_[region].find(std::make_pair(sr_module, sr_instance)); + /* Return an empty vector if not found */ + if (result != wl_sr_instance_source_blwl_ids_[region].end()) { return result->second; } return std::vector(); @@ -133,36 +202,71 @@ std::vector MemoryBankShiftRegisterBanks::wl_bank_data_ports(const Co } void MemoryBankShiftRegisterBanks::resize_regions(const size_t& num_regions) { - sr_instance_sink_child_ids_.resize(num_regions); - sr_instance_sink_child_pin_ids_.resize(num_regions); - sr_instance_source_blwl_ids_.resize(num_regions); + bl_bank_ids_.resize(num_regions); + bl_bank_data_ports_.resize(num_regions); + bl_sr_instance_sink_child_ids_.resize(num_regions); + bl_sr_instance_sink_child_pin_ids_.resize(num_regions); + bl_sr_instance_source_blwl_ids_.resize(num_regions); + + wl_bank_ids_.resize(num_regions); + wl_bank_data_ports_.resize(num_regions); + wl_sr_instance_sink_child_ids_.resize(num_regions); + wl_sr_instance_sink_child_pin_ids_.resize(num_regions); + wl_sr_instance_source_blwl_ids_.resize(num_regions); } -void MemoryBankShiftRegisterBanks::add_shift_register_instance(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) { +void MemoryBankShiftRegisterBanks::add_bl_shift_register_instance(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) { VTR_ASSERT(valid_region_id(region)); - sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)]; - sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)]; - sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)]; + bl_sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)]; + bl_sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)]; + bl_sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)]; } -void MemoryBankShiftRegisterBanks::add_shift_register_sink_nodes(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_child_id, - const size_t& sink_child_pin_id) { +void MemoryBankShiftRegisterBanks::add_bl_shift_register_sink_nodes(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_child_id, + const size_t& sink_child_pin_id) { VTR_ASSERT(valid_region_id(region)); - sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_id); - sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_pin_id); + bl_sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_id); + bl_sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_pin_id); } -void MemoryBankShiftRegisterBanks::add_shift_register_source_blwls(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_blwl_id) { +void MemoryBankShiftRegisterBanks::add_bl_shift_register_source_blwls(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_blwl_id) { VTR_ASSERT(valid_region_id(region)); - sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_blwl_id); + bl_sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_blwl_id); +} + +void MemoryBankShiftRegisterBanks::add_wl_shift_register_instance(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) { + VTR_ASSERT(valid_region_id(region)); + wl_sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)]; + wl_sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)]; + wl_sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)]; +} + +void MemoryBankShiftRegisterBanks::add_wl_shift_register_sink_nodes(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_child_id, + const size_t& sink_child_pin_id) { + VTR_ASSERT(valid_region_id(region)); + wl_sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_id); + wl_sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_pin_id); +} + +void MemoryBankShiftRegisterBanks::add_wl_shift_register_source_blwls(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_blwl_id) { + VTR_ASSERT(valid_region_id(region)); + wl_sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_blwl_id); } void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks) { @@ -215,7 +319,7 @@ void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank(const bool MemoryBankShiftRegisterBanks::valid_region_id(const ConfigRegionId& region) const { - return size_t(region) < sr_instance_sink_child_ids_.size(); + return size_t(region) < bl_sr_instance_sink_child_ids_.size(); } bool MemoryBankShiftRegisterBanks::valid_bl_bank_id(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h index 56da677b2..740d2676d 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.h +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -45,56 +45,68 @@ class MemoryBankShiftRegisterBanks { std::vector wl_bank_data_ports(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; /* @brief Return a list of modules of unique shift register banks across all the regions */ - std::vector shift_register_bank_unique_modules() const; + std::vector bl_shift_register_bank_unique_modules() const; /* @brief Return a list of modules of shift register banks under a specific configuration region of top-level module */ - std::vector shift_register_bank_modules(const ConfigRegionId& region) const; + std::vector bl_shift_register_bank_modules(const ConfigRegionId& region) const; /* @brief Return a list of instances of shift register banks under a specific configuration region of top-level module */ - std::vector shift_register_bank_instances(const ConfigRegionId& region) const; + std::vector bl_shift_register_bank_instances(const ConfigRegionId& region) const; /* @brief Return a list of ids of reconfigurable children for a given instance of shift register bank * under a specific configuration region of top-level module */ - std::vector shift_register_bank_sink_child_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const; + std::vector bl_shift_register_bank_sink_child_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const; - /* @brief Return a list of BL/WL ids of reconfigurable children for a given instance of shift register bank + /* @brief Return a list of BL ids of reconfigurable children for a given instance of shift register bank * under a specific configuration region of top-level module */ - std::vector shift_register_bank_sink_pin_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const; - - /* @brief Return a list of BL/WL ids of a given instance of shift register bank - * under a specific configuration region of top-level module - */ - std::vector shift_register_bank_source_blwl_ids(const ConfigRegionId& region, + std::vector bl_shift_register_bank_sink_pin_ids(const ConfigRegionId& region, const ModuleId& sr_module, const size_t& sr_instance) const; + /* @brief Return a list of BL ids of a given instance of shift register bank + * under a specific configuration region of top-level module + */ + std::vector bl_shift_register_bank_source_blwl_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const; + + /* @brief Return a list of modules of unique shift register banks across all the regions */ + std::vector wl_shift_register_bank_unique_modules() const; + + /* @brief Return a list of modules of shift register banks under a specific configuration region of top-level module */ + std::vector wl_shift_register_bank_modules(const ConfigRegionId& region) const; + + /* @brief Return a list of instances of shift register banks under a specific configuration region of top-level module */ + std::vector wl_shift_register_bank_instances(const ConfigRegionId& region) const; + + /* @brief Return a list of ids of reconfigurable children for a given instance of shift register bank + * under a specific configuration region of top-level module + */ + std::vector wl_shift_register_bank_sink_child_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const; + + /* @brief Return a list of WL ids of reconfigurable children for a given instance of shift register bank + * under a specific configuration region of top-level module + */ + std::vector wl_shift_register_bank_sink_pin_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const; + + /* @brief Return a list of WL ids of a given instance of shift register bank + * under a specific configuration region of top-level module + */ + std::vector wl_shift_register_bank_source_blwl_ids(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance) const; + public: /* Mutators */ void resize_regions(const size_t& num_regions); - /* @brief Add the module id and instance id of a shift register under a specific configuration region of top-level module */ - void add_shift_register_instance(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance); - - /* @brief Add the child id and pin id of BL/WL to which a shift register is connected to under a specific configuration region of top-level module */ - void add_shift_register_sink_nodes(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_child_id, - const size_t& sink_child_pin_id); - - /* @brief Add the BL/WL id under a specific configuration region of top-level module to which a shift register is connected to */ - void add_shift_register_source_blwls(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_blwl_id); - /* Reserve a number of banks to be memory efficent */ void reserve_bl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks); void reserve_wl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks); @@ -115,6 +127,42 @@ class MemoryBankShiftRegisterBanks { const FabricWordLineBankId& bank_id, const openfpga::BasicPort& data_port); + /* @brief Add the module id and instance id of a shift register under a specific configuration region of top-level module */ + void add_bl_shift_register_instance(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance); + + /* @brief Add the child id and pin id of BL to which a shift register is connected to under a specific configuration region of top-level module */ + void add_bl_shift_register_sink_nodes(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_child_id, + const size_t& sink_child_pin_id); + + /* @brief Add the BL id under a specific configuration region of top-level module to which a shift register is connected to */ + void add_bl_shift_register_source_blwls(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_blwl_id); + + /* @brief Add the module id and instance id of a shift register under a specific configuration region of top-level module */ + void add_wl_shift_register_instance(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance); + + /* @brief Add the child id and pin id of WL to which a shift register is connected to under a specific configuration region of top-level module */ + void add_wl_shift_register_sink_nodes(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_child_id, + const size_t& sink_child_pin_id); + + /* @brief Add the BL/WL id under a specific configuration region of top-level module to which a shift register is connected to */ + void add_wl_shift_register_source_blwls(const ConfigRegionId& region, + const ModuleId& sr_module, + const size_t& sr_instance, + const size_t& sink_blwl_id); + public: /* Validators */ bool valid_region_id(const ConfigRegionId& region) const; bool valid_bl_bank_id(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; @@ -125,14 +173,20 @@ class MemoryBankShiftRegisterBanks { vtr::vector> bl_bank_ids_; vtr::vector>> bl_bank_data_ports_; + /* BL: [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/ + vtr::vector, std::vector>> bl_sr_instance_sink_child_ids_; + vtr::vector, std::vector>> bl_sr_instance_sink_child_pin_ids_; + vtr::vector, std::vector>> bl_sr_instance_source_blwl_ids_; + /* General information about the WL shift register bank */ vtr::vector> wl_bank_ids_; vtr::vector>> wl_bank_data_ports_; - /* [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/ - vtr::vector, std::vector>> sr_instance_sink_child_ids_; - vtr::vector, std::vector>> sr_instance_sink_child_pin_ids_; - vtr::vector, std::vector>> sr_instance_source_blwl_ids_; + /* WL: [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/ + vtr::vector, std::vector>> wl_sr_instance_sink_child_ids_; + vtr::vector, std::vector>> wl_sr_instance_sink_child_pin_ids_; + vtr::vector, std::vector>> wl_sr_instance_source_blwl_ids_; + }; } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index 8ac019781..8b6603fc5 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -55,7 +55,7 @@ namespace openfpga { ********************************************************************/ void fpga_fabric_verilog(ModuleManager &module_manager, NetlistManager &netlist_manager, - const std::array& blwl_sr_banks, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const CircuitLibrary &circuit_lib, const MuxLibrary &mux_lib, const DecoderLibrary &decoder_lib, diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index ef550c76d..454921e26 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -36,7 +36,7 @@ namespace openfpga { void fpga_fabric_verilog(ModuleManager& module_manager, NetlistManager& netlist_manager, - const std::array& blwl_sr_banks, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const CircuitLibrary& circuit_lib, const MuxLibrary& mux_lib, const DecoderLibrary& decoder_lib, diff --git a/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp b/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp index 4d629a0cb..d950094ab 100644 --- a/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp +++ b/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp @@ -34,7 +34,7 @@ namespace openfpga { ********************************************************************/ void print_verilog_submodule_shift_register_banks(const ModuleManager& module_manager, NetlistManager& netlist_manager, - const std::array& blwl_sr_banks, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const std::string& submodule_dir, const FabricVerilogOption& options) { @@ -54,17 +54,26 @@ void print_verilog_submodule_shift_register_banks(const ModuleManager& module_ma print_verilog_file_header(fp, "Shift register banks used in FPGA"); /* Create the memory circuits for the multiplexer */ - for (const auto& sr_bank : blwl_sr_banks) { - for (const ModuleId& sr_module : sr_bank.shift_register_bank_unique_modules()) { - VTR_ASSERT(true == module_manager.valid_module_id(sr_module)); - /* Write the module content in Verilog format */ - write_verilog_module_to_file(fp, module_manager, sr_module, - options.explicit_port_mapping(), - options.default_net_type()); + for (const ModuleId& sr_module : blwl_sr_banks.bl_shift_register_bank_unique_modules()) { + VTR_ASSERT(true == module_manager.valid_module_id(sr_module)); + /* Write the module content in Verilog format */ + write_verilog_module_to_file(fp, module_manager, sr_module, + options.explicit_port_mapping(), + options.default_net_type()); - /* Add an empty line as a splitter */ - fp << std::endl; - } + /* Add an empty line as a splitter */ + fp << std::endl; + } + + for (const ModuleId& sr_module : blwl_sr_banks.wl_shift_register_bank_unique_modules()) { + VTR_ASSERT(true == module_manager.valid_module_id(sr_module)); + /* Write the module content in Verilog format */ + write_verilog_module_to_file(fp, module_manager, sr_module, + options.explicit_port_mapping(), + options.default_net_type()); + + /* Add an empty line as a splitter */ + fp << std::endl; } /* Close the file stream */ diff --git a/openfpga/src/fpga_verilog/verilog_shift_register_banks.h b/openfpga/src/fpga_verilog/verilog_shift_register_banks.h index 2de1bedee..433104a62 100644 --- a/openfpga/src/fpga_verilog/verilog_shift_register_banks.h +++ b/openfpga/src/fpga_verilog/verilog_shift_register_banks.h @@ -20,7 +20,7 @@ namespace openfpga { void print_verilog_submodule_shift_register_banks(const ModuleManager& module_manager, NetlistManager& netlist_manager, - const std::array& blwl_sr_banks, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const std::string& submodule_dir, const FabricVerilogOption& options); diff --git a/openfpga/src/fpga_verilog/verilog_submodule.cpp b/openfpga/src/fpga_verilog/verilog_submodule.cpp index 0cb2c97a4..b98dd6ecb 100644 --- a/openfpga/src/fpga_verilog/verilog_submodule.cpp +++ b/openfpga/src/fpga_verilog/verilog_submodule.cpp @@ -34,7 +34,7 @@ namespace openfpga { ********************************************************************/ void print_verilog_submodule(ModuleManager& module_manager, NetlistManager& netlist_manager, - const std::array& blwl_sr_banks, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const MuxLibrary& mux_lib, const DecoderLibrary& decoder_lib, const CircuitLibrary& circuit_lib, diff --git a/openfpga/src/fpga_verilog/verilog_submodule.h b/openfpga/src/fpga_verilog/verilog_submodule.h index d25ec4844..a5f88df16 100644 --- a/openfpga/src/fpga_verilog/verilog_submodule.h +++ b/openfpga/src/fpga_verilog/verilog_submodule.h @@ -20,7 +20,7 @@ namespace openfpga { void print_verilog_submodule(ModuleManager& module_manager, NetlistManager& netlist_manager, - const std::array& blwl_sr_banks, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const MuxLibrary& mux_lib, const DecoderLibrary& decoder_lib, const CircuitLibrary& circuit_lib, diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index a4f676b81..b04a28d1c 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -399,7 +399,7 @@ std::vector reshape_bitstream_vectors_to_first_element(const std::v MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream, const bool& fast_configuration, - //const std::array& blwl_sr_banks, + //const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& bit_value_to_skip, const char& dont_care_bit) { MemoryBankFlattenFabricBitstream raw_fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip, dont_care_bit); diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index ff822802e..ac0bca14a 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -96,7 +96,7 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons *******************************************************************/ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream, const bool& fast_configuration, - //const std::array& blwl_sr_banks, + //const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& bit_value_to_skip, const char& dont_care_bit = 'x'); From 39a69e0d888d287aa69b13d6f166c1fb6813a070 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 8 Oct 2021 17:58:06 -0700 Subject: [PATCH 192/229] [Engine] Upgrading fabric generator to support customizable shift register banks from fabric key and configuration protocols --- openfpga/src/fabric/build_top_module.cpp | 13 ++ .../fabric/build_top_module_memory_bank.cpp | 115 ++++++++++++++++++ .../src/fabric/build_top_module_memory_bank.h | 8 ++ .../memory_bank_shift_register_banks.cpp | 47 ++++++- .../fabric/memory_bank_shift_register_banks.h | 11 ++ 5 files changed, 189 insertions(+), 5 deletions(-) diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index 1bd5dc703..b0ab747a8 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -23,6 +23,7 @@ #include "build_top_module_utils.h" #include "build_top_module_connection.h" #include "build_top_module_memory.h" +#include "build_top_module_memory_bank.h" #include "build_top_module_directs.h" #include "build_module_graph_utils.h" @@ -382,6 +383,11 @@ int build_top_module(ModuleManager& module_manager, if (CMD_EXEC_FATAL_ERROR == status) { return status; } + + status = load_top_module_shift_register_banks_from_fabric_key(fabric_key, blwl_sr_banks); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } } /* Shuffle the configurable children in a random sequence */ @@ -389,6 +395,13 @@ int build_top_module(ModuleManager& module_manager, shuffle_top_module_configurable_children(module_manager, top_module, config_protocol); } + /* Build shift register bank detailed connections */ + sync_memory_bank_shift_register_banks_with_config_protocol_settings(module_manager, + blwl_sr_banks, + config_protocol, + top_module, + circuit_lib); + /* Add shared SRAM ports from the sub-modules under this Verilog module * This is a much easier job after adding sub modules (instances), * we just need to find all the I/O ports from the child modules and build a list of it diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index e58ab9b4c..077bf4d78 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -1728,4 +1728,119 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, } } +/******************************************************************** + * Load the shift register bank -related data from fabric key to + * the dedicated and unified data structure + ********************************************************************/ +int load_top_module_shift_register_banks_from_fabric_key(const FabricKey& fabric_key, + MemoryBankShiftRegisterBanks& blwl_sr_banks) { + blwl_sr_banks.resize_regions(fabric_key.regions().size()); + + /* Load Bit-Line shift register banks */ + for (const auto& region : fabric_key.regions()) { + blwl_sr_banks.reserve_bl_shift_register_banks(region, fabric_key.bl_banks(region).size()); + for (const auto& bank : fabric_key.bl_banks(region)) { + FabricBitLineBankId sr_bank = blwl_sr_banks.create_bl_shift_register_bank(region); + for (const auto& data_port : fabric_key.bl_bank_data_ports(region, bank)) { + blwl_sr_banks.add_data_port_to_bl_shift_register_bank(region, sr_bank, data_port); + } + } + } + + /* Load Bit-Line shift register banks */ + for (const auto& region : fabric_key.regions()) { + blwl_sr_banks.reserve_wl_shift_register_banks(region, fabric_key.wl_banks(region).size()); + for (const auto& bank : fabric_key.wl_banks(region)) { + FabricWordLineBankId sr_bank = blwl_sr_banks.create_wl_shift_register_bank(region); + for (const auto& data_port : fabric_key.wl_bank_data_ports(region, bank)) { + blwl_sr_banks.add_data_port_to_wl_shift_register_bank(region, sr_bank, data_port); + } + } + } +} + +/******************************************************************** + * @brief This functions synchronize the settings in configuration protocol (from architecture description) + * and the existing information (loaded from fabric key files) + * @note This function should be called AFTER load_top_module_shift_register_banks_from_fabric_key() + ********************************************************************/ +void sync_memory_bank_shift_register_banks_with_config_protocol_settings(ModuleManager& module_manager, + MemoryBankShiftRegisterBanks& blwl_sr_banks, + const ConfigProtocol& config_protocol, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib) { + /* ONLY synchronize when the configuration protocol is memory bank using shift registers */ + if ( CONFIG_MEM_QL_MEMORY_BANK != config_protocol.type() + || BLWL_PROTOCOL_SHIFT_REGISTER != config_protocol.bl_protocol_type() + || BLWL_PROTOCOL_SHIFT_REGISTER != config_protocol.wl_protocol_type() ) { + return; + } + + /* Fabric key has a higher priority in defining the shift register bank organization */ + if (!blwl_sr_banks.empty()) { + return; + } + + CircuitModelId sram_model = config_protocol.memory_model(); + + /* Reach here, if means we do not have any definition from fabric key files, use the settings from the configuration protocol */ + blwl_sr_banks.resize_regions(module_manager.regions(top_module).size()); + + /* Based on the number of shift register banks, evenly distribute the BLs in each region for each shift register bank */ + for (const auto& config_region : module_manager.regions(top_module)) { + size_t num_bls = compute_memory_bank_regional_num_bls(module_manager, top_module, + config_region, + circuit_lib, sram_model); + size_t num_bl_banks = config_protocol.bl_num_banks(); + blwl_sr_banks.reserve_bl_shift_register_banks(config_region, num_bl_banks); + + size_t regular_sr_bank_size = num_bls / num_bl_banks; + size_t cur_bl_index = 0; + for (size_t ibank = 0; ibank < num_bl_banks; ++ibank) { + /* For last bank, use all the residual sizes */ + size_t cur_sr_bank_size = regular_sr_bank_size; + if (ibank == num_bl_banks - 1) { + cur_sr_bank_size = num_bls - ibank * regular_sr_bank_size; + } + /* Create a bank and assign data ports */ + FabricBitLineBankId bank = blwl_sr_banks.create_bl_shift_register_bank(config_region); + BasicPort data_ports(std::string(MEMORY_BL_PORT_NAME), cur_bl_index, cur_bl_index + cur_sr_bank_size - 1); + blwl_sr_banks.add_data_port_to_bl_shift_register_bank(config_region, bank, data_ports); + + /* Increment the bl index */ + cur_bl_index += cur_sr_bank_size; + } + + VTR_ASSERT(cur_bl_index == num_bls); + } + + /* Based on the number of shift register banks, evenly distribute the WLs in each region for each shift register bank */ + for (const auto& config_region : module_manager.regions(top_module)) { + size_t num_wls = compute_memory_bank_regional_num_wls(module_manager, top_module, + config_region, + circuit_lib, sram_model); + size_t num_wl_banks = config_protocol.wl_num_banks(); + blwl_sr_banks.reserve_wl_shift_register_banks(config_region, num_wl_banks); + + size_t regular_sr_bank_size = num_wls / num_wl_banks; + size_t cur_wl_index = 0; + for (size_t ibank = 0; ibank < num_wl_banks; ++ibank) { + /* For last bank, use all the residual sizes */ + size_t cur_sr_bank_size = regular_sr_bank_size; + if (ibank == num_wl_banks - 1) { + cur_sr_bank_size = num_wls - ibank * regular_sr_bank_size; + } + /* Create a bank and assign data ports */ + FabricWordLineBankId bank = blwl_sr_banks.create_wl_shift_register_bank(config_region); + BasicPort data_ports(std::string(MEMORY_WL_PORT_NAME), cur_wl_index, cur_wl_index + cur_sr_bank_size - 1); + blwl_sr_banks.add_data_port_to_wl_shift_register_bank(config_region, bank, data_ports); + + /* Increment the bl index */ + cur_wl_index += cur_sr_bank_size; + } + + VTR_ASSERT(cur_wl_index == num_wls); + } +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_memory_bank.h b/openfpga/src/fabric/build_top_module_memory_bank.h index 5617271df..74bcdcc7a 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.h +++ b/openfpga/src/fabric/build_top_module_memory_bank.h @@ -38,6 +38,14 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, const ConfigProtocol& config_protocol, const TopModuleNumConfigBits& num_config_bits); +int load_top_module_shift_register_banks_from_fabric_key(const FabricKey& fabric_key, + MemoryBankShiftRegisterBanks& blwl_sr_banks); + +void sync_memory_bank_shift_register_banks_with_config_protocol_settings(ModuleManager& module_manager, + MemoryBankShiftRegisterBanks& blwl_sr_banks, + const ConfigProtocol& config_protocol, + const ModuleId& top_module, + const CircuitLibrary& circuit_lib); } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index 43278f2f5..bdd403ebc 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -275,12 +275,22 @@ void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const ConfigR bl_bank_data_ports_[region_id].reserve(num_banks); } +void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) { + ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); + reserve_bl_shift_register_banks(config_region_id, num_banks); +} + void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks) { VTR_ASSERT(valid_region_id(region_id)); wl_bank_ids_[region_id].reserve(num_banks); wl_bank_data_ports_[region_id].reserve(num_banks); } +void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) { + ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); + reserve_wl_shift_register_banks(config_region_id, num_banks); +} + FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank(const ConfigRegionId& region_id) { VTR_ASSERT(valid_region_id(region_id)); @@ -292,13 +302,30 @@ FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank( return bank; } +FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank(const FabricRegionId& region_id) { + ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); + return create_bl_shift_register_bank(config_region_id); +} + +void MemoryBankShiftRegisterBanks::add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id, + const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port) { + ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); + add_data_port_to_bl_shift_register_bank(config_region_id, bank_id, data_port); +} + void MemoryBankShiftRegisterBanks::add_data_port_to_bl_shift_register_bank(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const openfpga::BasicPort& data_port) { + const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port) { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); bl_bank_data_ports_[region_id][bank_id].push_back(data_port); } +FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank(const FabricRegionId& region_id) { + ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); + return create_wl_shift_register_bank(config_region_id); +} + FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank(const ConfigRegionId& region_id) { VTR_ASSERT(valid_region_id(region_id)); @@ -310,14 +337,20 @@ FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank return bank; } +void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id, + const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port) { + ConfigRegionId config_region_id = ConfigRegionId(size_t(region_id)); + add_data_port_to_wl_shift_register_bank(config_region_id, bank_id, data_port); +} + void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id, - const openfpga::BasicPort& data_port) { + const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port) { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); wl_bank_data_ports_[region_id][bank_id].push_back(data_port); } - bool MemoryBankShiftRegisterBanks::valid_region_id(const ConfigRegionId& region) const { return size_t(region) < bl_sr_instance_sink_child_ids_.size(); } @@ -336,4 +369,8 @@ bool MemoryBankShiftRegisterBanks::valid_wl_bank_id(const ConfigRegionId& region return ( size_t(bank_id) < wl_bank_ids_[region_id].size() ) && ( bank_id == wl_bank_ids_[region_id][bank_id] ); } +bool MemoryBankShiftRegisterBanks::empty() const { + return bl_bank_ids_.empty() && wl_bank_ids_.empty(); +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h index 740d2676d..0041df1ac 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.h +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -108,21 +108,31 @@ class MemoryBankShiftRegisterBanks { void resize_regions(const size_t& num_regions); /* Reserve a number of banks to be memory efficent */ + void reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks); void reserve_bl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks); + void reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks); void reserve_wl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks); /* Create a new shift register bank for BLs and return an id */ + FabricBitLineBankId create_bl_shift_register_bank(const FabricRegionId& region_id); FabricBitLineBankId create_bl_shift_register_bank(const ConfigRegionId& region_id); /* Add a data port to a given BL shift register bank */ + void add_data_port_to_bl_shift_register_bank(const FabricRegionId& region_id, + const FabricBitLineBankId& bank_id, + const openfpga::BasicPort& data_port); void add_data_port_to_bl_shift_register_bank(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id, const openfpga::BasicPort& data_port); /* Create a new shift register bank for WLs and return an id */ + FabricWordLineBankId create_wl_shift_register_bank(const FabricRegionId& region_id); FabricWordLineBankId create_wl_shift_register_bank(const ConfigRegionId& region_id); /* Add a data port to a given WL shift register bank */ + void add_data_port_to_wl_shift_register_bank(const FabricRegionId& region_id, + const FabricWordLineBankId& bank_id, + const openfpga::BasicPort& data_port); void add_data_port_to_wl_shift_register_bank(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id, const openfpga::BasicPort& data_port); @@ -167,6 +177,7 @@ class MemoryBankShiftRegisterBanks { bool valid_region_id(const ConfigRegionId& region) const; bool valid_bl_bank_id(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; bool valid_wl_bank_id(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; + bool empty() const; private: /* Internal data */ /* General information about the BL shift register bank */ From e3ff40d9e0144c9df3d7024855309bd37567209d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 8 Oct 2021 20:17:55 -0700 Subject: [PATCH 193/229] [Engine] Add missing return value --- openfpga/src/fabric/build_top_module_memory_bank.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 077bf4d78..0a3186453 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -1757,6 +1757,8 @@ int load_top_module_shift_register_banks_from_fabric_key(const FabricKey& fabric } } } + + return 0; } /******************************************************************** From 932beb480a7a6873658cf5a3f77314d5e720a82f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 8 Oct 2021 22:00:01 -0700 Subject: [PATCH 194/229] [Engine] Add fast look-up to the shift register bank data structure --- .../memory_bank_shift_register_banks.cpp | 103 ++++++++++++++++++ .../fabric/memory_bank_shift_register_banks.h | 32 ++++++ 2 files changed, 135 insertions(+) diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index bdd403ebc..0c5855ae8 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -1,5 +1,6 @@ #include #include "vtr_assert.h" +#include "openfpga_reserved_words.h" #include "memory_bank_shift_register_banks.h" /* begin namespace openfpga */ @@ -201,6 +202,62 @@ std::vector MemoryBankShiftRegisterBanks::wl_bank_data_ports(const Co return wl_bank_data_ports_[region_id][bank_id]; } +FabricBitLineBankId MemoryBankShiftRegisterBanks::find_bl_shift_register_bank_id(const ConfigRegionId& region, + const BasicPort& bl_port) const { + if (is_bl_bank_dirty_) { + build_bl_port_fast_lookup(); + } + + VTR_ASSERT(valid_region_id(region)); + const auto& result = bl_ports_to_sr_bank_ids_[region].find(bl_port); + if (result == bl_ports_to_sr_bank_ids_[region].end()) { + return FabricBitLineBankId::INVALID(); + } + return result->second; +} + +BasicPort MemoryBankShiftRegisterBanks::find_bl_shift_register_bank_data_port(const ConfigRegionId& region, + const BasicPort& bl_port) const { + if (is_bl_bank_dirty_) { + build_bl_port_fast_lookup(); + } + + VTR_ASSERT(valid_region_id(region)); + const auto& result = bl_ports_to_sr_bank_ports_[region].find(bl_port); + if (result == bl_ports_to_sr_bank_ports_[region].end()) { + return BasicPort(); + } + return result->second; +} + +FabricWordLineBankId MemoryBankShiftRegisterBanks::find_wl_shift_register_bank_id(const ConfigRegionId& region, + const BasicPort& wl_port) const { + if (is_wl_bank_dirty_) { + build_wl_port_fast_lookup(); + } + + VTR_ASSERT(valid_region_id(region)); + const auto& result = wl_ports_to_sr_bank_ids_[region].find(wl_port); + if (result == wl_ports_to_sr_bank_ids_[region].end()) { + return FabricWordLineBankId::INVALID(); + } + return result->second; +} + +BasicPort MemoryBankShiftRegisterBanks::find_wl_shift_register_bank_data_port(const ConfigRegionId& region, + const BasicPort& wl_port) const { + if (is_wl_bank_dirty_) { + build_wl_port_fast_lookup(); + } + + VTR_ASSERT(valid_region_id(region)); + const auto& result = wl_ports_to_sr_bank_ports_[region].find(wl_port); + if (result == wl_ports_to_sr_bank_ports_[region].end()) { + return BasicPort(); + } + return result->second; +} + void MemoryBankShiftRegisterBanks::resize_regions(const size_t& num_regions) { bl_bank_ids_.resize(num_regions); bl_bank_data_ports_.resize(num_regions); @@ -319,6 +376,7 @@ void MemoryBankShiftRegisterBanks::add_data_port_to_bl_shift_register_bank(const const openfpga::BasicPort& data_port) { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); bl_bank_data_ports_[region_id][bank_id].push_back(data_port); + is_bl_bank_dirty_ = true; } FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank(const FabricRegionId& region_id) { @@ -349,6 +407,7 @@ void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank(const const openfpga::BasicPort& data_port) { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); wl_bank_data_ports_[region_id][bank_id].push_back(data_port); + is_wl_bank_dirty_ = true; } bool MemoryBankShiftRegisterBanks::valid_region_id(const ConfigRegionId& region) const { @@ -373,4 +432,48 @@ bool MemoryBankShiftRegisterBanks::empty() const { return bl_bank_ids_.empty() && wl_bank_ids_.empty(); } +void MemoryBankShiftRegisterBanks::build_bl_port_fast_lookup() const { + bl_ports_to_sr_bank_ids_.resize(bl_bank_data_ports_.size()); + for (const auto& region : bl_bank_data_ports_) { + size_t bl_index = 0; + for (const auto& bank : region) { + for (const auto& port : bank) { + for (const auto& pin : port.pins()) { + BasicPort bl_port(std::string(MEMORY_BL_PORT_NAME), bl_index, bl_index); + BasicPort sr_bl_port(std::string(MEMORY_BL_PORT_NAME), pin, pin); + ConfigRegionId region_id = ConfigRegionId(®ion - &bl_bank_data_ports_[ConfigRegionId(0)]); + FabricBitLineBankId bank_id = FabricBitLineBankId(&bank - ®ion[FabricBitLineBankId(0)]); + bl_ports_to_sr_bank_ids_[region_id][bl_port] = bank_id; + bl_ports_to_sr_bank_ports_[region_id][bl_port] = sr_bl_port; + bl_index++; + } + } + } + } + /* Clear the flag, now fast look-up is synchronized */ + is_bl_bank_dirty_ = false; +} + +void MemoryBankShiftRegisterBanks::build_wl_port_fast_lookup() const { + wl_ports_to_sr_bank_ids_.resize(wl_bank_data_ports_.size()); + for (const auto& region : wl_bank_data_ports_) { + size_t wl_index = 0; + for (const auto& bank : region) { + for (const auto& port : bank) { + for (const auto& pin : port.pins()) { + BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), wl_index, wl_index); + BasicPort sr_wl_port(std::string(MEMORY_WL_PORT_NAME), pin, pin); + ConfigRegionId region_id = ConfigRegionId(®ion - &wl_bank_data_ports_[ConfigRegionId(0)]); + FabricWordLineBankId bank_id = FabricWordLineBankId(&bank - ®ion[FabricWordLineBankId(0)]); + wl_ports_to_sr_bank_ids_[region_id][wl_port] = bank_id; + wl_ports_to_sr_bank_ports_[region_id][wl_port] = sr_wl_port; + wl_index++; + } + } + } + } + /* Clear the flag, now fast look-up is synchronized */ + is_wl_bank_dirty_ = false; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h index 0041df1ac..7a3eb2188 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.h +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -104,6 +104,18 @@ class MemoryBankShiftRegisterBanks { const ModuleId& sr_module, const size_t& sr_instance) const; + /** @brief find the BL shift register bank id to which a BL port is connected to */ + FabricBitLineBankId find_bl_shift_register_bank_id(const ConfigRegionId& region, const BasicPort& bl_port) const; + + /** @brief find the data port of a BL shift register bank id to which a BL port is connected to */ + BasicPort find_bl_shift_register_bank_data_port(const ConfigRegionId& region, const BasicPort& bl_port) const; + + /** @brief find the WL shift register bank id to which a BL port is connected to */ + FabricWordLineBankId find_wl_shift_register_bank_id(const ConfigRegionId& region, const BasicPort& wl_port) const; + + /** @brief find the data port of a WL shift register bank id to which a BL port is connected to */ + BasicPort find_wl_shift_register_bank_data_port(const ConfigRegionId& region, const BasicPort& wl_port) const; + public: /* Mutators */ void resize_regions(const size_t& num_regions); @@ -179,6 +191,14 @@ class MemoryBankShiftRegisterBanks { bool valid_wl_bank_id(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; bool empty() const; + private: /* Internal Mutators */ + /** @brief Build the mapping from a BL/WL port to shift register bank and assoicated pins + * @note we use const here because the caller functions, e.g., find_bl_shift_register_bank_id(), is const + * even though it does modify internal data + */ + void build_bl_port_fast_lookup() const; + void build_wl_port_fast_lookup() const; + private: /* Internal data */ /* General information about the BL shift register bank */ vtr::vector> bl_bank_ids_; @@ -198,6 +218,18 @@ class MemoryBankShiftRegisterBanks { vtr::vector, std::vector>> wl_sr_instance_sink_child_pin_ids_; vtr::vector, std::vector>> wl_sr_instance_source_blwl_ids_; + /* Fast look-up: given a BL/Wl port, e.g., bl[i], find out + * - the shift register bank id + * - the output pin id of the shift register bank + */ + mutable vtr::vector> bl_ports_to_sr_bank_ids_; + mutable vtr::vector> bl_ports_to_sr_bank_ports_; + mutable vtr::vector> wl_ports_to_sr_bank_ids_; + mutable vtr::vector> wl_ports_to_sr_bank_ports_; + + /* A flag to indicate that the general information of the shift register banks have been modified, fast look-up has to be updated */ + mutable bool is_bl_bank_dirty_ = false; + mutable bool is_wl_bank_dirty_ = false; }; } /* end namespace openfpga */ From 19a551e6416c4f3bcb9bcf19265700ea8c42d692 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 9 Oct 2021 16:44:04 -0700 Subject: [PATCH 195/229] [Engine] Upgrade fabric generator to support multiple shift register banks in a configuration region --- openfpga/src/fabric/build_top_module.cpp | 1 + .../src/fabric/build_top_module_memory.cpp | 3 +- openfpga/src/fabric/build_top_module_memory.h | 1 + .../fabric/build_top_module_memory_bank.cpp | 435 +++++++++++------- .../src/fabric/build_top_module_memory_bank.h | 1 + .../memory_bank_shift_register_banks.cpp | 402 ++++++++-------- .../fabric/memory_bank_shift_register_banks.h | 216 +++++---- .../verilog_shift_register_banks.cpp | 4 +- 8 files changed, 574 insertions(+), 489 deletions(-) diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index b0ab747a8..2aad3f1f4 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -421,6 +421,7 @@ int build_top_module(ModuleManager& module_manager, add_top_module_sram_ports(module_manager, top_module, circuit_lib, sram_model, config_protocol, + const_cast(blwl_sr_banks), top_module_num_config_bits); } diff --git a/openfpga/src/fabric/build_top_module_memory.cpp b/openfpga/src/fabric/build_top_module_memory.cpp index 9da2a3641..aee05c61c 100644 --- a/openfpga/src/fabric/build_top_module_memory.cpp +++ b/openfpga/src/fabric/build_top_module_memory.cpp @@ -807,6 +807,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const TopModuleNumConfigBits& num_config_bits) { std::vector sram_port_names = generate_sram_port_names(circuit_lib, sram_model, config_protocol.type()); size_t total_num_config_bits = 0; @@ -852,7 +853,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, break; } case CONFIG_MEM_QL_MEMORY_BANK: { - add_top_module_ql_memory_bank_sram_ports(module_manager, module_id, circuit_lib, config_protocol, num_config_bits); + add_top_module_ql_memory_bank_sram_ports(module_manager, module_id, circuit_lib, config_protocol, blwl_sr_banks, num_config_bits); break; } case CONFIG_MEM_SCAN_CHAIN: { diff --git a/openfpga/src/fabric/build_top_module_memory.h b/openfpga/src/fabric/build_top_module_memory.h index be4589490..244f6bfee 100644 --- a/openfpga/src/fabric/build_top_module_memory.h +++ b/openfpga/src/fabric/build_top_module_memory.h @@ -61,6 +61,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager, const CircuitLibrary& circuit_lib, const CircuitModelId& sram_model, const ConfigProtocol& config_protocol, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const TopModuleNumConfigBits& num_config_bits); void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 0a3186453..900eb8bb3 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -1073,49 +1073,36 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(ModuleManager /********************************************************************* * This function to add nets for QuickLogic memory bank - * We build the net connects between the head ports of shift register banks + * We build the net connects between the head ports of BL shift register banks * and the head ports of top-level module - * @note This function is applicable to both BL and WL shift registers **********************************************************************/ static -void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_heads(ModuleManager& module_manager, - const ModuleId& top_module, - const MemoryBankShiftRegisterBanks& sr_banks, - const std::string& head_port_name) { - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - ModulePortId blsr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(head_port_name, config_region)); - BasicPort blsr_head_port_info = module_manager.module_port(top_module, blsr_head_port); +void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_heads(ModuleManager& module_manager, + const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks) { + std::string head_port_name(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME); - size_t num_sr_bank_modules; - if (std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME) == head_port_name) { - num_sr_bank_modules = sr_banks.bl_shift_register_bank_modules(config_region).size(); - } else { - VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME) == head_port_name); - num_sr_bank_modules = sr_banks.wl_shift_register_bank_modules(config_region).size(); - } - for (size_t iinst = 0; iinst < num_sr_bank_modules; ++iinst) { - ModuleId sr_bank_module; - size_t sr_bank_instance; - if (std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME) == head_port_name) { - sr_bank_module = sr_banks.bl_shift_register_bank_modules(config_region)[iinst]; - sr_bank_instance = sr_banks.bl_shift_register_bank_instances(config_region)[iinst]; - } else { - VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME) == head_port_name); - sr_bank_module = sr_banks.wl_shift_register_bank_modules(config_region)[iinst]; - sr_bank_instance = sr_banks.wl_shift_register_bank_instances(config_region)[iinst]; - } + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + ModulePortId sr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(head_port_name, config_region)); + BasicPort sr_head_port_info = module_manager.module_port(top_module, sr_head_port); + + /* Iterate over each shift register banks */ + for (const auto& bank : sr_banks.bl_banks(config_region)) { + /* Get the module and instance ids */ + ModuleId sr_bank_module = sr_banks.bl_shift_register_bank_module(config_region, bank); + size_t sr_bank_instance = sr_banks.bl_shift_register_bank_instance(config_region, bank); VTR_ASSERT(sr_bank_module); ModulePortId sr_module_head_port = module_manager.find_module_port(sr_bank_module, head_port_name); BasicPort sr_module_head_port_info = module_manager.module_port(sr_bank_module, sr_module_head_port); - VTR_ASSERT(sr_module_head_port_info.get_width() == blsr_head_port_info.get_width()); + VTR_ASSERT(sr_module_head_port_info.get_width() == 1); for (size_t ipin = 0; ipin < sr_module_head_port_info.pins().size(); ++ipin) { /* Create net */ ModuleNetId net = create_module_source_pin_net(module_manager, top_module, top_module, 0, - blsr_head_port, - blsr_head_port_info.pins()[ipin]); + sr_head_port, + sr_head_port_info.pins()[size_t(bank)]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ @@ -1128,41 +1115,70 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_heads(ModuleMan /********************************************************************* * This function to add nets for QuickLogic memory bank - * We build the net connects between the head ports of shift register banks + * We build the net connects between the head ports of BL shift register banks * and the head ports of top-level module - * @note This function is applicable to both BL and WL shift registers **********************************************************************/ static -void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(ModuleManager& module_manager, - const ModuleId& top_module, - const MemoryBankShiftRegisterBanks& sr_banks, - const std::string& tail_port_name) { - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - ModulePortId blsr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(tail_port_name, config_region)); - BasicPort blsr_tail_port_info = module_manager.module_port(top_module, blsr_tail_port); +void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_heads(ModuleManager& module_manager, + const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks) { + std::string head_port_name(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME); - size_t num_sr_bank_modules; - if (std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME) == tail_port_name) { - num_sr_bank_modules = sr_banks.bl_shift_register_bank_modules(config_region).size(); - } else { - VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME) == tail_port_name); - num_sr_bank_modules = sr_banks.wl_shift_register_bank_modules(config_region).size(); - } - for (size_t iinst = 0; iinst < num_sr_bank_modules; ++iinst) { - ModuleId sr_bank_module; - size_t sr_bank_instance; - if (std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME) == tail_port_name) { - sr_bank_module = sr_banks.bl_shift_register_bank_modules(config_region)[iinst]; - sr_bank_instance = sr_banks.bl_shift_register_bank_instances(config_region)[iinst]; - } else { - VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME) == tail_port_name); - sr_bank_module = sr_banks.wl_shift_register_bank_modules(config_region)[iinst]; - sr_bank_instance = sr_banks.wl_shift_register_bank_instances(config_region)[iinst]; + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + ModulePortId sr_head_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(head_port_name, config_region)); + BasicPort sr_head_port_info = module_manager.module_port(top_module, sr_head_port); + + /* Iterate over each shift register banks */ + for (const auto& bank : sr_banks.wl_banks(config_region)) { + /* Get the module and instance ids */ + ModuleId sr_bank_module = sr_banks.wl_shift_register_bank_module(config_region, bank); + size_t sr_bank_instance = sr_banks.wl_shift_register_bank_instance(config_region, bank); + + VTR_ASSERT(sr_bank_module); + + ModulePortId sr_module_head_port = module_manager.find_module_port(sr_bank_module, head_port_name); + BasicPort sr_module_head_port_info = module_manager.module_port(sr_bank_module, sr_module_head_port); + VTR_ASSERT(sr_module_head_port_info.get_width() == 1); + for (size_t ipin = 0; ipin < sr_module_head_port_info.pins().size(); ++ipin) { + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + top_module, 0, + sr_head_port, + sr_head_port_info.pins()[size_t(bank)]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + sr_bank_module, sr_bank_instance, sr_module_head_port, sr_module_head_port_info.pins()[ipin]); } + } + } +} + +/********************************************************************* + * This function to add nets for QuickLogic memory bank + * We build the net connects between the tail ports of BL shift register banks + * and the tail ports of top-level module + **********************************************************************/ +static +void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_tails(ModuleManager& module_manager, + const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks) { + std::string tail_port_name(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME); + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + ModulePortId sr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(tail_port_name, config_region)); + BasicPort sr_tail_port_info = module_manager.module_port(top_module, sr_tail_port); + + /* Iterate over each shift register banks */ + for (const auto& bank : sr_banks.bl_banks(config_region)) { + /* Get the module and instance ids */ + ModuleId sr_bank_module = sr_banks.bl_shift_register_bank_module(config_region, bank); + size_t sr_bank_instance = sr_banks.bl_shift_register_bank_instance(config_region, bank); + VTR_ASSERT(sr_bank_module); ModulePortId sr_module_tail_port = module_manager.find_module_port(sr_bank_module, tail_port_name); BasicPort sr_module_tail_port_info = module_manager.module_port(sr_bank_module, sr_module_tail_port); - VTR_ASSERT(sr_module_tail_port_info.get_width() == blsr_tail_port_info.get_width()); + VTR_ASSERT(sr_module_tail_port_info.get_width() == 1); for (size_t ipin = 0; ipin < sr_module_tail_port_info.pins().size(); ++ipin) { /* Create net */ ModuleNetId net = create_module_source_pin_net(module_manager, top_module, @@ -1173,7 +1189,47 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(ModuleMan /* Add net sink */ module_manager.add_module_net_sink(top_module, net, top_module, 0, - blsr_tail_port, blsr_tail_port_info.pins()[ipin]); + sr_tail_port, sr_tail_port_info.pins()[size_t(bank)]); + } + } + } +} + +/********************************************************************* + * This function to add nets for QuickLogic memory bank + * We build the net connects between the tail ports of WL shift register banks + * and the tail ports of top-level module + **********************************************************************/ +static +void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_tails(ModuleManager& module_manager, + const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks) { + std::string tail_port_name(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME); + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + ModulePortId sr_tail_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(tail_port_name, config_region)); + BasicPort sr_tail_port_info = module_manager.module_port(top_module, sr_tail_port); + + /* Iterate over each shift register banks */ + for (const auto& bank : sr_banks.wl_banks(config_region)) { + /* Get the module and instance ids */ + ModuleId sr_bank_module = sr_banks.wl_shift_register_bank_module(config_region, bank); + size_t sr_bank_instance = sr_banks.wl_shift_register_bank_instance(config_region, bank); + VTR_ASSERT(sr_bank_module); + + ModulePortId sr_module_tail_port = module_manager.find_module_port(sr_bank_module, tail_port_name); + BasicPort sr_module_tail_port_info = module_manager.module_port(sr_bank_module, sr_module_tail_port); + VTR_ASSERT(sr_module_tail_port_info.get_width() == 1); + for (size_t ipin = 0; ipin < sr_module_tail_port_info.pins().size(); ++ipin) { + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + sr_bank_module, sr_bank_instance, + sr_module_tail_port, sr_module_tail_port_info.pins()[ipin]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + module_manager.add_module_net_sink(top_module, net, + top_module, 0, + sr_tail_port, sr_tail_port_info.pins()[size_t(bank)]); } } } @@ -1206,32 +1262,18 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(ModuleMan * @note optional BL/WL is applicable to WLR, which may not always exist */ static -void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleManager& module_manager, - const ModuleId& top_module, - const MemoryBankShiftRegisterBanks& sr_banks, - const std::string& sr_blwl_port_name, - const std::string& child_blwl_port_name, - const bool& optional_blwl = false) { +void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_bls(ModuleManager& module_manager, + const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks, + const std::string sr_blwl_port_name, + const std::string& child_blwl_port_name, + const bool& optional_blwl = false) { for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - size_t num_sr_bank_modules; - if (std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME) == sr_blwl_port_name) { - num_sr_bank_modules = sr_banks.bl_shift_register_bank_modules(config_region).size(); - } else { - VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME) == sr_blwl_port_name); - num_sr_bank_modules = sr_banks.wl_shift_register_bank_modules(config_region).size(); - } - for (size_t iinst = 0; iinst < num_sr_bank_modules; ++iinst) { - ModuleId sr_bank_module; - size_t sr_bank_instance; - if (std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME) == sr_blwl_port_name) { - sr_bank_module = sr_banks.bl_shift_register_bank_modules(config_region)[iinst]; - sr_bank_instance = sr_banks.bl_shift_register_bank_instances(config_region)[iinst]; - } else { - VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME) == sr_blwl_port_name); - sr_bank_module = sr_banks.wl_shift_register_bank_modules(config_region)[iinst]; - sr_bank_instance = sr_banks.wl_shift_register_bank_instances(config_region)[iinst]; - } - + /* Iterate over each shift register banks */ + for (const auto& bank : sr_banks.bl_banks(config_region)) { + /* Get the module and instance ids */ + ModuleId sr_bank_module = sr_banks.bl_shift_register_bank_module(config_region, bank); + size_t sr_bank_instance = sr_banks.bl_shift_register_bank_instance(config_region, bank); VTR_ASSERT(sr_bank_module); ModulePortId sr_module_blwl_port = module_manager.find_module_port(sr_bank_module, sr_blwl_port_name); @@ -1241,23 +1283,8 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan VTR_ASSERT(sr_module_blwl_port); BasicPort sr_module_blwl_port_info = module_manager.module_port(sr_bank_module, sr_module_blwl_port); - size_t num_sink_child_ids; - if (std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME) == sr_blwl_port_name) { - num_sink_child_ids = sr_banks.bl_shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance).size(); - } else { - VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME) == sr_blwl_port_name); - num_sink_child_ids = sr_banks.wl_shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance).size(); - } - - for (size_t sink_id = 0; sink_id < num_sink_child_ids; ++sink_id) { - size_t child_id; - if (std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME) == sr_blwl_port_name) { - child_id = sr_banks.bl_shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; - } else { - VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME) == sr_blwl_port_name); - child_id = sr_banks.wl_shift_register_bank_sink_child_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; - } - + for (const BasicPort& src_port : sr_banks.bl_shift_register_bank_source_ports(config_region, bank)) { + size_t child_id = sr_banks.bl_shift_register_bank_sink_child_id(config_region, bank, src_port); ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; @@ -1265,32 +1292,93 @@ void add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(ModuleMan ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name); BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port); - size_t cur_sr_module_blwl_pin_id; - if (std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME) == sr_blwl_port_name) { - cur_sr_module_blwl_pin_id = sr_banks.bl_shift_register_bank_source_blwl_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; - } else { - VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME) == sr_blwl_port_name); - cur_sr_module_blwl_pin_id = sr_banks.wl_shift_register_bank_source_blwl_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; - } - + VTR_ASSERT(1 == src_port.get_width()); /* Create net */ ModuleNetId net = create_module_source_pin_net(module_manager, top_module, sr_bank_module, sr_bank_instance, sr_module_blwl_port, - sr_module_blwl_port_info.pins()[cur_sr_module_blwl_pin_id]); + src_port.pins()[0]); VTR_ASSERT(ModuleNetId::INVALID() != net); /* Add net sink */ - size_t sink_pin_id; - if (std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME) == sr_blwl_port_name) { - sink_pin_id = sr_banks.bl_shift_register_bank_sink_pin_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; - } else { - VTR_ASSERT(std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME) == sr_blwl_port_name); - sink_pin_id = sr_banks.wl_shift_register_bank_sink_pin_ids(config_region, sr_bank_module, sr_bank_instance)[sink_id]; - } - + size_t sink_child_pin_id = sr_banks.bl_shift_register_bank_sink_child_pin_id(config_region, bank, src_port); module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_blwl_port, sink_pin_id); + child_module, child_instance, child_blwl_port, sink_child_pin_id); + } + } + } +} + + +/************************************************************** + * Add BL/WL nets from shift register module to each configurable child + * BL pins of shift register module are connected to the BL input pins of each PB/CB/SB + * For all the PB/CB/SB in the same column, they share the same set of BLs + * A quick example + * + * +-----------------------+ + * | Shift register chain | + * +-----------------------+ + * BL[i .. i + sqrt(N)] + * | + * | CLB[1][H] + * | +---------+ + * | | SRAM | + * +-->| [0..N] | + * | +---------+ + * | + * ... + * | CLB[1][1] + * | +---------+ + * | | SRAM | + * +-->| [0..N] | + * | +---------+ + * | + * @note optional BL/WL is applicable to WLR, which may not always exist + */ +static +void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls(ModuleManager& module_manager, + const ModuleId& top_module, + const MemoryBankShiftRegisterBanks& sr_banks, + const std::string sr_blwl_port_name, + const std::string& child_blwl_port_name, + const bool& optional_blwl = false) { + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + /* Iterate over each shift register banks */ + for (const auto& bank : sr_banks.wl_banks(config_region)) { + /* Get the module and instance ids */ + ModuleId sr_bank_module = sr_banks.wl_shift_register_bank_module(config_region, bank); + size_t sr_bank_instance = sr_banks.wl_shift_register_bank_instance(config_region, bank); + VTR_ASSERT(sr_bank_module); + + ModulePortId sr_module_blwl_port = module_manager.find_module_port(sr_bank_module, sr_blwl_port_name); + if (!sr_module_blwl_port && optional_blwl) { + continue; + } + VTR_ASSERT(sr_module_blwl_port); + BasicPort sr_module_blwl_port_info = module_manager.module_port(sr_bank_module, sr_module_blwl_port); + + for (const BasicPort& src_port : sr_banks.wl_shift_register_bank_source_ports(config_region, bank)) { + size_t child_id = sr_banks.wl_shift_register_bank_sink_child_id(config_region, bank, src_port); + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the BL port */ + ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name); + BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port); + + VTR_ASSERT(1 == src_port.get_width()); + /* Create net */ + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + sr_bank_module, sr_bank_instance, + sr_module_blwl_port, + src_port.pins()[0]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Add net sink */ + size_t sink_child_pin_id = sr_banks.wl_shift_register_bank_sink_child_pin_id(config_region, bank, src_port); + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_blwl_port, sink_child_pin_id); } } } @@ -1358,15 +1446,7 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module CircuitModelId sram_model = config_protocol.memory_model(); CircuitModelId bl_memory_model = config_protocol.bl_memory_model(); /* Find out the unique shift register chain sizes */ - vtr::vector unique_sr_sizes; - unique_sr_sizes.resize(module_manager.regions(top_module).size()); - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - /* TODO: Need to find how to cut the BLs when there are multiple banks for shift registers in a region */ - size_t num_bls = compute_memory_bank_regional_num_bls(module_manager, top_module, - config_region, - circuit_lib, sram_model); - unique_sr_sizes[config_region] = num_bls; - } + std::vector unique_sr_sizes = sr_banks.bl_bank_unique_sizes(); /* Build submodules for shift register chains */ for (const size_t& sr_size : unique_sr_sizes) { @@ -1379,17 +1459,22 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module } /* Instanciate the shift register chains in the top-level module */ - sr_banks.resize_regions(module_manager.regions(top_module).size()); for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), unique_sr_sizes[config_region]); - ModuleId sr_bank_module = module_manager.find_module(sr_module_name); - VTR_ASSERT(sr_bank_module); + for (const FabricBitLineBankId& sr_bank : sr_banks.bl_banks(config_region)) { + size_t bl_bank_size = sr_banks.bl_bank_size(config_region, sr_bank); + std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(bl_memory_model), bl_bank_size); + ModuleId sr_bank_module = module_manager.find_module(sr_module_name); + VTR_ASSERT(sr_bank_module); - size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module); - module_manager.add_child_module(top_module, sr_bank_module); + size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module); + module_manager.add_child_module(top_module, sr_bank_module); - sr_banks.add_bl_shift_register_instance(config_region, sr_bank_module, cur_inst); + sr_banks.link_bl_shift_register_bank_to_module(config_region, sr_bank, sr_bank_module); + sr_banks.link_bl_shift_register_bank_to_instance(config_region, sr_bank, cur_inst); + } + } + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric * The distribution is a matrix which contains the starting index of BL/WL for each column or row @@ -1411,10 +1496,13 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module size_t cur_bl_index = 0; for (const size_t& sink_bl_pin : child_bl_port_info.pins()) { + /* Find the shift register bank id for the driving BL port */ size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index; + BasicPort src_bl_port(std::string(MEMORY_BL_PORT_NAME), bl_pin_id, bl_pin_id); + FabricBitLineBankId sr_bank = sr_banks.find_bl_shift_register_bank_id(config_region, src_bl_port); + BasicPort sr_bank_port = sr_banks.find_bl_shift_register_bank_data_port(config_region, src_bl_port); - sr_banks.add_bl_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_bl_pin); - sr_banks.add_bl_shift_register_source_blwls(config_region, sr_bank_module, cur_inst, bl_pin_id); + sr_banks.add_bl_shift_register_bank_sink_node(config_region, sr_bank, sr_bank_port, child_id, sink_bl_pin); cur_bl_index++; } @@ -1425,16 +1513,14 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module * - Connect the head port from top-level module to each shift register bank * - Connect the tail port from each shift register bank to top-level module */ - add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_heads(module_manager, top_module, sr_banks, - std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME)); + add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_heads(module_manager, top_module, sr_banks); - add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(module_manager, top_module, sr_banks, - std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); + add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_tails(module_manager, top_module, sr_banks); /* Create connections between BLs of top-level module and BLs of child modules for each region */ - add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks, - std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME), - std::string(MEMORY_BL_PORT_NAME)); + add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_bls(module_manager, top_module, sr_banks, + std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME), + std::string(MEMORY_BL_PORT_NAME)); } /********************************************************************* @@ -1453,16 +1539,9 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module CircuitModelId sram_model = config_protocol.memory_model(); CircuitModelId wl_memory_model = config_protocol.wl_memory_model(); /* Find out the unique shift register chain sizes */ - vtr::vector unique_sr_sizes; - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - /* TODO: Need to find how to cut the BLs when there are multiple banks for shift registers in a region */ - size_t num_wls = compute_memory_bank_regional_num_wls(module_manager, top_module, - config_region, - circuit_lib, sram_model); - unique_sr_sizes.push_back(num_wls); - } + std::vector unique_sr_sizes = sr_banks.wl_bank_unique_sizes(); - /* TODO: Build submodules for shift register chains */ + /* Build submodules for shift register chains */ for (const size_t& sr_size : unique_sr_sizes) { std::string sr_module_name = generate_wl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), sr_size); build_wl_shift_register_chain_module(module_manager, @@ -1473,17 +1552,22 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module } /* Instanciate the shift register chains in the top-level module */ - sr_banks.resize_regions(module_manager.regions(top_module).size()); for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - std::string sr_module_name = generate_wl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), unique_sr_sizes[config_region]); - ModuleId sr_bank_module = module_manager.find_module(sr_module_name); - VTR_ASSERT(sr_bank_module); + for (const FabricWordLineBankId& sr_bank : sr_banks.wl_banks(config_region)) { + size_t wl_bank_size = sr_banks.wl_bank_size(config_region, sr_bank); + std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), wl_bank_size); + ModuleId sr_bank_module = module_manager.find_module(sr_module_name); + VTR_ASSERT(sr_bank_module); - size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module); - module_manager.add_child_module(top_module, sr_bank_module); + size_t cur_inst = module_manager.num_instance(top_module, sr_bank_module); + module_manager.add_child_module(top_module, sr_bank_module); - sr_banks.add_wl_shift_register_instance(config_region, sr_bank_module, cur_inst); + sr_banks.link_wl_shift_register_bank_to_module(config_region, sr_bank, sr_bank_module); + sr_banks.link_wl_shift_register_bank_to_instance(config_region, sr_bank, cur_inst); + } + } + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { /************************************************************** * Precompute the BLs and WLs distribution across the FPGA fabric * The distribution is a matrix which contains the starting index of BL/WL for each column or row @@ -1506,8 +1590,12 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module for (const size_t& sink_wl_pin : child_wl_port_info.pins()) { size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + cur_wl_index; - sr_banks.add_wl_shift_register_sink_nodes(config_region, sr_bank_module, cur_inst, child_id, sink_wl_pin); - sr_banks.add_wl_shift_register_source_blwls(config_region, sr_bank_module, cur_inst, wl_pin_id); + BasicPort src_wl_port(std::string(MEMORY_WL_PORT_NAME), wl_pin_id, wl_pin_id); + + FabricWordLineBankId sr_bank = sr_banks.find_wl_shift_register_bank_id(config_region, src_wl_port); + BasicPort sr_bank_port = sr_banks.find_wl_shift_register_bank_data_port(config_region, src_wl_port); + + sr_banks.add_wl_shift_register_bank_sink_node(config_region, sr_bank, sr_bank_port, child_id, sink_wl_pin); cur_wl_index++; } @@ -1518,20 +1606,18 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module * - Connect the head port from top-level module to each shift register bank * - Connect the tail port from each shift register bank to top-level module */ - add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_heads(module_manager, top_module, sr_banks, - std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME)); + add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_heads(module_manager, top_module, sr_banks); - add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_tails(module_manager, top_module, sr_banks, - std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME)); + add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_tails(module_manager, top_module, sr_banks); /* Create connections between BLs of top-level module and BLs of child modules for each region */ - add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks, - std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME), - std::string(MEMORY_WL_PORT_NAME)); - add_top_module_nets_cmos_ql_memory_bank_shift_register_bank_blwls(module_manager, top_module, sr_banks, - std::string(WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME), - std::string(MEMORY_WLR_PORT_NAME), - true); + add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls(module_manager, top_module, sr_banks, + std::string(WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME), + std::string(MEMORY_WL_PORT_NAME)); + add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls(module_manager, top_module, sr_banks, + std::string(WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME), + std::string(MEMORY_WLR_PORT_NAME), + true); } /********************************************************************* @@ -1629,6 +1715,7 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const TopModuleNumConfigBits& num_config_bits) { VTR_ASSERT_SAFE(CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()); CircuitModelId sram_model = config_protocol.memory_model(); @@ -1664,7 +1751,7 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, case BLWL_PROTOCOL_SHIFT_REGISTER: { /* Each region will have independent shift register banks */ for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - size_t num_heads = config_protocol.bl_num_banks(); + size_t num_heads = blwl_sr_banks.bl_banks(config_region).size(); BasicPort blsr_head_port(generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), num_heads); module_manager.add_port(module_id, blsr_head_port, ModuleManager::MODULE_INPUT_PORT); BasicPort blsr_tail_port(generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), num_heads); @@ -1713,7 +1800,7 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, case BLWL_PROTOCOL_SHIFT_REGISTER: { /* Each region will have independent shift register banks */ for (const ConfigRegionId& config_region : module_manager.regions(module_id)) { - size_t num_heads = config_protocol.wl_num_banks(); + size_t num_heads = blwl_sr_banks.wl_banks(config_region).size(); BasicPort wlsr_head_port(generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), num_heads); module_manager.add_port(module_id, wlsr_head_port, ModuleManager::MODULE_INPUT_PORT); BasicPort wlsr_tail_port(generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), num_heads); diff --git a/openfpga/src/fabric/build_top_module_memory_bank.h b/openfpga/src/fabric/build_top_module_memory_bank.h index 74bcdcc7a..3d76ec3f4 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.h +++ b/openfpga/src/fabric/build_top_module_memory_bank.h @@ -36,6 +36,7 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager, const ModuleId& module_id, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const TopModuleNumConfigBits& num_config_bits); int load_top_module_shift_register_banks_from_fabric_key(const FabricKey& fabric_key, diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index 0c5855ae8..048655533 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -6,17 +6,33 @@ /* begin namespace openfpga */ namespace openfpga { -std::vector MemoryBankShiftRegisterBanks::bl_bank_unique_sizes(const ConfigRegionId& region_id) const { +std::vector MemoryBankShiftRegisterBanks::bl_bank_unique_sizes() const { std::vector unique_sizes; - for (const auto& bank_id : bl_banks(region_id)) { - size_t cur_bank_size = bl_bank_size(region_id, bank_id); - if (unique_sizes.end() == std::find(unique_sizes.begin(), unique_sizes.end(), cur_bank_size)) { - unique_sizes.push_back(cur_bank_size); + for (const auto& region : bl_bank_data_ports_) { + for (const auto& bank : region) { + ConfigRegionId region_id = ConfigRegionId(®ion - &bl_bank_data_ports_[ConfigRegionId(0)]); + FabricBitLineBankId bank_id = FabricBitLineBankId(&bank - ®ion[FabricBitLineBankId(0)]); + size_t cur_bank_size = bl_bank_size(region_id, bank_id); + if (unique_sizes.end() == std::find(unique_sizes.begin(), unique_sizes.end(), cur_bank_size)) { + unique_sizes.push_back(cur_bank_size); + } } } return unique_sizes; } +std::vector MemoryBankShiftRegisterBanks::bl_bank_unique_modules() const { + std::vector unique_modules; + for (const auto& region : bl_bank_modules_) { + for (const auto& bank : region) { + if (unique_modules.end() == std::find(unique_modules.begin(), unique_modules.end(), bank)) { + unique_modules.push_back(bank); + } + } + } + return unique_modules; +} + size_t MemoryBankShiftRegisterBanks::bl_bank_size(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { size_t cur_bank_size = 0; for (const auto& data_port : bl_bank_data_ports(region_id, bank_id)) { @@ -30,17 +46,33 @@ FabricKey::fabric_bit_line_bank_range MemoryBankShiftRegisterBanks::bl_banks(con return vtr::make_range(bl_bank_ids_[region_id].begin(), bl_bank_ids_[region_id].end()); } -std::vector MemoryBankShiftRegisterBanks::wl_bank_unique_sizes(const ConfigRegionId& region_id) const { +std::vector MemoryBankShiftRegisterBanks::wl_bank_unique_sizes() const { std::vector unique_sizes; - for (const auto& bank_id : wl_banks(region_id)) { - size_t cur_bank_size = wl_bank_size(region_id, bank_id); - if (unique_sizes.end() == std::find(unique_sizes.begin(), unique_sizes.end(), cur_bank_size)) { - unique_sizes.push_back(cur_bank_size); + for (const auto& region : wl_bank_data_ports_) { + for (const auto& bank : region) { + ConfigRegionId region_id = ConfigRegionId(®ion - &wl_bank_data_ports_[ConfigRegionId(0)]); + FabricWordLineBankId bank_id = FabricWordLineBankId(&bank - ®ion[FabricWordLineBankId(0)]); + size_t cur_bank_size = wl_bank_size(region_id, bank_id); + if (unique_sizes.end() == std::find(unique_sizes.begin(), unique_sizes.end(), cur_bank_size)) { + unique_sizes.push_back(cur_bank_size); + } } } return unique_sizes; } +std::vector MemoryBankShiftRegisterBanks::wl_bank_unique_modules() const { + std::vector unique_modules; + for (const auto& region : wl_bank_modules_) { + for (const auto& bank : region) { + if (unique_modules.end() == std::find(unique_modules.begin(), unique_modules.end(), bank)) { + unique_modules.push_back(bank); + } + } + } + return unique_modules; +} + size_t MemoryBankShiftRegisterBanks::wl_bank_size(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const { size_t cur_bank_size = 0; for (const auto& data_port : wl_bank_data_ports(region_id, bank_id)) { @@ -54,144 +86,6 @@ FabricKey::fabric_word_line_bank_range MemoryBankShiftRegisterBanks::wl_banks(co return vtr::make_range(wl_bank_ids_[region_id].begin(), wl_bank_ids_[region_id].end()); } -std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_unique_modules() const { - std::vector sr_bank_modules; - for (const auto& region : bl_sr_instance_sink_child_ids_) { - for (const auto& pair : region) { - if (sr_bank_modules.end() == std::find(sr_bank_modules.begin(), sr_bank_modules.end(), pair.first.first)) { - sr_bank_modules.push_back(pair.first.first); - } - } - } - return sr_bank_modules; -} - -std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_modules(const ConfigRegionId& region) const { - std::vector sr_bank_modules; - VTR_ASSERT(valid_region_id(region)); - for (const auto& pair : bl_sr_instance_sink_child_ids_[region]) { - sr_bank_modules.push_back(pair.first.first); - } - return sr_bank_modules; -} - -std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_instances(const ConfigRegionId& region) const { - std::vector sr_bank_instances; - VTR_ASSERT(valid_region_id(region)); - for (const auto& pair : bl_sr_instance_sink_child_ids_[region]) { - sr_bank_instances.push_back(pair.first.second); - } - return sr_bank_instances; -} - -std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const { - VTR_ASSERT(valid_region_id(region)); - - auto result = bl_sr_instance_sink_child_ids_[region].find(std::make_pair(sr_module, sr_instance)); - /* Return an empty vector if not found */ - if (result != bl_sr_instance_sink_child_ids_[region].end()) { - return result->second; - } - return std::vector(); -} - -std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_pin_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const { - VTR_ASSERT(valid_region_id(region)); - - auto result = bl_sr_instance_sink_child_pin_ids_[region].find(std::make_pair(sr_module, sr_instance)); - /* Return an empty vector if not found */ - if (result != bl_sr_instance_sink_child_pin_ids_[region].end()) { - return result->second; - } - return std::vector(); -} - -std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_source_blwl_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const { - VTR_ASSERT(valid_region_id(region)); - - auto result = bl_sr_instance_source_blwl_ids_[region].find(std::make_pair(sr_module, sr_instance)); - /* Return an empty vector if not found */ - if (result != bl_sr_instance_source_blwl_ids_[region].end()) { - return result->second; - } - return std::vector(); -} - -std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_unique_modules() const { - std::vector sr_bank_modules; - for (const auto& region : wl_sr_instance_sink_child_ids_) { - for (const auto& pair : region) { - if (sr_bank_modules.end() == std::find(sr_bank_modules.begin(), sr_bank_modules.end(), pair.first.first)) { - sr_bank_modules.push_back(pair.first.first); - } - } - } - return sr_bank_modules; -} - -std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_modules(const ConfigRegionId& region) const { - std::vector sr_bank_modules; - VTR_ASSERT(valid_region_id(region)); - for (const auto& pair : wl_sr_instance_sink_child_ids_[region]) { - sr_bank_modules.push_back(pair.first.first); - } - return sr_bank_modules; -} - -std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_instances(const ConfigRegionId& region) const { - std::vector sr_bank_instances; - VTR_ASSERT(valid_region_id(region)); - for (const auto& pair : wl_sr_instance_sink_child_ids_[region]) { - sr_bank_instances.push_back(pair.first.second); - } - return sr_bank_instances; -} - -std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const { - VTR_ASSERT(valid_region_id(region)); - - auto result = wl_sr_instance_sink_child_ids_[region].find(std::make_pair(sr_module, sr_instance)); - /* Return an empty vector if not found */ - if (result != wl_sr_instance_sink_child_ids_[region].end()) { - return result->second; - } - return std::vector(); -} - -std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_pin_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const { - VTR_ASSERT(valid_region_id(region)); - - auto result = wl_sr_instance_sink_child_pin_ids_[region].find(std::make_pair(sr_module, sr_instance)); - /* Return an empty vector if not found */ - if (result != wl_sr_instance_sink_child_pin_ids_[region].end()) { - return result->second; - } - return std::vector(); -} - -std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_source_blwl_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const { - VTR_ASSERT(valid_region_id(region)); - - auto result = wl_sr_instance_source_blwl_ids_[region].find(std::make_pair(sr_module, sr_instance)); - /* Return an empty vector if not found */ - if (result != wl_sr_instance_source_blwl_ids_[region].end()) { - return result->second; - } - return std::vector(); -} - std::vector MemoryBankShiftRegisterBanks::bl_bank_data_ports(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); return bl_bank_data_ports_[region_id][bank_id]; @@ -230,6 +124,54 @@ BasicPort MemoryBankShiftRegisterBanks::find_bl_shift_register_bank_data_port(co return result->second; } +size_t MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_id(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const BasicPort& src_port) const { + VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); + auto result = bl_bank_sink_child_ids_[region_id][bank_id].find(src_port); + if (result == bl_bank_sink_child_ids_[region_id][bank_id].end()) { + return -1; /* Not found, return an invalid value */ + } + return result->second; +} + +size_t MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_pin_id(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const BasicPort& src_port) const { + VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); + auto result = bl_bank_sink_child_pin_ids_[region_id][bank_id].find(src_port); + if (result == bl_bank_sink_child_pin_ids_[region_id][bank_id].end()) { + return -1; /* Not found, return an invalid value */ + } + return result->second; +} + +std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_source_ports(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id) const { + VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); + std::vector src_ports; + + for (const BasicPort& wide_port : bl_bank_data_ports(region_id, bank_id)) { + for (const size_t& pin : wide_port.pins()) { + src_ports.push_back(BasicPort(wide_port.get_name(), pin, pin)); + } + } + + return src_ports; +} + +ModuleId MemoryBankShiftRegisterBanks::bl_shift_register_bank_module(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id) const { + VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); + return bl_bank_modules_[region_id][bank_id]; +} + +size_t MemoryBankShiftRegisterBanks::bl_shift_register_bank_instance(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id) const { + VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); + return bl_bank_instances_[region_id][bank_id]; +} + FabricWordLineBankId MemoryBankShiftRegisterBanks::find_wl_shift_register_bank_id(const ConfigRegionId& region, const BasicPort& wl_port) const { if (is_wl_bank_dirty_) { @@ -261,75 +203,75 @@ BasicPort MemoryBankShiftRegisterBanks::find_wl_shift_register_bank_data_port(co void MemoryBankShiftRegisterBanks::resize_regions(const size_t& num_regions) { bl_bank_ids_.resize(num_regions); bl_bank_data_ports_.resize(num_regions); - bl_sr_instance_sink_child_ids_.resize(num_regions); - bl_sr_instance_sink_child_pin_ids_.resize(num_regions); - bl_sr_instance_source_blwl_ids_.resize(num_regions); + bl_bank_modules_.resize(num_regions); + bl_bank_instances_.resize(num_regions); + bl_bank_sink_child_ids_.resize(num_regions); + bl_bank_sink_child_pin_ids_.resize(num_regions); wl_bank_ids_.resize(num_regions); wl_bank_data_ports_.resize(num_regions); - wl_sr_instance_sink_child_ids_.resize(num_regions); - wl_sr_instance_sink_child_pin_ids_.resize(num_regions); - wl_sr_instance_source_blwl_ids_.resize(num_regions); + wl_bank_modules_.resize(num_regions); + wl_bank_instances_.resize(num_regions); + wl_bank_sink_child_ids_.resize(num_regions); + wl_bank_sink_child_pin_ids_.resize(num_regions); } -void MemoryBankShiftRegisterBanks::add_bl_shift_register_instance(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) { - VTR_ASSERT(valid_region_id(region)); - bl_sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)]; - bl_sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)]; - bl_sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)]; +void MemoryBankShiftRegisterBanks::link_bl_shift_register_bank_to_module(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const ModuleId& module_id) { + VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); + bl_bank_modules_[region_id][bank_id] = module_id; } -void MemoryBankShiftRegisterBanks::add_bl_shift_register_sink_nodes(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_child_id, - const size_t& sink_child_pin_id) { - VTR_ASSERT(valid_region_id(region)); - bl_sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_id); - bl_sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_pin_id); +void MemoryBankShiftRegisterBanks::link_bl_shift_register_bank_to_instance(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const size_t& instance_id) { + VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); + bl_bank_instances_[region_id][bank_id] = instance_id; } -void MemoryBankShiftRegisterBanks::add_bl_shift_register_source_blwls(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_blwl_id) { - VTR_ASSERT(valid_region_id(region)); - bl_sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_blwl_id); -} - -void MemoryBankShiftRegisterBanks::add_wl_shift_register_instance(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) { - VTR_ASSERT(valid_region_id(region)); - wl_sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)]; - wl_sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)]; - wl_sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)]; +void MemoryBankShiftRegisterBanks::link_wl_shift_register_bank_to_module(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id, + const ModuleId& module_id) { + VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); + wl_bank_modules_[region_id][bank_id] = module_id; } -void MemoryBankShiftRegisterBanks::add_wl_shift_register_sink_nodes(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_child_id, - const size_t& sink_child_pin_id) { - VTR_ASSERT(valid_region_id(region)); - wl_sr_instance_sink_child_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_id); - wl_sr_instance_sink_child_pin_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_child_pin_id); +void MemoryBankShiftRegisterBanks::link_wl_shift_register_bank_to_instance(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id, + const size_t& instance_id) { + VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); + wl_bank_instances_[region_id][bank_id] = instance_id; } -void MemoryBankShiftRegisterBanks::add_wl_shift_register_source_blwls(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_blwl_id) { - VTR_ASSERT(valid_region_id(region)); - wl_sr_instance_source_blwl_ids_[region][std::make_pair(sr_module, sr_instance)].push_back(sink_blwl_id); -} +void MemoryBankShiftRegisterBanks::add_bl_shift_register_bank_sink_node(const ConfigRegionId& region, + const FabricBitLineBankId& bank, + const BasicPort& src_port, + const size_t& sink_child_id, + const size_t& sink_child_pin_id) { + VTR_ASSERT(valid_bl_bank_id(region, bank)); + bl_bank_sink_child_ids_[region][bank][src_port] = sink_child_id; + bl_bank_sink_child_pin_ids_[region][bank][src_port] = sink_child_pin_id; +} + +void MemoryBankShiftRegisterBanks::add_wl_shift_register_bank_sink_node(const ConfigRegionId& region, + const FabricWordLineBankId& bank, + const BasicPort& src_port, + const size_t& sink_child_id, + const size_t& sink_child_pin_id) { + VTR_ASSERT(valid_wl_bank_id(region, bank)); + wl_bank_sink_child_ids_[region][bank][src_port] = sink_child_id; + wl_bank_sink_child_pin_ids_[region][bank][src_port] = sink_child_pin_id; +} void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks) { VTR_ASSERT(valid_region_id(region_id)); bl_bank_ids_[region_id].reserve(num_banks); bl_bank_data_ports_[region_id].reserve(num_banks); + bl_bank_modules_[region_id].reserve(num_banks); + bl_bank_instances_[region_id].reserve(num_banks); + bl_bank_sink_child_ids_[region_id].reserve(num_banks); + bl_bank_sink_child_pin_ids_[region_id].reserve(num_banks); } void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) { @@ -341,6 +283,10 @@ void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks(const ConfigR VTR_ASSERT(valid_region_id(region_id)); wl_bank_ids_[region_id].reserve(num_banks); wl_bank_data_ports_[region_id].reserve(num_banks); + wl_bank_modules_[region_id].reserve(num_banks); + wl_bank_instances_[region_id].reserve(num_banks); + wl_bank_sink_child_ids_[region_id].reserve(num_banks); + wl_bank_sink_child_pin_ids_[region_id].reserve(num_banks); } void MemoryBankShiftRegisterBanks::reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks) { @@ -355,6 +301,10 @@ FabricBitLineBankId MemoryBankShiftRegisterBanks::create_bl_shift_register_bank( FabricBitLineBankId bank = FabricBitLineBankId(bl_bank_ids_[region_id].size()); bl_bank_ids_[region_id].push_back(bank); bl_bank_data_ports_[region_id].emplace_back(); + bl_bank_modules_[region_id].push_back(ModuleId::INVALID()); + bl_bank_instances_[region_id].emplace_back(); + bl_bank_sink_child_ids_[region_id].emplace_back(); + bl_bank_sink_child_pin_ids_[region_id].emplace_back(); return bank; } @@ -391,6 +341,10 @@ FabricWordLineBankId MemoryBankShiftRegisterBanks::create_wl_shift_register_bank FabricWordLineBankId bank = FabricWordLineBankId(wl_bank_ids_[region_id].size()); wl_bank_ids_[region_id].push_back(bank); wl_bank_data_ports_[region_id].emplace_back(); + wl_bank_modules_[region_id].push_back(ModuleId::INVALID()); + wl_bank_instances_[region_id].emplace_back(); + wl_bank_sink_child_ids_[region_id].emplace_back(); + wl_bank_sink_child_pin_ids_[region_id].emplace_back(); return bank; } @@ -410,8 +364,56 @@ void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank(const is_wl_bank_dirty_ = true; } +size_t MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_id(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id, + const BasicPort& src_port) const { + VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); + auto result = wl_bank_sink_child_ids_[region_id][bank_id].find(src_port); + if (result == wl_bank_sink_child_ids_[region_id][bank_id].end()) { + return -1; /* Not found, return an invalid value */ + } + return result->second; +} + +ModuleId MemoryBankShiftRegisterBanks::wl_shift_register_bank_module(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id) const { + VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); + return wl_bank_modules_[region_id][bank_id]; +} + +size_t MemoryBankShiftRegisterBanks::wl_shift_register_bank_instance(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id) const { + VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); + return wl_bank_instances_[region_id][bank_id]; +} + +size_t MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_pin_id(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id, + const BasicPort& src_port) const { + VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); + auto result = wl_bank_sink_child_pin_ids_[region_id][bank_id].find(src_port); + if (result == wl_bank_sink_child_pin_ids_[region_id][bank_id].end()) { + return -1; /* Not found, return an invalid value */ + } + return result->second; +} + +std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_source_ports(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id) const { + VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); + std::vector src_ports; + + for (const BasicPort& wide_port : wl_bank_data_ports(region_id, bank_id)) { + for (const size_t& pin : wide_port.pins()) { + src_ports.push_back(BasicPort(wide_port.get_name(), pin, pin)); + } + } + + return src_ports; +} + bool MemoryBankShiftRegisterBanks::valid_region_id(const ConfigRegionId& region) const { - return size_t(region) < bl_sr_instance_sink_child_ids_.size(); + return size_t(region) < bl_bank_ids_.size(); } bool MemoryBankShiftRegisterBanks::valid_bl_bank_id(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const { diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h index 7a3eb2188..9de627b58 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.h +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -27,7 +27,10 @@ class MemoryBankShiftRegisterBanks { FabricKey::fabric_word_line_bank_range wl_banks(const ConfigRegionId& region_id) const; public: /* Accessors */ /* @brief Return a list of unique sizes of shift register banks for BL protocol */ - std::vector bl_bank_unique_sizes(const ConfigRegionId& region_id) const; + std::vector bl_bank_unique_sizes() const; + + /* @brief Return a list of unique modules of shift register banks for BL protocol */ + std::vector bl_bank_unique_modules() const; /* @brief Return the size of a BL shift register bank */ size_t bl_bank_size(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; @@ -35,8 +38,41 @@ class MemoryBankShiftRegisterBanks { /* @brief Return a list of data ports which will be driven by a BL shift register bank */ std::vector bl_bank_data_ports(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; + /** @brief find the BL shift register bank id to which a BL port is connected to */ + FabricBitLineBankId find_bl_shift_register_bank_id(const ConfigRegionId& region, const BasicPort& bl_port) const; + + /** @brief find the data port of a BL shift register bank id to which a BL port is connected to */ + BasicPort find_bl_shift_register_bank_data_port(const ConfigRegionId& region, const BasicPort& bl_port) const; + + /** @brief Return the module id of a BL shift register bank */ + ModuleId bl_shift_register_bank_module(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id) const; + + /** @brief Return the instance id of a BL shift register bank */ + size_t bl_shift_register_bank_instance(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id) const; + + /** @brief return the child id at top-level module to which a data port (1-bit) of a BL shift register bank is connected to */ + size_t bl_shift_register_bank_sink_child_id(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const BasicPort& src_port) const; + + /** @brief return the child pin id of the child module at top-level module + * to which a data port (1-bit) of a BL shift register bank is connected to + */ + size_t bl_shift_register_bank_sink_child_pin_id(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const BasicPort& src_port) const; + + /** @brief Return a list of single-bit ports which are the data ports of a BL shift register bank */ + std::vector bl_shift_register_bank_source_ports(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id) const; + /* @brief Return a list of unique sizes of shift register banks for WL protocol */ - std::vector wl_bank_unique_sizes(const ConfigRegionId& region_id) const; + std::vector wl_bank_unique_sizes() const; + + /* @brief Return a list of unique modules of shift register banks for WL protocol */ + std::vector wl_bank_unique_modules() const; /* @brief Return the size of a WL shift register bank */ size_t wl_bank_size(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; @@ -44,86 +80,42 @@ class MemoryBankShiftRegisterBanks { /* @brief Return a list of data ports which will be driven by a WL shift register bank */ std::vector wl_bank_data_ports(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; - /* @brief Return a list of modules of unique shift register banks across all the regions */ - std::vector bl_shift_register_bank_unique_modules() const; - - /* @brief Return a list of modules of shift register banks under a specific configuration region of top-level module */ - std::vector bl_shift_register_bank_modules(const ConfigRegionId& region) const; - - /* @brief Return a list of instances of shift register banks under a specific configuration region of top-level module */ - std::vector bl_shift_register_bank_instances(const ConfigRegionId& region) const; - - /* @brief Return a list of ids of reconfigurable children for a given instance of shift register bank - * under a specific configuration region of top-level module - */ - std::vector bl_shift_register_bank_sink_child_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const; - - /* @brief Return a list of BL ids of reconfigurable children for a given instance of shift register bank - * under a specific configuration region of top-level module - */ - std::vector bl_shift_register_bank_sink_pin_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const; - - /* @brief Return a list of BL ids of a given instance of shift register bank - * under a specific configuration region of top-level module - */ - std::vector bl_shift_register_bank_source_blwl_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const; - - /* @brief Return a list of modules of unique shift register banks across all the regions */ - std::vector wl_shift_register_bank_unique_modules() const; - - /* @brief Return a list of modules of shift register banks under a specific configuration region of top-level module */ - std::vector wl_shift_register_bank_modules(const ConfigRegionId& region) const; - - /* @brief Return a list of instances of shift register banks under a specific configuration region of top-level module */ - std::vector wl_shift_register_bank_instances(const ConfigRegionId& region) const; - - /* @brief Return a list of ids of reconfigurable children for a given instance of shift register bank - * under a specific configuration region of top-level module - */ - std::vector wl_shift_register_bank_sink_child_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const; - - /* @brief Return a list of WL ids of reconfigurable children for a given instance of shift register bank - * under a specific configuration region of top-level module - */ - std::vector wl_shift_register_bank_sink_pin_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const; - - /* @brief Return a list of WL ids of a given instance of shift register bank - * under a specific configuration region of top-level module - */ - std::vector wl_shift_register_bank_source_blwl_ids(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance) const; - - /** @brief find the BL shift register bank id to which a BL port is connected to */ - FabricBitLineBankId find_bl_shift_register_bank_id(const ConfigRegionId& region, const BasicPort& bl_port) const; - - /** @brief find the data port of a BL shift register bank id to which a BL port is connected to */ - BasicPort find_bl_shift_register_bank_data_port(const ConfigRegionId& region, const BasicPort& bl_port) const; - /** @brief find the WL shift register bank id to which a BL port is connected to */ FabricWordLineBankId find_wl_shift_register_bank_id(const ConfigRegionId& region, const BasicPort& wl_port) const; /** @brief find the data port of a WL shift register bank id to which a BL port is connected to */ BasicPort find_wl_shift_register_bank_data_port(const ConfigRegionId& region, const BasicPort& wl_port) const; + /** @brief Return the module id of a WL shift register bank */ + ModuleId wl_shift_register_bank_module(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id) const; + + /** @brief Return the instance id of a WL shift register bank */ + size_t wl_shift_register_bank_instance(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id) const; + + /** @brief return the child id at top-level module to which a data port (1-bit) of a WL shift register bank is connected to */ + size_t wl_shift_register_bank_sink_child_id(const ConfigRegionId& region, + const FabricWordLineBankId& bank_id, + const BasicPort& src_port) const; + + /** @brief return the child pin id of the child module at top-level module + * to which a data port (1-bit) of a WL shift register bank is connected to + */ + size_t wl_shift_register_bank_sink_child_pin_id(const ConfigRegionId& region, + const FabricWordLineBankId& bank_id, + const BasicPort& src_port) const; + + /** @brief Return a list of single-bit ports which are the data ports of a WL shift register bank */ + std::vector wl_shift_register_bank_source_ports(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id) const; + public: /* Mutators */ void resize_regions(const size_t& num_regions); /* Reserve a number of banks to be memory efficent */ void reserve_bl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks); void reserve_bl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks); - void reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks); - void reserve_wl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks); /* Create a new shift register bank for BLs and return an id */ FabricBitLineBankId create_bl_shift_register_bank(const FabricRegionId& region_id); @@ -137,6 +129,27 @@ class MemoryBankShiftRegisterBanks { const FabricBitLineBankId& bank_id, const openfpga::BasicPort& data_port); + /* Link a BL shift register bank to a module id */ + void link_bl_shift_register_bank_to_module(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const ModuleId& module_id); + + /* Link a BL shift register bank to a instance id */ + void link_bl_shift_register_bank_to_instance(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const size_t& instance_id); + + /* @brief Add the child id and pin id of BL to which a shift register is connected to under a specific configuration region of top-level module */ + void add_bl_shift_register_bank_sink_node(const ConfigRegionId& region, + const FabricBitLineBankId& bank, + const BasicPort& src_port, + const size_t& sink_child_id, + const size_t& sink_child_pin_id); + + /* Reserve a number of banks to be memory efficent */ + void reserve_wl_shift_register_banks(const FabricRegionId& region_id, const size_t& num_banks); + void reserve_wl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks); + /* Create a new shift register bank for WLs and return an id */ FabricWordLineBankId create_wl_shift_register_bank(const FabricRegionId& region_id); FabricWordLineBankId create_wl_shift_register_bank(const ConfigRegionId& region_id); @@ -149,41 +162,22 @@ class MemoryBankShiftRegisterBanks { const FabricWordLineBankId& bank_id, const openfpga::BasicPort& data_port); - /* @brief Add the module id and instance id of a shift register under a specific configuration region of top-level module */ - void add_bl_shift_register_instance(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance); + /* Link a WL shift register bank to a module id */ + void link_wl_shift_register_bank_to_module(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id, + const ModuleId& module_id); - /* @brief Add the child id and pin id of BL to which a shift register is connected to under a specific configuration region of top-level module */ - void add_bl_shift_register_sink_nodes(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_child_id, - const size_t& sink_child_pin_id); - - /* @brief Add the BL id under a specific configuration region of top-level module to which a shift register is connected to */ - void add_bl_shift_register_source_blwls(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_blwl_id); - - /* @brief Add the module id and instance id of a shift register under a specific configuration region of top-level module */ - void add_wl_shift_register_instance(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance); + /* Link a WL shift register bank to a instance id */ + void link_wl_shift_register_bank_to_instance(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id, + const size_t& instance_id); /* @brief Add the child id and pin id of WL to which a shift register is connected to under a specific configuration region of top-level module */ - void add_wl_shift_register_sink_nodes(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_child_id, - const size_t& sink_child_pin_id); - - /* @brief Add the BL/WL id under a specific configuration region of top-level module to which a shift register is connected to */ - void add_wl_shift_register_source_blwls(const ConfigRegionId& region, - const ModuleId& sr_module, - const size_t& sr_instance, - const size_t& sink_blwl_id); + void add_wl_shift_register_bank_sink_node(const ConfigRegionId& region, + const FabricWordLineBankId& bank, + const BasicPort& src_port, + const size_t& sink_child_id, + const size_t& sink_child_pin_id); public: /* Validators */ bool valid_region_id(const ConfigRegionId& region) const; @@ -203,20 +197,18 @@ class MemoryBankShiftRegisterBanks { /* General information about the BL shift register bank */ vtr::vector> bl_bank_ids_; vtr::vector>> bl_bank_data_ports_; - - /* BL: [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/ - vtr::vector, std::vector>> bl_sr_instance_sink_child_ids_; - vtr::vector, std::vector>> bl_sr_instance_sink_child_pin_ids_; - vtr::vector, std::vector>> bl_sr_instance_source_blwl_ids_; + vtr::vector> bl_bank_modules_; + vtr::vector> bl_bank_instances_; + vtr::vector>> bl_bank_sink_child_ids_; + vtr::vector>> bl_bank_sink_child_pin_ids_; /* General information about the WL shift register bank */ vtr::vector> wl_bank_ids_; vtr::vector>> wl_bank_data_ports_; - - /* WL: [config_region][(shift_register_module, shift_register_instance)][i] = (reconfigurable_child_id, blwl_port_pin_index)*/ - vtr::vector, std::vector>> wl_sr_instance_sink_child_ids_; - vtr::vector, std::vector>> wl_sr_instance_sink_child_pin_ids_; - vtr::vector, std::vector>> wl_sr_instance_source_blwl_ids_; + vtr::vector> wl_bank_modules_; + vtr::vector> wl_bank_instances_; + vtr::vector>> wl_bank_sink_child_ids_; + vtr::vector>> wl_bank_sink_child_pin_ids_; /* Fast look-up: given a BL/Wl port, e.g., bl[i], find out * - the shift register bank id diff --git a/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp b/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp index d950094ab..3b482a752 100644 --- a/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp +++ b/openfpga/src/fpga_verilog/verilog_shift_register_banks.cpp @@ -54,7 +54,7 @@ void print_verilog_submodule_shift_register_banks(const ModuleManager& module_ma print_verilog_file_header(fp, "Shift register banks used in FPGA"); /* Create the memory circuits for the multiplexer */ - for (const ModuleId& sr_module : blwl_sr_banks.bl_shift_register_bank_unique_modules()) { + for (const ModuleId& sr_module : blwl_sr_banks.bl_bank_unique_modules()) { VTR_ASSERT(true == module_manager.valid_module_id(sr_module)); /* Write the module content in Verilog format */ write_verilog_module_to_file(fp, module_manager, sr_module, @@ -65,7 +65,7 @@ void print_verilog_submodule_shift_register_banks(const ModuleManager& module_ma fp << std::endl; } - for (const ModuleId& sr_module : blwl_sr_banks.wl_shift_register_bank_unique_modules()) { + for (const ModuleId& sr_module : blwl_sr_banks.wl_bank_unique_modules()) { VTR_ASSERT(true == module_manager.valid_module_id(sr_module)); /* Write the module content in Verilog format */ write_verilog_module_to_file(fp, module_manager, sr_module, From fa08f4410782aa9103df168a15462b7119d75a16 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 9 Oct 2021 16:58:56 -0700 Subject: [PATCH 196/229] [Engine] Bug fix --- openfpga/src/fabric/build_top_module_memory_bank.cpp | 2 +- openfpga/src/fabric/memory_bank_shift_register_banks.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 900eb8bb3..88062d5b2 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -1555,7 +1555,7 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { for (const FabricWordLineBankId& sr_bank : sr_banks.wl_banks(config_region)) { size_t wl_bank_size = sr_banks.wl_bank_size(config_region, sr_bank); - std::string sr_module_name = generate_bl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), wl_bank_size); + std::string sr_module_name = generate_wl_shift_register_module_name(circuit_lib.model_name(wl_memory_model), wl_bank_size); ModuleId sr_bank_module = module_manager.find_module(sr_module_name); VTR_ASSERT(sr_bank_module); diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index 048655533..a593f2831 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -436,6 +436,7 @@ bool MemoryBankShiftRegisterBanks::empty() const { void MemoryBankShiftRegisterBanks::build_bl_port_fast_lookup() const { bl_ports_to_sr_bank_ids_.resize(bl_bank_data_ports_.size()); + bl_ports_to_sr_bank_ports_.resize(bl_bank_data_ports_.size()); for (const auto& region : bl_bank_data_ports_) { size_t bl_index = 0; for (const auto& bank : region) { @@ -458,6 +459,7 @@ void MemoryBankShiftRegisterBanks::build_bl_port_fast_lookup() const { void MemoryBankShiftRegisterBanks::build_wl_port_fast_lookup() const { wl_ports_to_sr_bank_ids_.resize(wl_bank_data_ports_.size()); + wl_ports_to_sr_bank_ports_.resize(wl_bank_data_ports_.size()); for (const auto& region : wl_bank_data_ports_) { size_t wl_index = 0; for (const auto& bank : region) { From aac74d91632ee9210ae46cb7e642d56ecf324fb0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 9 Oct 2021 18:46:20 -0700 Subject: [PATCH 197/229] [Engine] Bug fix --- .../fabric/build_top_module_memory_bank.cpp | 54 ++++++++------- .../memory_bank_shift_register_banks.cpp | 68 ++++++++++--------- .../fabric/memory_bank_shift_register_banks.h | 42 +++++++----- 3 files changed, 90 insertions(+), 74 deletions(-) diff --git a/openfpga/src/fabric/build_top_module_memory_bank.cpp b/openfpga/src/fabric/build_top_module_memory_bank.cpp index 88062d5b2..5ed22c70c 100644 --- a/openfpga/src/fabric/build_top_module_memory_bank.cpp +++ b/openfpga/src/fabric/build_top_module_memory_bank.cpp @@ -1284,14 +1284,6 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_bls(ModuleMa BasicPort sr_module_blwl_port_info = module_manager.module_port(sr_bank_module, sr_module_blwl_port); for (const BasicPort& src_port : sr_banks.bl_shift_register_bank_source_ports(config_region, bank)) { - size_t child_id = sr_banks.bl_shift_register_bank_sink_child_id(config_region, bank, src_port); - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; - - /* Find the BL port */ - ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name); - BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port); - VTR_ASSERT(1 == src_port.get_width()); /* Create net */ ModuleNetId net = create_module_source_pin_net(module_manager, top_module, @@ -1300,10 +1292,20 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_bank_bls(ModuleMa src_port.pins()[0]); VTR_ASSERT(ModuleNetId::INVALID() != net); - /* Add net sink */ - size_t sink_child_pin_id = sr_banks.bl_shift_register_bank_sink_child_pin_id(config_region, bank, src_port); - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_blwl_port, sink_child_pin_id); + for (size_t ichild = 0; ichild < sr_banks.bl_shift_register_bank_sink_child_ids(config_region, bank, src_port).size(); ++ichild) { + size_t child_id = sr_banks.bl_shift_register_bank_sink_child_ids(config_region, bank, src_port)[ichild]; + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the BL port */ + ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name); + BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port); + + /* Add net sink */ + size_t sink_child_pin_id = sr_banks.bl_shift_register_bank_sink_child_pin_ids(config_region, bank, src_port)[ichild]; + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_blwl_port, sink_child_pin_id); + } } } } @@ -1359,14 +1361,6 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls(ModuleMa BasicPort sr_module_blwl_port_info = module_manager.module_port(sr_bank_module, sr_module_blwl_port); for (const BasicPort& src_port : sr_banks.wl_shift_register_bank_source_ports(config_region, bank)) { - size_t child_id = sr_banks.wl_shift_register_bank_sink_child_id(config_region, bank, src_port); - ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; - size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; - - /* Find the BL port */ - ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name); - BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port); - VTR_ASSERT(1 == src_port.get_width()); /* Create net */ ModuleNetId net = create_module_source_pin_net(module_manager, top_module, @@ -1375,10 +1369,20 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_bank_wls(ModuleMa src_port.pins()[0]); VTR_ASSERT(ModuleNetId::INVALID() != net); - /* Add net sink */ - size_t sink_child_pin_id = sr_banks.wl_shift_register_bank_sink_child_pin_id(config_region, bank, src_port); - module_manager.add_module_net_sink(top_module, net, - child_module, child_instance, child_blwl_port, sink_child_pin_id); + for (size_t ichild = 0; ichild < sr_banks.wl_shift_register_bank_sink_child_ids(config_region, bank, src_port).size(); ++ichild) { + size_t child_id = sr_banks.wl_shift_register_bank_sink_child_ids(config_region, bank, src_port)[ichild]; + ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id]; + size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id]; + + /* Find the BL port */ + ModulePortId child_blwl_port = module_manager.find_module_port(child_module, child_blwl_port_name); + BasicPort child_blwl_port_info = module_manager.module_port(child_module, child_blwl_port); + + /* Add net sink */ + size_t sink_child_pin_id = sr_banks.wl_shift_register_bank_sink_child_pin_ids(config_region, bank, src_port)[ichild]; + module_manager.add_module_net_sink(top_module, net, + child_module, child_instance, child_blwl_port, sink_child_pin_id); + } } } } @@ -1501,6 +1505,7 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(Module BasicPort src_bl_port(std::string(MEMORY_BL_PORT_NAME), bl_pin_id, bl_pin_id); FabricBitLineBankId sr_bank = sr_banks.find_bl_shift_register_bank_id(config_region, src_bl_port); BasicPort sr_bank_port = sr_banks.find_bl_shift_register_bank_data_port(config_region, src_bl_port); + VTR_ASSERT(sr_bank_port.is_valid()); sr_banks.add_bl_shift_register_bank_sink_node(config_region, sr_bank, sr_bank_port, child_id, sink_bl_pin); @@ -1594,6 +1599,7 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_shift_register_config_bus(Module FabricWordLineBankId sr_bank = sr_banks.find_wl_shift_register_bank_id(config_region, src_wl_port); BasicPort sr_bank_port = sr_banks.find_wl_shift_register_bank_data_port(config_region, src_wl_port); + VTR_ASSERT(sr_bank_port.is_valid()); sr_banks.add_wl_shift_register_bank_sink_node(config_region, sr_bank, sr_bank_port, child_id, sink_wl_pin); diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index a593f2831..0a506b9ae 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -124,24 +124,24 @@ BasicPort MemoryBankShiftRegisterBanks::find_bl_shift_register_bank_data_port(co return result->second; } -size_t MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_id(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const BasicPort& src_port) const { +std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_ids(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const BasicPort& src_port) const { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); auto result = bl_bank_sink_child_ids_[region_id][bank_id].find(src_port); if (result == bl_bank_sink_child_ids_[region_id][bank_id].end()) { - return -1; /* Not found, return an invalid value */ + return std::vector(); /* Not found, return an empty list */ } return result->second; } -size_t MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_pin_id(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const BasicPort& src_port) const { +std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sink_child_pin_ids(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const BasicPort& src_port) const { VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); auto result = bl_bank_sink_child_pin_ids_[region_id][bank_id].find(src_port); if (result == bl_bank_sink_child_pin_ids_[region_id][bank_id].end()) { - return -1; /* Not found, return an invalid value */ + return std::vector(); /* Not found, return an empty list */ } return result->second; } @@ -151,9 +151,11 @@ std::vector MemoryBankShiftRegisterBanks::bl_shift_register_bank_sour VTR_ASSERT(valid_bl_bank_id(region_id, bank_id)); std::vector src_ports; + size_t cur_pin =0; for (const BasicPort& wide_port : bl_bank_data_ports(region_id, bank_id)) { - for (const size_t& pin : wide_port.pins()) { - src_ports.push_back(BasicPort(wide_port.get_name(), pin, pin)); + for (size_t ipin = 0; ipin < wide_port.pins().size(); ++ipin) { + src_ports.push_back(BasicPort(std::string(MEMORY_BL_PORT_NAME), cur_pin, cur_pin)); + cur_pin++; } } @@ -250,8 +252,8 @@ void MemoryBankShiftRegisterBanks::add_bl_shift_register_bank_sink_node(const Co const size_t& sink_child_id, const size_t& sink_child_pin_id) { VTR_ASSERT(valid_bl_bank_id(region, bank)); - bl_bank_sink_child_ids_[region][bank][src_port] = sink_child_id; - bl_bank_sink_child_pin_ids_[region][bank][src_port] = sink_child_pin_id; + bl_bank_sink_child_ids_[region][bank][src_port].push_back(sink_child_id); + bl_bank_sink_child_pin_ids_[region][bank][src_port].push_back(sink_child_pin_id); } void MemoryBankShiftRegisterBanks::add_wl_shift_register_bank_sink_node(const ConfigRegionId& region, @@ -260,8 +262,8 @@ void MemoryBankShiftRegisterBanks::add_wl_shift_register_bank_sink_node(const Co const size_t& sink_child_id, const size_t& sink_child_pin_id) { VTR_ASSERT(valid_wl_bank_id(region, bank)); - wl_bank_sink_child_ids_[region][bank][src_port] = sink_child_id; - wl_bank_sink_child_pin_ids_[region][bank][src_port] = sink_child_pin_id; + wl_bank_sink_child_ids_[region][bank][src_port].push_back(sink_child_id); + wl_bank_sink_child_pin_ids_[region][bank][src_port].push_back(sink_child_pin_id); } void MemoryBankShiftRegisterBanks::reserve_bl_shift_register_banks(const ConfigRegionId& region_id, const size_t& num_banks) { @@ -364,13 +366,13 @@ void MemoryBankShiftRegisterBanks::add_data_port_to_wl_shift_register_bank(const is_wl_bank_dirty_ = true; } -size_t MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_id(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id, - const BasicPort& src_port) const { +std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_ids(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id, + const BasicPort& src_port) const { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); auto result = wl_bank_sink_child_ids_[region_id][bank_id].find(src_port); if (result == wl_bank_sink_child_ids_[region_id][bank_id].end()) { - return -1; /* Not found, return an invalid value */ + return std::vector(); /* Not found, return an empty list */ } return result->second; } @@ -387,13 +389,13 @@ size_t MemoryBankShiftRegisterBanks::wl_shift_register_bank_instance(const Confi return wl_bank_instances_[region_id][bank_id]; } -size_t MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_pin_id(const ConfigRegionId& region_id, - const FabricWordLineBankId& bank_id, - const BasicPort& src_port) const { +std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sink_child_pin_ids(const ConfigRegionId& region_id, + const FabricWordLineBankId& bank_id, + const BasicPort& src_port) const { VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); auto result = wl_bank_sink_child_pin_ids_[region_id][bank_id].find(src_port); if (result == wl_bank_sink_child_pin_ids_[region_id][bank_id].end()) { - return -1; /* Not found, return an invalid value */ + return std::vector(); /* Not found, return an empty list */ } return result->second; } @@ -403,9 +405,11 @@ std::vector MemoryBankShiftRegisterBanks::wl_shift_register_bank_sour VTR_ASSERT(valid_wl_bank_id(region_id, bank_id)); std::vector src_ports; + size_t cur_pin = 0; for (const BasicPort& wide_port : wl_bank_data_ports(region_id, bank_id)) { - for (const size_t& pin : wide_port.pins()) { - src_ports.push_back(BasicPort(wide_port.get_name(), pin, pin)); + for (size_t ipin = 0; ipin < wide_port.pins().size(); ++ipin) { + src_ports.push_back(BasicPort(std::string(MEMORY_WL_PORT_NAME), cur_pin, cur_pin)); + cur_pin++; } } @@ -438,17 +442,17 @@ void MemoryBankShiftRegisterBanks::build_bl_port_fast_lookup() const { bl_ports_to_sr_bank_ids_.resize(bl_bank_data_ports_.size()); bl_ports_to_sr_bank_ports_.resize(bl_bank_data_ports_.size()); for (const auto& region : bl_bank_data_ports_) { - size_t bl_index = 0; for (const auto& bank : region) { + size_t cur_pin = 0; for (const auto& port : bank) { - for (const auto& pin : port.pins()) { + for (const size_t& bl_index : port.pins()) { BasicPort bl_port(std::string(MEMORY_BL_PORT_NAME), bl_index, bl_index); - BasicPort sr_bl_port(std::string(MEMORY_BL_PORT_NAME), pin, pin); + BasicPort sr_bl_port(std::string(MEMORY_BL_PORT_NAME), cur_pin, cur_pin); ConfigRegionId region_id = ConfigRegionId(®ion - &bl_bank_data_ports_[ConfigRegionId(0)]); FabricBitLineBankId bank_id = FabricBitLineBankId(&bank - ®ion[FabricBitLineBankId(0)]); bl_ports_to_sr_bank_ids_[region_id][bl_port] = bank_id; bl_ports_to_sr_bank_ports_[region_id][bl_port] = sr_bl_port; - bl_index++; + cur_pin++; } } } @@ -461,17 +465,17 @@ void MemoryBankShiftRegisterBanks::build_wl_port_fast_lookup() const { wl_ports_to_sr_bank_ids_.resize(wl_bank_data_ports_.size()); wl_ports_to_sr_bank_ports_.resize(wl_bank_data_ports_.size()); for (const auto& region : wl_bank_data_ports_) { - size_t wl_index = 0; for (const auto& bank : region) { + size_t cur_pin = 0; for (const auto& port : bank) { - for (const auto& pin : port.pins()) { + for (const size_t& wl_index : port.pins()) { BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), wl_index, wl_index); - BasicPort sr_wl_port(std::string(MEMORY_WL_PORT_NAME), pin, pin); + BasicPort sr_wl_port(std::string(MEMORY_WL_PORT_NAME), cur_pin, cur_pin); ConfigRegionId region_id = ConfigRegionId(®ion - &wl_bank_data_ports_[ConfigRegionId(0)]); FabricWordLineBankId bank_id = FabricWordLineBankId(&bank - ®ion[FabricWordLineBankId(0)]); wl_ports_to_sr_bank_ids_[region_id][wl_port] = bank_id; wl_ports_to_sr_bank_ports_[region_id][wl_port] = sr_wl_port; - wl_index++; + cur_pin++; } } } diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h index 9de627b58..fd226ded0 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.h +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -52,17 +52,20 @@ class MemoryBankShiftRegisterBanks { size_t bl_shift_register_bank_instance(const ConfigRegionId& region_id, const FabricBitLineBankId& bank_id) const; - /** @brief return the child id at top-level module to which a data port (1-bit) of a BL shift register bank is connected to */ - size_t bl_shift_register_bank_sink_child_id(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const BasicPort& src_port) const; + /** @brief return the child ids at top-level module to which a data port (1-bit) of a BL shift register bank is connected to + * @note a BL may drive multiple children (children on the same column share the same BLs) + */ + std::vector bl_shift_register_bank_sink_child_ids(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const BasicPort& src_port) const; /** @brief return the child pin id of the child module at top-level module * to which a data port (1-bit) of a BL shift register bank is connected to + * @note a BL may drive multiple children (children on the same column share the same BLs) */ - size_t bl_shift_register_bank_sink_child_pin_id(const ConfigRegionId& region_id, - const FabricBitLineBankId& bank_id, - const BasicPort& src_port) const; + std::vector bl_shift_register_bank_sink_child_pin_ids(const ConfigRegionId& region_id, + const FabricBitLineBankId& bank_id, + const BasicPort& src_port) const; /** @brief Return a list of single-bit ports which are the data ports of a BL shift register bank */ std::vector bl_shift_register_bank_source_ports(const ConfigRegionId& region_id, @@ -94,17 +97,20 @@ class MemoryBankShiftRegisterBanks { size_t wl_shift_register_bank_instance(const ConfigRegionId& region_id, const FabricWordLineBankId& bank_id) const; - /** @brief return the child id at top-level module to which a data port (1-bit) of a WL shift register bank is connected to */ - size_t wl_shift_register_bank_sink_child_id(const ConfigRegionId& region, - const FabricWordLineBankId& bank_id, - const BasicPort& src_port) const; + /** @brief return the child id at top-level module to which a data port (1-bit) of a WL shift register bank is connected to + * @note a WL may drive multiple children (children on the same row share the same WLs) + */ + std::vector wl_shift_register_bank_sink_child_ids(const ConfigRegionId& region, + const FabricWordLineBankId& bank_id, + const BasicPort& src_port) const; /** @brief return the child pin id of the child module at top-level module * to which a data port (1-bit) of a WL shift register bank is connected to + * @note a WL may drive multiple children (children on the same row share the same WLs) */ - size_t wl_shift_register_bank_sink_child_pin_id(const ConfigRegionId& region, - const FabricWordLineBankId& bank_id, - const BasicPort& src_port) const; + std::vector wl_shift_register_bank_sink_child_pin_ids(const ConfigRegionId& region, + const FabricWordLineBankId& bank_id, + const BasicPort& src_port) const; /** @brief Return a list of single-bit ports which are the data ports of a WL shift register bank */ std::vector wl_shift_register_bank_source_ports(const ConfigRegionId& region_id, @@ -199,16 +205,16 @@ class MemoryBankShiftRegisterBanks { vtr::vector>> bl_bank_data_ports_; vtr::vector> bl_bank_modules_; vtr::vector> bl_bank_instances_; - vtr::vector>> bl_bank_sink_child_ids_; - vtr::vector>> bl_bank_sink_child_pin_ids_; + vtr::vector>>> bl_bank_sink_child_ids_; + vtr::vector>>> bl_bank_sink_child_pin_ids_; /* General information about the WL shift register bank */ vtr::vector> wl_bank_ids_; vtr::vector>> wl_bank_data_ports_; vtr::vector> wl_bank_modules_; vtr::vector> wl_bank_instances_; - vtr::vector>> wl_bank_sink_child_ids_; - vtr::vector>> wl_bank_sink_child_pin_ids_; + vtr::vector>>> wl_bank_sink_child_ids_; + vtr::vector>>> wl_bank_sink_child_pin_ids_; /* Fast look-up: given a BL/Wl port, e.g., bl[i], find out * - the shift register bank id From 34575f72229489bb7ae3632fdccaf4c253f72111 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 9 Oct 2021 20:39:45 -0700 Subject: [PATCH 198/229] [FPGA-Bitstream] Upgrade bitstream generator to support multiple shift register banks in a configuration region for QuickLogic memory bank --- openfpga/src/base/openfpga_bitstream.cpp | 1 + openfpga/src/base/openfpga_context.h | 2 +- openfpga/src/base/openfpga_verilog.cpp | 1 + .../memory_bank_shift_register_banks.cpp | 8 ++ .../fabric/memory_bank_shift_register_banks.h | 3 + .../write_text_fabric_bitstream.cpp | 5 +- .../write_text_fabric_bitstream.h | 2 + openfpga/src/fpga_verilog/verilog_api.cpp | 3 +- openfpga/src/fpga_verilog/verilog_api.h | 1 + .../fpga_verilog/verilog_top_testbench.cpp | 15 ++- .../src/fpga_verilog/verilog_top_testbench.h | 2 + .../verilog_top_testbench_memory_bank.cpp | 11 +- .../verilog_top_testbench_memory_bank.h | 5 +- openfpga/src/utils/fabric_bitstream_utils.cpp | 113 +++++++++++++++++- openfpga/src/utils/fabric_bitstream_utils.h | 2 +- 15 files changed, 158 insertions(+), 16 deletions(-) diff --git a/openfpga/src/base/openfpga_bitstream.cpp b/openfpga/src/base/openfpga_bitstream.cpp index ea390ae08..9dff1c7a8 100644 --- a/openfpga/src/base/openfpga_bitstream.cpp +++ b/openfpga/src/base/openfpga_bitstream.cpp @@ -122,6 +122,7 @@ int write_fabric_bitstream(const OpenfpgaContext& openfpga_ctx, /* By default, output in plain text format */ status = write_fabric_bitstream_to_text_file(openfpga_ctx.bitstream_manager(), openfpga_ctx.fabric_bitstream(), + openfpga_ctx.blwl_shift_register_banks(), openfpga_ctx.arch().config_protocol, openfpga_ctx.fabric_global_port_info(), cmd_context.option_value(cmd, opt_file), diff --git a/openfpga/src/base/openfpga_context.h b/openfpga/src/base/openfpga_context.h index 3719a2fa7..f4d356550 100644 --- a/openfpga/src/base/openfpga_context.h +++ b/openfpga/src/base/openfpga_context.h @@ -66,7 +66,7 @@ class OpenfpgaContext : public Context { const openfpga::DeviceRRGSB& device_rr_gsb() const { return device_rr_gsb_; } const openfpga::MuxLibrary& mux_lib() const { return mux_lib_; } const openfpga::DecoderLibrary& decoder_lib() const { return decoder_lib_; } - const openfpga::MemoryBankShiftRegisterBanks& blwl_shift_register_banks() { return blwl_sr_banks_; } + const openfpga::MemoryBankShiftRegisterBanks& blwl_shift_register_banks() const { return blwl_sr_banks_; } const openfpga::TileDirect& tile_direct() const { return tile_direct_; } const openfpga::ModuleManager& module_graph() const { return module_graph_; } const openfpga::FlowManager& flow_manager() const { return flow_manager_; } diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index 2f3dd892f..4d4a615e7 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -107,6 +107,7 @@ int write_full_testbench(const OpenfpgaContext& openfpga_ctx, return fpga_verilog_full_testbench(openfpga_ctx.module_graph(), openfpga_ctx.bitstream_manager(), openfpga_ctx.fabric_bitstream(), + openfpga_ctx.blwl_shift_register_banks(), g_vpr_ctx.atom(), g_vpr_ctx.placement(), pin_constraints, diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp index 0a506b9ae..39eaa8ad3 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.cpp +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.cpp @@ -6,6 +6,10 @@ /* begin namespace openfpga */ namespace openfpga { +ModuleManager::region_range MemoryBankShiftRegisterBanks::regions() const { + return vtr::make_range(config_region_ids_.begin(), config_region_ids_.end()); +} + std::vector MemoryBankShiftRegisterBanks::bl_bank_unique_sizes() const { std::vector unique_sizes; for (const auto& region : bl_bank_data_ports_) { @@ -203,6 +207,10 @@ BasicPort MemoryBankShiftRegisterBanks::find_wl_shift_register_bank_data_port(co } void MemoryBankShiftRegisterBanks::resize_regions(const size_t& num_regions) { + config_region_ids_.resize(num_regions); + for (size_t iregion = 0; iregion < num_regions; ++iregion) { + config_region_ids_[ConfigRegionId(iregion)] = ConfigRegionId(iregion); + } bl_bank_ids_.resize(num_regions); bl_bank_data_ports_.resize(num_regions); bl_bank_modules_.resize(num_regions); diff --git a/openfpga/src/fabric/memory_bank_shift_register_banks.h b/openfpga/src/fabric/memory_bank_shift_register_banks.h index fd226ded0..32df3444e 100644 --- a/openfpga/src/fabric/memory_bank_shift_register_banks.h +++ b/openfpga/src/fabric/memory_bank_shift_register_banks.h @@ -23,6 +23,7 @@ namespace openfpga { ******************************************************************************/ class MemoryBankShiftRegisterBanks { public: /* Accessors: aggregates */ + ModuleManager::region_range regions() const; FabricKey::fabric_bit_line_bank_range bl_banks(const ConfigRegionId& region_id) const; FabricKey::fabric_word_line_bank_range wl_banks(const ConfigRegionId& region_id) const; public: /* Accessors */ @@ -200,6 +201,8 @@ class MemoryBankShiftRegisterBanks { void build_wl_port_fast_lookup() const; private: /* Internal data */ + vtr::vector config_region_ids_; + /* General information about the BL shift register bank */ vtr::vector> bl_bank_ids_; vtr::vector>> bl_bank_data_ports_; diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp index 51be3783a..9854398dd 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp @@ -244,6 +244,7 @@ int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream& const bool& fast_configuration, const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& keep_dont_care_bits) { int status = 0; @@ -251,7 +252,7 @@ int write_memory_bank_shift_register_fabric_bitstream_to_text_file(std::fstream& if (keep_dont_care_bits) { dont_care_bit = DONT_CARE_CHAR; } - MemoryBankShiftRegisterFabricBitstream fabric_bits = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip, dont_care_bit); + MemoryBankShiftRegisterFabricBitstream fabric_bits = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, blwl_sr_banks, fast_configuration, bit_value_to_skip, dont_care_bit); /* Output information about how to intepret the bitstream */ fp << "// Bitstream word count: " << fabric_bits.num_words() << std::endl; @@ -363,6 +364,7 @@ int write_frame_based_fabric_bitstream_to_text_file(std::fstream& fp, *******************************************************************/ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const ConfigProtocol& config_protocol, const FabricGlobalPortInfo& global_ports, const std::string& fname, @@ -439,6 +441,7 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage apply_fast_configuration, bit_value_to_skip, fabric_bitstream, + blwl_sr_banks, keep_dont_care_bits); } break; diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h index 6a30cf773..e63cea5c9 100644 --- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h +++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.h @@ -9,6 +9,7 @@ #include "bitstream_manager.h" #include "fabric_bitstream.h" #include "config_protocol.h" +#include "memory_bank_shift_register_banks.h" #include "fabric_global_port_info.h" /******************************************************************** @@ -20,6 +21,7 @@ namespace openfpga { int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const ConfigProtocol& config_protocol, const FabricGlobalPortInfo& global_ports, const std::string& fname, diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index 8b6603fc5..b3cc6e858 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -149,6 +149,7 @@ void fpga_fabric_verilog(ModuleManager &module_manager, int fpga_verilog_full_testbench(const ModuleManager &module_manager, const BitstreamManager &bitstream_manager, const FabricBitstream &fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const AtomContext &atom_ctx, const PlacementContext &place_ctx, const PinConstraints& pin_constraints, @@ -175,7 +176,7 @@ int fpga_verilog_full_testbench(const ModuleManager &module_manager, /* Generate full testbench for verification, including configuration phase and operating phase */ std::string top_testbench_file_path = src_dir_path + netlist_name + std::string(AUTOCHECK_TOP_TESTBENCH_VERILOG_FILE_POSTFIX); print_verilog_full_testbench(module_manager, - bitstream_manager, fabric_bitstream, + bitstream_manager, fabric_bitstream, blwl_sr_banks, circuit_lib, config_protocol, fabric_global_port_info, diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index 454921e26..6f83d3684 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -48,6 +48,7 @@ void fpga_fabric_verilog(ModuleManager& module_manager, int fpga_verilog_full_testbench(const ModuleManager& module_manager, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const PinConstraints& pin_constraints, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index f45e84c9d..af50ce55d 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -1132,6 +1132,7 @@ int print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& fp const bool& fast_configuration, const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const float& prog_clock_period, const float& timescale) { /* Validate the file stream */ @@ -1147,7 +1148,8 @@ int print_verilog_top_testbench_configuration_protocol_stimulus(std::fstream& fp return print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(fp, config_protocol, sim_settings, module_manager, top_module, - fast_configuration, bit_value_to_skip, fabric_bitstream, + fast_configuration, bit_value_to_skip, + fabric_bitstream, blwl_sr_banks, prog_clock_period, timescale); break; case CONFIG_MEM_MEMORY_BANK: @@ -1738,7 +1740,8 @@ void print_verilog_full_testbench_bitstream(std::fstream& fp, const ModuleManager& module_manager, const ModuleId& top_module, const BitstreamManager& bitstream_manager, - const FabricBitstream& fabric_bitstream) { + const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks) { /* Branch on the type of configuration protocol */ switch (config_protocol.type()) { @@ -1771,7 +1774,7 @@ void print_verilog_full_testbench_bitstream(std::fstream& fp, fast_configuration, bit_value_to_skip, module_manager, top_module, - fabric_bitstream); + fabric_bitstream, blwl_sr_banks); break; case CONFIG_MEM_FRAME_BASED: print_verilog_full_testbench_frame_decoder_bitstream(fp, bitstream_file, @@ -1893,6 +1896,7 @@ void print_verilog_top_testbench_check(std::fstream& fp, int print_verilog_full_testbench(const ModuleManager& module_manager, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, const FabricGlobalPortInfo& global_ports, @@ -1984,7 +1988,8 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, status = print_verilog_top_testbench_configuration_protocol_stimulus(fp, config_protocol, simulation_parameters, module_manager, top_module, - fast_configuration, bit_value_to_skip, fabric_bitstream, + fast_configuration, bit_value_to_skip, + fabric_bitstream, blwl_sr_banks, prog_clock_period, VERILOG_SIM_TIMESCALE); @@ -2057,7 +2062,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager, apply_fast_configuration, bit_value_to_skip, module_manager, top_module, - bitstream_manager, fabric_bitstream); + bitstream_manager, fabric_bitstream, blwl_sr_banks); /* Add signal initialization: * Bypass writing codes to files due to the autogenerated codes are very large. diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.h b/openfpga/src/fpga_verilog/verilog_top_testbench.h index aff108d72..bbad08125 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.h @@ -17,6 +17,7 @@ #include "fabric_global_port_info.h" #include "vpr_netlist_annotation.h" #include "simulation_setting.h" +#include "memory_bank_shift_register_banks.h" #include "verilog_testbench_options.h" /******************************************************************** @@ -29,6 +30,7 @@ namespace openfpga { int print_verilog_full_testbench(const ModuleManager& module_manager, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol, const FabricGlobalPortInfo& global_ports, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index c933cc939..b9eb69d96 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -326,6 +326,7 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s const bool& fast_configuration, const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const float& prog_clock_period, const float& timescale) { ModulePortId en_port_id = module_manager.find_module_port(top_module, @@ -350,6 +351,7 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s /* Reorganize the fabric bitstream by the same address across regions */ if (CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) { MemoryBankShiftRegisterFabricBitstream fabric_bits_by_addr = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, + blwl_sr_banks, fast_configuration, bit_value_to_skip); @@ -541,12 +543,14 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f const bool& bit_value_to_skip, const ModuleManager& module_manager, const ModuleId& top_module, - const FabricBitstream& fabric_bitstream) { + const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks) { /* Validate the file stream */ valid_file_stream(fp); /* Reorganize the fabric bitstream by the same address across regions */ MemoryBankShiftRegisterFabricBitstream fabric_bits_by_addr = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, + blwl_sr_banks, fast_configuration, bit_value_to_skip); @@ -940,7 +944,8 @@ void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp, const bool& bit_value_to_skip, const ModuleManager& module_manager, const ModuleId& top_module, - const FabricBitstream& fabric_bitstream) { + const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks) { if ( (BLWL_PROTOCOL_DECODER == config_protocol.bl_protocol_type()) && (BLWL_PROTOCOL_DECODER == config_protocol.wl_protocol_type()) ) { print_verilog_full_testbench_ql_memory_bank_decoder_bitstream(fp, bitstream_file, @@ -961,7 +966,7 @@ void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp, fast_configuration, bit_value_to_skip, module_manager, top_module, - fabric_bitstream); + fabric_bitstream, blwl_sr_banks); } } diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h index e3a4edc7e..6bcd50903 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.h @@ -17,6 +17,7 @@ #include "fabric_global_port_info.h" #include "vpr_netlist_annotation.h" #include "simulation_setting.h" +#include "memory_bank_shift_register_banks.h" #include "verilog_testbench_options.h" /******************************************************************** @@ -53,6 +54,7 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s const bool& fast_configuration, const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const float& prog_clock_period, const float& timescale); @@ -67,7 +69,8 @@ void print_verilog_full_testbench_ql_memory_bank_bitstream(std::fstream& fp, const bool& bit_value_to_skip, const ModuleManager& module_manager, const ModuleId& top_module, - const FabricBitstream& fabric_bitstream); + const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks); } /* end namespace openfpga */ diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index b04a28d1c..16074cb92 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -12,6 +12,7 @@ #include "vtr_log.h" /* Headers from openfpgautil library */ +#include "openfpga_reserved_words.h" #include "openfpga_decode.h" #include "fabric_bitstream_utils.h" @@ -397,9 +398,109 @@ std::vector reshape_bitstream_vectors_to_first_element(const std::v return rotated_vectors; } +/** @brief Split each BL vector in a configuration region into multiple shift register banks + * For example + * Original vector: 1xxx010xxx1 + * Resulting vector (2 register register banks): + * 1xxx0 + * 10xxx1 + */ +static +std::vector redistribute_bl_vectors_to_shift_register_banks(const std::vector bl_vectors, + const MemoryBankShiftRegisterBanks& blwl_sr_banks) { + std::vector multi_bank_bl_vec; + + /* Resize the vector by counting the dimension */ + /* Compute the start index of each region */ + vtr::vector region_start_index; + region_start_index.resize(blwl_sr_banks.regions().size(), 0); + size_t total_num_banks = 0; + for (const auto& region : blwl_sr_banks.regions()) { + region_start_index[region] = total_num_banks; + total_num_banks += blwl_sr_banks.bl_banks(region).size(); + } + multi_bank_bl_vec.resize(total_num_banks); + + /* Resize each bank to be memory efficient */ + size_t vec_start_index = 0; + for (const auto& region : blwl_sr_banks.regions()) { + for (const auto& bank : blwl_sr_banks.bl_banks(region)) { + size_t bank_size = blwl_sr_banks.bl_bank_size(region, bank); + multi_bank_bl_vec[vec_start_index].resize(bank_size); + vec_start_index++; + } + } + + for (const std::string& region_bl_vec : bl_vectors) { + ConfigRegionId region = ConfigRegionId(®ion_bl_vec - &bl_vectors[0]); + for (size_t ibit = 0; ibit < region_bl_vec.size(); ++ibit) { + /* Find the shift register bank id and the offset in data lines */ + BasicPort bl_port(std::string(MEMORY_BL_PORT_NAME), ibit, ibit); + FabricBitLineBankId bank_id = blwl_sr_banks.find_bl_shift_register_bank_id(region, bl_port); + BasicPort sr_port = blwl_sr_banks.find_bl_shift_register_bank_data_port(region, bl_port); + VTR_ASSERT(1 == sr_port.get_width()); + + size_t vec_index = region_start_index[region] + size_t(bank_id); + multi_bank_bl_vec[vec_index][sr_port.get_lsb()] = region_bl_vec[ibit]; + } + } + + return multi_bank_bl_vec; +} + +/** @brief Split each WL vector in a configuration region into multiple shift register banks + * For example + * Original vector: 1xxx010xxx1 + * Resulting vector (2 register register banks): + * 1xxx0 + * 10xxx1 + */ +static +std::vector redistribute_wl_vectors_to_shift_register_banks(const std::vector wl_vectors, + const MemoryBankShiftRegisterBanks& blwl_sr_banks) { + std::vector multi_bank_wl_vec; + + /* Resize the vector by counting the dimension */ + /* Compute the start index of each region */ + vtr::vector region_start_index; + region_start_index.resize(blwl_sr_banks.regions().size(), 0); + size_t total_num_banks = 0; + for (const auto& region : blwl_sr_banks.regions()) { + region_start_index[region] = total_num_banks; + total_num_banks += blwl_sr_banks.wl_banks(region).size(); + } + multi_bank_wl_vec.resize(total_num_banks); + + /* Resize each bank to be memory efficient */ + size_t vec_start_index = 0; + for (const auto& region : blwl_sr_banks.regions()) { + for (const auto& bank : blwl_sr_banks.wl_banks(region)) { + size_t bank_size = blwl_sr_banks.wl_bank_size(region, bank); + multi_bank_wl_vec[vec_start_index].resize(bank_size); + vec_start_index++; + } + } + + for (const std::string& region_wl_vec : wl_vectors) { + ConfigRegionId region = ConfigRegionId(®ion_wl_vec - &wl_vectors[0]); + for (size_t ibit = 0; ibit < region_wl_vec.size(); ++ibit) { + /* Find the shift register bank id and the offset in data lines */ + BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), ibit, ibit); + FabricWordLineBankId bank_id = blwl_sr_banks.find_wl_shift_register_bank_id(region, wl_port); + BasicPort sr_port = blwl_sr_banks.find_wl_shift_register_bank_data_port(region, wl_port); + VTR_ASSERT(1 == sr_port.get_width()); + + size_t vec_index = region_start_index[region] + size_t(bank_id); + multi_bank_wl_vec[vec_index][sr_port.get_lsb()] = region_wl_vec[ibit]; + } + } + + return multi_bank_wl_vec; +} + MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& fast_configuration, - //const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& bit_value_to_skip, const char& dont_care_bit) { MemoryBankFlattenFabricBitstream raw_fabric_bits = build_memory_bank_flatten_fabric_bitstream(fabric_bitstream, fast_configuration, bit_value_to_skip, dont_care_bit); @@ -411,7 +512,10 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b MemoryBankShiftRegisterFabricBitstreamWordId word_id = fabric_bits.create_word(); - std::vector reshaped_bl_vectors = reshape_bitstream_vectors_to_first_element(bl_vec, dont_care_bit); + /* Redistribute the BL vector to multiple banks */ + std::vector multi_bank_bl_vec = redistribute_bl_vectors_to_shift_register_banks(bl_vec, blwl_sr_banks); + + std::vector reshaped_bl_vectors = reshape_bitstream_vectors_to_first_element(multi_bank_bl_vec, dont_care_bit); /* Reverse the vectors due to the shift register chain nature: first-in first-out */ std::reverse(reshaped_bl_vectors.begin(), reshaped_bl_vectors.end()); /* Add the BL word to final bitstream */ @@ -419,7 +523,10 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b fabric_bits.add_bl_vectors(word_id, reshaped_bl_vec); } - std::vector reshaped_wl_vectors = reshape_bitstream_vectors_to_first_element(wl_vec, dont_care_bit); + /* Redistribute the WL vector to multiple banks */ + std::vector multi_bank_wl_vec = redistribute_wl_vectors_to_shift_register_banks(wl_vec, blwl_sr_banks); + + std::vector reshaped_wl_vectors = reshape_bitstream_vectors_to_first_element(multi_bank_wl_vec, dont_care_bit); /* Reverse the vectors due to the shift register chain nature: first-in first-out */ std::reverse(reshaped_wl_vectors.begin(), reshaped_wl_vectors.end()); /* Add the BL word to final bitstream */ diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h index ac0bca14a..3cb1285bb 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.h +++ b/openfpga/src/utils/fabric_bitstream_utils.h @@ -95,8 +95,8 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons * @note the std::map may cause large memory footprint for large bitstream databases! *******************************************************************/ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_bitstream(const FabricBitstream& fabric_bitstream, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& fast_configuration, - //const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& bit_value_to_skip, const char& dont_care_bit = 'x'); From 82e77b42c5f704879d151f8422858be9c585c066 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 9 Oct 2021 20:43:55 -0700 Subject: [PATCH 199/229] [Arch] Add an example architecture which uses multiple shift register chain for a single-ql-bank FPGA --- ..._N4_40nm_qlbanksr_multi_chain_openfpga.xml | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_multi_chain_openfpga.xml diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_multi_chain_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_multi_chain_openfpga.xml new file mode 100644 index 000000000..0c4598128 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_multi_chain_openfpga.xml @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 6122863548cf107100cf3b46d04e07f8cb2d50c8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 9 Oct 2021 20:44:28 -0700 Subject: [PATCH 200/229] [Test] Add a test case to validate the multi-shift-register-chain QL memory bank --- .../config/task.conf | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register_multi_chain/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register_multi_chain/config/task.conf b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register_multi_chain/config/task.conf new file mode 100644 index 000000000..f9e2febb6 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/full_testbench/ql_memory_bank_shift_register_multi_chain/config/task.conf @@ -0,0 +1,45 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +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/write_full_testbench_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_multi_chain_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml + +openfpga_vpr_device_layout= +openfpga_fast_configuration= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v +bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +bench1_top = or2 +bench1_chan_width = 300 + +bench2_top = and2_latch +bench2_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= From 8f9e564cd5990421c5beac9795462c35a588090a Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 9 Oct 2021 20:45:23 -0700 Subject: [PATCH 201/229] [Test] Add the new test to basic regression test --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index 5381920fe..0f7a0e1e2 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -61,6 +61,7 @@ run-task basic_tests/full_testbench/ql_memory_bank_flatten --debug --show_thread run-task basic_tests/full_testbench/ql_memory_bank_flatten_use_wlr --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_shift_register --debug --show_thread_logs run-task basic_tests/full_testbench/ql_memory_bank_shift_register_use_wlr --debug --show_thread_logs +run-task basic_tests/full_testbench/ql_memory_bank_shift_register_multi_chain --debug --show_thread_logs echo -e "Testing testbenches without self checking features"; run-task basic_tests/full_testbench/full_testbench_without_self_checking --debug --show_thread_logs From 7810f376c8defb6eddac9592126c0e6a3486cb0f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 9 Oct 2021 21:03:01 -0700 Subject: [PATCH 202/229] [FPGA-Bitstream] Patch code comments --- openfpga/src/utils/fabric_bitstream_utils.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 16074cb92..113635699 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -345,7 +345,7 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons } /******************************************************************** - * Reshape a list of vectors by aligning all of them to the last element + * Reshape a list of vectors by aligning all of them to the first element * For example: * - Align vectors to the last element * @@ -357,15 +357,16 @@ MemoryBankFlattenFabricBitstream build_memory_bank_flatten_fabric_bitstream(cons * - Fill void in each vector with desired bits (Here assume fill 'x' * index ----------------------> * vector 0: 000000001111101010 - * vector 1: xxxx00000011010101 - * vector 2: xx0010101111000110 + * vector 1: 00000011010101xxxx + * vector 2: 0010101111000110xx * * - Rotate the array by 90 degree * index -----------------------> - * vector 0: 0xx - * vector 1: 0xx + * vector 0: 000 + * vector 1: 000 + * vector 2: 001 * ... - * vector N: 010 + * vector N: 0xx * *******************************************************************/ static From 6aa4991314fd2c107969d4867ef21b1c41a99c2d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 9 Oct 2021 21:34:07 -0700 Subject: [PATCH 203/229] [FPGA-Verilog] Bug fix --- .../src/fpga_verilog/verilog_top_testbench_memory_bank.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index b9eb69d96..581149d1b 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -349,7 +349,9 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s BasicPort start_wl_sr_port(TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME, 1); /* Reorganize the fabric bitstream by the same address across regions */ - if (CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) { + if ( (CONFIG_MEM_QL_MEMORY_BANK == config_protocol.type()) + && (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) + && (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()) ) { MemoryBankShiftRegisterFabricBitstream fabric_bits_by_addr = build_memory_bank_shift_register_fabric_bitstream(fabric_bitstream, blwl_sr_banks, fast_configuration, From 1c46a92559cade2e2e35cc247c6db549d7a360a5 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 9 Oct 2021 21:59:56 -0700 Subject: [PATCH 204/229] [FPGA-Bitstream] Bug fix --- openfpga/src/utils/fabric_bitstream_utils.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp index 113635699..cd60d5879 100644 --- a/openfpga/src/utils/fabric_bitstream_utils.cpp +++ b/openfpga/src/utils/fabric_bitstream_utils.cpp @@ -408,7 +408,8 @@ std::vector reshape_bitstream_vectors_to_first_element(const std::v */ static std::vector redistribute_bl_vectors_to_shift_register_banks(const std::vector bl_vectors, - const MemoryBankShiftRegisterBanks& blwl_sr_banks) { + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const char& dont_care_bit) { std::vector multi_bank_bl_vec; /* Resize the vector by counting the dimension */ @@ -427,7 +428,7 @@ std::vector redistribute_bl_vectors_to_shift_register_banks(const s for (const auto& region : blwl_sr_banks.regions()) { for (const auto& bank : blwl_sr_banks.bl_banks(region)) { size_t bank_size = blwl_sr_banks.bl_bank_size(region, bank); - multi_bank_bl_vec[vec_start_index].resize(bank_size); + multi_bank_bl_vec[vec_start_index].resize(bank_size, dont_care_bit); vec_start_index++; } } @@ -458,7 +459,8 @@ std::vector redistribute_bl_vectors_to_shift_register_banks(const s */ static std::vector redistribute_wl_vectors_to_shift_register_banks(const std::vector wl_vectors, - const MemoryBankShiftRegisterBanks& blwl_sr_banks) { + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const char& dont_care_bit) { std::vector multi_bank_wl_vec; /* Resize the vector by counting the dimension */ @@ -477,7 +479,7 @@ std::vector redistribute_wl_vectors_to_shift_register_banks(const s for (const auto& region : blwl_sr_banks.regions()) { for (const auto& bank : blwl_sr_banks.wl_banks(region)) { size_t bank_size = blwl_sr_banks.wl_bank_size(region, bank); - multi_bank_wl_vec[vec_start_index].resize(bank_size); + multi_bank_wl_vec[vec_start_index].resize(bank_size, dont_care_bit); vec_start_index++; } } @@ -514,7 +516,7 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b MemoryBankShiftRegisterFabricBitstreamWordId word_id = fabric_bits.create_word(); /* Redistribute the BL vector to multiple banks */ - std::vector multi_bank_bl_vec = redistribute_bl_vectors_to_shift_register_banks(bl_vec, blwl_sr_banks); + std::vector multi_bank_bl_vec = redistribute_bl_vectors_to_shift_register_banks(bl_vec, blwl_sr_banks, dont_care_bit); std::vector reshaped_bl_vectors = reshape_bitstream_vectors_to_first_element(multi_bank_bl_vec, dont_care_bit); /* Reverse the vectors due to the shift register chain nature: first-in first-out */ @@ -525,7 +527,7 @@ MemoryBankShiftRegisterFabricBitstream build_memory_bank_shift_register_fabric_b } /* Redistribute the WL vector to multiple banks */ - std::vector multi_bank_wl_vec = redistribute_wl_vectors_to_shift_register_banks(wl_vec, blwl_sr_banks); + std::vector multi_bank_wl_vec = redistribute_wl_vectors_to_shift_register_banks(wl_vec, blwl_sr_banks, dont_care_bit); std::vector reshaped_wl_vectors = reshape_bitstream_vectors_to_first_element(multi_bank_wl_vec, dont_care_bit); /* Reverse the vectors due to the shift register chain nature: first-in first-out */ From de3275e9baedb36aa3ebc62b27d92addf0fe6a01 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 10 Oct 2021 16:56:07 -0700 Subject: [PATCH 205/229] [FPGA-Verilog] Fixed a critical in verilog testbench which caused the last bit of bitstream skipped when loading to shift register chains --- .../verilog_top_testbench_memory_bank.cpp | 118 +++++++++++++++++- 1 file changed, 113 insertions(+), 5 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 581149d1b..8e2d496ea 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -42,6 +42,8 @@ namespace openfpga { constexpr char* TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME = "bl_sr_clock"; constexpr char* TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME = "wl_sr_clock"; +constexpr char* TOP_TB_VIRTUAL_BL_SHIFT_REGISTER_CLOCK_PORT_NAME = "virtual_bl_sr_clock"; +constexpr char* TOP_TB_VIRTUAL_WL_SHIFT_REGISTER_CLOCK_PORT_NAME = "virtual_wl_sr_clock"; constexpr char* TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME = "start_bl_sr"; constexpr char* TOP_TB_START_WL_SHIFT_REGISTER_PORT_NAME = "start_wl_sr"; constexpr char* TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME = "bl_sr_count"; @@ -90,9 +92,12 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, } /* BL Shift register clock and registers */ + BasicPort virtual_sr_clock_port(std::string(TOP_TB_VIRTUAL_BL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); + fp << generate_verilog_port(VERILOG_PORT_REG, virtual_sr_clock_port) << ";" << std::endl; BasicPort sr_clock_port(std::string(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_port) << ";" << std::endl; + /* Register to enable/disable bl/wl shift register clocks */ BasicPort start_bl_sr_port(TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME, 1); fp << generate_verilog_port(VERILOG_PORT_REG, start_bl_sr_port) << ";" << std::endl; @@ -132,6 +137,8 @@ void print_verilog_top_testbench_ql_memory_bank_port(std::fstream& fp, } /* WL Shift register clock and registers */ + BasicPort virtual_sr_clock_port(std::string(TOP_TB_VIRTUAL_WL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); + fp << generate_verilog_port(VERILOG_PORT_REG, virtual_sr_clock_port) << ";" << std::endl; BasicPort sr_clock_port(std::string(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME), 1); fp << generate_verilog_port(VERILOG_PORT_REG, sr_clock_port) << ";" << std::endl; @@ -243,6 +250,49 @@ void print_verilog_top_testbench_global_shift_register_clock_ports_stimuli(std:: } } +/** + * @brief Generate the Verilog codes for a shift register virtual clock that controls BL/WL protocols + * The virtual clock is the reference clock, which include 1 additional clock cycle for reset + * when compared to the actual clock + */ +static +void print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator(std::fstream& fp, + const BasicPort& start_sr_port, + const BasicPort& sr_clock_port, + const float& sr_clock_period) { + /* Validate the file stream */ + valid_file_stream(fp); + + fp << "always"; + fp << " @(posedge " << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ")"; + fp << " begin"; + fp << std::endl; + + fp << "\t"; + fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); + fp << ";" << std::endl; + + fp << "\t"; + fp << "while (" << generate_verilog_port(VERILOG_PORT_CONKT, start_sr_port) << ") begin"; + fp << std::endl; + + fp << "\t\t"; + fp << "#" << sr_clock_period << " "; + print_verilog_register_connection(fp, sr_clock_port, sr_clock_port, true); + + fp << "\t"; + fp << "end"; + fp << std::endl; + + fp << "\t"; + fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); + fp << ";" << std::endl; + + fp << "end"; + fp << std::endl; +} + + /** * @brief Generate the Verilog codes for a shift register clocks that controls BL/WL protocols */ @@ -259,6 +309,11 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator( fp << " begin"; fp << std::endl; + /* Skip the first the clock cycle which is reserved for reset */ + fp << "\t"; + fp << "#" << sr_clock_period * 2. << ";" << std::endl; + fp << std::endl; + fp << "\t"; fp << generate_verilog_port_constant_values(sr_clock_port, std::vector(sr_clock_port.get_width(), 0), true); fp << ";" << std::endl; @@ -343,6 +398,8 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s /* Stimulus only for shift-register-based BL/WL protocols */ BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); + BasicPort virtual_bl_sr_clock_port(TOP_TB_VIRTUAL_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); + BasicPort virtual_wl_sr_clock_port(TOP_TB_VIRTUAL_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); BasicPort bl_sr_clock_port(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); BasicPort wl_sr_clock_port(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); BasicPort start_bl_sr_port(TOP_TB_START_BL_SHIFT_REGISTER_PORT_NAME, 1); @@ -389,11 +446,16 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s } if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.bl_protocol_type()) { + print_verilog_comment(fp, "----- BL Shift register virtual clock generator -----"); + print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator(fp, start_bl_sr_port, virtual_bl_sr_clock_port, bl_sr_clock_period); + print_verilog_comment(fp, "----- BL Shift register clock generator -----"); print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, start_bl_sr_port, bl_sr_clock_port, bl_sr_clock_period); } if (BLWL_PROTOCOL_SHIFT_REGISTER == config_protocol.wl_protocol_type()) { + print_verilog_comment(fp, "----- WL Shift register virtual clock generator -----"); + print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator(fp, start_wl_sr_port, virtual_wl_sr_clock_port, wl_sr_clock_period); print_verilog_comment(fp, "----- WL Shift register clock generator -----"); print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(fp, start_wl_sr_port, wl_sr_clock_port, wl_sr_clock_period); } @@ -644,13 +706,36 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << ";"; fp << std::endl; + BasicPort bl_sr_clock_port(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); + BasicPort wl_sr_clock_port(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); + + fp << "\t"; + fp << generate_verilog_port_constant_values(bl_sr_clock_port, std::vector(bl_sr_clock_port.get_width(), 0), true); + fp << ";"; + fp << std::endl; + + fp << "\t"; + fp << generate_verilog_port_constant_values(wl_sr_clock_port, std::vector(wl_sr_clock_port.get_width(), 0), true); + fp << ";"; + fp << std::endl; + + BasicPort virtual_bl_sr_clock_port(TOP_TB_VIRTUAL_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); + BasicPort virtual_wl_sr_clock_port(TOP_TB_VIRTUAL_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); + + fp << "\t"; + fp << generate_verilog_port_constant_values(virtual_bl_sr_clock_port, std::vector(virtual_bl_sr_clock_port.get_width(), 0), true); + fp << ";"; + fp << std::endl; + + fp << "\t"; + fp << generate_verilog_port_constant_values(virtual_wl_sr_clock_port, std::vector(virtual_wl_sr_clock_port.get_width(), 0), true); + fp << ";"; + fp << std::endl; + fp << "end"; fp << std::endl; - BasicPort prog_clock_port(std::string(TOP_TB_PROG_CLOCK_PORT_NAME) + std::string(TOP_TB_CLOCK_REG_POSTFIX), 1); - BasicPort bl_sr_clock_port(TOP_TB_BL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); - BasicPort wl_sr_clock_port(TOP_TB_WL_SHIFT_REGISTER_CLOCK_PORT_NAME, 1); print_verilog_comment(fp, "----- Begin bitstream loading during configuration phase -----"); fp << "always"; @@ -711,7 +796,7 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f /* Load data to BL shift register chains */ fp << "always"; - fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, bl_sr_clock_port) << ")"; + fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, virtual_bl_sr_clock_port) << ")"; fp << " begin"; fp << std::endl; @@ -727,6 +812,18 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << generate_verilog_port_constant_values(start_bl_sr_port, std::vector(start_bl_sr_port.get_width(), 0), true); fp << ";" << std::endl; + fp << "\t"; + fp << "end" << std::endl; + + + fp << "\t"; + fp << "if ("; + fp << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME; + fp << " >= "; + fp << "`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE; + fp << ") begin"; + fp << std::endl; + fp << "\t\t"; fp << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME << " = 0;"; fp << std::endl; @@ -755,7 +852,7 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f /* Load data to WL shift register chains */ fp << "always"; - fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, wl_sr_clock_port) << ")"; + fp << " @(negedge " << generate_verilog_port(VERILOG_PORT_CONKT, virtual_wl_sr_clock_port) << ")"; fp << " begin"; fp << std::endl; @@ -771,6 +868,17 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << generate_verilog_port_constant_values(start_wl_sr_port, std::vector(start_wl_sr_port.get_width(), 0), true); fp << ";" << std::endl; + fp << "\t"; + fp << "end" << std::endl; + + fp << "\t"; + fp << "if ("; + fp << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME; + fp << " >= "; + fp << "`" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE; + fp << ") begin"; + fp << std::endl; + fp << "\t\t"; fp << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME << " = 0;"; fp << std::endl; From 57159fc121b88e12c4867be65c41ea311d875f5f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 10 Oct 2021 17:46:45 -0700 Subject: [PATCH 206/229] [Doc] Update documentation for the new syntax in configuration protocol and fabric key file format --- .../manual/arch_lang/config_protocol.rst | 12 ++- .../source/manual/file_formats/fabric_key.rst | 76 +++++++++++++++++++ 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/docs/source/manual/arch_lang/config_protocol.rst b/docs/source/manual/arch_lang/config_protocol.rst index 1c124ddc0..26f9a304d 100644 --- a/docs/source/manual/arch_lang/config_protocol.rst +++ b/docs/source/manual/arch_lang/config_protocol.rst @@ -167,8 +167,8 @@ The BL and WL protocols can be customized through the XML syntax ``bl`` and ``wl - - + + @@ -203,6 +203,14 @@ The BL and WL protocols can be customized through the XML syntax ``bl`` and ``wl Example of (a) a memory organization using shift register chains to control BL/WLs; (b) single memory bank across the fabric; and (c) multiple memory banks across the fabric. +.. option:: num_banks="" + + Specify the number of shift register banks (i.e., independent shift register chains) to be used in each configuration region. When enabled, the length of each shift register chain will be sized by OpenFPGA automatically based on the number of BL/WLs in each configuration region. OpenFPGA will try to create similar sizes for the shift register chains, in order to minimize the number of HDL modules. If not specified, the default number of banks will be ``1``. + + + .. note:: This is available applicable to shift-register-based BL/WL protocols + + .. note:: More customization on the shift register chains can be enabled through :ref:`fabric_key` .. note:: The flip-flop for WL shift register requires an enable signal to gate WL signals when loading WL shift registers diff --git a/docs/source/manual/file_formats/fabric_key.rst b/docs/source/manual/file_formats/fabric_key.rst index 185e1b40a..b3088aa6b 100644 --- a/docs/source/manual/file_formats/fabric_key.rst +++ b/docs/source/manual/file_formats/fabric_key.rst @@ -24,21 +24,54 @@ The following example shows how to define multiple configuration regions in the + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -200,3 +233,46 @@ This key contains only ``name``, ``value``, ``row`` and ``column``. + +BL Shift Register Banks +^^^^^^^^^^^^^^^^^^^^^^^ + +.. note:: The customizable is only available when the shift-register-based memory bank is selected in :ref:`config_protocol` + +Each Bit-Line (BL) shift register bank is defined in the code block ````. +A shift register bank may contain multiple shift register chains. +- each shift register chain can be defined using the ``bank`` syntax +- the BLs controlled by each chain can be customized through the ``range`` syntax. + +.. option:: + + - ``id`` indicates the sequence of the shift register chain in the bank. The id denotes the index in the head or tail bus. For example, ``id="0"`` means the head or tail of the shift register will be in the first bit of a head bus ``head[0:4]`` + + - ``range`` indicates ``BL`` port to be controlled by this shift register chain. Multiple BL ports can be defined but the sequence matters. For example, ``bl[0:3], bl[6:10]`` infers a 9-bit shift register chain whose output ports are connected from ``bl[0]`` to ``bl[10]``. + + .. note:: When creating the range, you must know the number of BLs in the configuration region + + .. note:: ports must use ``bl`` as the reserved port name + + +WL Shift Register Banks +^^^^^^^^^^^^^^^^^^^^^^^ + +.. note:: The customizable is only available when the shift-register-based memory bank is selected in :ref:`config_protocol` + +Each Word-Line (WL) shift register bank is defined in the code block ````. +A shift register bank may contain multiple shift register chains. +- each shift register chain can be defined using the ``bank`` syntax +- the BLs controlled by each chain can be customized through the ``range`` syntax. + + +.. option:: + + - ``id`` indicates the sequence of the shift register chain in the bank. The id denotes the index in the head or tail bus. For example, ``id="0"`` means the head or tail of the shift register will be in the first bit of a head bus ``head[0:4]`` + + - ``range`` indicates ``WL`` port to be controlled by this shift register chain. Multiple WL ports can be defined but the sequence matters. For example, ``wl[0:3], wl[6:10]`` infers a 9-bit shift register chain whose output ports are connected from ``wl[0]`` to ``wl[10]``. + + .. note:: When creating the range, you must know the number of BLs in the configuration region + + .. note:: ports must use ``wl`` as the reserved port name + From 4e2df9d69c04b24d3c3cbd2b47ebc8e0416fbde2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 10 Oct 2021 17:59:11 -0700 Subject: [PATCH 207/229] [Lib] Bug fix in unintialized memory in fabric key --- libopenfpga/libfabrickey/src/fabric_key.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libopenfpga/libfabrickey/src/fabric_key.cpp b/libopenfpga/libfabrickey/src/fabric_key.cpp index f17f3deaa..500dec09a 100644 --- a/libopenfpga/libfabrickey/src/fabric_key.cpp +++ b/libopenfpga/libfabrickey/src/fabric_key.cpp @@ -91,6 +91,10 @@ std::vector FabricKey::wl_bank_data_ports(const FabricRegio void FabricKey::reserve_regions(const size_t& num_regions) { region_ids_.reserve(num_regions); region_key_ids_.reserve(num_regions); + bl_bank_ids_.reserve(num_regions); + bl_bank_data_ports_.reserve(num_regions); + wl_bank_ids_.reserve(num_regions); + wl_bank_data_ports_.reserve(num_regions); } FabricRegionId FabricKey::create_region() { @@ -98,6 +102,10 @@ FabricRegionId FabricKey::create_region() { FabricRegionId region = FabricRegionId(region_ids_.size()); region_ids_.push_back(region); region_key_ids_.emplace_back(); + bl_bank_ids_.emplace_back(); + bl_bank_data_ports_.emplace_back(); + wl_bank_ids_.emplace_back(); + wl_bank_data_ports_.emplace_back(); return region; } From 202b50c0e33b7866d315317c414c0a34d19ee49b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 10 Oct 2021 20:57:23 -0700 Subject: [PATCH 208/229] [FPGA-Verilog] Fixed a weird bug which causes totally different results in fixed and auto shift register clock freq; However, this is a dirty fix. Require further study to know why --- .../verilog_top_testbench_memory_bank.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 8e2d496ea..883eb6c81 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -416,10 +416,11 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s /* Compute the auto-tuned clock period first, this is the lower bound of the shift register clock periods: * - the BL/WL shift register clock only works in the second half of the programming clock period - * - add 2 idle clocks to avoid racing between programming clock and shift register clocks at edge + * - consider a 10% slack for clocks to avoid racing between programming clock and shift register clocks at edge + * TODO: To figure out what is the min. slack required here. See something strange in HDL simulation */ - float bl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.bl_word_size() + 2) / timescale; - float wl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.wl_word_size() + 2) / timescale; + float bl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.bl_word_size() * 1.1) / timescale; + float wl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.wl_word_size() * 1.1) / timescale; VTR_LOG("Precomputed clock frequency (=%g %s) for %s.\n", 1. / (2. * bl_sr_clock_period * timescale) / 1e6, @@ -804,7 +805,7 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "if ("; fp << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME; fp << " >= "; - fp << "`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " - 1"; + fp << "`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " - 0"; fp << ") begin"; fp << std::endl; @@ -860,7 +861,7 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "if ("; fp << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME; fp << " >= "; - fp << "`" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << " - 1"; + fp << "`" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << " - 0"; fp << ") begin"; fp << std::endl; From b9c540ec3fd622c64d2ce43bf138d055c7f4b82b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 10 Oct 2021 21:14:14 -0700 Subject: [PATCH 209/229] [Engine] Upgrade fabric key writer to support BL/WL shift register banks --- openfpga/src/base/openfpga_build_fabric.cpp | 1 + openfpga/src/fabric/fabric_key_writer.cpp | 31 ++++++++++++++++++++- openfpga/src/fabric/fabric_key_writer.h | 2 ++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/openfpga/src/base/openfpga_build_fabric.cpp b/openfpga/src/base/openfpga_build_fabric.cpp index 211048eb3..e63cab03e 100644 --- a/openfpga/src/base/openfpga_build_fabric.cpp +++ b/openfpga/src/base/openfpga_build_fabric.cpp @@ -135,6 +135,7 @@ int build_fabric(OpenfpgaContext& openfpga_ctx, curr_status = write_fabric_key_to_xml_file(openfpga_ctx.module_graph(), fkey_fname, openfpga_ctx.arch().config_protocol, + openfpga_ctx.mutable_blwl_shift_register_banks(), cmd_context.option_enable(cmd, opt_verbose)); /* If there is any error, final status cannot be overwritten by a success flag */ if (CMD_EXEC_SUCCESS != curr_status) { diff --git a/openfpga/src/fabric/fabric_key_writer.cpp b/openfpga/src/fabric/fabric_key_writer.cpp index 38cb599db..21f19766e 100644 --- a/openfpga/src/fabric/fabric_key_writer.cpp +++ b/openfpga/src/fabric/fabric_key_writer.cpp @@ -32,6 +32,7 @@ namespace openfpga { int write_fabric_key_to_xml_file(const ModuleManager& module_manager, const std::string& fname, const ConfigProtocol& config_protocol, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& verbose) { std::string timer_message = std::string("Write fabric key to XML file '") + fname + std::string("'"); @@ -65,10 +66,16 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager, size_t num_regions = module_manager.regions(top_module).size(); fabric_key.reserve_regions(num_regions); - /* Create regions for the keys and load keys by region */ + /* Create regions and build a id map */ + std::map region_id_map; for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { FabricRegionId fabric_region = fabric_key.create_region(); + region_id_map[config_region] = fabric_region; + } + /* Create regions for the keys and load keys by region */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + FabricRegionId fabric_region = region_id_map[config_region]; /* Each configuration protocol has some child which should not be in the list. They are typically decoders */ size_t curr_region_num_config_child = module_manager.region_configurable_children(top_module, config_region).size(); size_t num_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol, curr_region_num_config_child); @@ -97,6 +104,28 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager, } } + /* Add BL shift register bank information, if there is any */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + FabricRegionId fabric_region = region_id_map[config_region]; + for (const FabricBitLineBankId& bank : blwl_sr_banks.bl_banks(config_region)) { + FabricBitLineBankId fabric_bank = fabric_key.create_bl_shift_register_bank(fabric_region); + for (const BasicPort& data_port : blwl_sr_banks.bl_bank_data_ports(config_region, bank)) { + fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, fabric_bank, data_port); + } + } + } + + /* Add WL shift register bank information, if there is any */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + FabricRegionId fabric_region = region_id_map[config_region]; + for (const FabricWordLineBankId& bank : blwl_sr_banks.wl_banks(config_region)) { + FabricWordLineBankId fabric_bank = fabric_key.create_wl_shift_register_bank(fabric_region); + for (const BasicPort& data_port : blwl_sr_banks.wl_bank_data_ports(config_region, bank)) { + fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, fabric_bank, data_port); + } + } + } + VTR_LOGV(verbose, "Created %lu regions and %lu keys for the top module %s.\n", num_regions, num_keys, top_module_name.c_str()); diff --git a/openfpga/src/fabric/fabric_key_writer.h b/openfpga/src/fabric/fabric_key_writer.h index bdb860354..47d505f3e 100644 --- a/openfpga/src/fabric/fabric_key_writer.h +++ b/openfpga/src/fabric/fabric_key_writer.h @@ -7,6 +7,7 @@ #include #include "module_manager.h" #include "config_protocol.h" +#include "memory_bank_shift_register_banks.h" /******************************************************************** * Function declaration @@ -18,6 +19,7 @@ namespace openfpga { int write_fabric_key_to_xml_file(const ModuleManager& module_manager, const std::string& fname, const ConfigProtocol& config_protocol, + MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& verbose); } /* end namespace openfpga */ From 40fd89fdb430387e104299377bb76b90a00daa47 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 10 Oct 2021 22:03:49 -0700 Subject: [PATCH 210/229] [arch] Update fabric key for multi-region --- .../k4_N4_2x2_multi_region_qlbanksr_sample_key.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbanksr_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbanksr_sample_key.xml index 0b96c1930..9bf434709 100644 --- a/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbanksr_sample_key.xml +++ b/openfpga_flow/fabric_keys/k4_N4_2x2_multi_region_qlbanksr_sample_key.xml @@ -1,5 +1,11 @@ + + + + + + @@ -21,6 +27,12 @@ + + + + + + From 546350ae4107db4116b35b5bd4a99c4988f3e89f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 10 Oct 2021 23:19:39 -0700 Subject: [PATCH 211/229] [FPGA-Verilog] Revert back to the previous precomputing strategy for shift register clocks --- .../fpga_verilog/verilog_top_testbench_memory_bank.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp index 883eb6c81..7f6076c21 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench_memory_bank.cpp @@ -416,11 +416,11 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(s /* Compute the auto-tuned clock period first, this is the lower bound of the shift register clock periods: * - the BL/WL shift register clock only works in the second half of the programming clock period - * - consider a 10% slack for clocks to avoid racing between programming clock and shift register clocks at edge + * - consider two additional clocks to avoid racing between programming clock and shift register clocks at edge * TODO: To figure out what is the min. slack required here. See something strange in HDL simulation */ - float bl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.bl_word_size() * 1.1) / timescale; - float wl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.wl_word_size() * 1.1) / timescale; + float bl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.bl_word_size() + 2) / timescale; + float wl_sr_clock_period = 0.25 * prog_clock_period / (fabric_bits_by_addr.wl_word_size() + 2) / timescale; VTR_LOG("Precomputed clock frequency (=%g %s) for %s.\n", 1. / (2. * bl_sr_clock_period * timescale) / 1e6, @@ -805,7 +805,7 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "if ("; fp << TOP_TB_BL_SHIFT_REGISTER_COUNT_PORT_NAME; fp << " >= "; - fp << "`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " - 0"; + fp << "`" << TOP_TB_BITSTREAM_BL_WORD_SIZE_VARIABLE << " - 1"; fp << ") begin"; fp << std::endl; @@ -861,7 +861,7 @@ void print_verilog_full_testbench_ql_memory_bank_shift_register_bitstream(std::f fp << "if ("; fp << TOP_TB_WL_SHIFT_REGISTER_COUNT_PORT_NAME; fp << " >= "; - fp << "`" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << " - 0"; + fp << "`" << TOP_TB_BITSTREAM_WL_WORD_SIZE_VARIABLE << " - 1"; fp << ") begin"; fp << std::endl; From 982a324e0d891d3f2464506e015332a4ed719981 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sun, 10 Oct 2021 23:30:50 -0700 Subject: [PATCH 212/229] [Test] Temporarily disable some tests; Will go back later --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index 0f7a0e1e2..b6abcd5e2 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -85,7 +85,8 @@ run-task basic_tests/custom_fabric_netlist_location --debug --show_thread_logs echo -e "Testing user-defined simulation settings: clock frequency and number of cycles"; run-task basic_tests/fixed_simulation_settings/fixed_operating_clock_freq --debug --show_thread_logs -run-task basic_tests/fixed_simulation_settings/fixed_shift_register_clock_freq --debug --show_thread_logs +# TODO: This feature is temporarily out of test due to the emergency in delivering netlists for multi-chain shift-register memory bank +#run-task basic_tests/fixed_simulation_settings/fixed_shift_register_clock_freq --debug --show_thread_logs echo -e "Testing Secured FPGA fabrics"; run-task basic_tests/fabric_key/generate_vanilla_key --debug --show_thread_logs @@ -97,7 +98,8 @@ run-task basic_tests/fabric_key/load_external_key_cc_fpga --debug --show_thread_ run-task basic_tests/fabric_key/load_external_key_multi_region_cc_fpga --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key_qlbank_fpga --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga --debug --show_thread_logs -run-task basic_tests/fabric_key/load_external_key_multi_region_qlbanksr_fpga --debug --show_thread_logs +# TODO: This feature is temporarily out of test due to the emergency in delivering netlists for multi-chain shift-register memory bank +#run-task basic_tests/fabric_key/load_external_key_multi_region_qlbanksr_fpga --debug --show_thread_logs echo -e "Testing K4 series FPGA"; echo -e "Testing K4N4 with facturable LUTs"; From 6586ea78167be5d3a6f647cffe48dbd22e71ccc2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 11 Oct 2021 09:40:02 -0700 Subject: [PATCH 213/229] [Engine] Bug fix for fabric key writer which errors out when there is no BL/WL banks in the architecture --- openfpga/src/base/openfpga_build_fabric.cpp | 2 +- openfpga/src/fabric/fabric_key_writer.cpp | 48 +++++++++++++-------- openfpga/src/fabric/fabric_key_writer.h | 2 +- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/openfpga/src/base/openfpga_build_fabric.cpp b/openfpga/src/base/openfpga_build_fabric.cpp index e63cab03e..4e576ef6c 100644 --- a/openfpga/src/base/openfpga_build_fabric.cpp +++ b/openfpga/src/base/openfpga_build_fabric.cpp @@ -135,7 +135,7 @@ int build_fabric(OpenfpgaContext& openfpga_ctx, curr_status = write_fabric_key_to_xml_file(openfpga_ctx.module_graph(), fkey_fname, openfpga_ctx.arch().config_protocol, - openfpga_ctx.mutable_blwl_shift_register_banks(), + openfpga_ctx.blwl_shift_register_banks(), cmd_context.option_enable(cmd, opt_verbose)); /* If there is any error, final status cannot be overwritten by a success flag */ if (CMD_EXEC_SUCCESS != curr_status) { diff --git a/openfpga/src/fabric/fabric_key_writer.cpp b/openfpga/src/fabric/fabric_key_writer.cpp index 21f19766e..7ac8f90ea 100644 --- a/openfpga/src/fabric/fabric_key_writer.cpp +++ b/openfpga/src/fabric/fabric_key_writer.cpp @@ -32,7 +32,7 @@ namespace openfpga { int write_fabric_key_to_xml_file(const ModuleManager& module_manager, const std::string& fname, const ConfigProtocol& config_protocol, - MemoryBankShiftRegisterBanks& blwl_sr_banks, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& verbose) { std::string timer_message = std::string("Write fabric key to XML file '") + fname + std::string("'"); @@ -75,7 +75,11 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager, /* Create regions for the keys and load keys by region */ for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - FabricRegionId fabric_region = region_id_map[config_region]; + /* Must have a valid one-to-one region mapping */ + auto result = region_id_map.find(config_region); + VTR_ASSERT_SAFE(result != region_id_map.end()); + FabricRegionId fabric_region = result->second; + /* Each configuration protocol has some child which should not be in the list. They are typically decoders */ size_t curr_region_num_config_child = module_manager.region_configurable_children(top_module, config_region).size(); size_t num_child_to_skip = estimate_num_configurable_children_to_skip_by_config_protocol(config_protocol, curr_region_num_config_child); @@ -104,24 +108,34 @@ int write_fabric_key_to_xml_file(const ModuleManager& module_manager, } } - /* Add BL shift register bank information, if there is any */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - FabricRegionId fabric_region = region_id_map[config_region]; - for (const FabricBitLineBankId& bank : blwl_sr_banks.bl_banks(config_region)) { - FabricBitLineBankId fabric_bank = fabric_key.create_bl_shift_register_bank(fabric_region); - for (const BasicPort& data_port : blwl_sr_banks.bl_bank_data_ports(config_region, bank)) { - fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, fabric_bank, data_port); + /* Skip invalid region, some architecture may not have BL/WL banks */ + if (0 < blwl_sr_banks.regions().size()) { + /* Add BL shift register bank information, if there is any */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + auto result = region_id_map.find(config_region); + /* Must have a valid one-to-one region mapping */ + VTR_ASSERT_SAFE(result != region_id_map.end()); + FabricRegionId fabric_region = result->second; + for (const FabricBitLineBankId& bank : blwl_sr_banks.bl_banks(config_region)) { + FabricBitLineBankId fabric_bank = fabric_key.create_bl_shift_register_bank(fabric_region); + for (const BasicPort& data_port : blwl_sr_banks.bl_bank_data_ports(config_region, bank)) { + fabric_key.add_data_port_to_bl_shift_register_bank(fabric_region, fabric_bank, data_port); + } } } - } - /* Add WL shift register bank information, if there is any */ - for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { - FabricRegionId fabric_region = region_id_map[config_region]; - for (const FabricWordLineBankId& bank : blwl_sr_banks.wl_banks(config_region)) { - FabricWordLineBankId fabric_bank = fabric_key.create_wl_shift_register_bank(fabric_region); - for (const BasicPort& data_port : blwl_sr_banks.wl_bank_data_ports(config_region, bank)) { - fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, fabric_bank, data_port); + /* Add WL shift register bank information, if there is any */ + for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { + auto result = region_id_map.find(config_region); + /* Must have a valid one-to-one region mapping */ + VTR_ASSERT_SAFE(result != region_id_map.end()); + FabricRegionId fabric_region = result->second; + + for (const FabricWordLineBankId& bank : blwl_sr_banks.wl_banks(config_region)) { + FabricWordLineBankId fabric_bank = fabric_key.create_wl_shift_register_bank(fabric_region); + for (const BasicPort& data_port : blwl_sr_banks.wl_bank_data_ports(config_region, bank)) { + fabric_key.add_data_port_to_wl_shift_register_bank(fabric_region, fabric_bank, data_port); + } } } } diff --git a/openfpga/src/fabric/fabric_key_writer.h b/openfpga/src/fabric/fabric_key_writer.h index 47d505f3e..d80a7180f 100644 --- a/openfpga/src/fabric/fabric_key_writer.h +++ b/openfpga/src/fabric/fabric_key_writer.h @@ -19,7 +19,7 @@ namespace openfpga { int write_fabric_key_to_xml_file(const ModuleManager& module_manager, const std::string& fname, const ConfigProtocol& config_protocol, - MemoryBankShiftRegisterBanks& blwl_sr_banks, + const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& verbose); } /* end namespace openfpga */ From cdcb07256bc0e132c12fd787ef5645ed635d4e2f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 11 Oct 2021 09:49:22 -0700 Subject: [PATCH 214/229] [Arch] Add an example fabric key that models a shift-register-based QuickLogic memory bank using custom chain organization --- ...N4_1x1_qlbanksr_multi_chain_sample_key.xml | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 openfpga_flow/fabric_keys/k4_N4_1x1_qlbanksr_multi_chain_sample_key.xml diff --git a/openfpga_flow/fabric_keys/k4_N4_1x1_qlbanksr_multi_chain_sample_key.xml b/openfpga_flow/fabric_keys/k4_N4_1x1_qlbanksr_multi_chain_sample_key.xml new file mode 100644 index 000000000..0cb89d6fe --- /dev/null +++ b/openfpga_flow/fabric_keys/k4_N4_1x1_qlbanksr_multi_chain_sample_key.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From b8b02d37d5690d5a71b541ea75fc22d6cff60372 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 11 Oct 2021 09:53:23 -0700 Subject: [PATCH 215/229] [Test] Added a new test case to validate the correctness of custom shift register chain through fabric key file --- .../config/task.conf | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain/config/task.conf diff --git a/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain/config/task.conf b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain/config/task.conf new file mode 100644 index 000000000..0990a0fd0 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain/config/task.conf @@ -0,0 +1,39 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# 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 = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=vpr_blif + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/generate_secure_fabric_from_key_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_multi_chain_openfpga.xml +openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml +external_fabric_key_file=${PATH:OPENFPGA_PATH}/openfpga_flow/fabric_keys/k4_N4_1x1_qlbanksr_multi_chain_sample_key.xml +openfpga_vpr_device_layout= + +[ARCHITECTURES] +arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act +bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= +#vpr_fpga_verilog_formal_verification_top_netlist= From 2bf203cd009e011550b5a7f776a5700b85c99f02 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 11 Oct 2021 09:54:39 -0700 Subject: [PATCH 216/229] [Test] Deploy the new test to basic regression test --- openfpga_flow/regression_test_scripts/basic_reg_test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/openfpga_flow/regression_test_scripts/basic_reg_test.sh b/openfpga_flow/regression_test_scripts/basic_reg_test.sh index b6abcd5e2..76db04426 100755 --- a/openfpga_flow/regression_test_scripts/basic_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/basic_reg_test.sh @@ -98,6 +98,7 @@ run-task basic_tests/fabric_key/load_external_key_cc_fpga --debug --show_thread_ run-task basic_tests/fabric_key/load_external_key_multi_region_cc_fpga --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key_qlbank_fpga --debug --show_thread_logs run-task basic_tests/fabric_key/load_external_key_multi_region_qlbank_fpga --debug --show_thread_logs +run-task basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain_fpga --debug --show_thread_logs # TODO: This feature is temporarily out of test due to the emergency in delivering netlists for multi-chain shift-register memory bank #run-task basic_tests/fabric_key/load_external_key_multi_region_qlbanksr_fpga --debug --show_thread_logs From 8566e2a0cdbd6c475b2cbeac430e5b32e4b89002 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 11 Oct 2021 09:56:23 -0700 Subject: [PATCH 217/229] [Test] Renaming test case to follow naming convention as other fabric key test cases --- .../config/task.conf | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename openfpga_flow/tasks/basic_tests/fabric_key/{load_external_key_qlbanksr_multi_chain => load_external_key_qlbanksr_multi_chain_fpga}/config/task.conf (100%) diff --git a/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain/config/task.conf b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain_fpga/config/task.conf similarity index 100% rename from openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain/config/task.conf rename to openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain_fpga/config/task.conf From b2c4e3314e562cba574a5790e98d4c334475f585 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Mon, 11 Oct 2021 10:28:09 -0700 Subject: [PATCH 218/229] [Test] Bug fix in test cases --- .../config/task.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain_fpga/config/task.conf b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain_fpga/config/task.conf index 0990a0fd0..651f0accf 100644 --- a/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain_fpga/config/task.conf +++ b/openfpga_flow/tasks/basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain_fpga/config/task.conf @@ -20,7 +20,7 @@ openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scrip openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_multi_chain_openfpga.xml openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml external_fabric_key_file=${PATH:OPENFPGA_PATH}/openfpga_flow/fabric_keys/k4_N4_1x1_qlbanksr_multi_chain_sample_key.xml -openfpga_vpr_device_layout= +openfpga_vpr_device_layout=auto [ARCHITECTURES] arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml From 0f10cc4c81eb93ccf6d8f9a98bf33878e89227c8 Mon Sep 17 00:00:00 2001 From: nadeemyaseen-rs Date: Thu, 14 Oct 2021 19:43:37 +0500 Subject: [PATCH 219/229] change the path in ci_test.sh --- ci_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci_test.sh b/ci_test.sh index 0c3d8d166..6d48232f0 100755 --- a/ci_test.sh +++ b/ci_test.sh @@ -1,6 +1,6 @@ #!/bin/bash -export OPENFPGA_PATH=/home/komal.javed@lmlhr.com/rapidsilicon/openfpga_new +export OPENFPGA_PATH=~/rapidsilicon/openfpga_new for dir in RTL_Benchmark/*; do if [ -d "$dir" ]; then From 101e84aaa85b57270198cee7abb0a48039fbfc23 Mon Sep 17 00:00:00 2001 From: nadeemyaseen-rs Date: Wed, 20 Oct 2021 20:16:41 +0500 Subject: [PATCH 220/229] added auto_fetch.yml file to create automatic PR for update_from_upstream branch --- .github/workflows/auto_fetch.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/auto_fetch.yml diff --git a/.github/workflows/auto_fetch.yml b/.github/workflows/auto_fetch.yml new file mode 100644 index 000000000..af1ee3fad --- /dev/null +++ b/.github/workflows/auto_fetch.yml @@ -0,0 +1,25 @@ +me: Create Pull Request for Upstream Changes +on: + push: + branches: + - update_from_upstream +jobs: + pull-request: + runs-on: ubuntu-latest + env: + BRANCH_UPSTREAM: update_from_upstream + steps: + - uses: actions/checkout@v2 + - name: pull-request + uses: repo-sync/pull-request@v2 + with: + source_branch: ${{env.BRANCH_UPSTREAM}} # name of branch for PR + destination_branch: "master" # name of branch on which PR go + pr_title: "Pulling ${{ github.ref }} into master" # Title of pull request + pr_body: ":crown: *An automated PR*" # Full markdown support, requires pr_title + pr_reviewer: "tangxifan" # Comma-separated list (no spaces) + pr_assignee: "nadeemyaseen-rs,mahmoodulhassan-rs" # Comma-separated list (no spaces) + pr_label: "auto-pr" # Comma-separated list (no spaces) + pr_allow_empty: true # Creates pull request even if there are no changes + github_token: ${{ secrets.GITHUB_TOKEN }} + From 6e6225a33ea95b140ab330aa0b8f25f55636eb69 Mon Sep 17 00:00:00 2001 From: nadeemyaseen-rs <86344264+nadeemyaseen-rs@users.noreply.github.com> Date: Wed, 20 Oct 2021 20:19:35 +0500 Subject: [PATCH 221/229] corrected the syntax error --- .github/workflows/auto_fetch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto_fetch.yml b/.github/workflows/auto_fetch.yml index af1ee3fad..1e3f44a47 100644 --- a/.github/workflows/auto_fetch.yml +++ b/.github/workflows/auto_fetch.yml @@ -1,4 +1,4 @@ -me: Create Pull Request for Upstream Changes +name: Create Pull Request for Upstream Changes on: push: branches: From 1cf0fe0f4ecdb5ce2752fc20ada4b62484ef4898 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 20 Oct 2021 13:22:48 -0700 Subject: [PATCH 222/229] Update docker.yml --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index d1cf27e40..590940d34 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -11,7 +11,7 @@ jobs: base_images: name: Push Docker images runs-on: ubuntu-latest - if: ${{ secrets.DOCKER_REPO }} + if: ${{ env.DOCKER_REPO }} steps: - name: Checkout uses: actions/checkout@v2 From cbb839eb33876ebeb89a97a7b65044b4b08fa40b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Dec 2021 07:23:12 +0000 Subject: [PATCH 223/229] Bump yosys-plugins from `b48dda6` to `3fb0f3b` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `b48dda6` to `3fb0f3b`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/b48dda647aa07170b46185eff6496a2073ad0d8f...3fb0f3b553bbfa024260ed57e15cb526c02211b6) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index b48dda647..3fb0f3b55 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit b48dda647aa07170b46185eff6496a2073ad0d8f +Subproject commit 3fb0f3b553bbfa024260ed57e15cb526c02211b6 From d5ec6c58ef99fcec200daf29f28d8ae2c1d137de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Dec 2021 07:23:47 +0000 Subject: [PATCH 224/229] Bump yosys-plugins from `3fb0f3b` to `b40f6cd` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `3fb0f3b` to `b40f6cd`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/3fb0f3b553bbfa024260ed57e15cb526c02211b6...b40f6cd0c509d01e07e0c0df266d20211e03f76d) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index 3fb0f3b55..b40f6cd0c 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit 3fb0f3b553bbfa024260ed57e15cb526c02211b6 +Subproject commit b40f6cd0c509d01e07e0c0df266d20211e03f76d From c137b31bb4b8ca7844078c178b746614c168f88b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Dec 2021 07:28:31 +0000 Subject: [PATCH 225/229] Bump yosys-plugins from `b40f6cd` to `9ee3057` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `b40f6cd` to `9ee3057`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/b40f6cd0c509d01e07e0c0df266d20211e03f76d...9ee3057a714b8101aa7e0e787fed15f49dbd17d0) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index b40f6cd0c..9ee3057a7 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit b40f6cd0c509d01e07e0c0df266d20211e03f76d +Subproject commit 9ee3057a714b8101aa7e0e787fed15f49dbd17d0 From 53fd3918c02d7100206c3ededa3faab78fd7ef2c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Dec 2021 07:31:58 +0000 Subject: [PATCH 226/229] Bump yosys-plugins from `9ee3057` to `b79ad0d` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `9ee3057` to `b79ad0d`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/9ee3057a714b8101aa7e0e787fed15f49dbd17d0...b79ad0dee591bc481f7fc545fe200446bce0bc48) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index 9ee3057a7..b79ad0dee 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit 9ee3057a714b8101aa7e0e787fed15f49dbd17d0 +Subproject commit b79ad0dee591bc481f7fc545fe200446bce0bc48 From 51b008d04b86306a3bf6bd930407983f8c8cff13 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Dec 2021 07:25:14 +0000 Subject: [PATCH 227/229] Bump yosys-plugins from `b79ad0d` to `91d7db0` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `b79ad0d` to `91d7db0`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/b79ad0dee591bc481f7fc545fe200446bce0bc48...91d7db03ddbee23f9ff91f395de1692a37e51362) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index b79ad0dee..91d7db03d 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit b79ad0dee591bc481f7fc545fe200446bce0bc48 +Subproject commit 91d7db03ddbee23f9ff91f395de1692a37e51362 From aeb40fef60963c232a6d8c803dac0fb7d6cddc4d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 29 Dec 2021 10:51:06 -0800 Subject: [PATCH 228/229] [CI] cleanup --- .github/workflows/auto_fetch.yml | 25 ------------------------- .github/workflows/ci_test.yml | 32 -------------------------------- 2 files changed, 57 deletions(-) delete mode 100644 .github/workflows/auto_fetch.yml delete mode 100644 .github/workflows/ci_test.yml diff --git a/.github/workflows/auto_fetch.yml b/.github/workflows/auto_fetch.yml deleted file mode 100644 index 1e3f44a47..000000000 --- a/.github/workflows/auto_fetch.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Create Pull Request for Upstream Changes -on: - push: - branches: - - update_from_upstream -jobs: - pull-request: - runs-on: ubuntu-latest - env: - BRANCH_UPSTREAM: update_from_upstream - steps: - - uses: actions/checkout@v2 - - name: pull-request - uses: repo-sync/pull-request@v2 - with: - source_branch: ${{env.BRANCH_UPSTREAM}} # name of branch for PR - destination_branch: "master" # name of branch on which PR go - pr_title: "Pulling ${{ github.ref }} into master" # Title of pull request - pr_body: ":crown: *An automated PR*" # Full markdown support, requires pr_title - pr_reviewer: "tangxifan" # Comma-separated list (no spaces) - pr_assignee: "nadeemyaseen-rs,mahmoodulhassan-rs" # Comma-separated list (no spaces) - pr_label: "auto-pr" # Comma-separated list (no spaces) - pr_allow_empty: true # Creates pull request even if there are no changes - github_token: ${{ secrets.GITHUB_TOKEN }} - diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml deleted file mode 100644 index d0158fcf6..000000000 --- a/.github/workflows/ci_test.yml +++ /dev/null @@ -1,32 +0,0 @@ -# This is a basic workflow to help you get started with Actions - -name: CI - -# Controls when the workflow will run -on: - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # This workflow contains a single job called "build" - build: - # The type of runner that the job will run on - runs-on: self-hosted - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v1 - with: - submodules: true - - - name: Updating submodules - run: | - git submodule init - git submodule update --init --recursive - - # Runs a set of commands using the runners shell - - name: Executing Script - run: - ./ci_test.sh From 8ff6b5a393d291d26e6af962aaa279beb0bc44e8 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 29 Dec 2021 10:51:51 -0800 Subject: [PATCH 229/229] [Script] clean up --- ci_test.sh | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100755 ci_test.sh diff --git a/ci_test.sh b/ci_test.sh deleted file mode 100755 index 6d48232f0..000000000 --- a/ci_test.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -export OPENFPGA_PATH=~/rapidsilicon/openfpga_new - -for dir in RTL_Benchmark/*; do - if [ -d "$dir" ]; then - echo "Looking for top file in $dir/rtl" - - top_file="$(basename "$dir")" - - FILE=$dir/rtl/$top_file.v - - if [ -f "$FILE" ]; then - echo -e "${CYAN}$top_file exists ${ENDCOLOR}" - export design_path=${OPENFPGA_PATH}/$FILE - export design_top=$top_file - echo "design = $design_path" - python3 $OPENFPGA_PATH/openfpga_flow/scripts/run_ci_tests.py ci_tests - else - echo -e "${RED}Top file not found. Make sure design exists${ENDCOLOR}" - exit 1 - fi - fi -done - -