mirror of https://github.com/lnis-uofu/SOFA.git
607 lines
26 KiB
Makefile
607 lines
26 KiB
Makefile
# Design Project Makefile
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~
|
|
#
|
|
# This makefile is placed in the design project, it is used for generating
|
|
# verilog netlist, execute OpenFPGA and post-process the netlist to
|
|
# make it easier to place and route.
|
|
#
|
|
# List of important targets
|
|
#
|
|
# Planning:
|
|
#
|
|
# * **generate_shapes**: Render configured FPGA fabric
|
|
# * **generate_fabric_key**: Create fabric key and render
|
|
# * **generate_clock_tree**: Create feedthrough for clock signals
|
|
# * **generate_global_connectivity**: Create feedthrough for global signals
|
|
#
|
|
# Main flow:
|
|
#
|
|
# * **run_openfpga**: Generate netlist with OpenFPGA
|
|
# * **netlist_cleanup**: Collect sources and lint netlist for better version control
|
|
# * **netlist_synth**: Script to run after netlist is cleaned up
|
|
# * **restructure_netlist**: Restructure physical hierarchy of the netlist
|
|
# * **floorplan**: Perform explicit shaping if required
|
|
#
|
|
#
|
|
# .. graphviz::
|
|
#
|
|
# digraph main_project_makefiles {
|
|
# "generate_shapes" ->
|
|
# "run_openfpga" ->
|
|
# "netlist_cleanup" ->
|
|
# "netlist_synth" ->
|
|
# "restructure_netlist";
|
|
# "generate_shapes" ->
|
|
# "generate_clock_tree" ->
|
|
# "generate_global_connectivity" ->
|
|
# "restructure_netlist";
|
|
# "netlist_cleanup" ->
|
|
# "generate_fabric_key" ->
|
|
# "restructure_netlist" ->
|
|
# "floorplan" ->
|
|
# "write_source_files" ->
|
|
# "timing_extraction";
|
|
# }
|
|
|
|
|
|
SHELL =bash
|
|
PYTHON_EXEC ?= python3.8
|
|
ICC2_LM_EXEC = icc2_lm_shell
|
|
DC_SHELL_EXEC ?= dc_shell
|
|
PT_SHELL_EXEC ?= pt_shell
|
|
FM_SHELL_EXEC ?= fm_shell
|
|
RERUN = 0
|
|
TB = top
|
|
OPTIONS =
|
|
OPENPHY_ROOT ?= ../../
|
|
LOAD_TOOLS ?= ${OPENPHY_ROOT}/LoadTools.sh
|
|
CONF = task_simulation
|
|
VERDI_EXEC ?= Verdi-3
|
|
SCRIPTS_DIR ?=scripts
|
|
PYTHON_OPT ?=
|
|
|
|
.SILENT:
|
|
.ONESHELL:
|
|
.DEFAULT:help
|
|
|
|
generate_shapes:
|
|
# Renders the FPGA Fabric is SVG format
|
|
#
|
|
# Generate SVG for original floorplan and modified fllorplan in this script
|
|
# also store the pickle information (``RENDER_FABRIC_SCRIPT`` )
|
|
#
|
|
# Refer template : render_fabric.py
|
|
#
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
echo $${RENDER_FABRIC_SCRIPT}
|
|
RENDER_FABRIC_SCRIPT=$${RENDER_FABRIC_SCRIPT:='../../openfpga-physical/render_fabric.py'}
|
|
if test -f "$${RENDER_FABRIC_SCRIPT}"; then
|
|
[[ $$RENDER_FABRIC_SCRIPT == *".py"* ]] && $${PYTHON_EXEC} $${RENDER_FABRIC_SCRIPT}
|
|
[[ $$RENDER_FABRIC_SCRIPT == *".sh"* ]] && source $${RENDER_FABRIC_SCRIPT}
|
|
else
|
|
echo "[ERROR] RENDER_FABRIC_SCRIPT does not exist ($${RENDER_FABRIC_SCRIPT})"
|
|
fi
|
|
date > generate_shapes
|
|
|
|
generate_global_connectivity: generate_shapes
|
|
# generate_global_connectivity
|
|
#
|
|
# Generates post-OpenFPGA netlist modifications for global signals
|
|
#
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
if test -f "$${GLOBAL_FT_SCRIPT}"; then
|
|
[[ $$GLOBAL_FT_SCRIPT == *".py"* ]] && $${PYTHON_EXEC} $${GLOBAL_FT_SCRIPT}
|
|
[[ $$GLOBAL_FT_SCRIPT == *".sh"* ]] && source $${GLOBAL_FT_SCRIPT}
|
|
else
|
|
echo "[ERROR] GLOBAL_FT_SCRIPT does not exist ($${GLOBAL_FT_SCRIPT})"
|
|
fi
|
|
date > generate_global_connectivity
|
|
|
|
generate_clock_tree: generate_shapes
|
|
# generate_clock_tree
|
|
#
|
|
# Generates post-OpenFPGA netlist modifications for all clocks
|
|
#
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
if test -f "$${CLOCK_FT_SCRIPT}"; then
|
|
[[ $$CLOCK_FT_SCRIPT == *".py"* ]] && $${PYTHON_EXEC} $${CLOCK_FT_SCRIPT}
|
|
[[ $$CLOCK_FT_SCRIPT == *".sh"* ]] && source $${CLOCK_FT_SCRIPT}
|
|
else
|
|
echo "[ERROR] CLOCK_FT_SCRIPT does not exist ($${CLOCK_FT_SCRIPT})"
|
|
fi
|
|
date > generate_clock_tree
|
|
|
|
generate_fabric_key: generate_shapes
|
|
# Generate the fabric key and stores in <proj_name>_task/arch direcrory
|
|
#
|
|
# External python script is used to generate XML based fabric key file
|
|
# following parameters affect this receipe
|
|
#
|
|
# - ``GENERATE_FABRIC_KEY`` Python script which generates the fabric key XML file
|
|
# - ``FABRIC_KEY_PATTERN`` This parameter is passed to the the python script
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
RENDER_FABRIC_SCRIPT=$${GENERATE_FABRIC_KEY:='../../openfpga-physical/generate_fabric_key.py'}
|
|
echo "Executing $${RENDER_FABRIC_SCRIPT}"
|
|
if test -f "$${GENERATE_FABRIC_KEY}"; then
|
|
[[ $$GENERATE_FABRIC_KEY == *".py"* ]] && $${PYTHON_EXEC} ${PYTHON_OPT} $${GENERATE_FABRIC_KEY}
|
|
[[ $$GENERATE_FABRIC_KEY == *".sh"* ]] && source $${GENERATE_FABRIC_KEY}
|
|
else
|
|
echo "[ERROR] GENERATE_FABRIC_KEY does not exist ($${GENERATE_FABRIC_KEY})"
|
|
fi
|
|
date > generate_fabric_key
|
|
|
|
|
|
run_openfpga: generate_shapes
|
|
# Generates the FPGA verilog netlist from the ``task_generation.conf`` task
|
|
#
|
|
# Generated Verilog netlist is stored in the ``VERILOG_PROJ_DIR`` (`<PROJ_NAME>_verilog`) directory
|
|
# Following variables are refered from the ``config.sh`` file
|
|
#
|
|
# - ``TASK_DIR_NAME``:- Variable used as find the task, by default ``task_generation.conf`` is executed
|
|
# - ``CUSTOM_MODULES_LIST``:- This is a file list file which get copied to custom modules directory after netlist generation
|
|
|
|
SECONDS=0
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
CURR_OF_VERSION=$$($${OPENFPGA_PATH}/**/openfpga --version | head -n 1 | cut -c 10-16)
|
|
if test -f "$${OF_VERSION}"; then
|
|
if [[ $${CURR_OF_VERSION} != $${OF_VERSION} ]]; then
|
|
echo "OPENFPGA_VERSION is not compatible expected $${OF_VERSION}, found $${CURR_OF_VERSION}"
|
|
exit
|
|
fi
|
|
fi
|
|
# ============================================================================
|
|
# =================== Clean Previous Run ===================================
|
|
# ============================================================================
|
|
rm -f $${OPENFPGA_PATH}/openfpga_flow/tasks/$${TASK_DIR_NAME}
|
|
(cd ./$${TASK_DIR_NAME}/config && rm -f task.conf && cp task_generation.conf task.conf)
|
|
|
|
# ============================================================================
|
|
# ===================== Generate Netlist ===================================
|
|
# ============================================================================
|
|
rm -rf $${TASK_DIR_NAME}/run**
|
|
(currDir=$${PWD} && cd $$OPENFPGA_PATH && source openfpga.sh && cd $$currDir &&
|
|
run-task $${TASK_DIR_NAME} --remove_run_dir all
|
|
run-task $${TASK_DIR_NAME} ${OPTIONS})
|
|
if [ $$? -eq 1 ]; then
|
|
echo "X X X X X X Failed to generate netlist X X X X X X"; exit 1;
|
|
fi
|
|
# Created run directory locally
|
|
run_dir=$$(realpath --relative-to=$${PWD} $$(readlink -f */latest/*/*/*))
|
|
echo "Run Directory: $${run_dir}"
|
|
ln -sfn ./$${run_dir} _run_dir
|
|
|
|
# === Remove timestamps from generated sources for better version control ====
|
|
find ./$${TASK_DIR_NAME}/latest/*/*/*/ -type f -name "*.v" -print0 | xargs -0 sed -i "/^\/\/.*Date.*/d"
|
|
find ./$${TASK_DIR_NAME}/latest/*/*/*/ -type f -name "*.sdc" -print0 | xargs -0 sed -i "/^#.*Date.*/d"
|
|
find ./$${TASK_DIR_NAME}/latest/*/*/*/ -type f -name "*.xml" -print0 | xargs -0 sed -i "/^.*Date.*/d"
|
|
|
|
# ======================= Log runtime info =================================
|
|
duration=$$SECONDS
|
|
date > run_openfpga
|
|
echo "$$(($$duration / 60)) minutes and $$(($$duration % 60)) seconds elapsed." >> run_openfpga
|
|
|
|
netlist_cleanup: run_openfpga
|
|
# This clean up the netlist
|
|
#
|
|
# Following steps are executed to cleanup the netlist for versio control purpose
|
|
#
|
|
# * Remove datetime stamps from all files (.v/.xml/.sdc)
|
|
# * Create list of directories (SRC, SDC, TESTBENCH, SRCOutline, SRCOriginal, SRCLint )
|
|
# * Copy OpenFPGA generated verilog netlist and SDC to `SRCOriginal` and `SDC` diectory respectively
|
|
# * Copy all the files from `sc_verilog` and `CustomModules` directory available is ``*_task`` directory to ``*_verilog`` directory
|
|
# * If ``CUSTOM_MODULES_LIST`` varaible is set, copy all files listed in this file to `CustomModules` directory
|
|
# * Clean (remove variables lines) from openfpgashell.log file and backup in ``VERILOG_PROJ_DIR`` directory
|
|
# * Use ``spydrnet-physical`` to lint all verilog sources in ``SRCOriginal`` and store in ``SRCLint`` directory
|
|
# * Crate a copy of SRCLint to SRC before post processing netlistfor post processing
|
|
#
|
|
|
|
SECONDS=0
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
|
|
echo "spydrnet_physical" > .spydrnet
|
|
# ============================================================================
|
|
# ===================== Copy generated files ===============================
|
|
# ============================================================================
|
|
for directory in SDC XML GSB TESTBENCH SRCOutline SRCOriginal SRCLint \
|
|
/SRCOriginal/CustomModules /SRCOriginal/sc_verilog; do
|
|
echo "Creating directory $${VERILOG_PROJ_DIR}/$${directory}"
|
|
rm -rf $${VERILOG_PROJ_DIR}/$${directory}
|
|
mkdir -p $${VERILOG_PROJ_DIR}/$${directory}
|
|
done
|
|
|
|
cp -r ./$${TASK_DIR_NAME}/latest/*/*/*/SRC/* $${VERILOG_PROJ_DIR}/SRCOriginal
|
|
cp -r ./$${TASK_DIR_NAME}/latest/*/*/*/SDC/* $${VERILOG_PROJ_DIR}/SDC || true
|
|
cp -r ./$${TASK_DIR_NAME}/latest/*/*/*/gsb/* $${VERILOG_PROJ_DIR}/GSB || true
|
|
cp -r ./$${TASK_DIR_NAME}/latest/*/*/*/*.xml $${VERILOG_PROJ_DIR}/XML || true
|
|
cp ./$${TASK_DIR_NAME}/sc_verilog/*.v $${VERILOG_PROJ_DIR}/SRCOriginal/sc_verilog || true
|
|
cp -r ./$${TASK_DIR_NAME}/CustomModules/* $${VERILOG_PROJ_DIR}/SRCOriginal/CustomModules || true
|
|
|
|
# ============================================================================
|
|
# ===================== Copy Custom Modules =================================
|
|
# ============================================================================
|
|
if test -f "$${CUSTOM_MODULES_LIST}"; then
|
|
cat $${CUSTOM_MODULES_LIST} | grep -v '^#' | while read line; do
|
|
cp $$line $${VERILOG_PROJ_DIR}/SRCOriginal/CustomModules/;
|
|
echo "[ Info] Copied custom module $$line"
|
|
done
|
|
else
|
|
echo "[WARN] CUSTOM_MODULES_LIST variable not found, no custom module is copied ($${CUSTOM_MODULES_LIST})"
|
|
fi
|
|
# Flatterns the multi-line wire declaration
|
|
# find $${VERILOG_PROJ_DIR}/SRCOriginal/CustomModules -type f -name "*.v" -print0 | xargs -0 sed -i ':begin;$$!N;s/\([)|,]\)\n\s*/\1/;tbegin;P;D'
|
|
|
|
# ============================================================================
|
|
# ====================== Keep Copy of OpenFPGA.log ===========================
|
|
# ============================================================================
|
|
cp -r ./$${TASK_DIR_NAME}/latest/*/*/*/openfpgashell.log $${VERILOG_PROJ_DIR}
|
|
sed -i "s/^Compiled.*/--line removed--/" $${VERILOG_PROJ_DIR}/openfpgashell.log
|
|
sed -i "s/.*took.*seconds.*/--line removed--/" $${VERILOG_PROJ_DIR}/openfpgashell.log
|
|
sed -i "s/^\*\*.*/--line removed--/" $${VERILOG_PROJ_DIR}/openfpgashell.log
|
|
sed -i "s/\/.*xml/--line removed--/" $${VERILOG_PROJ_DIR}/openfpgashell.log
|
|
sed -i "s/\/.*openfpga -batch/--line removed-- openfpga -batch/" $${VERILOG_PROJ_DIR}/openfpgashell.log
|
|
sed -i "s/tool_comment.*/tool_comment=\"\">/" $${VERILOG_PROJ_DIR}/XML/*.xml
|
|
find ./$${VERILOG_PROJ_DIR}/GSB -name "*.xml" -type f -exec xmllint --output '{}' --format '{}' \;
|
|
find ./$${VERILOG_PROJ_DIR}/XML -name "*.xml" -type f -exec xmllint --output '{}' --format '{}' \;
|
|
|
|
# ============================================================================
|
|
# ======================= Pre Verilog Script ================================
|
|
# ============================================================================
|
|
|
|
if test -f "$${PRE_VERILOG_LINT}"; then
|
|
[[ $$PRE_VERILOG_LINT == *".py"* ]] && $${PYTHON_EXEC} $${PRE_VERILOG_LINT}
|
|
[[ $$PRE_VERILOG_LINT == *".sh"* ]] && source $${PRE_VERILOG_LINT}
|
|
fi
|
|
|
|
# ============================================================================
|
|
# ======================= Lint Original netlist =============================
|
|
# ============================================================================
|
|
find $${VERILOG_PROJ_DIR}/SRCOriginal -type f -name "*.v" -exec sed -i "s/^\`default_nettype/\/\/ \`default_nettype/g" '{}' \;
|
|
cp -r $${VERILOG_PROJ_DIR}/SRCOriginal/CustomModules $${VERILOG_PROJ_DIR}/SRCLint/
|
|
# To create a complete linted netlist version for version control
|
|
for eachFile in $$(grep -rln "^module " $${VERILOG_PROJ_DIR}/SRCOriginal/); do
|
|
[[ $$eachFile == *"_tb"* ]] && continue
|
|
[[ $$eachFile == *"_verification"* ]] && continue
|
|
[[ $$eachFile == *"sc_verilog"* ]] && continue
|
|
# Need to remove this currently this skips the linting of custom modules
|
|
[[ $$eachFile == *"CustomModules"* ]] && continue
|
|
if [[ $${eachFile} == *"fpga_top.v"* ]]; then
|
|
echo "Found fpga_top.v"
|
|
$${PYTHON_EXEC} -c "import spydrnet as sdn; import yaml; from pathlib import Path; import os;\
|
|
netlist = sdn.parse('$${eachFile}'); netlist.name='$$PROJ_NAME'; \
|
|
Path(os.path.dirname('$${eachFile/SRCOriginal/SRCLint}')).mkdir(parents=True, exist_ok=True); \
|
|
modules = sorted([e for e in netlist.top_instance.reference.get_definitions()], key=lambda x: x.name); \
|
|
instances = {m.name:sorted([i.name for i in m.references]) for m in modules}; \
|
|
yaml.dump(instances, open('$${VERILOG_PROJ_DIR}/SRCLint/top_hierarchy.yml', 'w'));\
|
|
sdn.compose(netlist, '$${eachFile/SRCOriginal/SRCLint}', write_blackbox=False, skip_constraints=True)" | grep -v "Plugins"
|
|
else
|
|
echo -n $${eachFile/SRCOriginal/SRCLint}
|
|
$${PYTHON_EXEC} -c "import spydrnet as sdn; import yaml; from pathlib import Path; import os;\
|
|
netlist = sdn.parse('$${eachFile}'); netlist.name='$$PROJ_NAME'; \
|
|
Path(os.path.dirname('$${eachFile/SRCOriginal/SRCLint}')).mkdir(parents=True, exist_ok=True); \
|
|
sdn.compose(netlist, '$${eachFile/SRCOriginal/SRCLint}', write_blackbox=False, skip_constraints=True)" | grep -v "Plugins"
|
|
echo " "$$?
|
|
fi
|
|
done
|
|
|
|
find $${VERILOG_PROJ_DIR}/SRCOriginal -type f -name "*.v" -exec sed -i "s/.*default_nettype/\`default_nettype/g" '{}' \;
|
|
|
|
# ============================================================================
|
|
# ======================= Post Verilog Script ================================
|
|
# ============================================================================
|
|
if test -f "$${POST_VERILOG_LINT}"; then
|
|
[[ $$POST_VERILOG_LINT == *".py"* ]] && $${PYTHON_EXEC} $${POST_VERILOG_LINT}
|
|
[[ $$POST_VERILOG_LINT == *".sh"* ]] && source $${POST_VERILOG_LINT}
|
|
fi
|
|
|
|
# ======================= Log runtime info =================================
|
|
duration=$$SECONDS
|
|
date > netlist_cleanup
|
|
echo "$$(($$duration / 60)) minutes and $$(($$duration % 60)) seconds elapsed." >> netlist_cleanup
|
|
|
|
netlist_synth: netlist_cleanup
|
|
# Post netlist clean up script
|
|
#
|
|
# - ``NETLIST_SYNTH_SCRIPT``:- This variable points to shell script which execute after verilog netlist generation
|
|
SECONDS=0
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
# ============================================================================
|
|
# ====================== Post RunOpenFPGA ====================================
|
|
# ============================================================================
|
|
if test -f "$${NETLIST_SYNTH_SCRIPT}"; then
|
|
if [[ $$NETLIST_SYNTH_SCRIPT == *".py"* ]]; then $${PYTHON_EXEC} $${NETLIST_SYNTH_SCRIPT}; fi
|
|
if [[ $$NETLIST_SYNTH_SCRIPT == *".sh"* ]]; then source $${NETLIST_SYNTH_SCRIPT}; fi
|
|
else
|
|
echo "[ERROR] NETLIST_SYNTH_SCRIPT does not exist ($${NETLIST_SYNTH_SCRIPT})"
|
|
fi
|
|
echo $$?
|
|
# ======================= Log runtime info =================================
|
|
duration=$$SECONDS
|
|
date > netlist_synth
|
|
echo "$$(($$duration / 60)) minutes and $$(($$duration % 60)) seconds elapsed." >> netlist_synth
|
|
|
|
|
|
restructure_netlist: netlist_synth generate_fabric_key
|
|
# This netlist restructuring phase,
|
|
#
|
|
# - Collect fabric_indepenent_bitstream.xml if its generated
|
|
# - Restructure netlist It reads netlist from ``SRCLint` directory and creates restructured version in ``SRC`` directory
|
|
# - Clean up GSB modules
|
|
#
|
|
# Following variables are refered from the ``config.sh`` file
|
|
# ``RESTRUCT_NETLIST``:- This is a python or bash file which will be executed to restructure the netlist
|
|
#
|
|
SECONDS=0
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
|
|
rm -rf $${VERILOG_PROJ_DIR}/SRC
|
|
mkdir -p $${VERILOG_PROJ_DIR}/SRC
|
|
cp -r $${VERILOG_PROJ_DIR}/SRCLint/CustomModules $${VERILOG_PROJ_DIR}/SRC/
|
|
|
|
# If there are any bitstream generate copy that and save in ${VERILOG_PROJ_DIR}/TESTBENCH/
|
|
for TBFileOriginal in $$(find ./$${TASK_DIR_NAME}/latest/*/*/*/* -name 'fabric_indepenent_bitstream.xml'); do
|
|
echo "= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = "
|
|
# Extract Topmodule name of the benchmark
|
|
TopModuleName=$$(echo $$TBFileOriginal | sed -e "s/.*_task\/[^\/]*\/[^\/]*\/\([^\/]*\).*/\1/g" )
|
|
mkdir -p $${VERILOG_PROJ_DIR}/TESTBENCH/$${TopModuleName}
|
|
cp -r ./$${TASK_DIR_NAME}/latest/*/$${TopModuleName}/*/*_bitstream.xml $${VERILOG_PROJ_DIR}/TESTBENCH/$${TopModuleName}
|
|
cp -r ./$${TASK_DIR_NAME}/latest/*/$${TopModuleName}/*/*_bitstream.bit $${VERILOG_PROJ_DIR}/TESTBENCH/$${TopModuleName}
|
|
done
|
|
|
|
# ============================================================================
|
|
# ====================== Execute Restructuring script ========================
|
|
# ============================================================================
|
|
if test -f "$${RESTRUCT_NETLIST}"; then
|
|
echo "Executing RESTRUCT_NETLIST: $${RESTRUCT_NETLIST}"
|
|
if [[ $$RESTRUCT_NETLIST == *".py"* ]]; then $${PYTHON_EXEC} $${RESTRUCT_NETLIST}; fi
|
|
if [[ $$RESTRUCT_NETLIST == *".sh"* ]]; then source $${RESTRUCT_NETLIST}; fi
|
|
fi
|
|
|
|
# ========================= Log runtime info =================================
|
|
duration=$$SECONDS
|
|
date > restructure_netlist
|
|
echo "$$(($$duration / 60)) minutes and $$(($$duration % 60)) seconds elapsed." >> restructure_netlist
|
|
|
|
|
|
floorplan: restructure_netlist
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
if test -f "$${FLOORPLAN_SCRIPT}"; then
|
|
[[ $$FLOORPLAN_SCRIPT == *".py"* ]] && $${PYTHON_EXEC} $${FLOORPLAN_SCRIPT}
|
|
[[ $$FLOORPLAN_SCRIPT == *".sh"* ]] && source $${FLOORPLAN_SCRIPT}
|
|
else
|
|
echo "[WARN] FLOORPLAN_SCRIPT does not exist ($${FLOORPLAN_SCRIPT})"
|
|
fi
|
|
date > floorplan
|
|
|
|
run_openfpga_sim:
|
|
# Run the simulation Deck
|
|
#
|
|
# TODO explain more
|
|
#
|
|
SECONDS=0
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
CONF=${CONF}
|
|
# =================== Clean Previous Run =================================
|
|
rm -f $${OPENFPGA_PATH}/openfpga_flow/tasks/$${TASK_DIR_NAME}
|
|
(cd ./$${TASK_DIR_NAME}/config && rm -f task.conf && cp ${CONF}.conf task.conf)
|
|
|
|
# ===================== Generate Netlist =================================
|
|
rm -rf $${TASK_DIR_NAME}/run**
|
|
(currDir=$${PWD} && cd $$OPENFPGA_PATH && source openfpga.sh && cd $$currDir &&
|
|
run-task $${TASK_DIR_NAME} --remove_run_dir all &&
|
|
run-task $${TASK_DIR_NAME} ${OPTIONS})
|
|
if [ $$? -eq 1 ]; then
|
|
echo "X X X X X X Failed to generate netlist X X X X X X"; exit 1;
|
|
fi
|
|
rm -rf $${VERILOG_PROJ_DIR}/TESTBENCH/${CONF}
|
|
# ================= Created run directory locally =================
|
|
run_dir=$$(realpath --relative-to=$${PWD} $$(readlink -f */latest/*/*/*))
|
|
echo "Run Directory: $${run_dir}"
|
|
ln -sfn ./$${run_dir} _run_dir
|
|
# ================= Copy Bitstream from generated source ===================
|
|
for TBFileOriginal in $$(find ./$${TASK_DIR_NAME}/latest/*/*/*/* -name '*fabric_bitstream.xml'); do
|
|
echo "= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = "
|
|
# Extract Topmodule name of the benchmark
|
|
TopModuleName=$$(echo $$TBFileOriginal | sed -e "s/.*_task\/[^\/]*\/[^\/]*\/\([^\/]*\).*/\1/g" )
|
|
echo "Found Testbench = $${TopModuleName}"
|
|
if test -f "$${OPENFPGA_RUN_POSTPROCESS}"; then
|
|
echo "Sourcing OPENFPGA_RUN_POSTPROCESS $${OPENFPGA_RUN_POSTPROCESS}"
|
|
source $${OPENFPGA_RUN_POSTPROCESS}
|
|
fi
|
|
done
|
|
|
|
all: floorplan
|
|
date > all
|
|
|
|
|
|
report_broken_symlinks:
|
|
# Reports broken symbolic links in current directory
|
|
#
|
|
symlinks -r .
|
|
|
|
extract_area:
|
|
# Extract module wise area of given design
|
|
#
|
|
# TCL_EXTRACT_AREA_SCRIPT: DC script which extracts area inforamtion
|
|
# ``../dp/fpga_top/custom_scripts_$${TECHNOLOGY}/design_compiler_$${TECHNOLOGY}.tcl"``
|
|
#
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
mkdir -p _dc_run && cd _dc_run
|
|
if test -f "../$${TCL_EXTRACT_AREA_SCRIPT}"; then
|
|
echo "Executing $${TCL_EXTRACT_AREA_SCRIPT} in DC"
|
|
${DC_SHELL_EXEC} -f ../$${TCL_EXTRACT_AREA_SCRIPT} ${DC_OPTIONS} | tee -i _dc_run.log
|
|
else
|
|
echo "[ ERR] TCL_EXTRACT_AREA_SCRIPT does not exist ($${TCL_EXTRACT_AREA_SCRIPT})"
|
|
fi
|
|
date > extract_area
|
|
|
|
run_primetime:
|
|
# Starts primetime sesession on PrePNR netlist
|
|
#
|
|
# PT_PRE_PNR_SCRIPT
|
|
#
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
mkdir -p _pt_run && cd _pt_run
|
|
REF_DIR=.. ${PT_SHELL_EXEC} -file ../$${PT_PRE_PNR_SCRIPT} | tee -i _primetime.log
|
|
date > run_primetime
|
|
|
|
run_formality:
|
|
# Starts primetime sesession on PrePNR netlist
|
|
#
|
|
# FM_PRE_PNR_SCRIPT
|
|
#
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
mkdir -p _fm_run && cd _fm_run
|
|
REF_DIR=.. ${FM_SHELL_EXEC} -file $${FM_PRE_PNR_SCRIPT} | tee -i _formality.log
|
|
date > run_formality
|
|
|
|
|
|
pt_post_pnr:
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
mkdir -p _pt_post_pnr_run && cd _pt_post_pnr_run
|
|
${PT_SHELL_EXEC} -f ../pnr/PrimeTimeScripts/post_pnr_pt_$${TECHNOLOGY}.tcl | tee -i post_pnr_pt.log
|
|
|
|
clean:
|
|
-\rm -rf netlist_cleanup generate_fabric_key cleanNetlist run_openfpga_sim run_openfpga restructure_netlist *.rpt *.net vpr_stdout.log
|
|
-\rm -rf **/task.conf **/latest **/run00*
|
|
|
|
clean_all: clean
|
|
-\rm -rf generate_shapes generate_global_connectivity generate_clock_tree proj_const.tcl release *_verilog _dc* _pt* _fm*
|
|
|
|
OpenVerdi:
|
|
# OpenVerdi for schematic
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
mkdir -p _verdi_run && cd _verdi_run
|
|
${VERDI_EXEC}
|
|
|
|
OpenVPR:
|
|
# OpenVPR GUI
|
|
#
|
|
# Useful when OpenFPGA execution
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
vpr_line=$$(find ./*_task/latest/*/** -type f -name 'openfpgashell.log')
|
|
vpr_cmd=$$(grep -r "Command line to execute: vpr " $$vpr_line)
|
|
vpr_cmd=$$(echo $${vpr_cmd} | sed "s/.*: vpr/vpr/")
|
|
echo "vpr_cmd=$${vpr_cmd}"
|
|
cd $$(dirname $$vpr_line)
|
|
VPR_EXEC=$$(readlink -f $${OPENFPGA_PATH}/build/*/vpr/vpr)
|
|
echo $$(dirname $${VPR_EXEC})/$${vpr_cmd}
|
|
eval $$(dirname $${VPR_EXEC})/$${vpr_cmd} --disp on
|
|
|
|
generate_fabric_bitstream:
|
|
# Modifies fabric_bitstream.xml for given ccff_chain
|
|
#
|
|
# Given a fabric_bitstream.xml and new sequence of ccff chain (hierarchical)
|
|
# it will create updated fabric_bitstream.xml
|
|
SECONDS=0
|
|
echo "Generating fabric bitstream"
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
DEFAULT_INPUT_BITSTREAM=$${VERILOG_PROJ_DIR}/XML/and_openfpga_sample_bitstream.xml
|
|
INPUT_BITSTREAM=$${INPUT_BITSTREAM:-$${DEFAULT_INPUT_BITSTREAM}}
|
|
echo "INPUT_BITSTREAM : $${INPUT_BITSTREAM}"
|
|
OUTPUT_BITSTREAM=$${OUTPUT_BITSTREAM:-_recompiled_bitstream.xml}
|
|
$${PYTHON_EXEC} -u $${FABRIC_BITSTREAM_GENERATE} \
|
|
--original_bitstream $${INPUT_BITSTREAM} \
|
|
--original_bitstream_distribution $${VERILOG_PROJ_DIR}/XML/and_bitstream_distribution.xml \
|
|
--instance_mapping $${RELEASE_DIRECTORY}/post_restruct_rpts/InstanceMap.json \
|
|
--ccff_path_directory $${RELEASE_DIRECTORY}/pre_pnr_performance/post_tile_ccff/{}_ccff.yaml \
|
|
--output_bitstream_xml $${OUTPUT_BITSTREAM} \
|
|
--tile_instance_mapping $${RELEASE_DIRECTORY}/post_restruct_rpts/tile_instances.yaml \
|
|
--verbose
|
|
sed -i ':a;N;$$!ba;s/\n\s*<\/bit/<\/bit/g' $${OUTPUT_BITSTREAM}
|
|
echo "Saved file: $${OUTPUT_BITSTREAM}"
|
|
duration=$$SECONDS
|
|
echo "$$(($$duration / 60)) minutes and $$(($$duration % 60)) seconds elapsed."
|
|
|
|
generate_fabric_constraints:
|
|
# Generate TCL constraint file based on the fabric_dependent_bitstream.xml
|
|
SECONDS=0
|
|
output_constraint_file=$${OUTPUT_CONSTRINTS:-_recompiled_constraints.tcl}
|
|
bitstream_file=$${INPUT_BITSTREAM:-_recompiled_bitstream.xml}
|
|
cat $${bitstream_file} | grep "new_path" \
|
|
| sed -n 's#.*value="\(.*\)" path.*new_path="\(.*\)">.*#set_case_analysis \1 \2#p' > \
|
|
$${output_constraint_file}
|
|
|
|
sed -i '/set_case_analysis x .*/d' $${output_constraint_file}
|
|
if [ -n "$${CLEAN_CONSTRAINT}" ]; then
|
|
echo "Removing set_case_analysis to 0"
|
|
sed -i '/set_case_analysis 0 .*/d' $${output_constraint_file}
|
|
fi
|
|
duration=$$SECONDS
|
|
echo -n "Written $${output_constraint_file} "
|
|
echo "$$(($$duration / 60)) minutes and $$(($$duration % 60)) seconds elapsed."
|
|
|
|
split_bitstream:
|
|
source ${LOAD_TOOLS}
|
|
source config.sh
|
|
rm -rf $${RELEASE_DIRECTORY}/split_bitstreams
|
|
$${PYTHON_EXEC} -c "from spydrnet_physical.util import split_fabric_bitstream;
|
|
split_fabric_bitstream('$${VERILOG_PROJ_DIR}/XML/fabric_independent_bitstream.xml', \
|
|
'$${VERILOG_PROJ_DIR}/SRCLint/top_hierarchy.yml', output_dir='$${RELEASE_DIRECTORY}/split_bitstreams')"
|
|
find $${RELEASE_DIRECTORY}/split_bitstreams -name "*.xml" -type f -exec xmllint --output '{}' --format '{}' \;
|
|
|
|
merge_bitstream:
|
|
$${PYTHON_EXEC} -c "from spydrnet_physical.util import merge_fabric_bitstream;
|
|
merge_fabric_bitstream('$${VERILOG_PROJ_DIR}/XML/fabric_independent_bitstream_regenerated.xml', \
|
|
'$${VERILOG_PROJ_DIR}/SRCLint/top_hierarchy.yml', output_dir='split_bitstreams')"
|
|
|
|
# XMLLint regenerated bitstream file
|
|
xml_file=fabric_independent_bitstream_regenerated.xml
|
|
XMLLINT_INDENT=" " xmllint --format $${xml_file} > _reg.tmp && mv _reg.tmp $${xml_file}
|
|
|
|
# XMLLint original bitstream file
|
|
xml_file=./${DESIGN_NAME}_bitstreams/top/fabric_independent_bitstream.xml
|
|
XMLLINT_INDENT=" " xmllint --format $${xml_file} > _reg.tmp && mv _reg.tmp $${xml_file}
|
|
|
|
find ./${DESIGN_NAME}_gsb -name "*.xml" -type f -exec xmllint --output '{}' --format '{}' \;
|
|
|
|
|
|
split_defs:
|
|
# Split defs files in mutiple files based on sections
|
|
#
|
|
sed -n '/^VIAS/, /END VIAS/p' release/dp/floorplan/cbx_1__0_/floorplan.def
|
|
sed -n '/^PINS/, /END PINS/p' release/dp/floorplan/cbx_1__0_/floorplan.def
|
|
sed -n '/^PINPROPERTIES/, /END PINPROPERTIES/p' release/dp/floorplan/cbx_1__0_/floorplan.def
|
|
sed -n '/^SPECIALNETS/, /END SPECIALNETS/p' release/dp/floorplan/cbx_1__0_/floorplan.def
|
|
sed -n '/^COMPONENTS/, /END COMPONENTS/p' release/dp/floorplan/cbx_1__0_/floorplan.def
|
|
sed -n '/^NETS/, /END NETS/p' release/dp/floorplan/cbx_1__0_/floorplan.def
|
|
|
|
merge_defs:
|
|
# Merges nultiple def file in to one single .def file
|
|
#
|
|
echo "NotImplemented"
|
|
|
|
-include ./Makefile_*
|
|
|
|
|
|
export COMMENT_EXTRACT
|
|
help:
|
|
# Prints help message for this makefile
|
|
@${PYTHON_EXEC} -c "$$COMMENT_EXTRACT"
|
|
|
|
define COMMENT_EXTRACT
|
|
import re
|
|
with open ('Makefile', 'r' ) as f:
|
|
matches = re.finditer('^([a-zA-Z-_]*):.*\n#(.*)', f.read(), flags=re.M)
|
|
space, help = 0, []
|
|
for _, match in enumerate(matches, start=1):
|
|
space = max(space, len(match[1]))
|
|
help.append((match[1], match[2]))
|
|
print("\n".join([(a.ljust(space) + b) for a, b in help]))
|
|
endef |