[Engine] Upgraded fabric generator to support flatten BL/WL bus for memory banks
This commit is contained in:
parent
be4c850d2d
commit
74ffc8578f
|
@ -315,7 +315,7 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus(ModuleManager
|
||||||
*
|
*
|
||||||
* @note this function only adds the WL configuration bus for decoders
|
* @note this function only adds the WL configuration bus for decoders
|
||||||
*
|
*
|
||||||
* @note see detailed explanation on the bus connection in function add_top_module_nets_cmos_ql_memory_bank_config_bus()
|
* @note see detailed explanation on the bus connection in function add_top_module_nets_cmos_ql_memory_bank_bl_decoder_config_bus()
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
static
|
static
|
||||||
void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager& module_manager,
|
void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager& module_manager,
|
||||||
|
@ -433,14 +433,17 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager
|
||||||
BasicPort wl_decoder_dout_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_dout_port);
|
BasicPort wl_decoder_dout_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_dout_port);
|
||||||
|
|
||||||
/* Note we skip the last child which is the bl decoder added */
|
/* Note we skip the last child which is the bl decoder added */
|
||||||
for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size() - 1; ++child_id) {
|
for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) {
|
||||||
ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id];
|
ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id];
|
||||||
vtr::Point<int> coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id];
|
vtr::Point<int> coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id];
|
||||||
|
|
||||||
size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id];
|
size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id];
|
||||||
|
|
||||||
/* Find the WL port */
|
/* Find the WL port. If the child does not have WL port, bypass it. It is usually a decoder module */
|
||||||
ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME));
|
ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME));
|
||||||
|
if (!child_wl_port) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port);
|
BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port);
|
||||||
|
|
||||||
size_t cur_wl_index = 0;
|
size_t cur_wl_index = 0;
|
||||||
|
@ -477,8 +480,11 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager
|
||||||
|
|
||||||
size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id];
|
size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id];
|
||||||
|
|
||||||
/* Find the WL port */
|
/* Find the WLR port. If the child does not have WLR port, bypass it. It is usually a decoder module */
|
||||||
ModulePortId child_wlr_port = module_manager.find_module_port(child_module, std::string(MEMORY_WLR_PORT_NAME));
|
ModulePortId child_wlr_port = module_manager.find_module_port(child_module, std::string(MEMORY_WLR_PORT_NAME));
|
||||||
|
if (!child_wlr_port) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
BasicPort child_wlr_port_info = module_manager.module_port(child_module, child_wlr_port);
|
BasicPort child_wlr_port_info = module_manager.module_port(child_module, child_wlr_port);
|
||||||
|
|
||||||
size_t cur_wlr_index = 0;
|
size_t cur_wlr_index = 0;
|
||||||
|
@ -516,6 +522,229 @@ void add_top_module_nets_cmos_ql_memory_bank_wl_decoder_config_bus(ModuleManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* This function to add nets for quicklogic memory banks using flatten BLs and WLs
|
||||||
|
* Each configuration region has independent BL/WLs
|
||||||
|
* - Find the number of BLs and WLs required for each region
|
||||||
|
* - Create nets to connect from top-level module inputs to BL/WL of configurable children
|
||||||
|
*
|
||||||
|
* @note this function only adds the BL configuration bus
|
||||||
|
*
|
||||||
|
* Detailed schematic of each memory bank:
|
||||||
|
* @note The numbers are just made to show a simplified example, practical cases are more complicated!
|
||||||
|
*
|
||||||
|
* BL[0:9] BL[10:17] BL[18:22]
|
||||||
|
* | | |
|
||||||
|
* | | |
|
||||||
|
* WL[0:3]-->-----------+---------------+---- ... |------+-->
|
||||||
|
* | | | | | |
|
||||||
|
* | v | v | v
|
||||||
|
* | +-------+ | +-------+ | +------+
|
||||||
|
* +-->| SRAM | +-->| SRAM | +->| SRAM |
|
||||||
|
* | | [0:8] | | | [0:5] | ... | | [0:7]|
|
||||||
|
* | +-------+ | +-------+ | +------+
|
||||||
|
* | | |
|
||||||
|
* WL[4:14] -----------+--------------+--------- | -----+-->
|
||||||
|
* | | | | | |
|
||||||
|
* | v | v | v
|
||||||
|
* | +-------+ | +-------+ | +-------+
|
||||||
|
* +-->| SRAM | | | SRAM | +->| SRAM |
|
||||||
|
* | | [0:80]| | | [0:63]| ... | | [0:31]|
|
||||||
|
* | +-------+ | +-------+ | +-------+
|
||||||
|
* | |
|
||||||
|
* | ... ... ... | ...
|
||||||
|
* | | |
|
||||||
|
* WL[15:18] -----------+---------------+---- --- | -----+-->
|
||||||
|
* | | | | | |
|
||||||
|
* | v | v | v
|
||||||
|
* | +-------+ | +-------+ | +-------+
|
||||||
|
* +-->| SRAM | +-->| SRAM | +->| SRAM |
|
||||||
|
* | |[0:5] | | | [0:8] | ... | | [0:2] |
|
||||||
|
* | +-------+ | +-------+ | +-------+
|
||||||
|
* v v v
|
||||||
|
* WL[0:9] WL[0:7] WL[0:4]
|
||||||
|
*
|
||||||
|
**********************************************************************/
|
||||||
|
static
|
||||||
|
void add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(ModuleManager& module_manager,
|
||||||
|
const ModuleId& top_module,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const CircuitModelId& sram_model) {
|
||||||
|
/* Create connections between BLs of top-level module and BLs of child modules for each region */
|
||||||
|
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
|
||||||
|
/**************************************************************
|
||||||
|
* Precompute the BLs and WLs distribution across the FPGA fabric
|
||||||
|
* The distribution is a matrix which contains the starting index of BL/WL for each column or row
|
||||||
|
*/
|
||||||
|
std::pair<int, int> child_x_range = compute_memory_bank_regional_configurable_child_x_range(module_manager, top_module, config_region);
|
||||||
|
std::map<int, size_t> num_bls_per_tile = compute_memory_bank_regional_bitline_numbers_per_tile(module_manager, top_module,
|
||||||
|
config_region,
|
||||||
|
circuit_lib, sram_model);
|
||||||
|
std::map<int, size_t> bl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_x_range, num_bls_per_tile);
|
||||||
|
|
||||||
|
/**************************************************************
|
||||||
|
* Add BL nets from top module to each configurable child
|
||||||
|
* BL pins of top module are connected to the BL input pins of each PB/CB/SB
|
||||||
|
* For all the PB/CB/SB in the same column, they share the same set of BLs
|
||||||
|
* A quick example
|
||||||
|
*
|
||||||
|
* BL[i .. i + sqrt(N)]
|
||||||
|
* |
|
||||||
|
* | CLB[1][H]
|
||||||
|
* | +---------+
|
||||||
|
* | | SRAM |
|
||||||
|
* +-->| [0..N] |
|
||||||
|
* | +---------+
|
||||||
|
* |
|
||||||
|
* ...
|
||||||
|
* | CLB[1][1]
|
||||||
|
* | +---------+
|
||||||
|
* | | SRAM |
|
||||||
|
* +-->| [0..N] |
|
||||||
|
* | +---------+
|
||||||
|
* |
|
||||||
|
*/
|
||||||
|
ModulePortId top_module_bl_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_BL_PORT_NAME), config_region));
|
||||||
|
BasicPort top_module_bl_port_info = module_manager.module_port(top_module, top_module_bl_port);
|
||||||
|
|
||||||
|
for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) {
|
||||||
|
ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id];
|
||||||
|
vtr::Point<int> coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id];
|
||||||
|
|
||||||
|
size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id];
|
||||||
|
|
||||||
|
/* Find the BL port */
|
||||||
|
ModulePortId child_bl_port = module_manager.find_module_port(child_module, std::string(MEMORY_BL_PORT_NAME));
|
||||||
|
BasicPort child_bl_port_info = module_manager.module_port(child_module, child_bl_port);
|
||||||
|
|
||||||
|
size_t cur_bl_index = 0;
|
||||||
|
|
||||||
|
for (const size_t& sink_bl_pin : child_bl_port_info.pins()) {
|
||||||
|
size_t bl_pin_id = bl_start_index_per_tile[coord.x()] + cur_bl_index;
|
||||||
|
VTR_ASSERT(bl_pin_id < top_module_bl_port_info.pins().size());
|
||||||
|
|
||||||
|
/* Create net */
|
||||||
|
ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
|
||||||
|
top_module, 0,
|
||||||
|
top_module_bl_port,
|
||||||
|
top_module_bl_port_info.pins()[bl_pin_id]);
|
||||||
|
VTR_ASSERT(ModuleNetId::INVALID() != net);
|
||||||
|
|
||||||
|
/* Add net sink */
|
||||||
|
module_manager.add_module_net_sink(top_module, net,
|
||||||
|
child_module, child_instance, child_bl_port, sink_bl_pin);
|
||||||
|
|
||||||
|
cur_bl_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Top-level function to add nets for quicklogic memory banks using flatten BL/WLs
|
||||||
|
* Each configuration region has independent BL/WLs
|
||||||
|
* - Find the number of BLs and WLs required for each region
|
||||||
|
* - Create nets to connect from top-level module inputs to BL/WL of configurable children
|
||||||
|
*
|
||||||
|
* @note this function only adds the WL configuration bus
|
||||||
|
*
|
||||||
|
* @note see detailed explanation on the bus connection in function add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus()
|
||||||
|
**********************************************************************/
|
||||||
|
static
|
||||||
|
void add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(ModuleManager& module_manager,
|
||||||
|
const ModuleId& top_module,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const CircuitModelId& sram_model) {
|
||||||
|
/* Create connections between WLs of top-level module and WLs of child modules for each region */
|
||||||
|
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
|
||||||
|
/**************************************************************
|
||||||
|
* Precompute the BLs and WLs distribution across the FPGA fabric
|
||||||
|
* The distribution is a matrix which contains the starting index of BL/WL for each column or row
|
||||||
|
*/
|
||||||
|
std::pair<int, int> child_y_range = compute_memory_bank_regional_configurable_child_y_range(module_manager, top_module, config_region);
|
||||||
|
std::map<int, size_t> num_wls_per_tile = compute_memory_bank_regional_wordline_numbers_per_tile(module_manager, top_module,
|
||||||
|
config_region,
|
||||||
|
circuit_lib, sram_model);
|
||||||
|
std::map<int, size_t> wl_start_index_per_tile = compute_memory_bank_regional_blwl_start_index_per_tile(child_y_range, num_wls_per_tile);
|
||||||
|
|
||||||
|
/**************************************************************
|
||||||
|
* Add WL nets from top module to each configurable child
|
||||||
|
*/
|
||||||
|
ModulePortId top_module_wl_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region));
|
||||||
|
BasicPort top_module_wl_port_info = module_manager.module_port(top_module, top_module_wl_port);
|
||||||
|
|
||||||
|
for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) {
|
||||||
|
ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id];
|
||||||
|
vtr::Point<int> coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id];
|
||||||
|
|
||||||
|
size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id];
|
||||||
|
|
||||||
|
/* Find the WL port */
|
||||||
|
ModulePortId child_wl_port = module_manager.find_module_port(child_module, std::string(MEMORY_WL_PORT_NAME));
|
||||||
|
BasicPort child_wl_port_info = module_manager.module_port(child_module, child_wl_port);
|
||||||
|
|
||||||
|
size_t cur_wl_index = 0;
|
||||||
|
|
||||||
|
for (const size_t& sink_wl_pin : child_wl_port_info.pins()) {
|
||||||
|
size_t wl_pin_id = wl_start_index_per_tile[coord.y()] + cur_wl_index;
|
||||||
|
VTR_ASSERT(wl_pin_id < top_module_wl_port_info.pins().size());
|
||||||
|
|
||||||
|
/* Create net */
|
||||||
|
ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
|
||||||
|
top_module, 0,
|
||||||
|
top_module_wl_port,
|
||||||
|
top_module_wl_port_info.pins()[wl_pin_id]);
|
||||||
|
VTR_ASSERT(ModuleNetId::INVALID() != net);
|
||||||
|
|
||||||
|
/* Add net sink */
|
||||||
|
module_manager.add_module_net_sink(top_module, net,
|
||||||
|
child_module, child_instance, child_wl_port, sink_wl_pin);
|
||||||
|
|
||||||
|
cur_wl_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************
|
||||||
|
* Optional: Add WLR nets from top module to each configurable child
|
||||||
|
*/
|
||||||
|
ModulePortId top_module_wlr_port = module_manager.find_module_port(top_module, generate_regional_blwl_port_name(std::string(MEMORY_WLR_PORT_NAME), config_region));
|
||||||
|
BasicPort top_module_wlr_port_info;
|
||||||
|
if (top_module_wlr_port) {
|
||||||
|
top_module_wlr_port_info = module_manager.module_port(top_module, top_module_wlr_port);
|
||||||
|
for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) {
|
||||||
|
ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id];
|
||||||
|
vtr::Point<int> coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id];
|
||||||
|
|
||||||
|
size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id];
|
||||||
|
|
||||||
|
/* Find the WL port */
|
||||||
|
ModulePortId child_wlr_port = module_manager.find_module_port(child_module, std::string(MEMORY_WLR_PORT_NAME));
|
||||||
|
BasicPort child_wlr_port_info = module_manager.module_port(child_module, child_wlr_port);
|
||||||
|
|
||||||
|
size_t cur_wlr_index = 0;
|
||||||
|
|
||||||
|
for (const size_t& sink_wlr_pin : child_wlr_port_info.pins()) {
|
||||||
|
size_t wlr_pin_id = wl_start_index_per_tile[coord.y()] + cur_wlr_index;
|
||||||
|
VTR_ASSERT(wlr_pin_id < top_module_wlr_port_info.pins().size());
|
||||||
|
|
||||||
|
/* Create net */
|
||||||
|
ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
|
||||||
|
top_module, 0,
|
||||||
|
top_module_wlr_port,
|
||||||
|
top_module_wlr_port_info.pins()[wlr_pin_id]);
|
||||||
|
VTR_ASSERT(ModuleNetId::INVALID() != net);
|
||||||
|
|
||||||
|
/* Add net sink */
|
||||||
|
module_manager.add_module_net_sink(top_module, net,
|
||||||
|
child_module, child_instance, child_wlr_port, sink_wlr_pin);
|
||||||
|
|
||||||
|
cur_wlr_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* Top-level function to add nets for quicklogic memory banks
|
* Top-level function to add nets for quicklogic memory banks
|
||||||
* - Each configuration region has independent memory bank circuitry
|
* - Each configuration region has independent memory bank circuitry
|
||||||
|
@ -545,7 +774,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BLWL_PROTOCOL_FLATTEN: {
|
case BLWL_PROTOCOL_FLATTEN: {
|
||||||
//add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(module_manager, decoder_lib, top_module, circuit_lib, num_config_bits);
|
add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(module_manager, top_module, circuit_lib, sram_model);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BLWL_PROTOCOL_SHIFT_REGISTER: {
|
case BLWL_PROTOCOL_SHIFT_REGISTER: {
|
||||||
|
@ -564,7 +793,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BLWL_PROTOCOL_FLATTEN: {
|
case BLWL_PROTOCOL_FLATTEN: {
|
||||||
//add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(module_manager, decoder_lib, top_module, circuit_lib, num_config_bits);
|
add_top_module_nets_cmos_ql_memory_bank_wl_flatten_config_bus(module_manager, top_module, circuit_lib, sram_model);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BLWL_PROTOCOL_SHIFT_REGISTER: {
|
case BLWL_PROTOCOL_SHIFT_REGISTER: {
|
||||||
|
@ -675,6 +904,12 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager,
|
||||||
size_t wl_size = num_config_bits[config_region].first;
|
size_t wl_size = num_config_bits[config_region].first;
|
||||||
BasicPort wl_port(generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region), wl_size);
|
BasicPort wl_port(generate_regional_blwl_port_name(std::string(MEMORY_WL_PORT_NAME), config_region), wl_size);
|
||||||
module_manager.add_port(module_id, wl_port, ModuleManager::MODULE_INPUT_PORT);
|
module_manager.add_port(module_id, wl_port, ModuleManager::MODULE_INPUT_PORT);
|
||||||
|
|
||||||
|
/* Optional: If we have WLR port, we should add a read-back port */
|
||||||
|
if (!circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR).empty()) {
|
||||||
|
BasicPort readback_port(std::string(MEMORY_WLR_PORT_NAME), config_protocol.num_regions());
|
||||||
|
module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue