bug fixing for global and gpio port wiring; start refactoring top-level module
This commit is contained in:
parent
6793c67c8d
commit
f779ad7ecf
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue