[OpenFPGA Tool] Add multiple configuration chain support in top module builder

This commit is contained in:
tangxifan 2020-09-28 19:03:19 -06:00
parent 552dddffd0
commit f93d46a870
3 changed files with 169 additions and 15 deletions

View File

@ -431,7 +431,7 @@ int build_top_module(ModuleManager& module_manager,
if (0 < module_num_config_bits) {
add_top_module_sram_ports(module_manager, top_module,
circuit_lib, sram_model,
config_protocol.type(), module_num_config_bits);
config_protocol, module_num_config_bits);
}
/* Add module nets to connect memory cells inside
@ -440,7 +440,7 @@ int build_top_module(ModuleManager& module_manager,
if (0 < module_manager.configurable_children(top_module).size()) {
add_top_module_nets_memory_config_bus(module_manager, decoder_lib,
top_module,
config_protocol.type(), circuit_lib.design_tech_type(sram_model),
config_protocol, circuit_lib.design_tech_type(sram_model),
module_num_config_bits);
}

View File

@ -579,6 +579,41 @@ int load_top_module_memory_modules_from_fabric_key(ModuleManager& module_manager
return CMD_EXEC_SUCCESS;
}
/********************************************************************
* Generate a list of ports that are used for SRAM configuration
* to the top-level module
* 1. Standalone SRAMs:
* use the suggested port_size
* 2. Scan-chain Flip-flops:
* IMPORTANT: the port size will be limited by the number of configurable regions
* 3. Memory decoders:
* use the suggested port_size
********************************************************************/
static
size_t generate_top_module_sram_port_size(const ConfigProtocol& config_protocol,
const size_t& num_config_bits) {
size_t sram_port_size = num_config_bits;
switch (config_protocol.type()) {
case CONFIG_MEM_STANDALONE:
break;
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:
break;
case CONFIG_MEM_FRAME_BASED:
break;
default:
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Invalid type of SRAM organization!\n");
exit(1);
}
return sram_port_size;
}
/********************************************************************
* Add a list of ports that are used for SRAM configuration to the FPGA
* top-level module
@ -606,13 +641,13 @@ void add_top_module_sram_ports(ModuleManager& module_manager,
const ModuleId& module_id,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_config_protocol_type sram_orgz_type,
const ConfigProtocol& config_protocol,
const size_t& num_config_bits) {
std::vector<std::string> sram_port_names = generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type);
size_t sram_port_size = generate_sram_port_size(sram_orgz_type, num_config_bits);
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);
/* Add ports to the module manager */
switch (sram_orgz_type) {
switch (config_protocol.type()) {
case CONFIG_MEM_STANDALONE: {
for (const std::string& sram_port_name : sram_port_names) {
/* Add generated ports to the ModuleManager */
@ -928,6 +963,124 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag
module_manager.add_configurable_child(top_module, wl_decoder_module, 0);
}
/********************************************************************
* Connect all the memory modules under the parent module in a chain
*
* Region 0:
* +--------+ +--------+ +--------+
* ccff_head[0] --->| Memory |--->| Memory |--->... --->| Memory |----> ccff_tail[0]
* | Module | | Module | | Module |
* | [0] | | [1] | | [N-1] |
* +--------+ +--------+ +--------+
*
* Region 1:
* +--------+ +--------+ +--------+
* ccff_head[1] --->| Memory |--->| Memory |--->... --->| Memory |----> ccff_tail[1]
* | Module | | Module | | Module |
* | [0] | | [1] | | [N-1] |
* +--------+ +--------+ +--------+
*
* For the 1st memory module:
* net source is the configuration chain head of the primitive module
* net sink is the configuration chain head of the next memory module
*
* For the rest of memory modules:
* net source is the configuration chain tail of the previous memory module
* net sink is the configuration chain head of the next memory module
*********************************************************************/
static
void add_top_module_nets_cmos_memory_chain_config_bus(ModuleManager& module_manager,
const ModuleId& parent_module,
const ConfigProtocol& config_protocol) {
for (const ConfigRegionId& config_region : module_manager.regions(parent_module)) {
for (size_t mem_index = 0; mem_index < module_manager.region_configurable_children(parent_module, config_region).size(); ++mem_index) {
ModuleId net_src_module_id;
size_t net_src_instance_id;
ModulePortId net_src_port_id;
size_t net_src_pin_id;
ModuleId net_sink_module_id;
size_t net_sink_instance_id;
ModulePortId net_sink_port_id;
size_t net_sink_pin_id;
if (0 == mem_index) {
/* Find the port name of configuration chain head */
std::string src_port_name = generate_sram_port_name(config_protocol.type(), CIRCUIT_MODEL_PORT_INPUT);
net_src_module_id = parent_module;
net_src_instance_id = 0;
net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name);
net_src_pin_id = size_t(config_region);
/* Find the port name of next memory module */
std::string sink_port_name = generate_configuration_chain_head_name();
net_sink_module_id = module_manager.region_configurable_children(parent_module, config_region)[mem_index];
net_sink_instance_id = module_manager.region_configurable_child_instances(parent_module, config_region)[mem_index];
net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name);
net_sink_pin_id = 0;
} else {
/* Find the port name of previous memory module */
std::string src_port_name = generate_configuration_chain_tail_name();
net_src_module_id = module_manager.region_configurable_children(parent_module, config_region)[mem_index - 1];
net_src_instance_id = module_manager.region_configurable_child_instances(parent_module, config_region)[mem_index - 1];
net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name);
net_src_pin_id = 0;
/* Find the port name of next memory module */
std::string sink_port_name = generate_configuration_chain_head_name();
net_sink_module_id = module_manager.region_configurable_children(parent_module, config_region)[mem_index];
net_sink_instance_id = module_manager.region_configurable_child_instances(parent_module, config_region)[mem_index];
net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name);
net_sink_pin_id = 0;
}
/* Get the pin id for source port */
BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id);
/* Get the pin id for sink port */
BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id);
VTR_ASSERT(net_src_pin_id < net_src_port.get_width());
VTR_ASSERT(net_sink_pin_id < net_sink_port.get_width());
/* Create a net and add source and sink to it */
ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[net_src_pin_id]);
/* Add net sink */
module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[net_sink_pin_id]);
}
/* For the last memory module:
* net source is the configuration chain tail of the previous memory module
* net sink is the configuration chain tail of the primitive module
*/
/* Find the port name of previous memory module */
std::string src_port_name = generate_configuration_chain_tail_name();
ModuleId net_src_module_id = module_manager.region_configurable_children(parent_module, config_region).back();
size_t net_src_instance_id = module_manager.region_configurable_child_instances(parent_module, config_region).back();
ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name);
size_t net_src_pin_id = 0;
/* Find the port name of next memory module */
std::string sink_port_name = generate_sram_port_name(config_protocol.type(), CIRCUIT_MODEL_PORT_OUTPUT);
ModuleId net_sink_module_id = parent_module;
size_t net_sink_instance_id = 0;
ModulePortId net_sink_port_id = module_manager.find_module_port(net_sink_module_id, sink_port_name);
size_t net_sink_pin_id = size_t(config_region);
/* Get the pin id for source port */
BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id);
/* Get the pin id for sink port */
BasicPort net_sink_port = module_manager.module_port(net_sink_module_id, net_sink_port_id);
VTR_ASSERT(net_src_pin_id < net_src_port.get_width());
VTR_ASSERT(net_sink_pin_id < net_sink_port.get_width());
/* Create a net and add source and sink to it */
ModuleNetId net = create_module_source_pin_net(module_manager, parent_module, net_src_module_id, net_src_instance_id, net_src_port_id, net_src_port.pins()[net_src_pin_id]);
/* Add net sink */
module_manager.add_module_net_sink(parent_module, net, net_sink_module_id, net_sink_instance_id, net_sink_port_id, net_sink_port.pins()[net_sink_pin_id]);
}
}
/*********************************************************************
* Add the port-to-port connection between all the memory modules
* and their parent module
@ -976,17 +1129,17 @@ static
void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager,
DecoderLibrary& decoder_lib,
const ModuleId& parent_module,
const e_config_protocol_type& sram_orgz_type,
const ConfigProtocol& config_protocol,
const size_t& num_config_bits) {
switch (sram_orgz_type) {
switch (config_protocol.type()) {
case CONFIG_MEM_STANDALONE:
add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module,
sram_orgz_type, CIRCUIT_MODEL_PORT_BL);
config_protocol.type(), CIRCUIT_MODEL_PORT_BL);
add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module,
sram_orgz_type, CIRCUIT_MODEL_PORT_WL);
config_protocol.type(), CIRCUIT_MODEL_PORT_WL);
break;
case CONFIG_MEM_SCAN_CHAIN: {
add_module_nets_cmos_memory_chain_config_bus(module_manager, parent_module, CONFIG_MEM_SCAN_CHAIN);
add_top_module_nets_cmos_memory_chain_config_bus(module_manager, parent_module, config_protocol);
break;
}
case CONFIG_MEM_MEMORY_BANK:
@ -1037,7 +1190,7 @@ void add_top_module_nets_cmos_memory_config_bus(ModuleManager& module_manager,
void add_top_module_nets_memory_config_bus(ModuleManager& module_manager,
DecoderLibrary& decoder_lib,
const ModuleId& parent_module,
const e_config_protocol_type& sram_orgz_type,
const ConfigProtocol& config_protocol,
const e_circuit_model_design_tech& mem_tech,
const size_t& num_config_bits) {
@ -1047,7 +1200,7 @@ void add_top_module_nets_memory_config_bus(ModuleManager& module_manager,
case CIRCUIT_MODEL_DESIGN_CMOS:
add_top_module_nets_cmos_memory_config_bus(module_manager, decoder_lib,
parent_module,
sram_orgz_type,
config_protocol,
num_config_bits);
break;
case CIRCUIT_MODEL_DESIGN_RRAM:

View File

@ -16,6 +16,7 @@
#include "device_grid.h"
#include "device_rr_gsb.h"
#include "fabric_key.h"
#include "config_protocol.h"
/********************************************************************
* Function declaration
@ -48,13 +49,13 @@ void add_top_module_sram_ports(ModuleManager& module_manager,
const ModuleId& module_id,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_config_protocol_type sram_orgz_type,
const ConfigProtocol& config_protocol,
const size_t& num_config_bits);
void add_top_module_nets_memory_config_bus(ModuleManager& module_manager,
DecoderLibrary& decoder_lib,
const ModuleId& parent_module,
const e_config_protocol_type& sram_orgz_type,
const ConfigProtocol& config_protocol,
const e_circuit_model_design_tech& mem_tech,
const size_t& num_config_bits);