start supporting global output ports in module manager
This commit is contained in:
parent
32c74ad811
commit
836f722f20
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue