bug fixing for global and gpio port wiring; start refactoring top-level module

This commit is contained in:
tangxifan 2019-10-14 15:53:04 -06:00
parent 6793c67c8d
commit f779ad7ecf
6 changed files with 287 additions and 29 deletions

View File

@ -785,3 +785,21 @@ std::string generate_fpga_global_io_port_name(const std::string& prefix,
return port_name;
}
/*********************************************************************
* Generate the module name for the top-level module
* The top-level module is actually the FPGA fabric
* We give a fixed name here, because it is independent from benchmark file
********************************************************************/
std::string generate_fpga_top_module_name() {
return std::string("fpga_top");
}
/*********************************************************************
* Generate the netlist name for the top-level module
* The top-level module is actually the FPGA fabric
* We give a fixed name here, because it is independent from benchmark file
********************************************************************/
std::string generate_fpga_top_netlist_name(const std::string& postfix) {
return std::string("fpga_top" + postfix);
}

View File

@ -146,4 +146,9 @@ std::string generate_pb_type_port_name(t_port* pb_type_port);
std::string generate_fpga_global_io_port_name(const std::string& prefix,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model);
std::string generate_fpga_top_module_name();
std::string generate_fpga_top_netlist_name(const std::string& postfix);
#endif

View File

@ -866,11 +866,12 @@ size_t find_module_num_config_bits(const ModuleManager& module_manager,
}
/********************************************************************
* Add global ports to the module:
* Add GPIO ports to the module:
* In this function, the following tasks are done:
* 1. find all the GPIO ports from the child modules and build a list of it,
* 2. Merge all the GPIO ports with the same name
* 3. add the ports to the pb_module
* 4. add module nets to connect to the GPIO ports of each sub module
*
* Note: This function should be call ONLY after all the sub modules (instances)
* have been added to the pb_module!
@ -882,37 +883,84 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager,
/* Iterate over the child modules */
for (const ModuleId& child : module_manager.child_modules(module_id)) {
/* Find all the global ports, whose port type is special */
for (BasicPort gpio_port : module_manager.module_ports_by_type(child, ModuleManager::MODULE_GPIO_PORT)) {
/* If this port is not mergeable, we update the list */
bool is_mergeable = false;
for (BasicPort& gpio_port_to_add : gpio_ports_to_add) {
if (false == gpio_port_to_add.mergeable(gpio_port)) {
continue;
/* Iterate over the child instances */
for (size_t i = 0; i < module_manager.num_instance(module_id, child); ++i) {
/* Find all the global ports, whose port type is special */
for (BasicPort gpio_port : module_manager.module_ports_by_type(child, ModuleManager::MODULE_GPIO_PORT)) {
/* If this port is not mergeable, we update the list */
bool is_mergeable = false;
for (BasicPort& gpio_port_to_add : gpio_ports_to_add) {
if (false == gpio_port_to_add.mergeable(gpio_port)) {
continue;
}
is_mergeable = true;
/* For mergeable ports, we combine the port
* Note: do NOT use the merge() method!
* the GPIO ports should be accumulated by the sizes of ports
* not by the LSB/MSB range !!!
*/
gpio_port_to_add.combine(gpio_port);
break;
}
if (false == is_mergeable) {
/* Reach here, this is an unique gpio port, update the list */
gpio_ports_to_add.push_back(gpio_port);
}
is_mergeable = true;
/* For mergeable ports, we do a strong merge */
gpio_port_to_add.merge(gpio_port);
break;
}
if (false == is_mergeable) {
/* Reach here, this is an unique gpio port, update the list */
gpio_ports_to_add.push_back(gpio_port);
}
}
}
/* Record the port id for each type of GPIO port */
std::vector<ModulePortId> gpio_port_ids;
/* Add the gpio ports for the module */
for (const BasicPort& gpio_port_to_add : gpio_ports_to_add) {
module_manager.add_port(module_id, gpio_port_to_add, ModuleManager::MODULE_GPIO_PORT);
ModulePortId port_id = module_manager.add_port(module_id, gpio_port_to_add, ModuleManager::MODULE_GPIO_PORT);
gpio_port_ids.push_back(port_id);
}
/* Set up a counter for each type of GPIO port */
std::vector<size_t> gpio_port_lsb(gpio_ports_to_add.size(), 0);
/* Add module nets to connect the GPIOs of the module to the GPIOs of the sub module */
for (const ModuleId& child : module_manager.child_modules(module_id)) {
/* Iterate over the child instances */
for (const size_t& child_instance : module_manager.child_module_instances(module_id, child)) {
/* Find all the global ports, whose port type is special */
for (ModulePortId child_gpio_port_id : module_manager.module_port_ids_by_type(child, ModuleManager::MODULE_GPIO_PORT)) {
BasicPort child_gpio_port = module_manager.module_port(child, child_gpio_port_id);
/* Find the port with the same name! */
for (size_t iport = 0; iport < gpio_ports_to_add.size(); ++iport) {
if (false == gpio_ports_to_add[iport].mergeable(child_gpio_port)) {
continue;
}
/* For each pin of the child port, create a net and do wiring */
for (const size_t& pin_id : child_gpio_port.pins()) {
/* Reach here, it means this is the port we want, create a net and configure its source and sink */
ModuleNetId net = module_manager.create_module_net(module_id);
module_manager.add_module_net_source(module_id, net, module_id, 0, gpio_port_ids[iport], gpio_port_lsb[iport]);
module_manager.add_module_net_sink(module_id, net, child, child_instance, child_gpio_port_id, pin_id);
/* Update the LSB counter */
gpio_port_lsb[iport]++;
}
/* We finish for this child gpio port */
break;
}
}
}
}
/* Check: all the lsb should now match the size of each GPIO port */
for (size_t iport = 0; iport < gpio_ports_to_add.size(); ++iport) {
if (gpio_ports_to_add[iport].get_width() != gpio_port_lsb[iport])
VTR_ASSERT(gpio_ports_to_add[iport].get_width() == gpio_port_lsb[iport]);
}
}
/********************************************************************
* Add GPIO ports to the module:
* Add global ports to the module:
* In this function, the following tasks are done:
* 1. find all the global ports from the child modules and build a list of it,
* 2. add the ports to the pb_module
* 3. add the module nets to connect the pb_module global ports to those of child modules
*
* Note: This function should be call ONLY after all the sub modules (instances)
* have been added to the pb_module!
@ -924,21 +972,54 @@ void add_module_global_ports_from_child_modules(ModuleManager& module_manager,
/* Iterate over the child modules */
for (const ModuleId& child : module_manager.child_modules(module_id)) {
/* Find all the global ports, whose port type is special */
for (BasicPort global_port : module_manager.module_ports_by_type(child, ModuleManager::MODULE_GLOBAL_PORT)) {
/* Search in the global port list to be added, if this is unique, we update the list */
std::vector<BasicPort>::iterator it = std::find(global_ports_to_add.begin(), global_ports_to_add.end(), global_port);
if (it != global_ports_to_add.end()) {
continue;
/* Iterate over the child instances */
for (size_t i = 0; i < module_manager.num_instance(module_id, child); ++i) {
/* Find all the global ports, whose port type is special */
for (BasicPort global_port : module_manager.module_ports_by_type(child, ModuleManager::MODULE_GLOBAL_PORT)) {
/* Search in the global port list to be added, if this is unique, we update the list */
std::vector<BasicPort>::iterator it = std::find(global_ports_to_add.begin(), global_ports_to_add.end(), global_port);
if (it != global_ports_to_add.end()) {
continue;
}
/* Reach here, this is an unique global port, update the list */
global_ports_to_add.push_back(global_port);
}
/* Reach here, this is an unique global port, update the list */
global_ports_to_add.push_back(global_port);
}
}
/* Record the port id for each type of global port */
std::vector<ModulePortId> global_port_ids;
/* Add the global ports for the module */
for (const BasicPort& global_port_to_add : global_ports_to_add) {
module_manager.add_port(module_id, global_port_to_add, ModuleManager::MODULE_GLOBAL_PORT);
ModulePortId port_id = module_manager.add_port(module_id, global_port_to_add, ModuleManager::MODULE_GLOBAL_PORT);
global_port_ids.push_back(port_id);
}
/* Add module nets to connect the global ports of the module to the global ports of the sub module */
/* Iterate over the child modules */
for (const ModuleId& child : module_manager.child_modules(module_id)) {
/* Iterate over the child instances */
for (const size_t& child_instance : module_manager.child_module_instances(module_id, child)) {
/* Find all the global ports, whose port type is special */
for (ModulePortId child_global_port_id : module_manager.module_port_ids_by_type(child, ModuleManager::MODULE_GLOBAL_PORT)) {
BasicPort child_global_port = module_manager.module_port(child, child_global_port_id);
/* Search in the global port list to be added, find the port id */
std::vector<BasicPort>::iterator it = std::find(global_ports_to_add.begin(), global_ports_to_add.end(), child_global_port);
VTR_ASSERT(it != global_ports_to_add.end());
ModulePortId module_global_port_id = global_port_ids[it - global_ports_to_add.begin()];
BasicPort module_global_port = module_manager.module_port(module_id, module_global_port_id);
/* The global ports should match in size */
VTR_ASSERT(module_global_port.get_width() == child_global_port.get_width());
/* For each pin of the child port, create a net and do wiring */
for (size_t pin_id = 0; pin_id < child_global_port.pins().size(); ++pin_id) {
/* Reach here, it means this is the port we want, create a net and configure its source and sink */
ModuleNetId net = module_manager.create_module_net(module_id);
module_manager.add_module_net_source(module_id, net, module_id, 0, module_global_port_id, module_global_port.pins()[pin_id]);
module_manager.add_module_net_sink(module_id, net, child, child_instance, child_global_port_id, child_global_port.pins()[pin_id]);
/* We finish for this child gpio port */
}
}
}
}
}

View File

@ -45,6 +45,7 @@
#include "verilog_pbtypes.h"
#include "verilog_grid.h"
#include "verilog_routing.h"
#include "verilog_top_module.h"
#include "verilog_compact_netlist.h"
#include "verilog_top_testbench.h"
#include "verilog_autocheck_top_testbench.h"
@ -298,7 +299,7 @@ void vpr_fpga_verilog(t_vpr_setup vpr_setup,
print_verilog_grids(module_manager, Arch.spice->circuit_lib, mux_lib,
sram_verilog_orgz_info,
std::string(src_dir_path), std::string(lb_dir_path),
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
/* Generate the Verilog module of the configuration peripheral protocol
* which loads bitstream to FPGA fabric
@ -313,7 +314,13 @@ void vpr_fpga_verilog(t_vpr_setup vpr_setup,
/* TODO: This is the old function, which will be deprecated when refactoring is done */
dump_verilog_config_peripherals(sram_verilog_orgz_info, src_dir_path, submodule_dir_path);
/* Dump top-level verilog */
/* Print top-level Verilog module */
print_verilog_top_module(module_manager, Arch.spice->circuit_lib, sram_verilog_orgz_info,
std::string(vpr_setup.FileNameOpts.ArchFile),
std::string(src_dir_path),
TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
/* TODO: This is the old function, which will be deprecated when refactoring is done */
dump_compact_verilog_top_netlist(sram_verilog_orgz_info, chomped_circuit_name,
top_netlist_path, src_dir_path, submodule_dir_path, lb_dir_path, rr_dir_path,
num_rr_nodes, rr_node, rr_node_indices,

View File

@ -0,0 +1,127 @@
/********************************************************************
* This file includes functions that are used to print the top-level
* module for the FPGA fabric in Verilog format
*******************************************************************/
#include <fstream>
#include "vtr_assert.h"
#include "fpga_x2p_naming.h"
#include "fpga_x2p_utils.h"
#include "module_manager_utils.h"
#include "verilog_global.h"
#include "verilog_writer_utils.h"
#include "verilog_module_writer.h"
#include "verilog_top_module.h"
/********************************************************************
* Print the top-level module for the FPGA fabric in Verilog format
* This function will
* 1. name the top-level module
* 2. include dependent netlists
* - User defined netlists
* - Auto-generated netlists
* 3. Add the submodules to the top-level graph
* 4. Add module nets to connect datapath ports
* 5. Add module nets/submodules to connect configuration ports
*******************************************************************/
void print_verilog_top_module(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
t_sram_orgz_info* cur_sram_orgz_info,
const std::string& arch_name,
const std::string& verilog_dir,
const bool& use_explicit_mapping) {
/* Create a module as the top-level fabric, and add it to the module manager */
std::string top_module_name = generate_fpga_top_module_name();
ModuleId top_module = module_manager.add_module(top_module_name);
/* TODO: Add sub modules, which are grid, SB and CBX/CBY modules as instances */
/* TODO: Add module nets to connect the sub modules */
/* TODO: Add global ports to the top-level module */
/* TODO: Add module nets to connect the top-level ports to sub modules */
/* TODO: Add global ports to the pb_module:
* This is a much easier job after adding sub modules (instances),
* we just need to find all the global ports from the child modules and build a list of it
*/
add_module_global_ports_from_child_modules(module_manager, top_module);
/* TODO: Count GPIO ports from the sub-modules under this Verilog module
* This is a much easier job after adding sub modules (instances),
* we just need to find all the I/O ports from the child modules and build a list of it
*/
add_module_gpio_ports_from_child_modules(module_manager, top_module);
/* TODO: Count shared SRAM ports from the sub-modules under this Verilog module
* This is a much easier job after adding sub modules (instances),
* we just need to find all the I/O ports from the child modules and build a list of it
*/
size_t module_num_shared_config_bits = find_module_num_shared_config_bits_from_child_modules(module_manager, top_module);
if (0 < module_num_shared_config_bits) {
add_reserved_sram_ports_to_module_manager(module_manager, top_module, module_num_shared_config_bits);
}
/* TODO: this should be added to the cur_sram_orgz_info !!! */
t_spice_model* mem_model = NULL;
get_sram_orgz_info_mem_model(cur_sram_orgz_info, & mem_model);
CircuitModelId sram_model = circuit_lib.model(mem_model->name);
VTR_ASSERT(CircuitModelId::INVALID() != sram_model);
/* TODO: Count SRAM ports from the sub-modules under this Verilog module
* This is a much easier job after adding sub modules (instances),
* we just need to find all the I/O ports from the child modules and build a list of it
*/
size_t module_num_config_bits = find_module_num_config_bits_from_child_modules(module_manager, top_module, circuit_lib, sram_model, cur_sram_orgz_info->type);
if (0 < module_num_config_bits) {
add_sram_ports_to_module_manager(module_manager, top_module, circuit_lib, sram_model, cur_sram_orgz_info->type, module_num_config_bits);
}
/* Vectors to record all the memory modules have been added
* They are used to add module nets of configuration bus
*/
std::vector<ModuleId> memory_modules;
std::vector<size_t> memory_instances;
/* TODO: Add module nets to connect memory cells inside
* This is a one-shot addition that covers all the memory modules in this pb module!
*/
if (false == memory_modules.empty()) {
add_module_nets_memory_config_bus(module_manager, top_module,
memory_modules, memory_instances,
cur_sram_orgz_info->type, circuit_lib.design_tech_type(sram_model));
}
/* Start printing out Verilog netlists */
/* Create the file name for Verilog netlist */
std::string verilog_fname(verilog_dir + generate_fpga_top_netlist_name(std::string(verilog_netlist_file_postfix)));
/* TODO: remove the bak file when the file is ready */
verilog_fname += ".bak";
vpr_printf(TIO_MESSAGE_INFO,
"Writing Verilog Netlist for top-level module of FPGA fabric (%s)...\n",
verilog_fname.c_str());
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
check_file_handler(fp);
print_verilog_file_header(fp, std::string("Top-level Verilog module for FPGA architecture: " + std::string(arch_name)));
/* Print preprocessing flags */
print_verilog_include_defines_preproc_file(fp, verilog_dir);
/* Write the module content in Verilog format */
write_verilog_module_to_file(fp, module_manager, top_module, use_explicit_mapping);
/* Add an empty line as a splitter */
fp << std::endl;
/* Close file handler */
fp.close();
}

View File

@ -0,0 +1,20 @@
/********************************************************************
* Header file for verilog_top_module.cpp
*******************************************************************/
#ifndef VERILOG_TOP_MODULE_H
#define VERILOG_TOP_MODULE_H
#include <string>
#include "spice_types.h"
#include "circuit_library.h"
#include "module_manager.h"
void print_verilog_top_module(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
t_sram_orgz_info* cur_sram_orgz_info,
const std::string& arch_name,
const std::string& verilog_dir,
const bool& use_explicit_mapping);
#endif