Merge pull request #526 from lnis-uofu/tb

Now preconfigured top-level module has the same port name as reference benchmarks
This commit is contained in:
tangxifan 2022-02-13 23:01:27 -08:00 committed by GitHub
commit c58cadafce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 74 additions and 10 deletions

View File

@ -150,12 +150,18 @@ void print_verilog_random_testbench_fpga_instance(std::fstream& fp,
print_verilog_comment(fp, std::string("----- FPGA fabric instanciation -------"));
/* VPR added a prefix of "out_" to the output ports of input benchmark */
std::vector<std::string> prefix_to_remove;
prefix_to_remove.push_back(std::string(VPR_BENCHMARK_OUT_PORT_PREFIX));
prefix_to_remove.push_back(std::string(OPENFPGA_BENCHMARK_OUT_PORT_PREFIX));
/* Always use explicit port mapping */
print_verilog_testbench_benchmark_instance(fp, std::string(circuit_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_POSTFIX)),
std::string(FPGA_INSTANCE_NAME),
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
std::vector<std::string>(),
std::string(),
std::string(),
prefix_to_remove,
std::string(FPGA_PORT_POSTFIX),
atom_ctx, netlist_annotation,
pin_constraints,

View File

@ -14,6 +14,7 @@
/* Headers from openfpgautil library */
#include "openfpga_port.h"
#include "openfpga_digest.h"
#include "openfpga_reserved_words.h"
#include "bitstream_manager_utils.h"
#include "openfpga_atom_netlist_utils.h"
@ -66,12 +67,26 @@ void print_verilog_preconfig_top_module_ports(std::fstream &fp,
if (true == netlist_annotation.is_block_renamed(atom_blk)) {
block_name = netlist_annotation.block_name(atom_blk);
}
/* For output block, remove the prefix which is added by VPR */
std::vector<std::string> output_port_prefix_to_remove;
output_port_prefix_to_remove.push_back(std::string(VPR_BENCHMARK_OUT_PORT_PREFIX));
output_port_prefix_to_remove.push_back(std::string(OPENFPGA_BENCHMARK_OUT_PORT_PREFIX));
if (AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)) {
for (const std::string& prefix_to_remove : output_port_prefix_to_remove) {
if (!prefix_to_remove.empty()) {
if (0 == block_name.find(prefix_to_remove)) {
block_name.erase(0, prefix_to_remove.length());
break;
}
}
}
}
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);
BasicPort module_port(std::string(block_name), 1);
fp << generate_verilog_port(port_type2type_map[atom_ctx.nlist.block_type(atom_blk)], module_port);
/* Update port counter */
@ -100,6 +115,8 @@ void print_verilog_preconfig_top_module_internal_wires(std::fstream &fp,
print_verilog_comment(fp, std::string("----- Local wires for FPGA fabric -----"));
for (const ModulePortId &module_port_id : module_manager.module_ports(top_module)) {
BasicPort module_port = module_manager.module_port(top_module, module_port_id);
/* Add a postfix to the internal wires to be different from other reserved ports */
module_port.set_name(module_port.get_name() + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX));
fp << generate_verilog_port(VERILOG_PORT_WIRE, module_port) << ";" << std::endl;
}
/* Add an empty line as a splitter */
@ -132,10 +149,10 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp,
&& (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]);
BasicPort module_clock_pin(module_global_port.get_name() + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), 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(module_clock_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))
@ -159,7 +176,7 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp,
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);
BasicPort benchmark_clock_pin(clock_name_to_connect, 1);
print_verilog_wire_connection(fp, module_clock_pin, benchmark_clock_pin, false);
}
/* Finish, go to the next */
@ -168,7 +185,7 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp,
/* 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(),
BasicPort module_global_pin(module_global_port.get_name() + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
module_global_port.pins()[pin_id],
module_global_port.pins()[pin_id]);
@ -180,7 +197,7 @@ int print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp,
*/
if ( (false == pin_constraints.unconstrained_net(constrained_net_name))
&& (false == pin_constraints.unmapped_net(constrained_net_name))) {
BasicPort benchmark_pin(constrained_net_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), 1);
BasicPort benchmark_pin(constrained_net_name, 1);
print_verilog_wire_connection(fp, module_global_pin, benchmark_pin, false);
} else {
VTR_ASSERT_SAFE(std::string(PIN_CONSTRAINT_OPEN_NET) == constrained_net_name);
@ -454,6 +471,7 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager,
/* Instanciate FPGA top-level module */
print_verilog_testbench_fpga_instance(fp, module_manager, top_module,
std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME),
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
options.explicit_port_mapping());
/* Find clock ports in benchmark */
@ -468,11 +486,16 @@ int print_verilog_preconfig_top_module(const ModuleManager &module_manager,
}
/* Connect I/Os to benchmark I/Os or constant driver */
std::vector<std::string> prefix_to_remove;
prefix_to_remove.push_back(std::string(VPR_BENCHMARK_OUT_PORT_PREFIX));
prefix_to_remove.push_back(std::string(OPENFPGA_BENCHMARK_OUT_PORT_PREFIX));
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),
std::string(),
std::string(),
prefix_to_remove,
(size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE);
/* Assign the SRAM model applied to the FPGA fabric */

