[Tool] Deploy pin constraints to preconfig Verilog module generation
This commit is contained in:
parent
e17a5cbbf2
commit
0670c2de59
|
@ -17,6 +17,9 @@
|
||||||
|
|
||||||
#include "pin_constraints_fwd.h"
|
#include "pin_constraints_fwd.h"
|
||||||
|
|
||||||
|
/* Constants */
|
||||||
|
constexpr char* PIN_CONSTRAINT_OPEN_NET = "OPEN";
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* A data structure to describe the pin constraints for FPGA fabrics
|
* A data structure to describe the pin constraints for FPGA fabrics
|
||||||
* This data structure may include a number of pin constraints
|
* This data structure may include a number of pin constraints
|
||||||
|
|
|
@ -26,6 +26,7 @@ target_link_libraries(libopenfpga
|
||||||
librepackdc
|
librepackdc
|
||||||
libfpgabitstream
|
libfpgabitstream
|
||||||
libini
|
libini
|
||||||
|
libpcf
|
||||||
libvtrutil
|
libvtrutil
|
||||||
libvpr)
|
libvpr)
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
#include "verilog_api.h"
|
#include "verilog_api.h"
|
||||||
#include "openfpga_verilog.h"
|
#include "openfpga_verilog.h"
|
||||||
|
|
||||||
|
/* Headers from pcf library */
|
||||||
|
#include "read_xml_pin_constraints.h"
|
||||||
|
|
||||||
/* Include global variables of VPR */
|
/* Include global variables of VPR */
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
|
@ -62,6 +65,7 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
|
||||||
|
|
||||||
CommandOptionId opt_output_dir = cmd.option("file");
|
CommandOptionId opt_output_dir = cmd.option("file");
|
||||||
CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path");
|
CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path");
|
||||||
|
CommandOptionId opt_pcf = cmd.option("pin_constraints_file");
|
||||||
CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path");
|
CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path");
|
||||||
CommandOptionId opt_print_top_testbench = cmd.option("print_top_testbench");
|
CommandOptionId opt_print_top_testbench = cmd.option("print_top_testbench");
|
||||||
CommandOptionId opt_fast_configuration = cmd.option("fast_configuration");
|
CommandOptionId opt_fast_configuration = cmd.option("fast_configuration");
|
||||||
|
@ -89,22 +93,26 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
|
||||||
options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init));
|
options.set_include_signal_init(cmd_context.option_enable(cmd, opt_include_signal_init));
|
||||||
options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator));
|
options.set_support_icarus_simulator(cmd_context.option_enable(cmd, opt_support_icarus_simulator));
|
||||||
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
|
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
|
||||||
|
|
||||||
fpga_verilog_testbench(openfpga_ctx.module_graph(),
|
|
||||||
openfpga_ctx.bitstream_manager(),
|
|
||||||
openfpga_ctx.fabric_bitstream(),
|
|
||||||
g_vpr_ctx.atom(),
|
|
||||||
g_vpr_ctx.placement(),
|
|
||||||
openfpga_ctx.io_location_map(),
|
|
||||||
openfpga_ctx.fabric_global_port_info(),
|
|
||||||
openfpga_ctx.vpr_netlist_annotation(),
|
|
||||||
openfpga_ctx.arch().circuit_lib,
|
|
||||||
openfpga_ctx.simulation_setting(),
|
|
||||||
openfpga_ctx.arch().config_protocol,
|
|
||||||
options);
|
|
||||||
|
|
||||||
/* TODO: should identify the error code from internal function execution */
|
/* If pin constraints are enabled by command options, read the file */
|
||||||
return CMD_EXEC_SUCCESS;
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
return fpga_verilog_testbench(openfpga_ctx.module_graph(),
|
||||||
|
openfpga_ctx.bitstream_manager(),
|
||||||
|
openfpga_ctx.fabric_bitstream(),
|
||||||
|
g_vpr_ctx.atom(),
|
||||||
|
g_vpr_ctx.placement(),
|
||||||
|
pin_constraints,
|
||||||
|
openfpga_ctx.io_location_map(),
|
||||||
|
openfpga_ctx.fabric_global_port_info(),
|
||||||
|
openfpga_ctx.vpr_netlist_annotation(),
|
||||||
|
openfpga_ctx.arch().circuit_lib,
|
||||||
|
openfpga_ctx.simulation_setting(),
|
||||||
|
openfpga_ctx.arch().config_protocol,
|
||||||
|
options);
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
|
@ -70,6 +70,11 @@ ShellCommandId add_openfpga_write_verilog_testbench_command(openfpga::Shell<Open
|
||||||
CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "Specify the file path to the fabric Verilog netlist");
|
CommandOptionId fabric_netlist_opt = shell_cmd.add_option("fabric_netlist_file_path", false, "Specify the file path to the fabric Verilog netlist");
|
||||||
shell_cmd.set_option_require_value(fabric_netlist_opt, openfpga::OPT_STRING);
|
shell_cmd.set_option_require_value(fabric_netlist_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 '--reference_benchmark_file_path'*/
|
/* Add an option '--reference_benchmark_file_path'*/
|
||||||
CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", true, "Specify the file path to the reference Verilog netlist");
|
CommandOptionId ref_bm_opt = shell_cmd.add_option("reference_benchmark_file_path", true, "Specify the file path to the reference Verilog netlist");
|
||||||
shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING);
|
shell_cmd.set_option_require_value(ref_bm_opt, openfpga::OPT_STRING);
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "vtr_assert.h"
|
#include "vtr_assert.h"
|
||||||
#include "vtr_time.h"
|
#include "vtr_time.h"
|
||||||
|
|
||||||
|
#include "command_exit_codes.h"
|
||||||
|
|
||||||
#include "circuit_library_utils.h"
|
#include "circuit_library_utils.h"
|
||||||
|
|
||||||
/* Headers from openfpgautil library */
|
/* Headers from openfpgautil library */
|
||||||
|
@ -147,18 +149,19 @@ void fpga_fabric_verilog(ModuleManager &module_manager,
|
||||||
* This testbench is created for quick verification and formal verification purpose.
|
* This testbench is created for quick verification and formal verification purpose.
|
||||||
* - Verilog netlist including preprocessing flags and all the Verilog netlists that have been generated
|
* - Verilog netlist including preprocessing flags and all the Verilog netlists that have been generated
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
void fpga_verilog_testbench(const ModuleManager &module_manager,
|
int fpga_verilog_testbench(const ModuleManager &module_manager,
|
||||||
const BitstreamManager &bitstream_manager,
|
const BitstreamManager &bitstream_manager,
|
||||||
const FabricBitstream &fabric_bitstream,
|
const FabricBitstream &fabric_bitstream,
|
||||||
const AtomContext &atom_ctx,
|
const AtomContext &atom_ctx,
|
||||||
const PlacementContext &place_ctx,
|
const PlacementContext &place_ctx,
|
||||||
const IoLocationMap &io_location_map,
|
const PinConstraints& pin_constraints,
|
||||||
const FabricGlobalPortInfo &fabric_global_port_info,
|
const IoLocationMap &io_location_map,
|
||||||
const VprNetlistAnnotation &netlist_annotation,
|
const FabricGlobalPortInfo &fabric_global_port_info,
|
||||||
const CircuitLibrary &circuit_lib,
|
const VprNetlistAnnotation &netlist_annotation,
|
||||||
const SimulationSetting &simulation_setting,
|
const CircuitLibrary &circuit_lib,
|
||||||
const ConfigProtocol &config_protocol,
|
const SimulationSetting &simulation_setting,
|
||||||
const VerilogTestbenchOption &options) {
|
const ConfigProtocol &config_protocol,
|
||||||
|
const VerilogTestbenchOption &options) {
|
||||||
|
|
||||||
vtr::ScopedStartFinishTimer timer("Write Verilog testbenches for FPGA fabric\n");
|
vtr::ScopedStartFinishTimer timer("Write Verilog testbenches for FPGA fabric\n");
|
||||||
|
|
||||||
|
@ -166,6 +169,8 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
|
||||||
|
|
||||||
std::string netlist_name = atom_ctx.nlist.netlist_name();
|
std::string netlist_name = atom_ctx.nlist.netlist_name();
|
||||||
|
|
||||||
|
int status = CMD_EXEC_SUCCESS;
|
||||||
|
|
||||||
/* Create directories */
|
/* Create directories */
|
||||||
create_directory(src_dir_path);
|
create_directory(src_dir_path);
|
||||||
|
|
||||||
|
@ -176,14 +181,19 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
|
||||||
/* Generate wrapper module for FPGA fabric (mapped by the input benchmark and pre-configured testbench for verification */
|
/* Generate wrapper module for FPGA fabric (mapped by the input benchmark and pre-configured testbench for verification */
|
||||||
if (true == options.print_formal_verification_top_netlist()) {
|
if (true == options.print_formal_verification_top_netlist()) {
|
||||||
std::string formal_verification_top_netlist_file_path = src_dir_path + netlist_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX);
|
std::string formal_verification_top_netlist_file_path = src_dir_path + netlist_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX);
|
||||||
print_verilog_preconfig_top_module(module_manager, bitstream_manager,
|
status = print_verilog_preconfig_top_module(module_manager, bitstream_manager,
|
||||||
config_protocol,
|
config_protocol,
|
||||||
circuit_lib, fabric_global_port_info,
|
circuit_lib, fabric_global_port_info,
|
||||||
atom_ctx, place_ctx, io_location_map,
|
atom_ctx, place_ctx,
|
||||||
netlist_annotation,
|
pin_constraints,
|
||||||
netlist_name,
|
io_location_map,
|
||||||
formal_verification_top_netlist_file_path,
|
netlist_annotation,
|
||||||
options.explicit_port_mapping());
|
netlist_name,
|
||||||
|
formal_verification_top_netlist_file_path,
|
||||||
|
options.explicit_port_mapping());
|
||||||
|
if (status == CMD_EXEC_FATAL_ERROR) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (true == options.print_preconfig_top_testbench()) {
|
if (true == options.print_preconfig_top_testbench()) {
|
||||||
|
@ -234,6 +244,8 @@ void fpga_verilog_testbench(const ModuleManager &module_manager,
|
||||||
netlist_name,
|
netlist_name,
|
||||||
options.fabric_netlist_file_path(),
|
options.fabric_netlist_file_path(),
|
||||||
options.reference_benchmark_file_path());
|
options.reference_benchmark_file_path());
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "bitstream_manager.h"
|
#include "bitstream_manager.h"
|
||||||
#include "fabric_bitstream.h"
|
#include "fabric_bitstream.h"
|
||||||
#include "simulation_setting.h"
|
#include "simulation_setting.h"
|
||||||
|
#include "pin_constraints.h"
|
||||||
#include "io_location_map.h"
|
#include "io_location_map.h"
|
||||||
#include "fabric_global_port_info.h"
|
#include "fabric_global_port_info.h"
|
||||||
#include "vpr_netlist_annotation.h"
|
#include "vpr_netlist_annotation.h"
|
||||||
|
@ -42,18 +43,19 @@ void fpga_fabric_verilog(ModuleManager& module_manager,
|
||||||
const DeviceRRGSB& device_rr_gsb,
|
const DeviceRRGSB& device_rr_gsb,
|
||||||
const FabricVerilogOption& options);
|
const FabricVerilogOption& options);
|
||||||
|
|
||||||
void fpga_verilog_testbench(const ModuleManager& module_manager,
|
int fpga_verilog_testbench(const ModuleManager& module_manager,
|
||||||
const BitstreamManager& bitstream_manager,
|
const BitstreamManager& bitstream_manager,
|
||||||
const FabricBitstream& fabric_bitstream,
|
const FabricBitstream& fabric_bitstream,
|
||||||
const AtomContext& atom_ctx,
|
const AtomContext& atom_ctx,
|
||||||
const PlacementContext& place_ctx,
|
const PlacementContext& place_ctx,
|
||||||
const IoLocationMap& io_location_map,
|
const PinConstraints& pin_constraints,
|
||||||
const FabricGlobalPortInfo &fabric_global_port_info,
|
const IoLocationMap& io_location_map,
|
||||||
const VprNetlistAnnotation& netlist_annotation,
|
const FabricGlobalPortInfo &fabric_global_port_info,
|
||||||
const CircuitLibrary& circuit_lib,
|
const VprNetlistAnnotation& netlist_annotation,
|
||||||
const SimulationSetting& simulation_parameters,
|
const CircuitLibrary& circuit_lib,
|
||||||
const ConfigProtocol& config_protocol,
|
const SimulationSetting& simulation_parameters,
|
||||||
const VerilogTestbenchOption& options);
|
const ConfigProtocol& config_protocol,
|
||||||
|
const VerilogTestbenchOption& options);
|
||||||
|
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include "vtr_log.h"
|
#include "vtr_log.h"
|
||||||
#include "vtr_time.h"
|
#include "vtr_time.h"
|
||||||
|
|
||||||
|
#include "command_exit_codes.h"
|
||||||
|
|
||||||
/* Headers from openfpgautil library */
|
/* Headers from openfpgautil library */
|
||||||
#include "openfpga_port.h"
|
#include "openfpga_port.h"
|
||||||
#include "openfpga_digest.h"
|
#include "openfpga_digest.h"
|
||||||
|
@ -24,254 +26,217 @@
|
||||||
#include "verilog_preconfig_top_module.h"
|
#include "verilog_preconfig_top_module.h"
|
||||||
|
|
||||||
/* begin namespace openfpga */
|
/* begin namespace openfpga */
|
||||||
namespace openfpga
|
namespace openfpga {
|
||||||
{
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Print module declaration and ports for the pre-configured
|
* Print module declaration and ports for the pre-configured
|
||||||
* FPGA top module
|
* FPGA top module
|
||||||
* The module ports do exactly match the input benchmark
|
* The module ports do exactly match the input benchmark
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
static void print_verilog_preconfig_top_module_ports(std::fstream &fp,
|
static
|
||||||
const std::string &circuit_name,
|
void print_verilog_preconfig_top_module_ports(std::fstream &fp,
|
||||||
const AtomContext &atom_ctx,
|
const std::string &circuit_name,
|
||||||
const VprNetlistAnnotation &netlist_annotation)
|
const AtomContext &atom_ctx,
|
||||||
{
|
const VprNetlistAnnotation &netlist_annotation) {
|
||||||
|
|
||||||
/* Validate the file stream */
|
/* Validate the file stream */
|
||||||
valid_file_stream(fp);
|
valid_file_stream(fp);
|
||||||
|
|
||||||
/* Module declaration */
|
/* Module declaration */
|
||||||
fp << "module " << circuit_name << std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX);
|
fp << "module " << circuit_name << std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX);
|
||||||
fp << " (" << std::endl;
|
fp << " (" << std::endl;
|
||||||
|
|
||||||
/* Add module ports */
|
/* Add module ports */
|
||||||
size_t port_counter = 0;
|
size_t port_counter = 0;
|
||||||
|
|
||||||
/* Port type-to-type mapping */
|
/* Port type-to-type mapping */
|
||||||
std::map<AtomBlockType, enum e_dump_verilog_port_type> port_type2type_map;
|
std::map<AtomBlockType, enum e_dump_verilog_port_type> port_type2type_map;
|
||||||
port_type2type_map[AtomBlockType::INPAD] = VERILOG_PORT_INPUT;
|
port_type2type_map[AtomBlockType::INPAD] = VERILOG_PORT_INPUT;
|
||||||
port_type2type_map[AtomBlockType::OUTPAD] = VERILOG_PORT_OUTPUT;
|
port_type2type_map[AtomBlockType::OUTPAD] = VERILOG_PORT_OUTPUT;
|
||||||
|
|
||||||
/* Print all the I/Os of the circuit implementation to be tested*/
|
/* Print all the I/Os of the circuit implementation to be tested*/
|
||||||
for (const AtomBlockId &atom_blk : atom_ctx.nlist.blocks())
|
for (const AtomBlockId &atom_blk : atom_ctx.nlist.blocks()) {
|
||||||
{
|
/* We only care I/O logical blocks !*/
|
||||||
/* We only care I/O logical blocks !*/
|
if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk))) {
|
||||||
if ((AtomBlockType::INPAD != atom_ctx.nlist.block_type(atom_blk)) && (AtomBlockType::OUTPAD != atom_ctx.nlist.block_type(atom_blk)))
|
continue;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 < port_counter)
|
|
||||||
{
|
|
||||||
fp << "," << std::endl;
|
|
||||||
}
|
|
||||||
/* Both input and output ports have only size of 1 */
|
|
||||||
BasicPort module_port(std::string(block_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)), 1);
|
|
||||||
fp << generate_verilog_port(port_type2type_map[atom_ctx.nlist.block_type(atom_blk)], module_port);
|
|
||||||
|
|
||||||
/* Update port counter */
|
|
||||||
port_counter++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fp << ");" << std::endl;
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
/* Add an empty line as a splitter */
|
if (0 < port_counter) {
|
||||||
fp << std::endl;
|
fp << "," << std::endl;
|
||||||
|
}
|
||||||
|
/* Both input and output ports have only size of 1 */
|
||||||
|
BasicPort module_port(std::string(block_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX)), 1);
|
||||||
|
fp << generate_verilog_port(port_type2type_map[atom_ctx.nlist.block_type(atom_blk)], module_port);
|
||||||
|
|
||||||
|
/* Update port counter */
|
||||||
|
port_counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
fp << ");" << std::endl;
|
||||||
|
|
||||||
|
/* Add an empty line as a splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
* Print internal wires for the pre-configured FPGA top module
|
* Print internal wires for the pre-configured FPGA top module
|
||||||
* The internal wires are tailored for the ports of FPGA top module
|
* The internal wires are tailored for the ports of FPGA top module
|
||||||
* which will be different in various configuration protocols
|
* which will be different in various configuration protocols
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
static void print_verilog_preconfig_top_module_internal_wires(std::fstream &fp,
|
static
|
||||||
const ModuleManager &module_manager,
|
void print_verilog_preconfig_top_module_internal_wires(std::fstream &fp,
|
||||||
const ModuleId &top_module)
|
const ModuleManager &module_manager,
|
||||||
{
|
const ModuleId &top_module) {
|
||||||
/* Validate the file stream */
|
/* Validate the file stream */
|
||||||
valid_file_stream(fp);
|
valid_file_stream(fp);
|
||||||
|
|
||||||
/* Global ports of top-level module */
|
/* Global ports of top-level module */
|
||||||
print_verilog_comment(fp, std::string("----- Local wires for FPGA fabric -----"));
|
print_verilog_comment(fp, std::string("----- Local wires for FPGA fabric -----"));
|
||||||
for (const ModulePortId &module_port_id : module_manager.module_ports(top_module))
|
for (const ModulePortId &module_port_id : module_manager.module_ports(top_module)) {
|
||||||
{
|
BasicPort module_port = module_manager.module_port(top_module, module_port_id);
|
||||||
BasicPort module_port = module_manager.module_port(top_module, module_port_id);
|
fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" << std::endl;
|
||||||
fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" << std::endl;
|
|
||||||
}
|
|
||||||
/* Add an empty line as a splitter */
|
|
||||||
fp << std::endl;
|
|
||||||
}
|
}
|
||||||
|
/* Add an empty line as a splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Connect global ports of FPGA top module to constants except:
|
* Connect global ports of FPGA top module to constants except:
|
||||||
* 1. operating clock, which should be wired to the clock port of
|
* 1. operating clock, which should be wired to the clock port of
|
||||||
* this pre-configured FPGA top module
|
* this pre-configured FPGA top module
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
static void print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp,
|
static
|
||||||
const ModuleManager &module_manager,
|
int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp,
|
||||||
const ModuleId &top_module,
|
const ModuleManager &module_manager,
|
||||||
const FabricGlobalPortInfo &fabric_global_ports,
|
const ModuleId &top_module,
|
||||||
const std::vector<std::string> &benchmark_clock_port_names)
|
const PinConstraints& pin_constraints,
|
||||||
{
|
const FabricGlobalPortInfo &fabric_global_ports,
|
||||||
/* Validate the file stream */
|
const std::vector<std::string> &benchmark_clock_port_names) {
|
||||||
valid_file_stream(fp);
|
/* Validate the file stream */
|
||||||
|
valid_file_stream(fp);
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- Begin Connect Global ports of FPGA top module -----"));
|
print_verilog_comment(fp, std::string("----- Begin Connect Global ports of FPGA top module -----"));
|
||||||
|
|
||||||
for (const FabricGlobalPortId& global_port_id : fabric_global_ports.global_ports()) {
|
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);
|
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));
|
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);
|
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! */
|
/* 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))
|
if ((true == fabric_global_ports.global_port_is_clock(global_port_id))
|
||||||
&& (false == fabric_global_ports.global_port_is_prog(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 */
|
/* Wiring to each pin of the global port: benchmark clock is always 1-bit */
|
||||||
for (const size_t &pin : module_global_port.pins()) {
|
for (size_t pin_id = 0; pin_id < module_global_port.pins().size(); ++pin_id) {
|
||||||
for (const std::string &clock_port_name : benchmark_clock_port_names) {
|
BasicPort module_clock_pin(module_global_port.get_name(), module_global_port.pins()[pin_id], module_global_port.pins()[pin_id]);
|
||||||
BasicPort module_clock_pin(module_global_port.get_name(), pin, pin);
|
|
||||||
BasicPort benchmark_clock_pin(clock_port_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), 1);
|
/* If the clock port name is in the pin constraints, we should wire it to the constrained pin */
|
||||||
print_verilog_wire_connection(fp, module_clock_pin, benchmark_clock_pin, false);
|
std::string constrained_net_name;
|
||||||
|
for (const PinConstraintId& pin_constraint : pin_constraints.pin_constraints()) {
|
||||||
|
if (module_clock_pin == pin_constraints.pin(pin_constraint)) {
|
||||||
|
constrained_net_name = pin_constraints.net(pin_constraint);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Finish, go to the next */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For other ports, give an default value */
|
/* If constrained to an open net, we assign it to a default value */
|
||||||
std::vector<size_t> default_values(module_global_port.get_width(), fabric_global_ports.global_port_default_value(global_port_id));
|
if (std::string(PIN_CONSTRAINT_OPEN_NET) == constrained_net_name) {
|
||||||
print_verilog_wire_constant_values(fp, module_global_port, default_values);
|
std::vector<size_t> default_values(1, fabric_global_ports.global_port_default_value(global_port_id));
|
||||||
|
print_verilog_wire_constant_values(fp, module_clock_pin, default_values);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string clock_name_to_connect;
|
||||||
|
if (!constrained_net_name.empty()) {
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicPort benchmark_clock_pin(clock_name_to_connect + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), 1);
|
||||||
|
print_verilog_wire_connection(fp, module_clock_pin, benchmark_clock_pin, false);
|
||||||
|
}
|
||||||
|
/* Finish, go to the next */
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- End Connect Global ports of FPGA top module -----"));
|
/* For other ports, give an default value */
|
||||||
|
std::vector<size_t> default_values(module_global_port.get_width(), fabric_global_ports.global_port_default_value(global_port_id));
|
||||||
/* Add an empty line as a splitter */
|
print_verilog_wire_constant_values(fp, module_global_port, default_values);
|
||||||
fp << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
print_verilog_comment(fp, std::string("----- End Connect Global ports of FPGA top module -----"));
|
||||||
|
|
||||||
|
/* Add an empty line as a splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
|
return CMD_EXEC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
* Impose the bitstream on the configuration memories
|
* Impose the bitstream on the configuration memories
|
||||||
* This function uses 'assign' syntax to impost the bitstream at mem port
|
* This function uses 'assign' syntax to impost the bitstream at mem port
|
||||||
* while uses 'force' syntax to impost the bitstream at mem_inv port
|
* while uses 'force' syntax to impost the bitstream at mem_inv port
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
static void print_verilog_preconfig_top_module_assign_bitstream(std::fstream &fp,
|
static
|
||||||
const ModuleManager &module_manager,
|
void print_verilog_preconfig_top_module_assign_bitstream(std::fstream &fp,
|
||||||
const ModuleId &top_module,
|
const ModuleManager &module_manager,
|
||||||
const BitstreamManager &bitstream_manager,
|
const ModuleId &top_module,
|
||||||
const bool& output_datab_bits)
|
const BitstreamManager &bitstream_manager,
|
||||||
{
|
const bool& output_datab_bits) {
|
||||||
/* Validate the file stream */
|
/* Validate the file stream */
|
||||||
valid_file_stream(fp);
|
valid_file_stream(fp);
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- Begin assign bitstream to configuration memories -----"));
|
print_verilog_comment(fp, std::string("----- Begin assign bitstream to configuration memories -----"));
|
||||||
|
|
||||||
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks())
|
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks()) {
|
||||||
{
|
/* We only cares blocks with configuration bits */
|
||||||
/* We only cares blocks with configuration bits */
|
if (0 == bitstream_manager.block_bits(config_block_id).size()) {
|
||||||
if (0 == bitstream_manager.block_bits(config_block_id).size())
|
continue;
|
||||||
{
|
}
|
||||||
continue;
|
/* Build the hierarchical path of the configuration bit in modules */
|
||||||
}
|
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id);
|
||||||
/* Build the hierarchical path of the configuration bit in modules */
|
/* Drop the first block, which is the top module, it should be replaced by the instance name here */
|
||||||
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id);
|
/* Ensure that this is the module we want to drop! */
|
||||||
/* Drop the first block, which is the top module, it should be replaced by the instance name here */
|
VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0])));
|
||||||
/* Ensure that this is the module we want to drop! */
|
block_hierarchy.erase(block_hierarchy.begin());
|
||||||
VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0])));
|
/* Build the full hierarchy path */
|
||||||
block_hierarchy.erase(block_hierarchy.begin());
|
std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME);
|
||||||
/* Build the full hierarchy path */
|
for (const ConfigBlockId &temp_block : block_hierarchy) {
|
||||||
std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME);
|
|
||||||
for (const ConfigBlockId &temp_block : block_hierarchy)
|
|
||||||
{
|
|
||||||
bit_hierarchy_path += std::string(".");
|
|
||||||
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
|
|
||||||
}
|
|
||||||
bit_hierarchy_path += std::string(".");
|
bit_hierarchy_path += std::string(".");
|
||||||
|
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
|
||||||
/* Find the bit index in the parent block */
|
|
||||||
BasicPort config_data_port(bit_hierarchy_path + generate_configurable_memory_data_out_name(),
|
|
||||||
bitstream_manager.block_bits(config_block_id).size());
|
|
||||||
|
|
||||||
/* Wire it to the configuration bit: access both data out and data outb ports */
|
|
||||||
std::vector<size_t> config_data_values;
|
|
||||||
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id))
|
|
||||||
{
|
|
||||||
config_data_values.push_back(bitstream_manager.bit_value(config_bit));
|
|
||||||
}
|
|
||||||
print_verilog_wire_constant_values(fp, config_data_port, config_data_values);
|
|
||||||
}
|
}
|
||||||
|
bit_hierarchy_path += std::string(".");
|
||||||
|
|
||||||
if (true == output_datab_bits) {
|
/* Find the bit index in the parent block */
|
||||||
fp << "initial begin" << std::endl;
|
BasicPort config_data_port(bit_hierarchy_path + generate_configurable_memory_data_out_name(),
|
||||||
|
bitstream_manager.block_bits(config_block_id).size());
|
||||||
|
|
||||||
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks())
|
/* Wire it to the configuration bit: access both data out and data outb ports */
|
||||||
{
|
std::vector<size_t> config_data_values;
|
||||||
/* We only cares blocks with configuration bits */
|
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) {
|
||||||
if (0 == bitstream_manager.block_bits(config_block_id).size())
|
config_data_values.push_back(bitstream_manager.bit_value(config_bit));
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Build the hierarchical path of the configuration bit in modules */
|
|
||||||
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id);
|
|
||||||
/* Drop the first block, which is the top module, it should be replaced by the instance name here */
|
|
||||||
/* Ensure that this is the module we want to drop! */
|
|
||||||
VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0])));
|
|
||||||
block_hierarchy.erase(block_hierarchy.begin());
|
|
||||||
/* Build the full hierarchy path */
|
|
||||||
std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME);
|
|
||||||
for (const ConfigBlockId &temp_block : block_hierarchy)
|
|
||||||
{
|
|
||||||
bit_hierarchy_path += std::string(".");
|
|
||||||
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
|
|
||||||
}
|
|
||||||
bit_hierarchy_path += std::string(".");
|
|
||||||
|
|
||||||
/* Find the bit index in the parent block */
|
|
||||||
BasicPort config_datab_port(bit_hierarchy_path + generate_configurable_memory_inverted_data_out_name(),
|
|
||||||
bitstream_manager.block_bits(config_block_id).size());
|
|
||||||
|
|
||||||
std::vector<size_t> config_datab_values;
|
|
||||||
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id))
|
|
||||||
{
|
|
||||||
config_datab_values.push_back(!bitstream_manager.bit_value(config_bit));
|
|
||||||
}
|
|
||||||
print_verilog_force_wire_constant_values(fp, config_datab_port, config_datab_values);
|
|
||||||
}
|
|
||||||
|
|
||||||
fp << "end" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
print_verilog_wire_constant_values(fp, config_data_port, config_data_values);
|
||||||
print_verilog_comment(fp, std::string("----- End assign bitstream to configuration memories -----"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
if (true == output_datab_bits) {
|
||||||
* Impose the bitstream on the configuration memories
|
|
||||||
* This function uses '$deposit' syntax to do so
|
|
||||||
*******************************************************************/
|
|
||||||
static void print_verilog_preconfig_top_module_deposit_bitstream(std::fstream &fp,
|
|
||||||
const ModuleManager &module_manager,
|
|
||||||
const ModuleId &top_module,
|
|
||||||
const BitstreamManager &bitstream_manager,
|
|
||||||
const bool& output_datab_bits)
|
|
||||||
{
|
|
||||||
/* Validate the file stream */
|
|
||||||
valid_file_stream(fp);
|
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- Begin deposit bitstream to configuration memories -----"));
|
|
||||||
|
|
||||||
fp << "initial begin" << std::endl;
|
fp << "initial begin" << std::endl;
|
||||||
|
|
||||||
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks())
|
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks()) {
|
||||||
{
|
|
||||||
/* We only cares blocks with configuration bits */
|
/* We only cares blocks with configuration bits */
|
||||||
if (0 == bitstream_manager.block_bits(config_block_id).size())
|
if (0 == bitstream_manager.block_bits(config_block_id).size()) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Build the hierarchical path of the configuration bit in modules */
|
/* Build the hierarchical path of the configuration bit in modules */
|
||||||
|
@ -282,94 +247,144 @@ namespace openfpga
|
||||||
block_hierarchy.erase(block_hierarchy.begin());
|
block_hierarchy.erase(block_hierarchy.begin());
|
||||||
/* Build the full hierarchy path */
|
/* Build the full hierarchy path */
|
||||||
std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME);
|
std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME);
|
||||||
for (const ConfigBlockId &temp_block : block_hierarchy)
|
for (const ConfigBlockId &temp_block : block_hierarchy) {
|
||||||
{
|
|
||||||
bit_hierarchy_path += std::string(".");
|
bit_hierarchy_path += std::string(".");
|
||||||
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
|
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
|
||||||
}
|
}
|
||||||
bit_hierarchy_path += std::string(".");
|
bit_hierarchy_path += std::string(".");
|
||||||
|
|
||||||
/* Find the bit index in the parent block */
|
/* Find the bit index in the parent block */
|
||||||
BasicPort config_data_port(bit_hierarchy_path + generate_configurable_memory_data_out_name(),
|
|
||||||
bitstream_manager.block_bits(config_block_id).size());
|
|
||||||
|
|
||||||
/* Wire it to the configuration bit: access both data out and data outb ports */
|
|
||||||
std::vector<size_t> config_data_values;
|
|
||||||
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id))
|
|
||||||
{
|
|
||||||
config_data_values.push_back(bitstream_manager.bit_value(config_bit));
|
|
||||||
}
|
|
||||||
print_verilog_deposit_wire_constant_values(fp, config_data_port, config_data_values);
|
|
||||||
|
|
||||||
/* Skip datab ports if specified */
|
|
||||||
if (false == output_datab_bits) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicPort config_datab_port(bit_hierarchy_path + generate_configurable_memory_inverted_data_out_name(),
|
BasicPort config_datab_port(bit_hierarchy_path + generate_configurable_memory_inverted_data_out_name(),
|
||||||
bitstream_manager.block_bits(config_block_id).size());
|
bitstream_manager.block_bits(config_block_id).size());
|
||||||
|
|
||||||
|
|
||||||
std::vector<size_t> config_datab_values;
|
std::vector<size_t> config_datab_values;
|
||||||
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id))
|
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) {
|
||||||
{
|
|
||||||
config_datab_values.push_back(!bitstream_manager.bit_value(config_bit));
|
config_datab_values.push_back(!bitstream_manager.bit_value(config_bit));
|
||||||
}
|
}
|
||||||
print_verilog_deposit_wire_constant_values(fp, config_datab_port, config_datab_values);
|
print_verilog_force_wire_constant_values(fp, config_datab_port, config_datab_values);
|
||||||
}
|
}
|
||||||
|
|
||||||
fp << "end" << std::endl;
|
fp << "end" << std::endl;
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- End deposit bitstream to configuration memories -----"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
print_verilog_comment(fp, std::string("----- End assign bitstream to configuration memories -----"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Impose the bitstream on the configuration memories
|
||||||
|
* This function uses '$deposit' syntax to do so
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
void print_verilog_preconfig_top_module_deposit_bitstream(std::fstream &fp,
|
||||||
|
const ModuleManager &module_manager,
|
||||||
|
const ModuleId &top_module,
|
||||||
|
const BitstreamManager &bitstream_manager,
|
||||||
|
const bool& output_datab_bits) {
|
||||||
|
/* Validate the file stream */
|
||||||
|
valid_file_stream(fp);
|
||||||
|
|
||||||
|
print_verilog_comment(fp, std::string("----- Begin deposit bitstream to configuration memories -----"));
|
||||||
|
|
||||||
|
fp << "initial begin" << std::endl;
|
||||||
|
|
||||||
|
for (const ConfigBlockId &config_block_id : bitstream_manager.blocks()) {
|
||||||
|
/* We only cares blocks with configuration bits */
|
||||||
|
if (0 == bitstream_manager.block_bits(config_block_id).size()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Build the hierarchical path of the configuration bit in modules */
|
||||||
|
std::vector<ConfigBlockId> block_hierarchy = find_bitstream_manager_block_hierarchy(bitstream_manager, config_block_id);
|
||||||
|
/* Drop the first block, which is the top module, it should be replaced by the instance name here */
|
||||||
|
/* Ensure that this is the module we want to drop! */
|
||||||
|
VTR_ASSERT(0 == module_manager.module_name(top_module).compare(bitstream_manager.block_name(block_hierarchy[0])));
|
||||||
|
block_hierarchy.erase(block_hierarchy.begin());
|
||||||
|
/* Build the full hierarchy path */
|
||||||
|
std::string bit_hierarchy_path(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME);
|
||||||
|
for (const ConfigBlockId &temp_block : block_hierarchy) {
|
||||||
|
bit_hierarchy_path += std::string(".");
|
||||||
|
bit_hierarchy_path += bitstream_manager.block_name(temp_block);
|
||||||
|
}
|
||||||
|
bit_hierarchy_path += std::string(".");
|
||||||
|
|
||||||
|
/* Find the bit index in the parent block */
|
||||||
|
BasicPort config_data_port(bit_hierarchy_path + generate_configurable_memory_data_out_name(),
|
||||||
|
bitstream_manager.block_bits(config_block_id).size());
|
||||||
|
|
||||||
|
/* Wire it to the configuration bit: access both data out and data outb ports */
|
||||||
|
std::vector<size_t> config_data_values;
|
||||||
|
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) {
|
||||||
|
config_data_values.push_back(bitstream_manager.bit_value(config_bit));
|
||||||
|
}
|
||||||
|
print_verilog_deposit_wire_constant_values(fp, config_data_port, config_data_values);
|
||||||
|
|
||||||
|
/* Skip datab ports if specified */
|
||||||
|
if (false == output_datab_bits) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicPort config_datab_port(bit_hierarchy_path + generate_configurable_memory_inverted_data_out_name(),
|
||||||
|
bitstream_manager.block_bits(config_block_id).size());
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<size_t> config_datab_values;
|
||||||
|
for (const ConfigBitId config_bit : bitstream_manager.block_bits(config_block_id)) {
|
||||||
|
config_datab_values.push_back(!bitstream_manager.bit_value(config_bit));
|
||||||
|
}
|
||||||
|
print_verilog_deposit_wire_constant_values(fp, config_datab_port, config_datab_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp << "end" << std::endl;
|
||||||
|
|
||||||
|
print_verilog_comment(fp, std::string("----- End deposit bitstream to configuration memories -----"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
* Impose the bitstream on the configuration memories
|
* Impose the bitstream on the configuration memories
|
||||||
* We branch here for different simulators:
|
* We branch here for different simulators:
|
||||||
* 1. iVerilog Icarus prefers using 'assign' syntax to force the values
|
* 1. iVerilog Icarus prefers using 'assign' syntax to force the values
|
||||||
* 2. Mentor Modelsim prefers using '$deposit' syntax to do so
|
* 2. Mentor Modelsim prefers using '$deposit' syntax to do so
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
static void print_verilog_preconfig_top_module_load_bitstream(std::fstream &fp,
|
static
|
||||||
const ModuleManager &module_manager,
|
void print_verilog_preconfig_top_module_load_bitstream(std::fstream &fp,
|
||||||
const ModuleId &top_module,
|
const ModuleManager &module_manager,
|
||||||
const CircuitLibrary& circuit_lib,
|
const ModuleId &top_module,
|
||||||
const CircuitModelId& mem_model,
|
const CircuitLibrary& circuit_lib,
|
||||||
const BitstreamManager &bitstream_manager)
|
const CircuitModelId& mem_model,
|
||||||
{
|
const BitstreamManager &bitstream_manager) {
|
||||||
|
|
||||||
/* Skip the datab port if there is only 1 output port in memory model
|
/* Skip the datab port if there is only 1 output port in memory model
|
||||||
* Currently, it assumes that the data output port is always defined while datab is optional
|
* Currently, it assumes that the data output port is always defined while datab is optional
|
||||||
* If we see only 1 port, we assume datab is not defined by default.
|
* If we see only 1 port, we assume datab is not defined by default.
|
||||||
* TODO: this switch could be smarter: it should identify if only data or datab
|
* TODO: this switch could be smarter: it should identify if only data or datab
|
||||||
* ports are defined.
|
* ports are defined.
|
||||||
*/
|
*/
|
||||||
bool output_datab_bits = true;
|
bool output_datab_bits = true;
|
||||||
if (1 == circuit_lib.model_ports_by_type(mem_model, CIRCUIT_MODEL_PORT_OUTPUT).size()) {
|
if (1 == circuit_lib.model_ports_by_type(mem_model, CIRCUIT_MODEL_PORT_OUTPUT).size()) {
|
||||||
output_datab_bits = false;
|
output_datab_bits = false;
|
||||||
}
|
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- Begin load bitstream to configuration memories -----"));
|
|
||||||
|
|
||||||
print_verilog_preprocessing_flag(fp, std::string(ICARUS_SIMULATOR_FLAG));
|
|
||||||
|
|
||||||
/* Use assign syntax for Icarus simulator */
|
|
||||||
print_verilog_preconfig_top_module_assign_bitstream(fp, module_manager, top_module,
|
|
||||||
bitstream_manager,
|
|
||||||
output_datab_bits);
|
|
||||||
|
|
||||||
fp << "`else" << std::endl;
|
|
||||||
|
|
||||||
/* Use assign syntax for Icarus simulator */
|
|
||||||
print_verilog_preconfig_top_module_deposit_bitstream(fp, module_manager, top_module,
|
|
||||||
bitstream_manager,
|
|
||||||
output_datab_bits);
|
|
||||||
|
|
||||||
print_verilog_endif(fp);
|
|
||||||
|
|
||||||
print_verilog_comment(fp, std::string("----- End load bitstream to configuration memories -----"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
print_verilog_comment(fp, std::string("----- Begin load bitstream to configuration memories -----"));
|
||||||
|
|
||||||
|
print_verilog_preprocessing_flag(fp, std::string(ICARUS_SIMULATOR_FLAG));
|
||||||
|
|
||||||
|
/* Use assign syntax for Icarus simulator */
|
||||||
|
print_verilog_preconfig_top_module_assign_bitstream(fp, module_manager, top_module,
|
||||||
|
bitstream_manager,
|
||||||
|
output_datab_bits);
|
||||||
|
|
||||||
|
fp << "`else" << std::endl;
|
||||||
|
|
||||||
|
/* Use assign syntax for Icarus simulator */
|
||||||
|
print_verilog_preconfig_top_module_deposit_bitstream(fp, module_manager, top_module,
|
||||||
|
bitstream_manager,
|
||||||
|
output_datab_bits);
|
||||||
|
|
||||||
|
print_verilog_endif(fp);
|
||||||
|
|
||||||
|
print_verilog_comment(fp, std::string("----- End load bitstream to configuration memories -----"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
* Top-level function to generate a Verilog module of
|
* Top-level function to generate a Verilog module of
|
||||||
* a pre-configured FPGA fabric.
|
* a pre-configured FPGA fabric.
|
||||||
*
|
*
|
||||||
|
@ -401,87 +416,94 @@ namespace openfpga
|
||||||
* It includes wires to force constant values to part of FPGA datapath I/Os
|
* It includes wires to force constant values to part of FPGA datapath I/Os
|
||||||
* All these are hard to implement as a module in module manager
|
* All these are hard to implement as a module in module manager
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
void print_verilog_preconfig_top_module(const ModuleManager &module_manager,
|
int print_verilog_preconfig_top_module(const ModuleManager &module_manager,
|
||||||
const BitstreamManager &bitstream_manager,
|
const BitstreamManager &bitstream_manager,
|
||||||
const ConfigProtocol &config_protocol,
|
const ConfigProtocol &config_protocol,
|
||||||
const CircuitLibrary &circuit_lib,
|
const CircuitLibrary &circuit_lib,
|
||||||
const FabricGlobalPortInfo &global_ports,
|
const FabricGlobalPortInfo &global_ports,
|
||||||
const AtomContext &atom_ctx,
|
const AtomContext &atom_ctx,
|
||||||
const PlacementContext &place_ctx,
|
const PlacementContext &place_ctx,
|
||||||
const IoLocationMap &io_location_map,
|
const PinConstraints& pin_constraints,
|
||||||
const VprNetlistAnnotation &netlist_annotation,
|
const IoLocationMap &io_location_map,
|
||||||
const std::string &circuit_name,
|
const VprNetlistAnnotation &netlist_annotation,
|
||||||
const std::string &verilog_fname,
|
const std::string &circuit_name,
|
||||||
const bool &explicit_port_mapping)
|
const std::string &verilog_fname,
|
||||||
{
|
const bool &explicit_port_mapping) {
|
||||||
std::string timer_message = std::string("Write pre-configured FPGA top-level Verilog netlist for design '") + circuit_name + std::string("'");
|
std::string timer_message = std::string("Write pre-configured FPGA top-level Verilog netlist for design '") + circuit_name + std::string("'");
|
||||||
|
|
||||||
/* Start time count */
|
int status = CMD_EXEC_SUCCESS;
|
||||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
|
||||||
|
|
||||||
/* Create the file stream */
|
/* Start time count */
|
||||||
std::fstream fp;
|
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||||
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
|
|
||||||
|
|
||||||
/* Validate the file stream */
|
/* Create the file stream */
|
||||||
check_file_stream(verilog_fname.c_str(), fp);
|
std::fstream fp;
|
||||||
|
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
|
||||||
|
|
||||||
/* Generate a brief description on the Verilog file*/
|
/* Validate the file stream */
|
||||||
std::string title = std::string("Verilog netlist for pre-configured FPGA fabric by design: ") + circuit_name;
|
check_file_stream(verilog_fname.c_str(), fp);
|
||||||
print_verilog_file_header(fp, title);
|
|
||||||
|
|
||||||
/* Print module declaration and ports */
|
/* Generate a brief description on the Verilog file*/
|
||||||
print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx, netlist_annotation);
|
std::string title = std::string("Verilog netlist for pre-configured FPGA fabric by design: ") + circuit_name;
|
||||||
|
print_verilog_file_header(fp, title);
|
||||||
|
|
||||||
/* Find the top_module */
|
/* Print module declaration and ports */
|
||||||
ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name());
|
print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx, netlist_annotation);
|
||||||
VTR_ASSERT(true == module_manager.valid_module_id(top_module));
|
|
||||||
|
|
||||||
/* Print internal wires */
|
/* Find the top_module */
|
||||||
print_verilog_preconfig_top_module_internal_wires(fp, module_manager, top_module);
|
ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name());
|
||||||
|
VTR_ASSERT(true == module_manager.valid_module_id(top_module));
|
||||||
|
|
||||||
/* Instanciate FPGA top-level module */
|
/* Print internal wires */
|
||||||
print_verilog_testbench_fpga_instance(fp, module_manager, top_module,
|
print_verilog_preconfig_top_module_internal_wires(fp, module_manager, top_module);
|
||||||
std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME),
|
|
||||||
explicit_port_mapping);
|
|
||||||
|
|
||||||
/* Find clock ports in benchmark */
|
/* Instanciate FPGA top-level module */
|
||||||
std::vector<std::string> benchmark_clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation);
|
print_verilog_testbench_fpga_instance(fp, module_manager, top_module,
|
||||||
|
std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME),
|
||||||
|
explicit_port_mapping);
|
||||||
|
|
||||||
/* Connect FPGA top module global ports to constant or benchmark global signals! */
|
/* Find clock ports in benchmark */
|
||||||
print_verilog_preconfig_top_module_connect_global_ports(fp, module_manager, top_module,
|
std::vector<std::string> benchmark_clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation);
|
||||||
global_ports,
|
|
||||||
benchmark_clock_port_names);
|
|
||||||
|
|
||||||
/* Connect I/Os to benchmark I/Os or constant driver */
|
/* Connect FPGA top module global ports to constant or benchmark global signals! */
|
||||||
print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module,
|
status = print_verilog_preconfig_top_module_connect_global_ports(fp, module_manager, top_module,
|
||||||
atom_ctx, place_ctx, io_location_map,
|
pin_constraints, global_ports,
|
||||||
netlist_annotation,
|
benchmark_clock_port_names);
|
||||||
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
|
if (CMD_EXEC_FATAL_ERROR == status) {
|
||||||
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
|
return status;
|
||||||
(size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE);
|
|
||||||
|
|
||||||
/* Assign the SRAM model applied to the FPGA fabric */
|
|
||||||
CircuitModelId sram_model = config_protocol.memory_model();
|
|
||||||
VTR_ASSERT(true == circuit_lib.valid_model_id(sram_model));
|
|
||||||
|
|
||||||
/* Assign FPGA internal SRAM/Memory ports to bitstream values */
|
|
||||||
print_verilog_preconfig_top_module_load_bitstream(fp, module_manager, top_module,
|
|
||||||
circuit_lib, sram_model,
|
|
||||||
bitstream_manager);
|
|
||||||
|
|
||||||
/* Add signal initialization */
|
|
||||||
print_verilog_testbench_signal_initialization(fp,
|
|
||||||
std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME),
|
|
||||||
circuit_lib,
|
|
||||||
module_manager,
|
|
||||||
top_module);
|
|
||||||
|
|
||||||
/* Testbench ends*/
|
|
||||||
print_verilog_module_end(fp, std::string(circuit_name) + std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX));
|
|
||||||
|
|
||||||
/* Close the file stream */
|
|
||||||
fp.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Connect I/Os to benchmark I/Os or constant driver */
|
||||||
|
print_verilog_testbench_connect_fpga_ios(fp, module_manager, top_module,
|
||||||
|
atom_ctx, place_ctx, io_location_map,
|
||||||
|
netlist_annotation,
|
||||||
|
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
|
||||||
|
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
|
||||||
|
(size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE);
|
||||||
|
|
||||||
|
/* Assign the SRAM model applied to the FPGA fabric */
|
||||||
|
CircuitModelId sram_model = config_protocol.memory_model();
|
||||||
|
VTR_ASSERT(true == circuit_lib.valid_model_id(sram_model));
|
||||||
|
|
||||||
|
/* Assign FPGA internal SRAM/Memory ports to bitstream values */
|
||||||
|
print_verilog_preconfig_top_module_load_bitstream(fp, module_manager, top_module,
|
||||||
|
circuit_lib, sram_model,
|
||||||
|
bitstream_manager);
|
||||||
|
|
||||||
|
/* Add signal initialization */
|
||||||
|
print_verilog_testbench_signal_initialization(fp,
|
||||||
|
std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME),
|
||||||
|
circuit_lib,
|
||||||
|
module_manager,
|
||||||
|
top_module);
|
||||||
|
|
||||||
|
/* Testbench ends*/
|
||||||
|
print_verilog_module_end(fp, std::string(circuit_name) + std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX));
|
||||||
|
|
||||||
|
/* Close the file stream */
|
||||||
|
fp.close();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "vpr_context.h"
|
#include "vpr_context.h"
|
||||||
#include "module_manager.h"
|
#include "module_manager.h"
|
||||||
#include "bitstream_manager.h"
|
#include "bitstream_manager.h"
|
||||||
|
#include "pin_constraints.h"
|
||||||
#include "io_location_map.h"
|
#include "io_location_map.h"
|
||||||
#include "fabric_global_port_info.h"
|
#include "fabric_global_port_info.h"
|
||||||
#include "config_protocol.h"
|
#include "config_protocol.h"
|
||||||
|
@ -22,18 +23,19 @@
|
||||||
/* begin namespace openfpga */
|
/* begin namespace openfpga */
|
||||||
namespace openfpga {
|
namespace openfpga {
|
||||||
|
|
||||||
void print_verilog_preconfig_top_module(const ModuleManager& module_manager,
|
int print_verilog_preconfig_top_module(const ModuleManager& module_manager,
|
||||||
const BitstreamManager& bitstream_manager,
|
const BitstreamManager& bitstream_manager,
|
||||||
const ConfigProtocol &config_protocol,
|
const ConfigProtocol &config_protocol,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
const FabricGlobalPortInfo &global_ports,
|
const FabricGlobalPortInfo &global_ports,
|
||||||
const AtomContext& atom_ctx,
|
const AtomContext& atom_ctx,
|
||||||
const PlacementContext& place_ctx,
|
const PlacementContext& place_ctx,
|
||||||
const IoLocationMap& io_location_map,
|
const PinConstraints& pin_constraints,
|
||||||
const VprNetlistAnnotation& netlist_annotation,
|
const IoLocationMap& io_location_map,
|
||||||
const std::string& circuit_name,
|
const VprNetlistAnnotation& netlist_annotation,
|
||||||
const std::string& verilog_fname,
|
const std::string& circuit_name,
|
||||||
const bool& explicit_port_mapping);
|
const std::string& verilog_fname,
|
||||||
|
const bool& explicit_port_mapping);
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue