Merge pull request #1186 from lnis-uofu/xt_mock_wrapper

Support mock FPGA wrapper generation
This commit is contained in:
tangxifan 2023-05-27 17:31:30 -07:00 committed by GitHub
commit 2e3625aa7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 1287 additions and 24 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View File

@ -10,3 +10,5 @@ FPGA-Verilog
fabric_netlist
testbench
mock_fpga_wrapper

View File

@ -0,0 +1,25 @@
.. _fpga_verilog_mock_fpga_wrapper:
Mock FPGA Wrapper
-----------------
OpenFPGA can generates HDL netlists that model a complete eFPGA fabric (see details in :ref:`fabric_netlists`).
Through bitstream forcing, users can verify the eFPGAs that are mapped by various applications in the context of SoC (see details in :numref:`fig_preconfig_module`).
However, the complete eFPGA fabric is very costly in design verification runtime.
To reduce runtime, a mock eFPGA wrapper is required to bridge the application HDL and other components in the SoC.
As illustrated in :numref:`fig_mock_fpga_wrapper`, a 3-bit counter application is mapped to an FPGA, while a mock wrapper is interfacing the signals between the counter module and the SoC.
The mock wrapper consists of the same ports as the FPGA fabric, which is generated by the OpenFPGA command ``write_fabric_verilog``. See :ref:`openfpga_verilog_commands` for its detailed usage.
The only difference lies in that the mock wrapper contains an instance of the application HDL design which is implemented on the FPGA, while the FPGA fabric contains a complete structure of programmable resources.
.. note:: The mock wrapper is useful for connectivity checks on FPGA datapaths. It does not cover any configuration protocols (see details in :ref:`config_protocol`)
.. _fig_mock_fpga_wrapper:
.. figure:: figures/mock_fpga_wrapper.png
:width: 100%
:alt: Illustraion of a mock FPGA wrapper
Principles of a mock FPGA wrapper: ease SoC-level design verification

View File

@ -22,7 +22,7 @@ To enable self-testing, the FPGA and user's RTL design (simulate using an HDL si
.. _fig_verilog_testbench_organization:
.. figure:: figures/full_testbench_block_diagram.svg
:scale: 50%
:width: 100%
:alt: Verilog testbench principles
Principles of Verilog testbenches: (1) using common input stimuli; (2) applying bitstream; (3) checking output vectors.
@ -30,7 +30,7 @@ To enable self-testing, the FPGA and user's RTL design (simulate using an HDL si
.. _fig_verilog_full_testbench_waveform:
.. figure:: figures/full_testbench_waveform.svg
:scale: 50%
:width: 100%
:alt: Full testbench waveform
Illustration on the waveforms in full testbench
@ -48,7 +48,7 @@ Formal-oriented Testbench
The formal-oriented testbench aims to test a programmed FPGA is instantiated with the user's bitstream.
The module of the programmed FPGA is encapsulated with the same port mapping as the user's RTL design and thus can be fed to a formal tool for a 100% coverage formal verification. Compared to the full testbench, this skips the time-consuming configuration phase, reducing the simulation time, potentially also significantly accelerating the functional verification, especially for large FPGAs.
.. warning:: Formal-oriented testbenches do not validate the configuration protocol of FPGAs. It is used to validate FPGA with a wide range of benchmarks.
.. warning:: Formal-oriented testbenches do not validate the configuration protocol of FPGAs. It is used to validate FPGA with a wide range of benchmarks.
General Usage
~~~~~~~~~~~~~
@ -59,7 +59,7 @@ Inside the directory, the Verilog testbenches are organized as illustrated in :n
.. _fig_verilog_testbench_hierarchy:
.. figure:: ./figures/verilog_testbench_hierarchy.svg
:scale: 100%
:width: 100%
Hierarchy of Verilog testbenches for a FPGA fabric implemented with an application
@ -91,7 +91,7 @@ Inside the directory, the Verilog testbenches are organized as illustrated in :n
.. _fig_preconfig_module:
.. figure:: ./figures/preconfig_module.png
:scale: 25%
:width: 100%
Internal structure of a pre-configured FPGA module

View File

