[Tool] Support multiple memory banks in top-level module

This commit is contained in:
tangxifan 2020-10-29 12:42:03 -06:00
parent bd49ea95d4
commit 448e88645a
7 changed files with 400 additions and 241 deletions

View File

@ -437,13 +437,13 @@ int build_top_module(ModuleManager& module_manager,
* This is a much easier job after adding sub modules (instances), * 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 * 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, config_protocol.type());
vtr::vector<ConfigRegionId, size_t> top_module_num_config_bits = find_top_module_regional_num_config_bit(module_manager, top_module, circuit_lib, sram_model, config_protocol.type()); vtr::vector<ConfigRegionId, size_t> top_module_num_config_bits = find_top_module_regional_num_config_bit(module_manager, top_module, circuit_lib, sram_model, config_protocol.type());
if (0 < module_num_config_bits) { if (!top_module_num_config_bits.empty()) {
add_top_module_sram_ports(module_manager, top_module, add_top_module_sram_ports(module_manager, top_module,
circuit_lib, sram_model, circuit_lib, sram_model,
config_protocol, module_num_config_bits); config_protocol,
top_module_num_config_bits);
} }
/* Add module nets to connect memory cells inside /* Add module nets to connect memory cells inside
@ -453,7 +453,7 @@ int build_top_module(ModuleManager& module_manager,
add_top_module_nets_memory_config_bus(module_manager, decoder_lib, add_top_module_nets_memory_config_bus(module_manager, decoder_lib,
top_module, top_module,
config_protocol, circuit_lib.design_tech_type(sram_model), config_protocol, circuit_lib.design_tech_type(sram_model),
module_num_config_bits); top_module_num_config_bits);
} }
return status; return status;

View File

@ -616,7 +616,7 @@ vtr::vector<ConfigRegionId, size_t> find_top_module_regional_num_config_bit(cons
*/ */
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
for (const ModuleId& child_module : module_manager.region_configurable_children(top_module, config_region)) { for (const ModuleId& child_module : module_manager.region_configurable_children(top_module, config_region)) {
num_config_bits[config_region] = find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type); num_config_bits[config_region] += find_module_num_config_bits(module_manager, child_module, circuit_lib, sram_model, config_protocol_type);
} }
} }
break; break;
@ -671,10 +671,9 @@ size_t generate_top_module_sram_port_size(const ConfigProtocol& config_protocol,
case CONFIG_MEM_STANDALONE: case CONFIG_MEM_STANDALONE:
break; break;
case CONFIG_MEM_SCAN_CHAIN: case CONFIG_MEM_SCAN_CHAIN:
/* CCFF head/tail are single-bit ports */
sram_port_size = config_protocol.num_regions();
break;
case CONFIG_MEM_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK:
/* CCFF head/tail, data input could be multi-bit ports */
sram_port_size = config_protocol.num_regions();
break; break;
case CONFIG_MEM_FRAME_BASED: case CONFIG_MEM_FRAME_BASED:
break; break;
@ -715,9 +714,13 @@ void add_top_module_sram_ports(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib, const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model, const CircuitModelId& sram_model,
const ConfigProtocol& config_protocol, const ConfigProtocol& config_protocol,
const size_t& num_config_bits) { const vtr::vector<ConfigRegionId, size_t>& num_config_bits) {
std::vector<std::string> sram_port_names = generate_sram_port_names(circuit_lib, sram_model, config_protocol.type()); std::vector<std::string> sram_port_names = generate_sram_port_names(circuit_lib, sram_model, config_protocol.type());
size_t sram_port_size = generate_top_module_sram_port_size(config_protocol, num_config_bits); size_t total_num_config_bits = 0;
for (const size_t& curr_num_config_bits : num_config_bits) {
total_num_config_bits += curr_num_config_bits;
}
size_t sram_port_size = generate_top_module_sram_port_size(config_protocol, total_num_config_bits);
/* Add ports to the module manager */ /* Add ports to the module manager */
switch (config_protocol.type()) { switch (config_protocol.type()) {
@ -733,15 +736,24 @@ void add_top_module_sram_ports(ModuleManager& module_manager,
BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1);
module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT);
size_t bl_addr_size = find_memory_decoder_addr_size(num_config_bits); /* BL address size is the largest among all the regions */
size_t bl_addr_size = 0;
for (const ConfigRegionId& config_region : module_manager.regions(module_id)) {
bl_addr_size = std::max(bl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region]));
}
BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), bl_addr_size); BasicPort bl_addr_port(std::string(DECODER_BL_ADDRESS_PORT_NAME), bl_addr_size);
module_manager.add_port(module_id, bl_addr_port, ModuleManager::MODULE_INPUT_PORT); module_manager.add_port(module_id, bl_addr_port, ModuleManager::MODULE_INPUT_PORT);
size_t wl_addr_size = find_memory_decoder_addr_size(num_config_bits); /* WL address size is the largest among all the regions */
size_t wl_addr_size = 0;
for (const ConfigRegionId& config_region : module_manager.regions(module_id)) {
wl_addr_size = std::max(wl_addr_size, find_memory_decoder_addr_size(num_config_bits[config_region]));
}
BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size); BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size);
module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT); module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT);
BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), 1); /* Data input should be dependent on the number of configuration regions*/
BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), config_protocol.num_regions());
module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT); module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT);
break; break;
@ -770,7 +782,7 @@ void add_top_module_sram_ports(ModuleManager& module_manager,
BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1);
module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT); module_manager.add_port(module_id, en_port, ModuleManager::MODULE_INPUT_PORT);
BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), num_config_bits); BasicPort addr_port(std::string(DECODER_ADDRESS_PORT_NAME), total_num_config_bits);
module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT); module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT);
BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), 1); BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), 1);
@ -787,11 +799,29 @@ void add_top_module_sram_ports(ModuleManager& module_manager,
/********************************************************************* /*********************************************************************
* Top-level function to add nets for memory banks * Top-level function to add nets for memory banks
* - Find the number of BLs and WLs required * Each configuration region has independent memory bank circuitry
* - Find the number of BLs and WLs required for each region
* - Create BL and WL decoders, and add them to decoder library * - Create BL and WL decoders, and add them to decoder library
* - Create nets to connect from top-level module inputs to inputs of decoders * - Create nets to connect from top-level module inputs to inputs of decoders
* - Create nets to connect from outputs of decoders to BL/WL of configurable children * - Create nets to connect from outputs of decoders to BL/WL of configurable children
* *
* Detailed schematic of how memory banks are connected in the top-level:
* Consider a random Region X, local BL address lines are aligned to the LSB of the
* top-level BL address lines
*
* top_bl_addr[N-1:0]
* ^
* | local_bl_addr[M-1:0], N > M
* |
* +-----+------------------+
* | | |
* | +-------------------+ |
* | | Word Line Decoder | |
* | +-------------------+ |
* | |
*
* Detailed schematic of each memory bank:
*
* WL_enable WL address * WL_enable WL address
* | | * | |
* v v * v v
@ -834,7 +864,7 @@ static
void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manager, void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manager,
DecoderLibrary& decoder_lib, DecoderLibrary& decoder_lib,
const ModuleId& top_module, const ModuleId& top_module,
const size_t& num_config_bits) { const vtr::vector<ConfigRegionId, size_t>& num_config_bits) {
/* Find Enable port from the top-level module */ /* Find Enable port from the top-level module */
ModulePortId en_port = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME)); ModulePortId en_port = module_manager.find_module_port(top_module, std::string(DECODER_ENABLE_PORT_NAME));
BasicPort en_port_info = module_manager.module_port(top_module, en_port); BasicPort en_port_info = module_manager.module_port(top_module, en_port);
@ -843,6 +873,9 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag
ModulePortId din_port = module_manager.find_module_port(top_module, std::string(DECODER_DATA_IN_PORT_NAME)); ModulePortId din_port = module_manager.find_module_port(top_module, std::string(DECODER_DATA_IN_PORT_NAME));
BasicPort din_port_info = module_manager.module_port(top_module, din_port); BasicPort din_port_info = module_manager.module_port(top_module, din_port);
/* Data in port should match the number of configuration regions */
VTR_ASSERT(din_port_info.get_width() == module_manager.regions(top_module).size());
/* Find BL and WL address port from the top-level module */ /* Find BL and WL address port from the top-level module */
ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME));
BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port); BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port);
@ -850,190 +883,240 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag
ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME));
BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port); BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port);
/* Find the number of BLs and WLs required to access each memory bit */ /* Find the top-level number of BLs and WLs required to access each memory bit */
size_t bl_addr_size = bl_addr_port_info.get_width(); size_t top_bl_addr_size = bl_addr_port_info.get_width();
size_t wl_addr_size = wl_addr_port_info.get_width(); size_t top_wl_addr_size = wl_addr_port_info.get_width();
size_t num_bls = find_memory_decoder_data_size(num_config_bits);
size_t num_wls = find_memory_decoder_data_size(num_config_bits);
/* Add the BL decoder module
* Search the decoder library
* If we find one, we use the module.
* Otherwise, we create one and add it to the decoder library
*/
DecoderId bl_decoder_id = decoder_lib.find_decoder(bl_addr_size, num_bls,
true, true, false);
if (DecoderId::INVALID() == bl_decoder_id) {
bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false);
}
VTR_ASSERT(DecoderId::INVALID() != bl_decoder_id);
/* Create a module if not existed yet */ /* Create separated memory bank circuitry, i.e., BL/WL decoders for each region */
std::string bl_decoder_module_name = generate_memory_decoder_with_data_in_subckt_name(bl_addr_size, num_bls); for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
ModuleId bl_decoder_module = module_manager.find_module(bl_decoder_module_name); /* Find the number of BL/WLs and address sizes for the local decoders in the region */
if (ModuleId::INVALID() == bl_decoder_module) { size_t num_bls = find_memory_decoder_data_size(num_config_bits[config_region]);
/* BL decoder has the same ports as the frame-based decoders size_t num_wls = find_memory_decoder_data_size(num_config_bits[config_region]);
* We reuse it here size_t local_bl_addr_size = find_memory_decoder_addr_size(num_config_bits[config_region]);
size_t local_wl_addr_size = find_memory_decoder_addr_size(num_config_bits[config_region]);
VTR_ASSERT(top_bl_addr_size >= local_bl_addr_size);
VTR_ASSERT(top_wl_addr_size >= local_wl_addr_size);
/**************************************************************
* Add the BL decoder module
* Search the decoder library
* If we find one, we use the module.
* Otherwise, we create one and add it to the decoder library
*/ */
bl_decoder_module = build_bl_memory_decoder_module(module_manager, DecoderId bl_decoder_id = decoder_lib.find_decoder(local_bl_addr_size, num_bls,
decoder_lib, true, true, false);
bl_decoder_id); if (DecoderId::INVALID() == bl_decoder_id) {
} bl_decoder_id = decoder_lib.add_decoder(local_bl_addr_size, num_bls, true, true, false);
VTR_ASSERT(ModuleId::INVALID() != bl_decoder_module); }
VTR_ASSERT(0 == module_manager.num_instance(top_module, bl_decoder_module)); VTR_ASSERT(DecoderId::INVALID() != bl_decoder_id);
module_manager.add_child_module(top_module, bl_decoder_module);
/* Add the WL decoder module /* Create a module if not existed yet */
* Search the decoder library std::string bl_decoder_module_name = generate_memory_decoder_with_data_in_subckt_name(local_bl_addr_size, num_bls);
* If we find one, we use the module. ModuleId bl_decoder_module = module_manager.find_module(bl_decoder_module_name);
* Otherwise, we create one and add it to the decoder library if (ModuleId::INVALID() == bl_decoder_module) {
*/ /* BL decoder has the same ports as the frame-based decoders
DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls, * We reuse it here
true, false, false); */
if (DecoderId::INVALID() == wl_decoder_id) { bl_decoder_module = build_bl_memory_decoder_module(module_manager,
wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false); decoder_lib,
} bl_decoder_id);
VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id); }
VTR_ASSERT(ModuleId::INVALID() != bl_decoder_module);
size_t curr_bl_decoder_instance_id = module_manager.num_instance(top_module, bl_decoder_module);
module_manager.add_child_module(top_module, bl_decoder_module);
/* Create a module if not existed yet */ /**************************************************************
std::string wl_decoder_module_name = generate_memory_decoder_subckt_name(wl_addr_size, num_wls); * Add the WL decoder module
ModuleId wl_decoder_module = module_manager.find_module(wl_decoder_module_name); * Search the decoder library
if (ModuleId::INVALID() == wl_decoder_module) { * If we find one, we use the module.
/* BL decoder has the same ports as the frame-based decoders * Otherwise, we create one and add it to the decoder library
* We reuse it here
*/ */
wl_decoder_module = build_wl_memory_decoder_module(module_manager, DecoderId wl_decoder_id = decoder_lib.find_decoder(local_wl_addr_size, num_wls,
decoder_lib, true, false, false);
wl_decoder_id); if (DecoderId::INVALID() == wl_decoder_id) {
} wl_decoder_id = decoder_lib.add_decoder(local_wl_addr_size, num_wls, true, false, false);
VTR_ASSERT(ModuleId::INVALID() != wl_decoder_module);
VTR_ASSERT(0 == module_manager.num_instance(top_module, wl_decoder_module));
module_manager.add_child_module(top_module, wl_decoder_module);
/* Add module nets from the top module to BL decoder's inputs */
ModulePortId bl_decoder_en_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME));
BasicPort bl_decoder_en_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_en_port);
ModulePortId bl_decoder_addr_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME));
BasicPort bl_decoder_addr_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_addr_port);
ModulePortId bl_decoder_din_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_IN_PORT_NAME));
BasicPort bl_decoder_din_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_din_port);
/* Top module Enable port -> BL Decoder Enable port */
add_module_bus_nets(module_manager,
top_module,
top_module, 0, en_port,
bl_decoder_module, 0, bl_decoder_en_port);
/* Top module Address port -> BL Decoder Address port */
add_module_bus_nets(module_manager,
top_module,
top_module, 0, bl_addr_port,
bl_decoder_module, 0, bl_decoder_addr_port);
/* Top module data_in port -> BL Decoder data_in port */
add_module_bus_nets(module_manager,
top_module,
top_module, 0, din_port,
bl_decoder_module, 0, bl_decoder_din_port);
/* Add module nets from the top module to WL decoder's inputs */
ModulePortId wl_decoder_en_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME));
BasicPort wl_decoder_en_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_en_port);
ModulePortId wl_decoder_addr_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME));
BasicPort wl_decoder_addr_port_info = module_manager.module_port(wl_decoder_module, bl_decoder_addr_port);
/* Top module Enable port -> WL Decoder Enable port */
add_module_bus_nets(module_manager,
top_module,
top_module, 0, en_port,
wl_decoder_module, 0, wl_decoder_en_port);
/* Top module Address port -> WL Decoder Address port */
add_module_bus_nets(module_manager,
top_module,
top_module, 0, wl_addr_port,
wl_decoder_module, 0, wl_decoder_addr_port);
/* Add nets from BL data out to each configurable child */
size_t cur_bl_index = 0;
ModulePortId bl_decoder_dout_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME));
BasicPort bl_decoder_dout_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_dout_port);
for (size_t child_id = 0; child_id < module_manager.configurable_children(top_module).size(); ++child_id) {
ModuleId child_module = module_manager.configurable_children(top_module)[child_id];
size_t child_instance = module_manager.configurable_child_instances(top_module)[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);
for (const size_t& sink_bl_pin : child_bl_port_info.pins()) {
/* Find the BL decoder data index:
* It should be the residual when divided by the number of BLs
*/
size_t bl_pin_id = std::floor(cur_bl_index / num_bls);
/* Create net */
ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
bl_decoder_module, 0,
bl_decoder_dout_port,
bl_decoder_dout_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);
/* Increment the BL index */
cur_bl_index++;
} }
} VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id);
/* Add nets from WL data out to each configurable child */ /* Create a module if not existed yet */
size_t cur_wl_index = 0; std::string wl_decoder_module_name = generate_memory_decoder_subckt_name(local_wl_addr_size, num_wls);
ModuleId wl_decoder_module = module_manager.find_module(wl_decoder_module_name);
ModulePortId wl_decoder_dout_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME)); if (ModuleId::INVALID() == wl_decoder_module) {
BasicPort wl_decoder_dout_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_dout_port); /* BL decoder has the same ports as the frame-based decoders
* We reuse it here
for (size_t child_id = 0; child_id < module_manager.configurable_children(top_module).size(); ++child_id) {
ModuleId child_module = module_manager.configurable_children(top_module)[child_id];
size_t child_instance = module_manager.configurable_child_instances(top_module)[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);
for (const size_t& sink_wl_pin : child_wl_port_info.pins()) {
/* Find the BL decoder data index:
* It should be the residual when divided by the number of BLs
*/ */
size_t wl_pin_id = cur_wl_index % num_wls; wl_decoder_module = build_wl_memory_decoder_module(module_manager,
decoder_lib,
/* Create net */ wl_decoder_id);
ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
wl_decoder_module, 0,
wl_decoder_dout_port,
wl_decoder_dout_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);
/* Increment the WL index */
cur_wl_index++;
} }
} VTR_ASSERT(ModuleId::INVALID() != wl_decoder_module);
size_t curr_wl_decoder_instance_id = module_manager.num_instance(top_module, wl_decoder_module);
module_manager.add_child_module(top_module, wl_decoder_module);
/* Add the BL and WL decoders to the end of configurable children list /**************************************************************
* Note: this MUST be done after adding all the module nets to other regular configurable children * Add module nets from the top module to BL decoder's inputs
*/ */
module_manager.add_configurable_child(top_module, bl_decoder_module, 0); ModulePortId bl_decoder_en_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME));
module_manager.add_configurable_child(top_module, wl_decoder_module, 0); BasicPort bl_decoder_en_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_en_port);
ModulePortId bl_decoder_addr_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME));
BasicPort bl_decoder_addr_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_addr_port);
ModulePortId bl_decoder_din_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_IN_PORT_NAME));
BasicPort bl_decoder_din_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_din_port);
/* Data in port of the local BL decoder should always be 1 */
VTR_ASSERT(1 == bl_decoder_din_port_info.get_width());
/* Top module Enable port -> BL Decoder Enable port */
add_module_bus_nets(module_manager,
top_module,
top_module, 0, en_port,
bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_en_port);
/* Top module Address port -> BL Decoder Address port */
add_module_bus_nets(module_manager,
top_module,
top_module, 0, bl_addr_port,
bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_addr_port,
true);
/* Top module data_in port -> BL Decoder data_in port:
* Note that each region has independent data_in connection from the top-level module
* The pin index is the configuration region index
*/
add_module_bus_nets(module_manager,
top_module,
top_module, 0, din_port,
bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_din_port);
ModuleNetId din_net = create_module_source_pin_net(module_manager, top_module,
top_module, 0,
din_port,
din_port_info.pins()[size_t(config_region)]);
VTR_ASSERT(ModuleNetId::INVALID() != din_net);
/* Configure the net sink */
module_manager.add_module_net_sink(top_module, din_net, bl_decoder_module, curr_bl_decoder_instance_id, bl_decoder_din_port, bl_decoder_din_port_info.pins()[0]);
/**************************************************************
* Add module nets from the top module to WL decoder's inputs
*/
ModulePortId wl_decoder_en_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ENABLE_PORT_NAME));
BasicPort wl_decoder_en_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_en_port);
ModulePortId wl_decoder_addr_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME));
BasicPort wl_decoder_addr_port_info = module_manager.module_port(wl_decoder_module, bl_decoder_addr_port);
/* Top module Enable port -> WL Decoder Enable port */
add_module_bus_nets(module_manager,
top_module,
top_module, 0, en_port,
wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_en_port);
/* Top module Address port -> WL Decoder Address port */
add_module_bus_nets(module_manager,
top_module,
top_module, 0, wl_addr_port,
wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_addr_port,
true);
/**************************************************************
* Add nets from BL data out to each configurable child
*/
size_t cur_bl_index = 0;
ModulePortId bl_decoder_dout_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME));
BasicPort bl_decoder_dout_port_info = module_manager.module_port(bl_decoder_module, bl_decoder_dout_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];
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);
for (const size_t& sink_bl_pin : child_bl_port_info.pins()) {
/* Find the BL decoder data index:
* It should be the residual when divided by the number of BLs
*/
size_t bl_pin_id = std::floor(cur_bl_index / num_bls);
if (!(bl_pin_id < bl_decoder_dout_port_info.pins().size()))
VTR_ASSERT(bl_pin_id < bl_decoder_dout_port_info.pins().size());
/* Create net */
ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
bl_decoder_module, curr_bl_decoder_instance_id,
bl_decoder_dout_port,
bl_decoder_dout_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);
/* Increment the BL index */
cur_bl_index++;
}
}
/**************************************************************
* Add nets from WL data out to each configurable child
*/
size_t cur_wl_index = 0;
ModulePortId wl_decoder_dout_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME));
BasicPort wl_decoder_dout_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_dout_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];
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);
for (const size_t& sink_wl_pin : child_wl_port_info.pins()) {
/* Find the BL decoder data index:
* It should be the residual when divided by the number of BLs
*/
size_t wl_pin_id = cur_wl_index % num_wls;
/* Create net */
ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
wl_decoder_module, curr_wl_decoder_instance_id,
wl_decoder_dout_port,
wl_decoder_dout_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);
/* Increment the WL index */
cur_wl_index++;
}
}
/**************************************************************
* Add the BL and WL decoders to the end of configurable children list
* Note: this MUST be done after adding all the module nets to other regular configurable children
*/
module_manager.add_configurable_child(top_module, bl_decoder_module, curr_bl_decoder_instance_id);
module_manager.add_configurable_child_to_region(top_module,
config_region,
bl_decoder_module,
curr_bl_decoder_instance_id,
module_manager.configurable_children(top_module).size() - 1);
module_manager.add_configurable_child(top_module, wl_decoder_module, curr_wl_decoder_instance_id);
module_manager.add_configurable_child_to_region(top_module,
config_region,
wl_decoder_module,
curr_wl_decoder_instance_id,
module_manager.configurable_children(top_module).size() - 1);
}
} }
/******************************************************************** /********************************************************************
@ -1203,7 +1286,7 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager,
DecoderLibrary& decoder_lib, DecoderLibrary& decoder_lib,
const ModuleId& parent_module, const ModuleId& parent_module,
const ConfigProtocol& config_protocol, const ConfigProtocol& config_protocol,
const size_t& num_config_bits) { const vtr::vector<ConfigRegionId, size_t>& num_config_bits) {
switch (config_protocol.type()) { switch (config_protocol.type()) {
case CONFIG_MEM_STANDALONE: case CONFIG_MEM_STANDALONE:
add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module,
@ -1265,7 +1348,7 @@ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager,
const ModuleId& parent_module, const ModuleId& parent_module,
const ConfigProtocol& config_protocol, const ConfigProtocol& config_protocol,
const e_circuit_model_design_tech& mem_tech, const e_circuit_model_design_tech& mem_tech,
const size_t& num_config_bits) { const vtr::vector<ConfigRegionId, size_t>& num_config_bits) {
vtr::ScopedStartFinishTimer timer("Add module nets for configuration buses"); vtr::ScopedStartFinishTimer timer("Add module nets for configuration buses");

View File

@ -57,14 +57,14 @@ void add_top_module_sram_ports(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib, const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model, const CircuitModelId& sram_model,
const ConfigProtocol& config_protocol, const ConfigProtocol& config_protocol,
const size_t& num_config_bits); const vtr::vector<ConfigRegionId, size_t>& num_config_bits);
void add_top_module_nets_memory_config_bus(ModuleManager& module_manager, void add_top_module_nets_memory_config_bus(ModuleManager& module_manager,
DecoderLibrary& decoder_lib, DecoderLibrary& decoder_lib,
const ModuleId& parent_module, const ModuleId& parent_module,
const ConfigProtocol& config_protocol, const ConfigProtocol& config_protocol,
const e_circuit_model_design_tech& mem_tech, const e_circuit_model_design_tech& mem_tech,
const size_t& num_config_bits); const vtr::vector<ConfigRegionId, size_t>& num_config_bits);
} /* end namespace openfpga */ } /* end namespace openfpga */

