Skip to content

Add Support for Parmys plugin in VTR/Yosys #2215

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jobs:
- {test: "vtr_reg_strong", cores: "16", options: "", cmake: "-DVTR_ASSERT_LEVEL=3", extra_pkgs: "libeigen3-dev"}
- {test: "vtr_reg_strong", cores: "16", options: "-skip_qor", cmake: "-DVTR_ASSERT_LEVEL=3 -DVTR_ENABLE_SANITIZE=ON", extra_pkgs: "libeigen3-dev"}
- {test: "vtr_reg_yosys", cores: "16", options: "", cmake: "-DWITH_YOSYS=ON -DYOSYS_SV_UHDM_PLUGIN=ON", extra_pkgs: ""}
- {test: "vtr_reg_yosys_parmys", cores: "16", options: "", cmake: "-DWITH_YOSYS=ON -DYOSYS_PARMYS_PLUGIN=ON", extra_pkgs: ""}
- {test: "vtr_reg_yosys_odin", cores: "16", options: "", cmake: "-DODIN_USE_YOSYS=ON -DYOSYS_SV_UHDM_PLUGIN=ON", extra_pkgs: ""}
- {test: "odin_tech_strong", cores: "16", options: "", cmake: "-DODIN_USE_YOSYS=ON", extra_pkgs: ""}
- {test: "odin_reg_strong", cores: "16", options: "", cmake: "", extra_pkgs: ""}
Expand Down
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ option(ODIN_SANITIZE "Enable building odin with sanitize flags" OFF)
option(WITH_YOSYS "Enable building Yosys" OFF)
option(ODIN_USE_YOSYS "Enable building Yosys" OFF)
option(YOSYS_SV_UHDM_PLUGIN "Enable building and installing Yosys SystemVerilog and UHDM plugins" OFF)
option(YOSYS_PARMYS_PLUGIN "Enable building and installing Parmys (Partial Mapper for Yosys) plugin" OFF)

set(VTR_VERSION_MAJOR 8)
set(VTR_VERSION_MINOR 1)
Expand Down Expand Up @@ -416,6 +417,13 @@ if(${YOSYS_SV_UHDM_PLUGIN})
endif()
endif()

# check YOSYS_PARMYS_PLUGIN flag
if(${YOSYS_PARMYS_PLUGIN})
if(NOT ${WITH_YOSYS})
message(SEND_ERROR "Using YOSYS_PARMYS_PLUGIN requires activating Yosys frontend. Please set WITH_YOSYS.")
endif()
endif()

