diff --git a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp index a4b24e769..d1c79f4fb 100644 --- a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp @@ -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 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(), + prefix_to_remove, std::string(FPGA_PORT_POSTFIX), atom_ctx, netlist_annotation, pin_constraints, diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index ea0f2ad01..c382acf8c 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -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 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 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 */ diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp index b47d06d1d..40a863c6e 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp @@ -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_), + .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 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& 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 default_values(module_unused_io_port.get_width(), unused_io_value); diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.h b/openfpga/src/fpga_verilog/verilog_testbench_utils.h index d06f267c9..84b3750bb 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.h +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.h @@ -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& output_port_prefix_to_remove, const size_t& unused_io_value); void print_verilog_timeout_and_vcd(std::fstream& fp, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index e81d413c0..0ec778222 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -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(), (size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE); /* Instanciate input benchmark */