@ -166,6 +166,45 @@ __ iverilog_website_
Show verbose log
write_mock_fpga_wrapper
~~~~~~~~~~~~~~~~~~~~~~~
Write the Verilog wrapper which mockes a mapped FPGA fabric. See details in :ref:`fpga_verilog_mock_fpga_wrapper`.
.. option:: --file <string> or -f <string>
The output directory for the netlists. We suggest the use of same output directory as fabric Verilog netlists. For example, ``--file /temp/testbench``
.. option:: --pin_constraints_file <string> or -pcf <string>
Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml``
Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`.
.. option:: --bus_group_file <string> or -bgf <string>
Specify the *Bus Group File* (BGF) if you want to group pins to buses. For example, ``-bgf bus_group.xml``
Strongly recommend when input HDL contains bus ports. See detailed file format about :ref:`file_format_bus_group_file`.
.. option:: --explicit_port_mapping
Use explicit port mapping when writing the Verilog netlists
.. option:: --use_relative_path
Force to use relative path in netlists when including other netlists. By default, this is off, which means that netlists use absolute paths when including other netlists
.. option:: --default_net_type <string>
Specify the default net type for the Verilog netlists. Currently, supported types are ``none`` and ``wire``. Default value: ``none``.
.. option:: --no_time_stamp
Do not print time stamp in Verilog netlists
.. option:: --verbose
Show verbose log
write_preconfigured_testbench
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -251,6 +251,78 @@ ShellCommandId add_write_preconfigured_fabric_wrapper_command_template(
return shell_cmd_id;
}
/********************************************************************
* - add a command to shell environment: write mock fpga wrapper
* - add associated options
* - add command dependency
*******************************************************************/
template <class T>
ShellCommandId add_write_mock_fpga_wrapper_command_template(
openfpga::Shell<T>& shell, const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds, const bool& hidden) {
Command shell_cmd("write_mock_fpga_wrapper");
/* add an option '--file' in short '-f'*/
CommandOptionId output_opt = shell_cmd.add_option(
"file", true, "specify the output directory for hdl netlists");
shell_cmd.set_option_short_name(output_opt, "f");
shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING);
/* add an option '--pin_constraints_file in short '-pcf' */
CommandOptionId pcf_opt =
shell_cmd.add_option("pin_constraints_file", false,
"specify the file path to the pin constraints");
shell_cmd.set_option_short_name(pcf_opt, "pcf");
shell_cmd.set_option_require_value(pcf_opt, openfpga::OPT_STRING);
/* add an option '--bus_group_file in short '-bgf' */
CommandOptionId bgf_opt = shell_cmd.add_option(
"bus_group_file", false, "specify the file path to the group pins to bus");
shell_cmd.set_option_short_name(bgf_opt, "bgf");
shell_cmd.set_option_require_value(bgf_opt, openfpga::OPT_STRING);
/* Add an option '--use_relative_path' */
shell_cmd.add_option(
"use_relative_path", false,
"Force to use relative path in netlists when including other netlists");
/* add an option '--explicit_port_mapping' */
shell_cmd.add_option("explicit_port_mapping", false,
"use explicit port mapping in verilog netlists");
/* Add an option '--default_net_type' */
CommandOptionId default_net_type_opt = shell_cmd.add_option(
"default_net_type", false,
"Set the default net type for Verilog netlists. Default value is 'none'");
shell_cmd.set_option_require_value(default_net_type_opt,
openfpga::OPT_STRING);
/* add an option '--explicit_port_mapping' */
shell_cmd.add_option("explicit_port_mapping", false,
"use explicit port mapping in verilog netlists");
/* Add an option '--no_time_stamp' */
shell_cmd.add_option("no_time_stamp", false,
"Do not print a time stamp in the output files");
/* add an option '--verbose' */
shell_cmd.add_option("verbose", false, "enable verbose output");
/* add command to the shell */
ShellCommandId shell_cmd_id = shell.add_command(
shell_cmd,
"generate a wrapper of a mock fpga fabric mapped with applications",
hidden);
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id,
write_mock_fpga_wrapper_template<T>);
/* add command dependency to the shell */
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
return shell_cmd_id;
}
/********************************************************************
* - Add a command to Shell environment: write preconfigured testbench
* - Add associated options
@ -435,6 +507,17 @@ void add_verilog_command_templates(openfpga::Shell<T>& shell,
shell, openfpga_verilog_cmd_class, preconfig_wrapper_dependent_cmds,
hidden);
/********************************
* Command 'write_mock_fpga_wrapper'
*/
/* The command 'write_mock_fpga_wrapper' should NOT be executed
* before 'build_fabric' */
std::vector<ShellCommandId> write_mock_fpga_wrapper_dependent_cmds;
write_mock_fpga_wrapper_dependent_cmds.push_back(build_fabric_cmd_id);
add_write_mock_fpga_wrapper_command_template<T>(
shell, openfpga_verilog_cmd_class, write_mock_fpga_wrapper_dependent_cmds,
hidden);
/********************************
* Command 'write_preconfigured_testbench'
*/

View File

@ -12,6 +12,7 @@
#include "read_xml_bus_group.h"
#include "read_xml_pin_constraints.h"
#include "verilog_api.h"
#include "verilog_mock_fpga_wrapper.h"
#include "vtr_log.h"
#include "vtr_time.h"
@ -207,6 +208,61 @@ int write_preconfigured_fabric_wrapper_template(
openfpga_ctx.arch().config_protocol, options);
}
/********************************************************************
* A wrapper function to call the mock fpga wrapper generator of
*FPGA-Verilog
*******************************************************************/
template <class T>
int write_mock_fpga_wrapper_template(const T& openfpga_ctx, const Command& cmd,
const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_pcf = cmd.option("pin_constraints_file");
CommandOptionId opt_bgf = cmd.option("bus_group_file");
CommandOptionId opt_explicit_port_mapping =
cmd.option("explicit_port_mapping");
CommandOptionId opt_use_relative_path = cmd.option("use_relative_path");
CommandOptionId opt_default_net_type = cmd.option("default_net_type");
CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp");
CommandOptionId opt_verbose = cmd.option("verbose");
/* This is an intermediate data structure which is designed to modularize the
* FPGA-Verilog Keep it independent from any other outside data structures
*/
VerilogTestbenchOption options;
options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir));
options.set_explicit_port_mapping(
cmd_context.option_enable(cmd, opt_explicit_port_mapping));
options.set_use_relative_path(
cmd_context.option_enable(cmd, opt_use_relative_path));
options.set_time_stamp(!cmd_context.option_enable(cmd, opt_no_time_stamp));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
if (true == cmd_context.option_enable(cmd, opt_default_net_type)) {
options.set_default_net_type(
cmd_context.option_value(cmd, opt_default_net_type));
}
/* If pin constraints are enabled by command options, read the file */
PinConstraints pin_constraints;
if (true == cmd_context.option_enable(cmd, opt_pcf)) {
pin_constraints =
read_xml_pin_constraints(cmd_context.option_value(cmd, opt_pcf).c_str());
}
/* If bug group file are enabled by command options, read the file */
BusGroup bus_group;
if (true == cmd_context.option_enable(cmd, opt_bgf)) {
bus_group =
read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str());
}
return fpga_verilog_mock_fpga_wrapper(
openfpga_ctx.module_graph(), g_vpr_ctx.atom(), g_vpr_ctx.placement(),
pin_constraints, bus_group, openfpga_ctx.io_location_map(),
openfpga_ctx.fabric_global_port_info(),
openfpga_ctx.vpr_netlist_annotation(), options);
}
/********************************************************************
* A wrapper function to call the preconfigured testbench generator of
*FPGA-Verilog

View File

@ -12,11 +12,13 @@
/* Headers from openfpgautil library */
#include "device_rr_gsb.h"
#include "openfpga_digest.h"
#include "openfpga_naming.h"
#include "openfpga_reserved_words.h"
#include "verilog_auxiliary_netlists.h"
#include "verilog_constants.h"
#include "verilog_formal_random_top_testbench.h"
#include "verilog_grid.h"
#include "verilog_mock_fpga_wrapper.h"
#include "verilog_preconfig_top_module.h"
#include "verilog_routing.h"
#include "verilog_simulation_info_writer.h"
@ -222,6 +224,60 @@ int fpga_verilog_preconfigured_fabric_wrapper(
return status;
}
/********************************************************************
* A top-level function of FPGA-Verilog which focuses on a wrapper module,
* which encapsulate the application HDL into a mock FPGA module
********************************************************************/
int fpga_verilog_mock_fpga_wrapper(
const ModuleManager &module_manager, const AtomContext &atom_ctx,
const PlacementContext &place_ctx, const PinConstraints &pin_constraints,
const BusGroup &bus_group, const IoLocationMap &io_location_map,
const FabricGlobalPortInfo &fabric_global_port_info,
const VprNetlistAnnotation &netlist_annotation,
const VerilogTestbenchOption &options) {
vtr::ScopedStartFinishTimer timer(
"Write a wrapper module to mock a mapped FPGA fabric\n");
std::string src_dir_path = format_dir_path(options.output_directory());
std::string netlist_name = atom_ctx.nlist.netlist_name();
int status = CMD_EXEC_SUCCESS;
NetlistManager netlist_manager;
/* Create directories */
create_directory(src_dir_path);
/* Generate wrapper module for FPGA fabric (mapped by the input benchmark and
* pre-configured testbench for verification */
std::string netlist_file_name =
generate_fpga_top_netlist_name(std::string(VERILOG_NETLIST_FILE_POSTFIX));
std::string netlist_file_path = src_dir_path + netlist_file_name;
status = print_verilog_mock_fpga_wrapper(
module_manager, fabric_global_port_info, atom_ctx, place_ctx,
pin_constraints, bus_group, io_location_map, netlist_annotation,
netlist_name, netlist_file_path, options);
/* Add fname to the netlist name list */
NetlistId nlist_id = NetlistId::INVALID();
if (options.use_relative_path()) {
nlist_id = netlist_manager.add_netlist(netlist_file_name);
} else {
nlist_id = netlist_manager.add_netlist(netlist_file_path);
}
VTR_ASSERT(nlist_id);
netlist_manager.set_netlist_type(nlist_id,
NetlistManager::TOP_MODULE_NETLIST);
/* Generate an netlist including all the fabric-related netlists */
print_verilog_mock_fabric_include_netlist(netlist_manager, src_dir_path,
options.use_relative_path(),
options.time_stamp());
return status;
}
/********************************************************************
* A top-level function of FPGA-Verilog which focuses on fabric Verilog
*generation This function will generate

View File

@ -68,6 +68,14 @@ int fpga_verilog_preconfigured_fabric_wrapper(
const CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol,
const VerilogTestbenchOption& options);
int fpga_verilog_mock_fpga_wrapper(
const ModuleManager& module_manager, const AtomContext& atom_ctx,
const PlacementContext& place_ctx, const PinConstraints& pin_constraints,
const BusGroup& bus_group, const IoLocationMap& io_location_map,
const FabricGlobalPortInfo& fabric_global_port_info,
const VprNetlistAnnotation& netlist_annotation,
const VerilogTestbenchOption& options);
int fpga_verilog_preconfigured_testbench(
const ModuleManager& module_manager, const AtomContext& atom_ctx,
const PinConstraints& pin_constraints, const BusGroup& bus_group,

View File

@ -23,6 +23,48 @@ namespace openfpga {
* Local constant variables
*******************************************************************/
/********************************************************************
* Print a file that includes all the fabric netlists
* that have been generated and user-defined.
* This does NOT include any testbenches!
* Some netlists are open to compile under specific preprocessing flags
*******************************************************************/
void print_verilog_mock_fabric_include_netlist(
const NetlistManager& netlist_manager, const std::string& src_dir_path,
const bool& use_relative_path, const bool& include_time_stamp) {
/* If we force the use of relative path, the src dir path should NOT be
* included in any output */
std::string src_dir = src_dir_path;
if (use_relative_path) {
src_dir.clear();
}
std::string verilog_fpath =
src_dir_path + std::string(FABRIC_INCLUDE_VERILOG_NETLIST_FILE_NAME);
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fpath, std::fstream::out | std::fstream::trunc);
/* Validate the file stream */
check_file_stream(verilog_fpath.c_str(), fp);
/* Print the title */
print_verilog_file_header(fp, std::string("Mock Fabric Netlist Summary"),
include_time_stamp);
/* Include FPGA top module */
print_verilog_comment(
fp, std::string("------ Include fabric top-level netlists -----"));
for (const NetlistId& nlist_id :
netlist_manager.netlists_by_type(NetlistManager::TOP_MODULE_NETLIST)) {
print_verilog_include_netlist(fp, netlist_manager.netlist_name(nlist_id));
}
fp << std::endl;
/* Close the file stream */
fp.close();
}
/********************************************************************
* Print a file that includes all the fabric netlists
* that have been generated and user-defined.

View File

@ -18,6 +18,10 @@
/* begin namespace openfpga */
namespace openfpga {
void print_verilog_mock_fabric_include_netlist(
const NetlistManager& netlist_manager, const std::string& src_dir_path,
const bool& use_relative_path, const bool& include_time_stamp);
void print_verilog_fabric_include_netlist(const NetlistManager& netlist_manager,
const std::string& src_dir_path,
const CircuitLibrary& circuit_lib,

View File

@ -116,8 +116,9 @@ static void print_verilog_top_random_testbench_benchmark_instance(
print_verilog_testbench_benchmark_instance(
fp, reference_verilog_top_name, std::string(BENCHMARK_INSTANCE_NAME),
std::string(), std::string(), std::string(),
std::string(BENCHMARK_PORT_POSTFIX), std::vector<std::string>(), atom_ctx,
netlist_annotation, pin_constraints, bus_group, explicit_port_mapping);
std::string(BENCHMARK_PORT_POSTFIX), std::vector<std::string>(), false,
atom_ctx, netlist_annotation, pin_constraints, bus_group,
explicit_port_mapping);
print_verilog_comment(
fp, std::string("----- End reference Benchmark Instanication -------"));
@ -147,7 +148,7 @@ static void print_verilog_random_testbench_fpga_instance(
std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX)),
std::string(FPGA_INSTANCE_NAME), std::string(), std::string(),
std::string(), std::string(FPGA_PORT_POSTFIX), std::vector<std::string>(),
atom_ctx, netlist_annotation, pin_constraints, bus_group,
false, atom_ctx, netlist_annotation, pin_constraints, bus_group,
explicit_port_mapping);
print_verilog_comment(

View File

@ -0,0 +1,491 @@
/********************************************************************
* This file includes functions that are used to generate
* a Verilog module of a pre-configured FPGA fabric
*******************************************************************/
#include <fstream>
/* Headers from vtrutil library */
#include "command_exit_codes.h"
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from openfpgautil library */
#include "bitstream_manager_utils.h"
#include "fabric_global_port_info_utils.h"
#include "module_manager_utils.h"
#include "openfpga_atom_netlist_utils.h"
#include "openfpga_digest.h"
#include "openfpga_naming.h"
#include "openfpga_port.h"
#include "openfpga_reserved_words.h"
#include "verilog_constants.h"
#include "verilog_mock_fpga_wrapper.h"
#include "verilog_testbench_utils.h"
#include "verilog_writer_utils.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Local variables used only in this file
*******************************************************************/
constexpr const char* APPINST_PORT_POSTFIX = "_bench";
constexpr const char* APP_INSTANCE_NAME = "MAPPED_DESIGN";
/********************************************************************
* This function adds stimuli to I/Os of FPGA fabric
* 1. For mapped I/Os, this function will wire them to the input ports
* of the pre-configured FPGA top module
* 2. For unmapped I/Os, this function will assign a constant value
* by default
*******************************************************************/
static void print_verilog_mock_fpga_wrapper_connect_ios(
std::fstream& fp, const ModuleManager& module_manager,
const ModuleId& top_module, const AtomContext& atom_ctx,
const PlacementContext& place_ctx, const IoLocationMap& io_location_map,
const PinConstraints& pin_constraints,
const FabricGlobalPortInfo& global_ports,
const VprNetlistAnnotation& netlist_annotation,
const std::string& net_name_postfix,
const std::string& io_input_port_name_postfix,
const std::string& io_output_port_name_postfix,
const std::vector<std::string>& clock_port_names,
const size_t& unused_io_value) {
/* Validate the file stream */
valid_file_stream(fp);
/* Only mappable i/o ports can be considered */
std::vector<ModulePortId> module_io_ports;
for (const ModuleManager::e_module_port_type& module_io_port_type :
MODULE_IO_PORT_TYPES) {
for (const ModulePortId& gpio_port_id :
module_manager.module_port_ids_by_type(top_module,
module_io_port_type)) {
/* Only care mappable I/O */
if (false ==
module_manager.port_is_mappable_io(top_module, gpio_port_id)) {
continue;
}
module_io_ports.push_back(gpio_port_id);
}
}
/* Keep tracking which I/Os have been used */
std::map<ModulePortId, std::vector<bool>> io_used;
for (const ModulePortId& module_io_port_id : module_io_ports) {
const BasicPort& module_io_port =
module_manager.module_port(top_module, module_io_port_id);
io_used[module_io_port_id] =
std::vector<bool>(module_io_port.get_width(), false);
}
/* Type mapping between VPR block and Module port */
std::map<AtomBlockType, ModuleManager::e_module_port_type>
atom_block_type_to_module_port_type;
atom_block_type_to_module_port_type[AtomBlockType::INPAD] =
ModuleManager::MODULE_GPIN_PORT;
atom_block_type_to_module_port_type[AtomBlockType::OUTPAD] =
ModuleManager::MODULE_GPOUT_PORT;
/* See if this I/O should be wired to a benchmark input/output */
/* Add signals from blif benchmark and short-wire them to FPGA I/O PADs
* This brings convenience to checking functionality
*/
print_verilog_comment(
fp, std::string("----- Link FPGA I/Os to Benchmark I/Os -----"));
for (const AtomBlockId& atom_blk : atom_ctx.nlist.blocks()) {
/* Bypass non-I/O atom blocks ! */
if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) &&
(AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) {
continue;
}
/* If there is a GPIO port, use it directly
* Otherwise, should find a GPIN for INPAD
* or should find a GPOUT for OUTPAD
*/
std::pair<ModulePortId, size_t> mapped_module_io_info =
std::make_pair(ModulePortId::INVALID(), -1);
for (const ModulePortId& module_io_port_id : module_io_ports) {
const BasicPort& module_io_port =
module_manager.module_port(top_module, module_io_port_id);
/* Find the index of the mapped GPIO in top-level FPGA fabric */
size_t temp_io_index = io_location_map.io_index(
place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.x,
place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.y,
place_ctx.block_locs[atom_ctx.lookup.atom_clb(atom_blk)].loc.sub_tile,
module_io_port.get_name());
/* Bypass invalid index (not mapped to this GPIO port) */
if (size_t(-1) == temp_io_index) {
continue;
}
/* If the port is an GPIO port, just use it */
if (ModuleManager::MODULE_GPIO_PORT ==
module_manager.port_type(top_module, module_io_port_id)) {
mapped_module_io_info =
std::make_pair(module_io_port_id, temp_io_index);
break;
}
/* If this is an INPAD, we can use an GPIN port (if available) */
if (atom_block_type_to_module_port_type[atom_ctx.nlist.block_type(
atom_blk)] ==
module_manager.port_type(top_module, module_io_port_id)) {
mapped_module_io_info =
std::make_pair(module_io_port_id, temp_io_index);
break;
}
}
/* We must find a valid one */
VTR_ASSERT(true == module_manager.valid_module_port_id(
top_module, mapped_module_io_info.first));
VTR_ASSERT(size_t(-1) != mapped_module_io_info.second);
/* Ensure that IO index is in range */
BasicPort module_mapped_io_port =
module_manager.module_port(top_module, mapped_module_io_info.first);
size_t io_index = mapped_module_io_info.second;
/* Set the port pin index */
VTR_ASSERT(io_index < module_mapped_io_port.get_width());
module_mapped_io_port.set_name(module_mapped_io_port.get_name() +
net_name_postfix);
module_mapped_io_port.set_width(io_index, io_index);
/* The block may be renamed as it contains special characters which violate
* Verilog syntax */
std::string block_name = atom_ctx.nlist.block_name(atom_blk);
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
block_name = netlist_annotation.block_name(atom_blk);
}
/* Note that VPR added a prefix to the name of output blocks
* We can remove this when specified through input argument
*/
if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) {
block_name = remove_atom_block_name_prefix(block_name);
}
/* Create the port for benchmark I/O, due to BLIF benchmark, each I/O always
* has a size of 1 In addition, the input and output ports may have
* different postfix in naming due to verification context! Here, we give
* full customization on naming
*/
BasicPort benchmark_io_port;
benchmark_io_port.set_width(1);
if (AtomBlockType::INPAD == atom_ctx.nlist.block_type(atom_blk)) {
/* If the port is a clock, skip it */
if (clock_port_names.end() != std::find(clock_port_names.begin(),
clock_port_names.end(),
block_name)) {
continue;
}
/* For global ports, use wires; otherwise, use registers*/
if (true == port_is_fabric_global_reset_port(
global_ports, module_manager,
pin_constraints.net_pin(block_name))) {
continue;
}
benchmark_io_port.set_name(
std::string(block_name + io_input_port_name_postfix));
print_verilog_comment(
fp, std::string("----- Blif Benchmark input " + block_name +
" is mapped to FPGA IOPAD " +
module_mapped_io_port.get_name() + "[" +
std::to_string(io_index) + "] -----"));
print_verilog_wire_connection(fp, benchmark_io_port,
module_mapped_io_port, false);
} else {
VTR_ASSERT(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk));
benchmark_io_port.set_name(
std::string(block_name + io_output_port_name_postfix));
print_verilog_comment(
fp, std::string("----- Blif Benchmark output " + block_name +
" is mapped to FPGA IOPAD " +
module_mapped_io_port.get_name() + "[" +
std::to_string(io_index) + "] -----"));
print_verilog_wire_connection(fp, module_mapped_io_port,
benchmark_io_port, false);
}
/* Mark this I/O has been used/wired */
io_used[mapped_module_io_info.first][io_index] = true;
/* Add an empty line as a splitter */
fp << std::endl;
}
/* Wire the unused iopads to a constant */
print_verilog_comment(
fp, std::string("----- Wire unused FPGA I/Os to constants -----"));
for (const ModulePortId& module_io_port_id : module_io_ports) {
for (size_t io_index = 0; io_index < io_used[module_io_port_id].size();
++io_index) {
/* Bypass used iopads */
if (true == io_used[module_io_port_id][io_index]) {
continue;
}
/* Bypass unused output pads */
if (ModuleManager::MODULE_GPOUT_PORT !=
module_manager.port_type(top_module, module_io_port_id)) {
continue;
}
/* Wire to a contant */
BasicPort module_unused_io_port =
module_manager.module_port(top_module, module_io_port_id);
/* Set the port pin index */
module_unused_io_port.set_name(module_unused_io_port.get_name() +
net_name_postfix);
module_unused_io_port.set_width(io_index, io_index);
std::vector<size_t> default_values(module_unused_io_port.get_width(),
unused_io_value);
print_verilog_wire_constant_values(fp, module_unused_io_port,
default_values);
}
/* Add an empty line as a splitter */
fp << std::endl;
}
}
/********************************************************************
* Connect global ports of FPGA top module to constants except:
* 1. operating clock, which should be wired to the clock port of
* this pre-configured FPGA top module
*******************************************************************/
static int print_verilog_mock_fpga_wrapper_connect_global_ports(
std::fstream& fp, const ModuleManager& module_manager,
const ModuleId& top_module, const PinConstraints& pin_constraints,
const FabricGlobalPortInfo& fabric_global_ports,
const std::vector<std::string>& benchmark_clock_port_names) {
/* Validate the file stream */
valid_file_stream(fp);
print_verilog_comment(
fp,
std::string(
"----- Begin Connect Global ports to FPGA top-level interface -----"));
for (const FabricGlobalPortId& global_port_id :
fabric_global_ports.global_ports()) {
ModulePortId module_global_port_id =
fabric_global_ports.global_module_port(global_port_id);
VTR_ASSERT(ModuleManager::MODULE_GLOBAL_PORT ==
module_manager.port_type(top_module, module_global_port_id));
BasicPort module_global_port =
module_manager.module_port(top_module, module_global_port_id);
/* Now, for operating clock port, we should wire it to the clock of
* benchmark! */
if ((true == fabric_global_ports.global_port_is_clock(global_port_id)) &&
(false == fabric_global_ports.global_port_is_prog(global_port_id))) {
/* Wiring to each pin of the global port: benchmark clock is always 1-bit
*/
for (size_t pin_id = 0; pin_id < module_global_port.pins().size();
++pin_id) {
BasicPort module_clock_pin(module_global_port.get_name(),
module_global_port.pins()[pin_id],
module_global_port.pins()[pin_id]);
/* If the clock port name is in the pin constraints, we should wire it
* to the constrained pin */
std::string constrained_net_name = pin_constraints.pin_net(BasicPort(
module_global_port.get_name(), module_global_port.pins()[pin_id],
module_global_port.pins()[pin_id]));
/* If constrained to an open net or there is no clock in the benchmark,
* we assign it to a default value */
if ((true == pin_constraints.unmapped_net(constrained_net_name)) ||
(true == benchmark_clock_port_names.empty())) {
continue;
}
std::string clock_name_to_connect;
if (!pin_constraints.unconstrained_net(constrained_net_name)) {
clock_name_to_connect = constrained_net_name;
} else {
/* Otherwise, we must have a clear one-to-one clock net
* corresponding!!! */
if (benchmark_clock_port_names.size() !=
module_global_port.get_width()) {
VTR_LOG_ERROR(
"Unable to map %lu benchmark clocks to %lu clock pins of "
"FPGA!\nRequire clear pin constraints!\n",
benchmark_clock_port_names.size(),
module_global_port.get_width());
return CMD_EXEC_FATAL_ERROR;
}
clock_name_to_connect = benchmark_clock_port_names[pin_id];
}
clock_name_to_connect += std::string(APPINST_PORT_POSTFIX);
BasicPort benchmark_clock_pin(clock_name_to_connect, 1);
print_verilog_wire_connection(fp, benchmark_clock_pin, module_clock_pin,
false);
}
/* Finish, go to the next */
continue;
}
/* For other ports, give an default value */
for (size_t pin_id = 0; pin_id < module_global_port.pins().size();
++pin_id) {
BasicPort module_global_pin(module_global_port.get_name(),
module_global_port.pins()[pin_id],
module_global_port.pins()[pin_id]);
/* If the global port name is in the pin constraints, we should wire it to
* the constrained pin */
std::string constrained_net_name =
pin_constraints.pin_net(module_global_pin);
if (constrained_net_name.empty()) {
continue;
}
constrained_net_name += std::string(APPINST_PORT_POSTFIX);
module_global_pin.set_name(module_global_port.get_name());
/* - If constrained to a given net in the benchmark, we connect the global
* pin to the net
* - If constrained to an open net in the benchmark, we assign it to a
* default value
*/
if ((false == pin_constraints.unconstrained_net(constrained_net_name)) &&
(false == pin_constraints.unmapped_net(constrained_net_name))) {
BasicPort benchmark_pin(constrained_net_name, 1);
print_verilog_wire_connection(fp, benchmark_pin, module_global_pin,
false);
}
}
}
print_verilog_comment(
fp, std::string(
"----- End Connect Global ports to FPGA top-level interface -----"));
/* Add an empty line as a splitter */
fp << std::endl;
return CMD_EXEC_SUCCESS;
}
/********************************************************************
* Top-level function to generate a Verilog module of
* a mock FPGA wrapper which contains an benchmark instance.
*
* Mock FPGA wrapper
* +--------------------------------------------
* |
* | Benchmark instance
* | +-------------------------------+
* | | |
* fpga_clock----->|--------->|benchmark_clock |
* | | |
* fpga_inputs---->|--------->|benchmark_inputs |
* | | |
* fpga_outputs<---|<---------|benchmark_output |
* | | |
* | +-------------------------------+
* |
* +-------------------------------------------
*
* Note: we do NOT put this module in the module manager.
* Because, it is not a standard module, where we just wrap an instance of
*application HDL (supposed to be implemented on FPGA).
*******************************************************************/
int print_verilog_mock_fpga_wrapper(
const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports,
const AtomContext& atom_ctx, const PlacementContext& place_ctx,
const PinConstraints& pin_constraints, const BusGroup& bus_group,
const IoLocationMap& io_location_map,
const VprNetlistAnnotation& netlist_annotation,
const std::string& circuit_name, const std::string& verilog_fname,
const VerilogTestbenchOption& options) {
std::string timer_message =
std::string("Write mock FPGA wrapper in Verilog format for design '") +
circuit_name + std::string("'");
int status = CMD_EXEC_SUCCESS;
/* Start time count */
vtr::ScopedStartFinishTimer timer(timer_message);
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
/* Validate the file stream */
check_file_stream(verilog_fname.c_str(), fp);
/* Generate a brief description on the Verilog file*/
std::string title =
std::string("Verilog netlist for mock FPGA fabric by design: ") +
circuit_name;
print_verilog_file_header(fp, title, options.time_stamp());
/* Find the top_module */
ModuleId top_module =
module_manager.find_module(generate_fpga_top_module_name());
VTR_ASSERT(true == module_manager.valid_module_id(top_module));
/* Print module declaration */
print_verilog_module_declaration(fp, module_manager, top_module,
options.default_net_type());
/* Find clock ports in benchmark */
std::vector<std::string> benchmark_clock_port_names =
find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation);
/* Print local wires */
print_verilog_testbench_shared_input_ports(
fp, module_manager, global_ports, pin_constraints, atom_ctx,
netlist_annotation, benchmark_clock_port_names, true,
std::string(APPINST_PORT_POSTFIX), false);
print_verilog_testbench_shared_benchmark_output_ports(
fp, atom_ctx, netlist_annotation, std::string(APPINST_PORT_POSTFIX));
/* Instanciate application HDL module */
print_verilog_testbench_benchmark_instance(
fp, circuit_name, std::string(APP_INSTANCE_NAME), std::string(),
std::string(), std::string(APPINST_PORT_POSTFIX),
std::string(APPINST_PORT_POSTFIX), benchmark_clock_port_names, true,
atom_ctx, netlist_annotation, pin_constraints, bus_group,
options.explicit_port_mapping());
/* Connect FPGA top module global ports to constant or benchmark global
* signals! */
status = print_verilog_mock_fpga_wrapper_connect_global_ports(
fp, module_manager, top_module, pin_constraints, global_ports,
benchmark_clock_port_names);
if (CMD_EXEC_FATAL_ERROR == status) {
return status;
}
/* Connect I/Os to benchmark I/Os or constant driver */
print_verilog_mock_fpga_wrapper_connect_ios(
fp, module_manager, top_module, atom_ctx, place_ctx, io_location_map,
pin_constraints, global_ports, netlist_annotation, std::string(),
std::string(APPINST_PORT_POSTFIX), std::string(APPINST_PORT_POSTFIX),
benchmark_clock_port_names, (size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE);
/* Testbench ends*/
print_verilog_module_end(fp, title);
/* Close the file stream */
fp.close();
return status;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,40 @@
#ifndef VERILOG_MOCK_FPGA_WRAPPER_H
#define VERILOG_MOCK_FPGA_WRAPPER_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include <vector>
#include "bitstream_manager.h"
#include "bus_group.h"
#include "circuit_library.h"
#include "config_protocol.h"
#include "fabric_global_port_info.h"
#include "io_location_map.h"
#include "module_manager.h"
#include "pin_constraints.h"
#include "verilog_testbench_options.h"
#include "vpr_context.h"
#include "vpr_netlist_annotation.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
int print_verilog_mock_fpga_wrapper(
const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports,
const AtomContext& atom_ctx, const PlacementContext& place_ctx,
const PinConstraints& pin_constraints, const BusGroup& bus_group,
const IoLocationMap& io_location_map,
const VprNetlistAnnotation& netlist_annotation,
const std::string& circuit_name, const std::string& verilog_fname,
const VerilogTestbenchOption& options);
} /* end namespace openfpga */
#endif

View File

@ -78,7 +78,8 @@ void print_verilog_testbench_benchmark_instance(
const std::string& module_input_port_postfix,
const std::string& module_output_port_postfix,
const std::string& input_port_postfix, const std::string& output_port_postfix,
const std::vector<std::string>& clock_port_names, const AtomContext& atom_ctx,
const std::vector<std::string>& clock_port_names,
const bool& include_clock_port_postfix, const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const PinConstraints& pin_constraints, const BusGroup& bus_group,
const bool& use_explicit_port_map) {
@ -183,6 +184,8 @@ void print_verilog_testbench_benchmark_instance(
clock_port_names.end(),
port_names[iport])) {
fp << input_port_postfix;
} else if (include_clock_port_postfix) {
fp << input_port_postfix;
}
pin_counter++;
@ -206,6 +209,8 @@ void print_verilog_testbench_benchmark_instance(
clock_port_names.end(),
port_names[iport])) {
fp << input_port_postfix;
} else if (include_clock_port_postfix) {
fp << input_port_postfix;
}
}
@ -914,20 +919,16 @@ void print_verilog_testbench_random_stimuli(
* which are
* 1. the shared input ports (registers) to drive both
* FPGA fabric and benchmark instance
* 2. the output ports (wires) for both FPGA fabric and benchmark instance
* 3. the checking flag ports to evaluate if outputs matches under the
* same input vectors
*******************************************************************/
void print_verilog_testbench_shared_ports(
void print_verilog_testbench_shared_input_ports(
std::fstream& fp, const ModuleManager& module_manager,
const FabricGlobalPortInfo& global_ports,
const PinConstraints& pin_constraints, const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const std::vector<std::string>& clock_port_names,
const std::string& shared_input_port_postfix,
const std::string& benchmark_output_port_postfix,
const std::string& fpga_output_port_postfix,
const std::string& check_flag_port_postfix, const bool& no_self_checking) {
const bool& include_clock_ports, const std::string& shared_input_port_postfix,
const bool& use_reg_port) {
/* Validate the file stream */
valid_file_stream(fp);
@ -950,7 +951,9 @@ void print_verilog_testbench_shared_ports(
if (clock_port_names.end() != std::find(clock_port_names.begin(),
clock_port_names.end(),
block_name)) {
continue;
if (!include_clock_ports) {
continue;
}
}
/* Each logical block assumes a single-width port */
@ -959,8 +962,13 @@ void print_verilog_testbench_shared_ports(
if (false ==
port_is_fabric_global_reset_port(global_ports, module_manager,
pin_constraints.net_pin(block_name))) {
fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, input_port) << ";"
<< std::endl;
if (use_reg_port) {
fp << "\t" << generate_verilog_port(VERILOG_PORT_REG, input_port) << ";"
<< std::endl;
} else {
fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, input_port)
<< ";" << std::endl;
}
} else {
fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, input_port) << ";"
<< std::endl;
@ -969,6 +977,19 @@ void print_verilog_testbench_shared_ports(
/* Add an empty line as splitter */
fp << std::endl;
}
/********************************************************************
* Print Verilog declaration of shared ports appear in testbenches
* which are
* 2. the output ports (wires) for FPGA fabric
*******************************************************************/
void print_verilog_testbench_shared_fpga_output_ports(
std::fstream& fp, const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const std::string& fpga_output_port_postfix) {
/* Validate the file stream */
valid_file_stream(fp);
/* Instantiate wires for FPGA fabric outputs */
print_verilog_comment(fp, std::string("----- FPGA fabric outputs -------"));
@ -996,10 +1017,19 @@ void print_verilog_testbench_shared_ports(
/* Add an empty line as splitter */
fp << std::endl;
}
if (no_self_checking) {
return;
}
/********************************************************************
* Print Verilog declaration of shared ports appear in testbenches
* which are
* 2. the output ports (wires) for benchmark instance
*******************************************************************/
void print_verilog_testbench_shared_benchmark_output_ports(
std::fstream& fp, const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const std::string& benchmark_output_port_postfix) {
/* Validate the file stream */
valid_file_stream(fp);
/* Instantiate wire for benchmark output */
print_verilog_comment(fp, std::string("----- Benchmark outputs -------"));
@ -1026,6 +1056,23 @@ void print_verilog_testbench_shared_ports(
/* Add an empty line as splitter */
fp << std::endl;
}
/********************************************************************
* Print Verilog declaration of shared ports appear in testbenches
* which are
* 1. the shared input ports (registers) to drive both
* FPGA fabric and benchmark instance
* 2. the output ports (wires) for both FPGA fabric and benchmark instance
* 3. the checking flag ports to evaluate if outputs matches under the
* same input vectors
*******************************************************************/
void print_verilog_testbench_shared_check_flags(
std::fstream& fp, const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const std::string& check_flag_port_postfix) {
/* Validate the file stream */
valid_file_stream(fp);
/* Instantiate register for output comparison */
print_verilog_comment(
@ -1054,6 +1101,44 @@ void print_verilog_testbench_shared_ports(
fp << std::endl;
}
/********************************************************************
* Print Verilog declaration of shared ports appear in testbenches
* which are
* 1. the shared input ports (registers) to drive both
* FPGA fabric and benchmark instance
* 2. the output ports (wires) for both FPGA fabric and benchmark instance
* 3. the checking flag ports to evaluate if outputs matches under the
* same input vectors
*******************************************************************/
void print_verilog_testbench_shared_ports(
std::fstream& fp, const ModuleManager& module_manager,
const FabricGlobalPortInfo& global_ports,
const PinConstraints& pin_constraints, const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const std::vector<std::string>& clock_port_names,
const std::string& shared_input_port_postfix,
const std::string& benchmark_output_port_postfix,
const std::string& fpga_output_port_postfix,
const std::string& check_flag_port_postfix, const bool& no_self_checking) {
print_verilog_testbench_shared_input_ports(
fp, module_manager, global_ports, pin_constraints, atom_ctx,
netlist_annotation, clock_port_names, false, shared_input_port_postfix,
true);
print_verilog_testbench_shared_fpga_output_ports(
fp, atom_ctx, netlist_annotation, fpga_output_port_postfix);
if (no_self_checking) {
return;
}
print_verilog_testbench_shared_benchmark_output_ports(
fp, atom_ctx, netlist_annotation, benchmark_output_port_postfix);
print_verilog_testbench_shared_check_flags(fp, atom_ctx, netlist_annotation,
check_flag_port_postfix);
}
/********************************************************************
* Print signal initialization which
* deposit initial values for the input ports of primitive circuit models

View File

@ -38,7 +38,8 @@ void print_verilog_testbench_benchmark_instance(
const std::string& module_input_port_postfix,
const std::string& module_output_port_postfix,
const std::string& input_port_postfix, const std::string& output_port_postfix,
const std::vector<std::string>& clock_port_names, const AtomContext& atom_ctx,
const std::vector<std::string>& clock_port_names,
const bool& include_clock_port_postfix, const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const PinConstraints& pin_constraints, const BusGroup& bus_group,
const bool& use_explicit_port_map);
@ -90,6 +91,30 @@ void print_verilog_testbench_random_stimuli(
const std::string& check_flag_port_postfix,
const std::vector<BasicPort>& clock_ports, const bool& no_self_checking);
void print_verilog_testbench_shared_input_ports(
std::fstream& fp, const ModuleManager& module_manager,
const FabricGlobalPortInfo& global_ports,
const PinConstraints& pin_constraints, const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const std::vector<std::string>& clock_port_names,
const bool& include_clock_ports, const std::string& shared_input_port_postfix,
const bool& use_reg_port);
void print_verilog_testbench_shared_fpga_output_ports(
std::fstream& fp, const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const std::string& fpga_output_port_postfix);
void print_verilog_testbench_shared_benchmark_output_ports(
std::fstream& fp, const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const std::string& benchmark_output_port_postfix);
void print_verilog_testbench_shared_check_flags(
std::fstream& fp, const AtomContext& atom_ctx,
const VprNetlistAnnotation& netlist_annotation,
const std::string& check_flag_port_postfix);
void print_verilog_testbench_shared_ports(
std::fstream& fp, const ModuleManager& module_manager,
const FabricGlobalPortInfo& global_ports,

View File

@ -1146,7 +1146,7 @@ static void print_verilog_top_testbench_benchmark_instance(
std::string(TOP_TESTBENCH_REFERENCE_INSTANCE_NAME), std::string(),
std::string(), std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX),
std::string(TOP_TESTBENCH_REFERENCE_OUTPUT_POSTFIX), clock_port_names,
atom_ctx, netlist_annotation, pin_constraints, bus_group,
false, atom_ctx, netlist_annotation, pin_constraints, bus_group,
explicit_port_mapping);
print_verilog_comment(

View File

@ -0,0 +1,72 @@
# Run VPR for the 'and' design
#--write_rr_graph example_rr_graph.xml
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling ideal
# 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 --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 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 ${OPENFPGA_REPACK_DESIGN_CONSTRAINTS} #--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
# Write the Verilog netlist for FPGA fabric
# - Enable the use of explicit port mapping in Verilog netlist
write_mock_fpga_wrapper --file ./SRC ${OPENFPGA_MOCK_WRAPPER_OPTIONS} ${OPENFPGA_MOCK_WRAPPER_BGF} ${OPENFPGA_MOCK_WRAPPER_PCF}
# 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_preconfigured_fabric_wrapper --embed_bitstream none --file ./SRC --explicit_port_mapping ${OPENFPGA_MOCK_WRAPPER_BGF} ${OPENFPGA_MOCK_WRAPPER_PCF}
write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --explicit_port_mapping ${OPENFPGA_MOCK_WRAPPER_BGF} ${OPENFPGA_MOCK_WRAPPER_PCF}
# 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

View File

@ -115,6 +115,12 @@ run-task basic_tests/fabric_key/load_external_key_qlbanksr_multi_chain_fpga $@
# 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 $@
echo -e "Testing mock wrapper"
run-task basic_tests/mock_wrapper/mock_wrapper_explicit_port_mapping $@
run-task basic_tests/mock_wrapper/mock_wrapper_implicit_port_mapping $@
run-task basic_tests/mock_wrapper/mock_wrapper_pcf $@
run-task basic_tests/mock_wrapper/mock_wrapper_bgf $@
echo -e "Testing K4 series FPGA";
echo -e "Testing K4N4 with facturable LUTs";
run-task basic_tests/k4_series/k4n4_frac_lut $@

View File

@ -0,0 +1,12 @@
<bus_group>
<bus name="result[7:0]" big_endian="false">
<pin id="0" name="result_0_"/>
<pin id="1" name="result_1_"/>
<pin id="2" name="result_2_"/>
<pin id="3" name="result_3_"/>
<pin id="4" name="result_4_"/>
<pin id="5" name="result_5_"/>
<pin id="6" name="result_6_"/>
<pin id="7" name="result_7_"/>
</bus>
</bus_group>

View File

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

View File

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

View File

@ -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 = false
spice_output=false
verilog_output=true
timeout_each_job = 20*60
fpga_flow=yosys_vpr
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/mock_wrapper_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
openfpga_repack_design_constraints=
openfpga_mock_wrapper_options=--explicit_port_mapping
openfpga_mock_wrapper_bgf=
openfpga_mock_wrapper_pcf=
[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]
bench_read_verilog_options_common = -nolatches
bench0_top = and2
bench1_top = or2
bench2_top = and2_latch
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=
vpr_fpga_verilog_formal_verification_top_netlist=

View File

@ -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 = false
spice_output=false
verilog_output=true
timeout_each_job = 20*60
fpga_flow=yosys_vpr
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/mock_wrapper_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
openfpga_repack_design_constraints=
openfpga_mock_wrapper_options=
openfpga_mock_wrapper_bgf=
openfpga_mock_wrapper_pcf=
[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]
bench_read_verilog_options_common = -nolatches
bench0_top = and2
bench1_top = or2
bench2_top = and2_latch
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=
vpr_fpga_verilog_formal_verification_top_netlist=

View File

@ -0,0 +1,11 @@
<pin_constraints>
<!-- For a given .blif file, we want to assign
- the clk0 signal to the clk[0] port of the FPGA fabric
- the clk1 signal to the clk[1] port of the FPGA fabric
-->
<set_io pin="clk[0]" net="clk0"/>
<set_io pin="clk[1]" net="clk1"/>
<set_io pin="clk[2]" net="OPEN"/>
<set_io pin="clk[3]" net="OPEN"/>
</pin_constraints>

View File

@ -0,0 +1,14 @@
<repack_design_constraints>
<!-- For a given .blif file, we want to assign
- the clk0 signal to the clk[0] port of all the clb tiles available in the FPGA fabric
- the clk1 signal to the clk[1] port of all the clb tiles available in the FPGA fabric
and ensure no signals could be mapped to
- the clk[2] port of all the clb tiles available in the FPGA fabric
- the clk[3] port of all the clb tiles available in the FPGA fabric
-->
<pin_constraint pb_type="clb" pin="clk[0]" net="clk0"/>
<pin_constraint pb_type="clb" pin="clk[1]" net="clk1"/>
<pin_constraint pb_type="clb" pin="clk[2]" net="OPEN"/>
<pin_constraint pb_type="clb" pin="clk[3]" net="OPEN"/>
</repack_design_constraints>

View File

@ -0,0 +1,43 @@
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# Configuration file for running experiments
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
# Each job execute fpga_flow script on combination of architecture & benchmark
# timeout_each_job is timeout for each job
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
[GENERAL]
run_engine=openfpga_shell
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
power_analysis = false
spice_output=false
verilog_output=true
timeout_each_job = 20*60
fpga_flow=yosys_vpr
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/mock_wrapper_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTile4Clk_cc_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_4clock_sim_openfpga.xml
openfpga_repack_design_constraints=--design_constraints ${PATH:TASK_DIR}/config/repack_pin_constraints.xml
openfpga_mock_wrapper_options=
openfpga_mock_wrapper_bgf=
openfpga_mock_wrapper_pcf=
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTile4Clk_40nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch_2clock/and2_latch_2clock.v
[SYNTHESIS_PARAM]
bench_read_verilog_options_common = -nolatches
bench0_top = and2_latch_2clock
bench0_openfpga_pin_constraints=--design_constraints ${PATH:TASK_DIR}/config/and2_latch_pin_constraints.xml
bench0_openfpga_mock_wrapper_pcf=-pcf ${PATH:TASK_DIR}/config/and2_latch_pin_constraints.xml
bench0_openfpga_mock_wrapper_bgf=
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=
vpr_fpga_verilog_formal_verification_top_netlist=