start supporting global output ports in module manager

This commit is contained in:
tangxifan 2020-04-05 15:19:46 -06:00
parent 32c74ad811
commit 836f722f20
5 changed files with 170 additions and 8 deletions

View File

@ -120,7 +120,7 @@ std::string ModuleManager::module_name(const ModuleId& module_id) const {
/* Get the string of a module port type */
std::string ModuleManager::module_port_type_str(const enum e_module_port_type& port_type) const {
std::array<const char*, NUM_MODULE_PORT_TYPES> MODULE_PORT_TYPE_STRING = {{"GLOBAL PORTS", "GPIO PORTS", "INOUT PORTS", "INPUT PORTS", "OUTPUT PORTS", "CLOCK PORTS"}};
std::array<const char*, NUM_MODULE_PORT_TYPES> MODULE_PORT_TYPE_STRING = {{"GLOBAL PORTS", "SPY PORTS", "GPIO PORTS", "INOUT PORTS", "INPUT PORTS", "OUTPUT PORTS", "CLOCK PORTS"}};
return MODULE_PORT_TYPE_STRING[port_type];
}

View File

@ -28,6 +28,7 @@ class ModuleManager {
public: /* Private data structures */
enum e_module_port_type {
MODULE_GLOBAL_PORT, /* Global inputs */
MODULE_SPY_PORT, /* Global outputs, which is designed for spypads */
MODULE_GPIO_PORT, /* General-purpose IOs, which are data IOs of the fabric */
MODULE_INOUT_PORT, /* Normal (non-global) inout ports */
MODULE_INPUT_PORT, /* Normal (non-global) input ports */

View File

@ -129,6 +129,7 @@ void print_verilog_module_definition(std::fstream& fp,
/* port type2type mapping */
std::map<ModuleManager::e_module_port_type, enum e_dump_verilog_port_type> port_type2type_map;
port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_SPY_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_GPIO_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_INOUT_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_INPUT_PORT] = VERILOG_PORT_CONKT;
@ -188,6 +189,7 @@ void print_verilog_module_ports(std::fstream& fp,
/* port type2type mapping */
std::map<ModuleManager::e_module_port_type, enum e_dump_verilog_port_type> port_type2type_map;
port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_INPUT;
port_type2type_map[ModuleManager::MODULE_SPY_PORT] = VERILOG_PORT_OUTPUT;
port_type2type_map[ModuleManager::MODULE_GPIO_PORT] = VERILOG_PORT_INOUT;
port_type2type_map[ModuleManager::MODULE_INOUT_PORT] = VERILOG_PORT_INOUT;
port_type2type_map[ModuleManager::MODULE_INPUT_PORT] = VERILOG_PORT_INPUT;
@ -344,6 +346,7 @@ void print_verilog_module_instance(std::fstream& fp,
/* port type2type mapping */
std::map<ModuleManager::e_module_port_type, enum e_dump_verilog_port_type> port_type2type_map;
port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_SPY_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_GPIO_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_INOUT_PORT] = VERILOG_PORT_CONKT;
port_type2type_map[ModuleManager::MODULE_INPUT_PORT] = VERILOG_PORT_CONKT;

View File

@ -36,10 +36,20 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
VTR_ASSERT(ModuleId::INVALID() != module);
/* Add ports */
/* Find global ports and add one by one */
/* Find global ports and add one by one
* Global input ports will be considered as global port in the context of module manager
* Global output ports will be considered as spy port in the context of module manager
*/
for (const auto& port : circuit_lib.model_global_ports(circuit_model, false)) {
BasicPort port_info(circuit_lib.port_prefix(port), circuit_lib.port_size(port));
if (CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port)) {
module_manager.add_port(module, port_info, ModuleManager::MODULE_GLOBAL_PORT);
} else if (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(port)) {
module_manager.add_port(module, port_info, ModuleManager::MODULE_GLOBAL_PORT);
} else {
VTR_ASSERT(CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port));
module_manager.add_port(module, port_info, ModuleManager::MODULE_SPY_PORT);
}
}
/* Find other ports and add one by one */
@ -1011,17 +1021,29 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager,
}
/********************************************************************
* Add global ports to the module:
* Add global input 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
* 1. find all the global input ports from the child modules and build a list of it,
* 2. add the input ports to the pb_module
* 3. add the module nets to connect the pb_module global ports to those of child modules
*
* Module
* +--------------------------
* | child[0]
* input_portA[0] ----+-+---->+----------
* | | |
* | | +----------
* | |
* | | child[1]
* | +---->+----------
* | |
* | +----------
*
* Note: This function should be call ONLY after all the sub modules (instances)
* have been added to the pb_module!
* Otherwise, some global ports of the sub modules may be missed!
*******************************************************************/
void add_module_global_ports_from_child_modules(ModuleManager& module_manager,
void add_module_global_input_ports_from_child_modules(ModuleManager& module_manager,
const ModuleId& module_id) {
std::vector<BasicPort> global_ports_to_add;
@ -1078,6 +1100,136 @@ void add_module_global_ports_from_child_modules(ModuleManager& module_manager,
}
}
/********************************************************************
* Add global output ports to the module:
* In this function, the following tasks are done:
* 1. find all the global output ports from the child modules and build a list of it,
* 2. add the output ports to the pb_module
* 3. add the module nets to connect the pb_module global ports to those of child modules
*
* Module
* ----------------------+
* |
* child[0] |
* -----------+ |
* |----------+----> outputA[0]
* -----------+ |
* |
* child[1] |
* -----------+ |
* |----------+----> outputA[1]
* -----------+ |
*
* Note: This function should be call ONLY after all the sub modules (instances)
* have been added to the pb_module!
* Otherwise, some global ports of the sub modules may be missed!
*******************************************************************/
void add_module_global_output_ports_from_child_modules(ModuleManager& module_manager,
const ModuleId& module_id) {
std::vector<BasicPort> global_ports_to_add;
/* Iterate over the child modules */
for (const ModuleId& child : module_manager.child_modules(module_id)) {
/* 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_SPY_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()) {
/* Found in the global port with the same name, increase the port size */
it->expand(global_port.get_width());
continue; /* Finish for the port already in the list */
}
/* 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) {
ModulePortId port_id = module_manager.add_port(module_id, global_port_to_add, ModuleManager::MODULE_SPY_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 */
/* Create a counter for each global port to record the current LSB */
std::vector<size_t> global_port_lsbs(global_port_ids.size(), 0);
/* 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_SPY_PORT)) {
/* Find the global port from the child module */
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());
/* Find the global port from the parent module */
size_t module_global_port_offset = it - global_ports_to_add.begin();
ModulePortId module_global_port_id = global_port_ids[module_global_port_offset];
BasicPort module_global_port = module_manager.module_port(module_id, module_global_port_id);
/* Current LSB should be in range */
VTR_ASSERT(module_global_port.get_width() > global_port_lsbs[module_global_port_offset]);
/* Set the global port from the parent module as the LSB recorded */
module_global_port.set_width(global_port_lsbs[module_global_port_offset], global_port_lsbs[module_global_port_offset]);
/* Update the LSB */
global_port_lsbs[module_global_port_offset]++;
/* 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, child, child_instance, child_global_port_id, child_global_port.pins()[pin_id]);
module_manager.add_module_net_sink(module_id, net, module_id, 0, module_global_port_id, module_global_port.pins()[pin_id]);
/* We finish for this child gpio port */
}
}
}
}
/* Find check: all the LSBs of global ports should match the MSB */
for (size_t iport = 0; iport < global_port_ids.size(); ++iport) {
BasicPort module_global_port = module_manager.module_port(module_id, global_port_ids[iport]);
VTR_ASSERT(module_global_port.get_width() == global_port_lsbs[iport]);
}
}
/********************************************************************
* Add global ports to the module:
* In this function, we will add global input ports and global output ports
* which are collected from the child modules
*
* - Input ports: the input ports will be uniquified by names
* Ports with the same name will be merged to the same pin
* See details inside the function
*
* - Output ports: the output ports will be uniquified by names
* Different from the input ports, output ports
* with the same name will be merged but will have indepedent pins
* See details inside the function
*
* Note: This function should be call ONLY after all the sub modules (instances)
* have been added to the pb_module!
* Otherwise, some global ports of the sub modules may be missed!
*******************************************************************/
void add_module_global_ports_from_child_modules(ModuleManager& module_manager,
const ModuleId& module_id) {
/* Input ports */
add_module_global_input_ports_from_child_modules(module_manager, module_id);
/* Output ports */
add_module_global_output_ports_from_child_modules(module_manager, module_id);
}
/********************************************************************
* Find the number of shared configuration bits for a module
* by selected the maximum number of shared configuration bits of child modules

View File

@ -108,6 +108,12 @@ size_t find_module_num_config_bits(const ModuleManager& module_manager,
const CircuitModelId& sram_model,
const e_config_protocol_type& sram_orgz_type);
void add_module_global_input_ports_from_child_modules(ModuleManager& module_manager,
const ModuleId& module_id);
void add_module_global_output_ports_from_child_modules(ModuleManager& module_manager,
const ModuleId& module_id);
void add_module_global_ports_from_child_modules(ModuleManager& module_manager,
const ModuleId& module_id);