View File

@ -58,7 +58,6 @@ void rec_build_module_fabric_dependent_chain_bitstream(const BitstreamManager& b
/* Find the child block that matches the instance name! */ /* Find the child block that matches the instance name! */
ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name);
/* We must have one valid block id! */ /* We must have one valid block id! */
if (true != bitstream_manager.valid_block_id(child_block))
VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block));
/* Go recursively */ /* Go recursively */
@ -79,7 +78,6 @@ void rec_build_module_fabric_dependent_chain_bitstream(const BitstreamManager& b
/* Find the child block that matches the instance name! */ /* Find the child block that matches the instance name! */
ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name); ConfigBlockId child_block = bitstream_manager.find_child_block(parent_block, instance_name);
/* We must have one valid block id! */ /* We must have one valid block id! */
if (true != bitstream_manager.valid_block_id(child_block))
VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block)); VTR_ASSERT(true == bitstream_manager.valid_block_id(child_block));
/* Go recursively */ /* Go recursively */
@ -126,6 +124,7 @@ void rec_build_module_fabric_dependent_memory_bank_bitstream(const BitstreamMana
const ModuleManager& module_manager, const ModuleManager& module_manager,
const ModuleId& top_module, const ModuleId& top_module,
const ModuleId& parent_module, const ModuleId& parent_module,
const ConfigRegionId& config_region,
const size_t& bl_addr_size, const size_t& bl_addr_size,
const size_t& wl_addr_size, const size_t& wl_addr_size,
const size_t& num_bls, const size_t& num_bls,
@ -138,11 +137,16 @@ void rec_build_module_fabric_dependent_memory_bank_bitstream(const BitstreamMana
* we dive to the next level first! * we dive to the next level first!
*/ */
if (0 < bitstream_manager.block_children(parent_block).size()) { if (0 < bitstream_manager.block_children(parent_block).size()) {
/* For top module, we will skip the two decoders at the end of the configurable children list */ /* For top module:
* - Use regional configurable children
* - we will skip the two decoders at the end of the configurable children list
*/
std::vector<ModuleId> configurable_children = module_manager.configurable_children(parent_module); std::vector<ModuleId> configurable_children = module_manager.configurable_children(parent_module);
size_t num_configurable_children = configurable_children.size(); size_t num_configurable_children = configurable_children.size();
if (parent_module == top_module) { if (parent_module == top_module) {
configurable_children = module_manager.region_configurable_children(parent_module, config_region);
VTR_ASSERT(2 <= configurable_children.size()); VTR_ASSERT(2 <= configurable_children.size());
num_configurable_children -= 2; num_configurable_children -= 2;
} }
@ -157,6 +161,10 @@ void rec_build_module_fabric_dependent_memory_bank_bitstream(const BitstreamMana
for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) { for (size_t child_id = 0; child_id < num_configurable_children; ++child_id) {
ModuleId child_module = configurable_children[child_id]; ModuleId child_module = configurable_children[child_id];
size_t child_instance = module_manager.configurable_child_instances(parent_module)[child_id]; size_t child_instance = module_manager.configurable_child_instances(parent_module)[child_id];
if (parent_module == top_module) {
child_instance = module_manager.region_configurable_child_instances(parent_module, config_region)[child_id];
}
/* Get the instance name and ensure it is not empty */ /* Get the instance name and ensure it is not empty */
std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance); std::string instance_name = module_manager.instance_name(parent_module, child_module, child_instance);
@ -169,6 +177,7 @@ void rec_build_module_fabric_dependent_memory_bank_bitstream(const BitstreamMana
/* Go recursively */ /* Go recursively */
rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, child_block, rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, child_block,
module_manager, top_module, child_module, module_manager, top_module, child_module,
config_region,
bl_addr_size, wl_addr_size, bl_addr_size, wl_addr_size,
num_bls, num_wls, num_bls, num_wls,
cur_mem_index, cur_mem_index,
@ -451,30 +460,14 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc
break; break;
} }
case CONFIG_MEM_MEMORY_BANK: { case CONFIG_MEM_MEMORY_BANK: {
/* Find global BL address port size */
size_t cur_mem_index = 0;
/* Find BL address port size */
ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME)); ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME));
BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port); BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port);
/* Find WL address port size */ /* Find global WL address port size */
ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME)); ModulePortId wl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_WL_ADDRESS_PORT_NAME));
BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port); BasicPort wl_addr_port_info = module_manager.module_port(top_module, wl_addr_port);
/* Find BL and WL decoders which are the last two configurable children*/
std::vector<ModuleId> configurable_children = module_manager.configurable_children(top_module);
VTR_ASSERT(2 <= configurable_children.size());
ModuleId bl_decoder_module = configurable_children[configurable_children.size() - 2];
VTR_ASSERT(0 == module_manager.configurable_child_instances(top_module)[configurable_children.size() - 2]);
ModuleId wl_decoder_module = configurable_children[configurable_children.size() - 1];
VTR_ASSERT(0 == module_manager.configurable_child_instances(top_module)[configurable_children.size() - 1]);
ModulePortId bl_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME));
BasicPort bl_port_info = module_manager.module_port(bl_decoder_module, bl_port);
ModulePortId wl_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME));
BasicPort wl_port_info = module_manager.module_port(wl_decoder_module, wl_port);
/* Reserve bits before build-up */ /* Reserve bits before build-up */
fabric_bitstream.set_use_address(true); fabric_bitstream.set_use_address(true);
fabric_bitstream.set_use_wl_address(true); fabric_bitstream.set_use_wl_address(true);
@ -482,13 +475,27 @@ void build_module_fabric_dependent_bitstream(const ConfigProtocol& config_protoc
fabric_bitstream.set_wl_address_length(wl_addr_port_info.get_width()); fabric_bitstream.set_wl_address_length(wl_addr_port_info.get_width());
fabric_bitstream.reserve_bits(bitstream_manager.num_bits()); fabric_bitstream.reserve_bits(bitstream_manager.num_bits());
/* TODO: Currently only support 1 region. Will expand later! */ size_t cur_mem_index = 0;
VTR_ASSERT(1 == module_manager.regions(top_module).size());
/* Build bitstreams by region */
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) { for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
/* Find port information for local BL and WL decoder in this region */
std::vector<ModuleId> configurable_children = module_manager.region_configurable_children(top_module, config_region);
VTR_ASSERT(2 <= configurable_children.size());
ModuleId bl_decoder_module = configurable_children[configurable_children.size() - 2];
ModuleId wl_decoder_module = configurable_children[configurable_children.size() - 1];
ModulePortId bl_port = module_manager.find_module_port(bl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME));
BasicPort bl_port_info = module_manager.module_port(bl_decoder_module, bl_port);
ModulePortId wl_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_OUT_PORT_NAME));
BasicPort wl_port_info = module_manager.module_port(wl_decoder_module, wl_port);
/* Build the bitstream for all the blocks in this region */
FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region(); FabricBitRegionId fabric_bitstream_region = fabric_bitstream.add_region();
rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, top_block, rec_build_module_fabric_dependent_memory_bank_bitstream(bitstream_manager, top_block,
module_manager, top_module, top_module, module_manager, top_module, top_module,
config_region,
bl_addr_port_info.get_width(), bl_addr_port_info.get_width(),
wl_addr_port_info.get_width(), wl_addr_port_info.get_width(),
bl_port_info.get_width(), bl_port_info.get_width(),

View File

@ -1517,6 +1517,7 @@ void print_verilog_top_testbench_memory_bank_bitstream(std::fstream& fp,
fp << ";"; fp << ";";
fp << std::endl; fp << std::endl;
fp << "\t\t";
fp << generate_verilog_port_constant_values(wl_addr_port, initial_wl_addr_values); fp << generate_verilog_port_constant_values(wl_addr_port, initial_wl_addr_values);
fp << ";"; fp << ";";
fp << std::endl; fp << std::endl;
@ -1528,37 +1529,87 @@ void print_verilog_top_testbench_memory_bank_bitstream(std::fstream& fp,
fp << std::endl; fp << std::endl;
/* Attention: the configuration chain protcol requires the last configuration bit is fed first /* Reorganize the fabric bitstream by the same address across regions:
* We will visit the fabric bitstream in a reverse way * This is due to that the length of fabric bitstream could be different in each region.
* Template:
* <bl_address> <wl_address> <din_values_from_different_regions>
* An example:
* 000000 00000 1011
*
* Note: the std::map may cause large memory footprint for large bitstream databases!
*/ */
for (const FabricBitId& bit_id : fabric_bitstream.bits()) { std::map<std::pair<std::string, std::string>, std::vector<bool>> fabric_bits_by_addr;
/* When fast configuration is enabled, we skip zero data_in values */ for (const FabricBitRegionId& region : fabric_bitstream.regions()) {
if ((true == fast_configuration) for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) {
&& (bit_value_to_skip == fabric_bitstream.bit_din(bit_id))) { /* Create string for BL address */
continue; VTR_ASSERT(bl_addr_port.get_width() == fabric_bitstream.bit_bl_address(bit_id).size());
std::string bl_addr_str;
for (const char& addr_bit : fabric_bitstream.bit_bl_address(bit_id)) {
bl_addr_str.push_back(addr_bit);
}
/* Create string for WL address */
VTR_ASSERT(wl_addr_port.get_width() == fabric_bitstream.bit_wl_address(bit_id).size());
std::string wl_addr_str;
for (const char& addr_bit : fabric_bitstream.bit_wl_address(bit_id)) {
wl_addr_str.push_back(addr_bit);
}
/* Place the config bit */
auto result = fabric_bits_by_addr.find(std::make_pair(bl_addr_str, wl_addr_str));
if (result == fabric_bits_by_addr.end()) {
/* This is a new bit, resize the vector to the number of regions
* and deposit '0' to all the bits
*/
fabric_bits_by_addr[std::make_pair(bl_addr_str, wl_addr_str)] = std::vector<bool>(fabric_bitstream.regions().size(), false);
fabric_bits_by_addr[std::make_pair(bl_addr_str, wl_addr_str)][size_t(region)] = fabric_bitstream.bit_din(bit_id);
} else {
VTR_ASSERT_SAFE(result != fabric_bits_by_addr.end());
result->second[size_t(region)] = fabric_bitstream.bit_din(bit_id);
}
}
}
for (const auto& addr_din_pair : fabric_bits_by_addr) {
/* When fast configuration is enabled,
* the rule to skip any configuration bit should consider the whole data input values.
* Only all the bits in the din port match the value to be skipped,
* the programming cycle can be skipped!
*/
if (true == fast_configuration) {
bool skip_curr_bits = true;
for (const bool& bit : addr_din_pair.second) {
if (bit_value_to_skip != bit) {
skip_curr_bits = false;
break;
}
}
if (true == skip_curr_bits) {
continue;
}
} }
fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME); fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME);
fp << "(" << bl_addr_port.get_width() << "'b"; fp << "(" << bl_addr_port.get_width() << "'b";
VTR_ASSERT(bl_addr_port.get_width() == fabric_bitstream.bit_bl_address(bit_id).size()); VTR_ASSERT(bl_addr_port.get_width() == addr_din_pair.first.first.length());
for (const char& addr_bit : fabric_bitstream.bit_bl_address(bit_id)) { fp << addr_din_pair.first.first;
fp << addr_bit;
}
fp << ", "; fp << ", ";
fp << wl_addr_port.get_width() << "'b"; fp << wl_addr_port.get_width() << "'b";
VTR_ASSERT(wl_addr_port.get_width() == fabric_bitstream.bit_wl_address(bit_id).size()); VTR_ASSERT(wl_addr_port.get_width() == addr_din_pair.first.second.length());
for (const char& addr_bit : fabric_bitstream.bit_wl_address(bit_id)) { fp << addr_din_pair.first.second;
fp << addr_bit;
}
fp << ", "; fp << ", ";
fp <<"1'b"; fp << din_port.get_width() << "'b";
if (true == fabric_bitstream.bit_din(bit_id)) { VTR_ASSERT(din_port.get_width() == addr_din_pair.second.size());
fp << "1"; for (const bool& din_value : addr_din_pair.second) {
} else { if (true == din_value) {
VTR_ASSERT(false == fabric_bitstream.bit_din(bit_id)); fp << "1";
fp << "0"; } else {
VTR_ASSERT(false == din_value);
fp << "0";
}
} }
fp << ");" << std::endl; fp << ");" << std::endl;
} }