View File

@ -32,11 +32,16 @@ namespace openfpga {
/********************************************************************
* Print an instance of the FPGA top-level module
* When net_postfix is not empty, the instance net will contain a postfix like
* fpga fpga_core(.in(in_<postfix>),
.out(out_postfix>)
);
*******************************************************************/
void print_verilog_testbench_fpga_instance(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const std::string& top_instance_name,
const std::string& net_postfix,
const bool& explicit_port_mapping) {
/* Validate the file stream */
valid_file_stream(fp);
@ -46,6 +51,14 @@ void print_verilog_testbench_fpga_instance(std::fstream& fp,
/* Create an empty port-to-port name mapping, because we use default names */
std::map<std::string, BasicPort> port2port_name_map;
if (!net_postfix.empty()) {
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 net_port = module_port;
net_port.set_name(module_port.get_name() + net_postfix);
port2port_name_map[module_port.get_name()] = net_port;
}
}
/* Use explicit port mapping for a clean instanciation */
print_verilog_module_instance(fp, module_manager, top_module,
@ -157,8 +170,10 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
const PlacementContext& place_ctx,
const IoLocationMap& io_location_map,
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>& output_port_prefix_to_remove,
const size_t& unused_io_value) {
/* Validate the file stream */
valid_file_stream(fp);
@ -242,6 +257,7 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
/* 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 */
@ -249,6 +265,18 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
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
*/
for (const std::string& prefix_to_remove : output_port_prefix_to_remove) {
if (!prefix_to_remove.empty()) {
if (0 == block_name.find(prefix_to_remove)) {
block_name.erase(0, prefix_to_remove.length());
break;
}
}
}
/* 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
@ -292,6 +320,7 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
/* 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);

View File

@ -27,6 +27,7 @@ void print_verilog_testbench_fpga_instance(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const std::string& top_instance_name,
const std::string& net_postfix,
const bool& explicit_port_mapping);
void print_verilog_testbench_benchmark_instance(std::fstream& fp,
@ -48,8 +49,10 @@ void print_verilog_testbench_connect_fpga_ios(std::fstream& fp,
const PlacementContext& place_ctx,
const IoLocationMap& io_location_map,
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>& output_port_prefix_to_remove,
const size_t& unused_io_value);
void print_verilog_timeout_and_vcd(std::fstream& fp,

View File

@ -2042,6 +2042,7 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
/* Instanciate FPGA top-level module */
print_verilog_testbench_fpga_instance(fp, module_manager, top_module,
std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME),
std::string(),
explicit_port_mapping);
/* Connect I/Os to benchmark I/Os or constant driver */
@ -2049,7 +2050,9 @@ int print_verilog_full_testbench(const ModuleManager& module_manager,
atom_ctx, place_ctx, io_location_map,
netlist_annotation,
std::string(),
std::string(),
std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX),
std::vector<std::string>(),
(size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE);
/* Instanciate input benchmark */