#Add extra compilation flags to suppress warnings from some libraries/tools
# Note that target_compile_options() *appends* to the current compilation options of
# the specified target
Expand Down
7 changes: 7 additions & 0 deletions ODIN_II/regression_test/tools/run_yosys.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ _YOSYS_EXEC="${VTR_DIR}/Yosys/bin/yosys"
_SURELOG_EXEC="${VTR_DIR}/Yosys/bin/surelog"
_UHDM_DUMP_EXEC="${VTR_DIR}/Yosys/bin/uhdm-dump"
_UHDM_HIER_EXEC="${VTR_DIR}/Yosys/bin/uhdm-hier"
_PARMYS_PLUGIN_EXEC="${VTR_DIR}/Yosys/share/yosys/plugins/parmys.so"
_INPUT_TYPE=""
_TEST_INPUT_LIST=()
_INPUT_LIST=()
Expand Down Expand Up @@ -461,6 +462,12 @@ function run_single_hdl() {
_exit_with_code "-1"
esac

if [ -f "${_PARMYS_PLUGIN_EXEC}" ]
then
export MAPPER="parmys";
else
export MAPPER="yosys";
fi

if [ -f "${OUTPUT_BLIF_PATH}/${TCL_BLIF_NAME}" ]; then
print_test_stat "E"
Expand Down
1 change: 1 addition & 0 deletions README.developers.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ will be triggered. The following tests are included in the workflow:
* [vtr_reg_nightly_test1-3](#vtr_reg_nightly_test1-3)
* [vtr_reg_strong](#vtr_reg_strong)
* vtr_reg_yosys
* vtr_reg_yosys_parmys
* vtr_reg_yosys_odin
* odin_tech_strong
* odin_reg_strong
Expand Down
22 changes: 20 additions & 2 deletions doc/src/vtr/run_vtr_flow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,14 @@ The parser for these runs is considered the Yosys conventional Verilog/SystemVer

Running the default VTR flow using the Yosys standalone front-end.
The Yosys HDL parser is considered as Yosys-SystemVerilog plugin (i.e., ``read_systemverilog``) and Yosys UHDM plugin (i.e., ``read_uhdm``), respectively.
It is worth mentioning that utilizing Yosys plugins requires passing the ``-DYOSYS_SV_UHDM_PLUGIN=ON`` compile flag to build and install the plugins for the Yosys front-end.
It is worth mentioning that utilizing Yosys plugins requires passing the ``-DYOSYS_SV_UHDM_PLUGIN=ON`` compile flag to build and install the plugins for the Yosys front-end.

.. code-block:: bash

# Using the Parmys (Partial Mapper for Yosys) plugin as partial mapper
./run_vtr_flow <path/to/Verilog/File> <path/to/arch/file> -start yosys -mapper parmys

Will run the VTR flow (default configuration) with Yosys frontend using Parmys plugin as partial mapper. To utilize the Parmys plugin, the ``-DYOSYS_PARMYS_PLUGIN=ON`` compile flag should be passed while building the VTR project with Yosys as a frontend.

Detailed Command-line Options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -312,4 +319,15 @@ Detailed Command-line Options
UHDM is used as a compiled interchange format in between SystemVerilog tools. Typical inputs to the UHDM flow are files with ``.v`` or ``.sv`` extensions.
The ``yosys-plugins`` parser, which represents the ``read_systemverilog`` command, reads SystemVerilog files directly in Yosys.
It executes Surelog with provided filenames and converts them (in memory) into UHDM file. Then, this UHDM file is converted into Yosys AST. `[Yosys-SystemVerilog] <https://github.com/antmicro/yosys-systemverilog#usage>`_
On the other hand, the ``surelog`` parser, which uses the ``read_uhdm`` Yosys command, walks the design tree and converts its nodes into Yosys AST nodes using Surelog. `[UHDM-Yosys <https://github.com/chipsalliance/UHDM-integration-tests#uhdm-yosys>`_, `Surelog] <https://github.com/chipsalliance/Surelog#surelog>`_
On the other hand, the ``surelog`` parser, which uses the ``read_uhdm`` Yosys command, walks the design tree and converts its nodes into Yosys AST nodes using Surelog. `[UHDM-Yosys <https://github.com/chipsalliance/UHDM-integration-tests#uhdm-yosys>`_, `Surelog] <https://github.com/chipsalliance/Surelog#surelog>`_

.. option:: -mapper <PARSER>

Choose a partial mapper for the Yosys synthesizer [yosys (default), parmys (Partial Mapper for Yosys plugin)].
The Yosys default partial mapper will be used if no mapper is specified.

**Default:** yosys

.. note::

Parmys is a Yosys plugin which provides intelligent partial mapping features (inference, binding, and hard/soft logic trade-offs) from Odin-II for Yosys. For more information on available paramters see the `Parmys <https://github.com/CAS-Atlantic/parmys-plugin.git>`_ plugin page.
37 changes: 37 additions & 0 deletions libs/EXTERNAL/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,40 @@ if(${ODIN_USE_YOSYS} OR ${WITH_YOSYS})
)
endif()

if(${YOSYS_PARMYS_PLUGIN})
set(YOSYS_DATDIR ${libyosys_BINARY_DIR}/share/yosys)
set(PARMYS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/parmys-plugin)

ExternalProject_Add(parmys-plugin
PREFIX ""

GIT_REPOSITORY https://github.com/CAS-Atlantic/parmys-plugin.git
GIT_TAG v1.0
GIT_PROGRESS TRUE

# setting source, build and install directories
SOURCE_DIR "${PARMYS_SOURCE_DIR}"
BUILD_IN_SOURCE TRUE
INSTALL_DIR ""

INSTALL_COMMAND ""
CONFIGURE_COMMAND ""
BUILD_COMMAND ${MAKE_PROGRAM} -C ${PARMYS_SOURCE_DIR}
PATH=${libyosys_BINARY_DIR}/bin/:$ENV{PATH}
install -j${CMAKE_BUILD_PARALLEL_LEVEL}

# redirect logs to a logfile
LOG_BUILD ON
LOG_UPDATE ON
LOG_INSTALL ON
LOG_CONFIGURE ON
LOG_OUTPUT_ON_FAILURE ON

# dependency
DEPENDS yosys
)
endif()

# In addition to libyosys in the build folder, we copy the libyosys directory
# into a temporary folder in the VTR root, named Yosys, to have access to Yosys
# (plugins) execs for using in VTR scripts (similar to VPR/vpr or ODIN_II/odin_II)
Expand All @@ -115,6 +149,9 @@ if(${ODIN_USE_YOSYS} OR ${WITH_YOSYS})
if(${YOSYS_SV_UHDM_PLUGIN})
add_dependencies(vtr-yosys yosys-plugins)
endif()
if(${YOSYS_PARMYS_PLUGIN})
add_dependencies(vtr-yosys parmys-plugin)
endif()

endif()

Expand Down
81 changes: 81 additions & 0 deletions vtr_flow/misc/yosyslib/synthesis_parmys.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
yosys -import

plugin -i parmys
yosys -import

read_verilog -nomem2reg +/parmys/vtr_primitives.v
setattr -mod -set keep_hierarchy 1 single_port_ram
setattr -mod -set keep_hierarchy 1 dual_port_ram

puts "Using parmys as partial mapper"

parmys_arch -a QQQ

if {$env(PARSER) == "surelog" } {
puts "Using Yosys read_uhdm command"
plugin -i systemverilog
yosys -import
read_uhdm -debug XXX
} elseif {$env(PARSER) == "yosys-plugin" } {
puts "Using Yosys read_systemverilog command"
plugin -i systemverilog
yosys -import
read_systemverilog -debug XXX
} elseif {$env(PARSER) == "yosys" } {
puts "Using Yosys read_verilog command"
read_verilog -sv -nolatches XXX
} else {
error "Invalid PARSER"
}

# Check that there are no combinational loops
scc -select
select -assert-none %
select -clear

hierarchy -check -auto-top -purge_lib

opt_expr
opt_clean
check
opt -nodffe -nosdff
procs -norom
fsm
opt
wreduce
peepopt
opt_clean
share

opt -full
memory -nomap
flatten

opt -full

techmap -map +/parmys/adff2dff.v
techmap -map +/parmys/adffe2dff.v
techmap -map +/parmys/aldff2dff.v
techmap -map +/parmys/aldffe2dff.v

opt -full

#stat

parmys -a QQQ -nopass -c odin_config.xml

opt -full

techmap
opt -fast

dffunmap
opt -fast -noff

#autoname

tee -o /dev/stdout stat

hierarchy -check -auto-top -purge_lib

write_blif -true + vcc -false + gnd -undef + unconn -blackbox ZZZ
1 change: 1 addition & 0 deletions vtr_flow/scripts/python_libs/vtr/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
yosys_exe_path = yosys_path / "bin" / "yosys"
yosys_lib_path = vtr_flow_path / "misc" / "yosyslib"
yosys_script_path = yosys_lib_path / "synthesis.tcl"
yosys_parmys_script_path = yosys_lib_path / "synthesis_parmys.tcl"

# ARCHFPGA paths
archfpga_path = root_path / "ArchFPGA"
Expand Down
93 changes: 92 additions & 1 deletion vtr_flow/scripts/python_libs/vtr/yosys/yosys.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import shutil
from collections import OrderedDict
from pathlib import Path
import xml.etree.ElementTree as ET
import vtr

# supported input file type by Yosys
Expand All @@ -31,6 +32,8 @@

YOSYS_PARSERS = ["yosys", "surelog", "yosys-plugin"]

YOSYS_MAPPERS = ["parmys", "yosys"]


def create_circuits_list(main_circuit, include_files):
"""Create a list of supported HDL files"""
Expand Down Expand Up @@ -68,6 +71,7 @@ def init_script_file(
memory_addr_width,
min_hard_mult_size,
min_hard_adder_size,
architecture_file_path,
):
"""initializing the raw yosys script file"""
# specify the input files type
Expand All @@ -89,6 +93,7 @@ def init_script_file(
"CCC": architecture_dsp_full_path,
"TTT": str(vtr.paths.yosys_lib_path),
"ZZZ": output_netlist,
"QQQ": architecture_file_path,
},
)

Expand All @@ -105,6 +110,58 @@ def init_script_file(
vtr.file_replace(yosys_dpram_rename_full_path, {"PPP": memory_addr_width})


# pylint: disable=too-many-arguments, too-many-locals
def init_config_file(
odin_config_full_path,
circuit_list,
architecture_file,
output_netlist,
odin_parser_arg,
memory_addr_width,
min_hard_mult_size,
min_hard_adder_size,
):
"""initializing the raw odin config file"""
# specify the input files type
file_extension = os.path.splitext(circuit_list[0])[-1]
if file_extension not in FILE_TYPES:
raise vtr.VtrError("Inavlid input file type '{}'".format(file_extension))
input_file_type = FILE_TYPES[file_extension]

# Check if the user specifically requested for the UHDM parser
if odin_parser_arg == "-u":
input_file_type = "uhdm"

# Update the config file
vtr.file_replace(
odin_config_full_path,
{
"YYY": architecture_file,
"TTT": input_file_type,
"ZZZ": output_netlist,
"PPP": memory_addr_width,
"MMM": min_hard_mult_size,
"AAA": min_hard_adder_size,
},
)

# loading the given config file
config_file = ET.parse(odin_config_full_path)
root = config_file.getroot()

# based on the base config file
verilog_files_tag = root.find("inputs")
# remove the template line XXX, verilog_files_tag [1] is a comment
verilog_files_tag.remove(verilog_files_tag[1])
for circuit in circuit_list:
verilog_file = ET.SubElement(verilog_files_tag, "input_path_and_name")
verilog_file.tail = "\n\n\t" if (circuit == circuit_list[-1]) else "\n\n\t\t"
verilog_file.text = circuit

# update the config file with new values
config_file.write(odin_config_full_path)


# pylint: disable=too-many-arguments, too-many-locals, too-many-statements, too-many-branches
def run(
architecture_file,
Expand Down Expand Up @@ -175,7 +232,10 @@ def run(
yosys_exec = str(vtr.paths.yosys_exe_path)

if yosys_script is None:
yosys_base_script = str(vtr.paths.yosys_script_path)
if yosys_args["mapper"] == "parmys":
yosys_base_script = str(vtr.paths.yosys_parmys_script_path)
else:
yosys_base_script = str(vtr.paths.yosys_script_path)
else:
yosys_base_script = str(Path(yosys_script).resolve())

Expand Down Expand Up @@ -210,6 +270,7 @@ def run(

write_arch_bb_exec = str(vtr.paths.write_arch_bb_exe_path)
architecture_dsp_full_path = str(vtr.paths.scripts_path / temp_dir / YOSYS_LIB_FILES["DSPBB"])
architecture_file_path = str(vtr.paths.scripts_path / architecture_file)

# executing write_arch_bb to extract the black box definitions of the given arch file
command_runner.run_system_command(
Expand Down Expand Up @@ -239,6 +300,25 @@ def run(
vtr.determine_memory_addr_width(str(architecture_file)),
min_hard_mult_size,
min_hard_adder_size,
architecture_file_path,
)

odin_base_config = str(vtr.paths.odin_cfg_path)

# Copy the config file
odin_config = "odin_config.xml"
odin_config_full_path = str(temp_dir / odin_config)
shutil.copyfile(odin_base_config, odin_config_full_path)

init_config_file(
odin_config_full_path,
circuit_list,
architecture_file.name,
output_netlist.name,
None,
vtr.determine_memory_addr_width(str(architecture_file)),
min_hard_mult_size,
min_hard_adder_size,
)

# set the parser
Expand All @@ -252,6 +332,17 @@ def run(
)
)

# set the partial mapper
if yosys_args["mapper"] in YOSYS_MAPPERS:
os.environ["MAPPER"] = yosys_args["mapper"]
del yosys_args["mapper"]
else:
raise vtr.VtrError(
"Invalid partial mapper is specified for Yosys, available parsers are [{}]".format(
" ".join(str(x) for x in YOSYS_MAPPERS)
)
)

cmd = [yosys_exec]

for arg, value in yosys_args.items():
Expand Down
Loading