View File

@ -1793,6 +1793,16 @@ ModuleNetId create_module_source_pin_net(ModuleManager& module_manager,
* - des_module should be the cur_module or a child of it * - des_module should be the cur_module or a child of it
* - src_instance should be valid and des_instance should be valid as well * - src_instance should be valid and des_instance should be valid as well
* - src port size should match the des port size * - src port size should match the des port size
*
* Power options:
* - align_to_lsb: This is by default turned off!
* When enabled, the source and destination ports
* will be connected pin-by-pin starting from
* the Least Significant Bit (LSB)
* The source and destination ports are not required
* to be same in sizes.
* BE CAREFUL! This may cause dangling pins!
* Use when you know what you are doing!
*******************************************************************/ *******************************************************************/
void add_module_bus_nets(ModuleManager& module_manager, void add_module_bus_nets(ModuleManager& module_manager,
const ModuleId& cur_module_id, const ModuleId& cur_module_id,
@ -1801,7 +1811,8 @@ void add_module_bus_nets(ModuleManager& module_manager,
const ModulePortId& src_module_port_id, const ModulePortId& src_module_port_id,
const ModuleId& des_module_id, const ModuleId& des_module_id,
const size_t& des_instance_id, const size_t& des_instance_id,
const ModulePortId& des_module_port_id) { const ModulePortId& des_module_port_id,
const bool& align_to_lsb) {
VTR_ASSERT(true == module_manager.valid_module_id(cur_module_id)); VTR_ASSERT(true == module_manager.valid_module_id(cur_module_id));
VTR_ASSERT(true == module_manager.valid_module_id(src_module_id)); VTR_ASSERT(true == module_manager.valid_module_id(src_module_id));
@ -1825,7 +1836,8 @@ void add_module_bus_nets(ModuleManager& module_manager,
const BasicPort& src_port = module_manager.module_port(src_module_id, src_module_port_id); const BasicPort& src_port = module_manager.module_port(src_module_id, src_module_port_id);
const BasicPort& des_port = module_manager.module_port(des_module_id, des_module_port_id); const BasicPort& des_port = module_manager.module_port(des_module_id, des_module_port_id);
if (src_port.get_width() != des_port.get_width()) { if ( (false == align_to_lsb)
&& (src_port.get_width() != des_port.get_width())) {
VTR_LOGF_ERROR(__FILE__, __LINE__, VTR_LOGF_ERROR(__FILE__, __LINE__,
"Unmatched port size: src_port %s is %lu while des_port %s is %lu!\n", "Unmatched port size: src_port %s is %lu while des_port %s is %lu!\n",
src_port.get_name().c_str(), src_port.get_name().c_str(),
@ -1837,6 +1849,11 @@ void add_module_bus_nets(ModuleManager& module_manager,
/* Create a net for each pin */ /* Create a net for each pin */
for (size_t pin_id = 0; pin_id < src_port.pins().size(); ++pin_id) { for (size_t pin_id = 0; pin_id < src_port.pins().size(); ++pin_id) {
/* Create net only when des_port has a valid pin! */
if (pin_id >= des_port.pins().size()) {
continue;
}
ModuleNetId net = create_module_source_pin_net(module_manager, cur_module_id, ModuleNetId net = create_module_source_pin_net(module_manager, cur_module_id,
src_module_id, src_instance_id, src_module_id, src_instance_id,
src_module_port_id, src_port.pins()[pin_id]); src_module_port_id, src_port.pins()[pin_id]);

View File

@ -165,7 +165,8 @@ void add_module_bus_nets(ModuleManager& module_manager,
const ModulePortId& src_module_port_id, const ModulePortId& src_module_port_id,
const ModuleId& des_module_id, const ModuleId& des_module_id,
const size_t& des_instance_id, const size_t& des_instance_id,
const ModulePortId& des_module_port_id); const ModulePortId& des_module_port_id,
const bool& align_to_lsb = false);
} /* end namespace openfpga */ } /* end namespace openfpga */